Merge branch 'dev' into sort-feedbacks
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
import { getContext, onMount } from 'svelte';
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
import { models } from '$lib/stores';
|
||||
import { settings } from '$lib/stores';
|
||||
import { verifyOpenAIConnection } from '$lib/apis/openai';
|
||||
import { verifyOllamaConnection } from '$lib/apis/ollama';
|
||||
|
||||
@@ -258,11 +258,17 @@
|
||||
|
||||
<div class="flex gap-2 mt-1.5">
|
||||
<div class="flex flex-col w-full">
|
||||
<div class=" mb-0.5 text-xs text-gray-500">{$i18n.t('URL')}</div>
|
||||
<label
|
||||
for="url-input"
|
||||
class={`mb-0.5 text-xs text-gray-500
|
||||
${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : ''}`}
|
||||
>{$i18n.t('URL')}</label
|
||||
>
|
||||
|
||||
<div class="flex-1">
|
||||
<input
|
||||
class="w-full text-sm bg-transparent placeholder:text-gray-300 dark:placeholder:text-gray-700 outline-hidden"
|
||||
id="url-input"
|
||||
class={`w-full text-sm bg-transparent ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
|
||||
type="text"
|
||||
bind:value={url}
|
||||
placeholder={$i18n.t('API Base URL')}
|
||||
@@ -279,11 +285,13 @@
|
||||
verifyHandler();
|
||||
}}
|
||||
type="button"
|
||||
aria-label={$i18n.t('Verify Connection')}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
aria-hidden="true"
|
||||
class="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
@@ -296,19 +304,27 @@
|
||||
</Tooltip>
|
||||
|
||||
<div class="flex flex-col shrink-0 self-end">
|
||||
<label class="sr-only" for="toggle-connection"
|
||||
>{$i18n.t('Toggle whether current connection is active.')}</label
|
||||
>
|
||||
<Tooltip content={enable ? $i18n.t('Enabled') : $i18n.t('Disabled')}>
|
||||
<Switch bind:state={enable} />
|
||||
<Switch id="toggle-connection" bind:state={enable} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2 mt-2">
|
||||
<div class="flex flex-col w-full">
|
||||
<div class=" mb-0.5 text-xs text-gray-500">{$i18n.t('Key')}</div>
|
||||
<div
|
||||
class={`mb-0.5 text-xs text-gray-500
|
||||
${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : ''}`}
|
||||
>
|
||||
{$i18n.t('Key')}
|
||||
</div>
|
||||
|
||||
<div class="flex-1">
|
||||
<SensitiveInput
|
||||
className="w-full text-sm bg-transparent placeholder:text-gray-300 dark:placeholder:text-gray-700 outline-hidden"
|
||||
inputClassName={`w-full text-sm bg-transparent ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
|
||||
bind:value={key}
|
||||
placeholder={$i18n.t('API Key')}
|
||||
required={false}
|
||||
@@ -317,7 +333,12 @@
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col w-full">
|
||||
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('Prefix ID')}</div>
|
||||
<label
|
||||
for="prefix-id-input"
|
||||
class={`mb-0.5 text-xs text-gray-500
|
||||
${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : ''}`}
|
||||
>{$i18n.t('Prefix ID')}</label
|
||||
>
|
||||
|
||||
<div class="flex-1">
|
||||
<Tooltip
|
||||
@@ -326,8 +347,9 @@
|
||||
)}
|
||||
>
|
||||
<input
|
||||
class="w-full text-sm bg-transparent placeholder:text-gray-300 dark:placeholder:text-gray-700 outline-hidden"
|
||||
class={`w-full text-sm bg-transparent ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
|
||||
type="text"
|
||||
id="prefix-id-input"
|
||||
bind:value={prefixId}
|
||||
placeholder={$i18n.t('Prefix ID')}
|
||||
autocomplete="off"
|
||||
@@ -340,11 +362,17 @@
|
||||
{#if azure}
|
||||
<div class="flex gap-2 mt-2">
|
||||
<div class="flex flex-col w-full">
|
||||
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('API Version')}</div>
|
||||
<label
|
||||
for="api-version-input"
|
||||
class={`mb-0.5 text-xs text-gray-500
|
||||
${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : ''}`}
|
||||
>{$i18n.t('API Version')}</label
|
||||
>
|
||||
|
||||
<div class="flex-1">
|
||||
<input
|
||||
class="w-full text-sm bg-transparent placeholder:text-gray-300 dark:placeholder:text-gray-700 outline-hidden"
|
||||
id="api-version-input"
|
||||
class={`w-full text-sm bg-transparent placeholder:text-gray-300 dark:placeholder:text-gray-700 ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
|
||||
type="text"
|
||||
bind:value={apiVersion}
|
||||
placeholder={$i18n.t('API Version')}
|
||||
@@ -358,7 +386,12 @@
|
||||
|
||||
<div class="flex gap-2 mt-2">
|
||||
<div class="flex flex-col w-full">
|
||||
<div class=" mb-1.5 text-xs text-gray-500">{$i18n.t('Tags')}</div>
|
||||
<div
|
||||
class={`mb-0.5 text-xs text-gray-500
|
||||
${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : ''}`}
|
||||
>
|
||||
{$i18n.t('Tags')}
|
||||
</div>
|
||||
|
||||
<div class="flex-1">
|
||||
<Tags
|
||||
@@ -383,18 +416,26 @@
|
||||
|
||||
<div class="flex flex-col w-full">
|
||||
<div class="mb-1 flex justify-between">
|
||||
<div class="text-xs text-gray-500">{$i18n.t('Model IDs')}</div>
|
||||
<div
|
||||
class={`mb-0.5 text-xs text-gray-500
|
||||
${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : ''}`}
|
||||
>
|
||||
{$i18n.t('Model IDs')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if modelIds.length > 0}
|
||||
<div class="flex flex-col">
|
||||
<ul class="flex flex-col">
|
||||
{#each modelIds as modelId, modelIdx}
|
||||
<div class=" flex gap-2 w-full justify-between items-center">
|
||||
<li class=" flex gap-2 w-full justify-between items-center">
|
||||
<div class=" text-sm flex-1 py-1 rounded-lg">
|
||||
{modelId}
|
||||
</div>
|
||||
<div class="shrink-0">
|
||||
<button
|
||||
aria-label={$i18n.t(`Remove {{MODELID}} from list.`, {
|
||||
MODELID: modelId
|
||||
})}
|
||||
type="button"
|
||||
on:click={() => {
|
||||
modelIds = modelIds.filter((_, idx) => idx !== modelIdx);
|
||||
@@ -403,11 +444,14 @@
|
||||
<Minus strokeWidth="2" className="size-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{/each}
|
||||
</div>
|
||||
</ul>
|
||||
{:else}
|
||||
<div class="text-gray-500 text-xs text-center py-2 px-10">
|
||||
<div
|
||||
class={`text-gray-500 text-xs text-center py-2 px-10
|
||||
${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : ''}`}
|
||||
>
|
||||
{#if ollama}
|
||||
{$i18n.t('Leave empty to include all models from "{{url}}/api/tags" endpoint', {
|
||||
url: url
|
||||
@@ -429,17 +473,22 @@
|
||||
<hr class=" border-gray-100 dark:border-gray-700/10 my-1.5 w-full" />
|
||||
|
||||
<div class="flex items-center">
|
||||
<label class="sr-only" for="add-model-id-input">{$i18n.t('Add a model ID')}</label>
|
||||
<input
|
||||
class="w-full py-1 text-sm rounded-lg bg-transparent {modelId
|
||||
? ''
|
||||
: 'text-gray-500'} placeholder:text-gray-300 dark:placeholder:text-gray-700 outline-hidden"
|
||||
: 'text-gray-500'} {($settings?.highContrastMode ?? false)
|
||||
? 'dark:placeholder:text-gray-100 placeholder:text-gray-700'
|
||||
: 'placeholder:text-gray-300 dark:placeholder:text-gray-700 outline-hidden'}"
|
||||
bind:value={modelId}
|
||||
id="add-model-id-input"
|
||||
placeholder={$i18n.t('Add a model ID')}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
aria-label={$i18n.t('Add')}
|
||||
on:click={() => {
|
||||
addModelHandler();
|
||||
}}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<script lang="ts">
|
||||
import Modal from '$lib/components/common/Modal.svelte';
|
||||
import { getContext } from 'svelte';
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
export let show = false;
|
||||
export let selectedFeedback = null;
|
||||
|
||||
export let onClose: () => void = () => {};
|
||||
|
||||
const close = () => {
|
||||
show = false;
|
||||
onClose();
|
||||
};
|
||||
</script>
|
||||
|
||||
<Modal size="sm" bind:show>
|
||||
{#if selectedFeedback}
|
||||
<div>
|
||||
<div class="flex justify-between dark:text-gray-300 px-5 pt-4 pb-2">
|
||||
<div class="text-lg font-medium self-center">
|
||||
{$i18n.t('Feedback Details')}
|
||||
</div>
|
||||
<button class="self-center" on:click={close} aria-label="Close">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
class="w-5 h-5"
|
||||
>
|
||||
<path
|
||||
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col md:flex-row w-full px-5 pb-4 md:space-x-4 dark:text-gray-200">
|
||||
<div class="flex flex-col w-full">
|
||||
<div class="flex flex-col w-full mb-2">
|
||||
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('Rating')}</div>
|
||||
|
||||
<div class="flex-1">
|
||||
<span>{selectedFeedback?.data?.details?.rating ?? '-'}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col w-full mb-2">
|
||||
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('Reason')}</div>
|
||||
|
||||
<div class="flex-1">
|
||||
<span>{selectedFeedback?.data?.reason || '-'}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
{#if selectedFeedback?.data?.tags && selectedFeedback?.data?.tags.length}
|
||||
<div class="flex flex-wrap gap-1 mt-1">
|
||||
{#each selectedFeedback?.data?.tags as tag}
|
||||
<span class="px-2 py-0.5 rounded bg-gray-100 dark:bg-gray-800 text-xs">{tag}</span
|
||||
>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<span>-</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="flex justify-end pt-3">
|
||||
<button
|
||||
class="px-3.5 py-1.5 text-sm font-medium bg-black hover:bg-gray-900 text-white dark:bg-white dark:text-black dark:hover:bg-gray-100 transition rounded-full"
|
||||
type="button"
|
||||
on:click={close}
|
||||
>
|
||||
{$i18n.t('Close')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</Modal>
|
||||
@@ -18,6 +18,7 @@
|
||||
import CloudArrowUp from '$lib/components/icons/CloudArrowUp.svelte';
|
||||
import Pagination from '$lib/components/common/Pagination.svelte';
|
||||
import FeedbackMenu from './FeedbackMenu.svelte';
|
||||
import FeedbackModal from './FeedbackModal.svelte';
|
||||
import EllipsisHorizontal from '$lib/components/icons/EllipsisHorizontal.svelte';
|
||||
|
||||
import ChevronUp from '$lib/components/icons/ChevronUp.svelte';
|
||||
@@ -92,6 +93,19 @@
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
let showFeedbackModal = false;
|
||||
let selectedFeedback = null;
|
||||
|
||||
const openFeedbackModal = (feedback) => {
|
||||
showFeedbackModal = true;
|
||||
selectedFeedback = feedback;
|
||||
};
|
||||
|
||||
const closeFeedbackModal = () => {
|
||||
showFeedbackModal = false;
|
||||
selectedFeedback = null;
|
||||
};
|
||||
|
||||
//////////////////////
|
||||
//
|
||||
@@ -151,6 +165,8 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<FeedbackModal bind:show={showFeedbackModal} {selectedFeedback} onClose={closeFeedbackModal} />
|
||||
|
||||
<div class="mt-0.5 mb-2 gap-1 flex flex-row justify-between">
|
||||
<div class="flex md:self-center text-lg font-medium px-0.5">
|
||||
{$i18n.t('Feedback History')}
|
||||
@@ -288,7 +304,10 @@
|
||||
</thead>
|
||||
<tbody class="">
|
||||
{#each paginatedFeedbacks as feedback (feedback.id)}
|
||||
<tr class="bg-white dark:bg-gray-900 dark:border-gray-850 text-xs">
|
||||
<tr
|
||||
class="bg-white dark:bg-gray-900 dark:border-gray-850 text-xs cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 transition"
|
||||
on:click={() => openFeedbackModal(feedback)}
|
||||
>
|
||||
<td class=" py-0.5 text-right font-semibold">
|
||||
<div class="flex justify-center">
|
||||
<Tooltip content={feedback?.user?.name}>
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
import { onMount, getContext } from 'svelte';
|
||||
import { models } from '$lib/stores';
|
||||
|
||||
import ModelModal from './LeaderboardModal.svelte';
|
||||
|
||||
import Spinner from '$lib/components/common/Spinner.svelte';
|
||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||
import MagnifyingGlass from '$lib/components/icons/MagnifyingGlass.svelte';
|
||||
@@ -66,6 +68,25 @@
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
//
|
||||
// Aggregate Level Modal
|
||||
//
|
||||
//////////////////////
|
||||
|
||||
let showLeaderboardModal = false;
|
||||
let selectedModel = null;
|
||||
|
||||
const openFeedbackModal = (model) => {
|
||||
showLeaderboardModal = true;
|
||||
selectedModel = model;
|
||||
};
|
||||
|
||||
const closeLeaderboardModal = () => {
|
||||
showLeaderboardModal = false;
|
||||
selectedModel = null;
|
||||
};
|
||||
|
||||
//////////////////////
|
||||
//
|
||||
// Rank models by Elo rating
|
||||
@@ -305,6 +326,13 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<ModelModal
|
||||
bind:show={showLeaderboardModal}
|
||||
model={selectedModel}
|
||||
{feedbacks}
|
||||
onClose={closeLeaderboardModal}
|
||||
/>
|
||||
|
||||
<div class="mt-0.5 mb-2 gap-1 flex flex-col md:flex-row justify-between">
|
||||
<div class="flex md:self-center text-lg font-medium px-0.5 shrink-0 items-center">
|
||||
<div class=" gap-1">
|
||||
@@ -475,7 +503,10 @@
|
||||
</thead>
|
||||
<tbody class="">
|
||||
{#each sortedModels as model, modelIdx (model.id)}
|
||||
<tr class="bg-white dark:bg-gray-900 dark:border-gray-850 text-xs group">
|
||||
<tr
|
||||
class="bg-white dark:bg-gray-900 dark:border-gray-850 text-xs group cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 transition"
|
||||
on:click={() => openFeedbackModal(model)}
|
||||
>
|
||||
<td class="px-3 py-1.5 text-left font-medium text-gray-900 dark:text-white w-fit">
|
||||
<div class=" line-clamp-1">
|
||||
{model?.rating !== '-' ? modelIdx + 1 : '-'}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
<script lang="ts">
|
||||
import Modal from '$lib/components/common/Modal.svelte';
|
||||
import { getContext } from 'svelte';
|
||||
export let show = false;
|
||||
export let model = null;
|
||||
export let feedbacks = [];
|
||||
export let onClose: () => void = () => {};
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
const close = () => {
|
||||
show = false;
|
||||
onClose();
|
||||
};
|
||||
|
||||
$: topTags = model ? getTopTagsForModel(model.id, feedbacks) : [];
|
||||
|
||||
const getTopTagsForModel = (modelId: string, feedbacks: any[], topN = 5) => {
|
||||
const tagCounts = new Map();
|
||||
feedbacks
|
||||
.filter((fb) => fb.data.model_id === modelId)
|
||||
.forEach((fb) => {
|
||||
(fb.data.tags || []).forEach((tag) => {
|
||||
tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1);
|
||||
});
|
||||
});
|
||||
return Array.from(tagCounts.entries())
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
.slice(0, topN)
|
||||
.map(([tag, count]) => ({ tag, count }));
|
||||
};
|
||||
</script>
|
||||
|
||||
<Modal size="sm" bind:show>
|
||||
{#if model}
|
||||
<div class="flex justify-between dark:text-gray-300 px-5 pt-4 pb-2">
|
||||
<div class="text-lg font-medium self-center">
|
||||
{model.name}
|
||||
</div>
|
||||
<button class="self-center" on:click={close} aria-label="Close">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
class="w-5 h-5"
|
||||
>
|
||||
<path
|
||||
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="px-5 pb-4 dark:text-gray-200">
|
||||
<div class="mb-2">
|
||||
{#if topTags.length}
|
||||
<div class="flex flex-wrap gap-1 mt-1">
|
||||
{#each topTags as tagInfo}
|
||||
<span class="px-2 py-0.5 rounded bg-gray-100 dark:bg-gray-800 text-xs">
|
||||
{tagInfo.tag} <span class="text-gray-500">({tagInfo.count})</span>
|
||||
</span>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<span>-</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="flex justify-end pt-3">
|
||||
<button
|
||||
class="px-3.5 py-1.5 text-sm font-medium bg-black hover:bg-gray-900 text-white dark:bg-white dark:text-black dark:hover:bg-gray-100 transition rounded-full"
|
||||
type="button"
|
||||
on:click={close}
|
||||
>
|
||||
{$i18n.t('Close')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</Modal>
|
||||
@@ -109,7 +109,7 @@
|
||||
>
|
||||
{decodeString(document?.metadata?.name ?? document.source.name)}
|
||||
</a>
|
||||
{#if document?.metadata?.page}
|
||||
{#if Number.isInteger(document?.metadata?.page)}
|
||||
<span class="text-xs text-gray-500 dark:text-gray-400">
|
||||
({$i18n.t('page')}
|
||||
{document.metadata.page + 1})
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
<div
|
||||
class=" snap-center w-full max-w-full m-1 border {history.messages[messageId]
|
||||
?.modelIdx == modelIdx
|
||||
? `border-gray-100 dark:border-gray-850 border-[1.5px] ${
|
||||
? `bg-gray-50 dark:bg-gray-850 border-gray-100 dark:border-gray-800 border-2 ${
|
||||
$mobile ? 'min-w-full' : 'min-w-80'
|
||||
}`
|
||||
: `border-gray-100 dark:border-gray-850 border-dashed ${
|
||||
|
||||
@@ -107,7 +107,11 @@
|
||||
}}
|
||||
/>
|
||||
|
||||
<div class=" flex w-full user-message" dir={$settings.chatDirection} id="message-{message.id}">
|
||||
<div
|
||||
class=" flex w-full user-message group"
|
||||
dir={$settings.chatDirection}
|
||||
id="message-{message.id}"
|
||||
>
|
||||
{#if !($settings?.chatBubble ?? true)}
|
||||
<div class={`shrink-0 ltr:mr-3 rtl:ml-3`}>
|
||||
<ProfileImage
|
||||
@@ -143,6 +147,16 @@
|
||||
{/if}
|
||||
</Name>
|
||||
</div>
|
||||
{:else if message.timestamp}
|
||||
<div class="flex justify-end pb-1 pr-2">
|
||||
<div
|
||||
class="text-xs invisible group-hover:visible text-gray-400 font-medium first-letter:capitalize translate-y-[1px]"
|
||||
>
|
||||
<Tooltip content={dayjs(message.timestamp * 1000).format('LLLL')}>
|
||||
<span class="line-clamp-1">{formatDate(message.timestamp * 1000)}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="chat-{message.role} w-full min-w-full markdown-prose">
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
<div class="flex gap-1">
|
||||
<Tooltip content={$i18n.t('Configure')} className="self-start">
|
||||
<button
|
||||
aria-label={$i18n.t('Open modal to configure connection')}
|
||||
class="self-center p-1 bg-transparent hover:bg-gray-100 dark:bg-gray-900 dark:hover:bg-gray-850 rounded-lg transition"
|
||||
on:click={() => {
|
||||
showConfigModal = true;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { createEventDispatcher, tick } from 'svelte';
|
||||
import { Switch } from 'bits-ui';
|
||||
export let state = true;
|
||||
export let id = '';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
@@ -10,6 +11,7 @@
|
||||
|
||||
<Switch.Root
|
||||
bind:checked={state}
|
||||
{id}
|
||||
class="flex h-5 min-h-5 w-9 shrink-0 cursor-pointer items-center rounded-full px-[3px] mx-[1px] transition {state
|
||||
? ' bg-emerald-600'
|
||||
: 'bg-gray-200 dark:bg-transparent'} outline outline-1 outline-gray-100 dark:outline-gray-800"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
export let tags = [];
|
||||
</script>
|
||||
|
||||
<div class="flex flex-row flex-wrap gap-1 line-clamp-1">
|
||||
<ul class="flex flex-row flex-wrap gap-1 line-clamp-1">
|
||||
<TagList
|
||||
{tags}
|
||||
on:delete={(e) => {
|
||||
@@ -23,4 +23,4 @@
|
||||
dispatch('add', e.detail);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</ul>
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
bind:value={tagName}
|
||||
class=" px-2 cursor-pointer self-center text-xs h-fit bg-transparent outline-hidden line-clamp-1 w-[6.5rem]"
|
||||
placeholder={$i18n.t('Add a tag')}
|
||||
aria-label={$i18n.t('Add a tag')}
|
||||
list="tagOptions"
|
||||
on:keydown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
@@ -48,6 +49,7 @@
|
||||
viewBox="0 0 16 16"
|
||||
fill="currentColor"
|
||||
stroke-width="2"
|
||||
aria-hidden="true"
|
||||
class="w-3 h-3"
|
||||
>
|
||||
<path
|
||||
@@ -72,6 +74,7 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 16 16"
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
class="w-3 h-3 {showTagInput ? 'rotate-45' : ''} transition-all transform"
|
||||
>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { getContext } from 'svelte';
|
||||
const i18n = getContext('i18n');
|
||||
import Tooltip from '../Tooltip.svelte';
|
||||
import XMark from '$lib/components/icons/XMark.svelte';
|
||||
import Badge from '../Badge.svelte';
|
||||
@@ -10,7 +12,7 @@
|
||||
|
||||
{#each tags as tag}
|
||||
<Tooltip content={tag.name}>
|
||||
<div
|
||||
<li
|
||||
class="relative group/tags px-1.5 py-[0.2px] gap-0.5 flex justify-between h-fit max-h-fit w-fit items-center rounded-full bg-gray-500/20 text-gray-700 dark:text-gray-200 transition cursor-pointer"
|
||||
>
|
||||
<div class=" text-[0.7rem] font-medium self-center line-clamp-1 w-fit">
|
||||
@@ -23,10 +25,11 @@
|
||||
dispatch('delete', tag.name);
|
||||
}}
|
||||
type="button"
|
||||
aria-label={$i18n.t('Remove this tag from list')}
|
||||
>
|
||||
<XMark className="size-3" strokeWidth="2.5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</Tooltip>
|
||||
{/each}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width={strokeWidth}
|
||||
aria-hidden="true"
|
||||
stroke="currentColor"
|
||||
class={className}
|
||||
>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
aria-hidden="true"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width={strokeWidth}
|
||||
stroke="currentColor"
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
stroke-width={strokeWidth}
|
||||
stroke="currentColor"
|
||||
class={className}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
||||
</svg>
|
||||
|
||||
@@ -507,7 +507,7 @@
|
||||
<img
|
||||
crossorigin="anonymous"
|
||||
src="{WEBUI_BASE_URL}/static/favicon.png"
|
||||
class=" size-5 -translate-x-1.5 rounded-full"
|
||||
class="sidebar-new-chat-icon size-5 -translate-x-1.5 rounded-full"
|
||||
alt="logo"
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user