Merge remote-tracking branch 'upstream/dev' into feat/rag-status

This commit is contained in:
hurxxxx
2025-01-29 02:01:50 +09:00
25 changed files with 163 additions and 72 deletions

View File

@@ -6,7 +6,9 @@
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import localizedFormat from 'dayjs/plugin/localizedFormat';
dayjs.extend(relativeTime);
dayjs.extend(localizedFormat);
import { toast } from 'svelte-sonner';
@@ -364,7 +366,7 @@
</td>
<td class=" px-3 py-1">
{dayjs(user.created_at * 1000).format($i18n.t('MMMM DD, YYYY'))}
{dayjs(user.created_at * 1000).format('LL')}
</td>
<td class=" px-3 py-1"> {user.oauth_sub ?? ''} </td>

View File

@@ -7,9 +7,11 @@
import { updateUserById } from '$lib/apis/users';
import Modal from '$lib/components/common/Modal.svelte';
import localizedFormat from 'dayjs/plugin/localizedFormat';
const i18n = getContext('i18n');
const dispatch = createEventDispatcher();
dayjs.extend(localizedFormat);
export let show = false;
export let selectedUser;
@@ -87,7 +89,7 @@
<div class="text-xs text-gray-500">
{$i18n.t('Created at')}
{dayjs(selectedUser.created_at * 1000).format($i18n.t('MMMM DD, YYYY'))}
{dayjs(selectedUser.created_at * 1000).format('LL')}
</div>
</div>
</div>

View File

@@ -2,8 +2,10 @@
import { toast } from 'svelte-sonner';
import dayjs from 'dayjs';
import { getContext, createEventDispatcher } from 'svelte';
import localizedFormat from 'dayjs/plugin/localizedFormat';
const dispatch = createEventDispatcher();
dayjs.extend(localizedFormat);
import { getChatListByUserId, deleteChatById, getArchivedChatList } from '$lib/apis/chats';
@@ -130,7 +132,7 @@
<td class=" px-3 py-1 hidden md:flex h-[2.5rem] justify-end">
<div class="my-auto shrink-0">
{dayjs(chat.updated_at * 1000).format($i18n.t('MMMM DD, YYYY HH:mm'))}
{dayjs(chat.updated_at * 1000).format('LLL')}
</div>
</td>

View File

@@ -3,10 +3,12 @@
import relativeTime from 'dayjs/plugin/relativeTime';
import isToday from 'dayjs/plugin/isToday';
import isYesterday from 'dayjs/plugin/isYesterday';
import localizedFormat from 'dayjs/plugin/localizedFormat';
dayjs.extend(relativeTime);
dayjs.extend(isToday);
dayjs.extend(isYesterday);
dayjs.extend(localizedFormat);
import { getContext, onMount } from 'svelte';
const i18n = getContext<Writable<i18nType>>('i18n');
@@ -154,9 +156,9 @@
class="mt-1.5 flex flex-shrink-0 items-center text-xs self-center invisible group-hover:visible text-gray-500 font-medium first-letter:capitalize"
>
<Tooltip
content={dayjs(message.created_at / 1000000).format('dddd, DD MMMM YYYY HH:mm')}
content={dayjs(message.created_at / 1000000).format('LLLL')}
>
{dayjs(message.created_at / 1000000).format('HH:mm')}
{dayjs(message.created_at / 1000000).format('LT')}
</Tooltip>
</div>
{/if}
@@ -175,7 +177,7 @@
class=" self-center text-xs invisible group-hover:visible text-gray-400 font-medium first-letter:capitalize ml-0.5 translate-y-[1px]"
>
<Tooltip
content={dayjs(message.created_at / 1000000).format('dddd, DD MMMM YYYY HH:mm')}
content={dayjs(message.created_at / 1000000).format('LLLL')}
>
<span class="line-clamp-1">{formatDate(message.created_at / 1000000)}</span>
</Tooltip>

View File

@@ -82,10 +82,12 @@
import EventConfirmDialog from '../common/ConfirmDialog.svelte';
import Placeholder from './Placeholder.svelte';
import NotificationToast from '../NotificationToast.svelte';
import Spinner from '../common/Spinner.svelte';
export let chatIdProp = '';
let loaded = false;
let loading = false;
const eventTarget = new EventTarget();
let controlPane;
let controlPaneComponent;
@@ -133,6 +135,7 @@
$: if (chatIdProp) {
(async () => {
loading = true;
console.log(chatIdProp);
prompt = '';
@@ -141,11 +144,9 @@
webSearchEnabled = false;
imageGenerationEnabled = false;
loaded = false;
if (chatIdProp && (await loadChat())) {
await tick();
loaded = true;
loading = false;
if (localStorage.getItem(`chat-input-${chatIdProp}`)) {
try {
@@ -1866,7 +1867,7 @@
: ' '} w-full max-w-full flex flex-col"
id="chat-container"
>
{#if !chatIdProp || (loaded && chatIdProp)}
{#if chatIdProp === '' || (!loading && chatIdProp)}
{#if $settings?.backgroundImageUrl ?? null}
<div
class="absolute {$showSidebar
@@ -2070,5 +2071,11 @@
{eventTarget}
/>
</PaneGroup>
{:else if loading}
<div class=" flex items-center justify-center h-full w-full">
<div class="m-auto">
<Spinner />
</div>
</div>
{/if}
</div>

View File

@@ -48,6 +48,9 @@
init();
}
let fileUploadEnabled = true;
$: fileUploadEnabled = $user.role === 'admin' || $user?.permissions?.chat?.file_upload;
const init = async () => {
if ($_tools === null) {
await _tools.set(await getTools(localStorage.token));
@@ -166,26 +169,44 @@
{/if}
{#if !$mobile}
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl"
on:click={() => {
screenCaptureHandler();
}}
<Tooltip
content={!fileUploadEnabled ? $i18n.t('You do not have permission to upload files') : ''}
className="w-full"
>
<CameraSolid />
<div class=" line-clamp-1">{$i18n.t('Capture')}</div>
</DropdownMenu.Item>
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl {!fileUploadEnabled
? 'opacity-50'
: ''}"
on:click={() => {
if (fileUploadEnabled) {
screenCaptureHandler();
}
}}
>
<CameraSolid />
<div class=" line-clamp-1">{$i18n.t('Capture')}</div>
</DropdownMenu.Item>
</Tooltip>
{/if}
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl"
on:click={() => {
uploadFilesHandler();
}}
<Tooltip
content={!fileUploadEnabled ? $i18n.t('You do not have permission to upload files') : ''}
className="w-full"
>
<DocumentArrowUpSolid />
<div class="line-clamp-1">{$i18n.t('Upload Files')}</div>
</DropdownMenu.Item>
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl {!fileUploadEnabled
? 'opacity-50'
: ''}"
on:click={() => {
if (fileUploadEnabled) {
uploadFilesHandler();
}
}}
>
<DocumentArrowUpSolid />
<div class="line-clamp-1">{$i18n.t('Upload Files')}</div>
</DropdownMenu.Item>
</Tooltip>
{#if $config?.features?.enable_google_drive_integration}
<DropdownMenu.Item

View File

@@ -16,7 +16,9 @@
import Markdown from './Markdown.svelte';
import Name from './Name.svelte';
import Skeleton from './Skeleton.svelte';
import localizedFormat from 'dayjs/plugin/localizedFormat';
const i18n = getContext('i18n');
dayjs.extend(localizedFormat);
export let chatId;
export let history;
@@ -264,7 +266,7 @@
<span
class=" self-center invisible group-hover:visible text-gray-400 text-xs font-medium uppercase ml-0.5 -mt-0.5"
>
{dayjs(message.timestamp * 1000).format($i18n.t('h:mm a'))}
{dayjs(message.timestamp * 1000).format('LT')}
</span>
{/if}
</Name>

View File

@@ -500,7 +500,7 @@
<div
class=" self-center text-xs invisible group-hover:visible text-gray-400 font-medium first-letter:capitalize ml-0.5 translate-y-[1px]"
>
<Tooltip content={dayjs(message.timestamp * 1000).format('dddd, DD MMMM YYYY HH:mm')}>
<Tooltip content={dayjs(message.timestamp * 1000).format('LLLL')}>
<span class="line-clamp-1">{formatDate(message.timestamp * 1000)}</span>
</Tooltip>
</div>

View File

@@ -13,8 +13,10 @@
import FileItem from '$lib/components/common/FileItem.svelte';
import Markdown from './Markdown.svelte';
import Image from '$lib/components/common/Image.svelte';
import localizedFormat from 'dayjs/plugin/localizedFormat';
const i18n = getContext('i18n');
dayjs.extend(localizedFormat);
export let user;
@@ -112,7 +114,7 @@
<div
class=" self-center text-xs invisible group-hover:visible text-gray-400 font-medium first-letter:capitalize ml-0.5 translate-y-[1px]"
>
<Tooltip content={dayjs(message.timestamp * 1000).format('dddd, DD MMMM YYYY HH:mm')}>
<Tooltip content={dayjs(message.timestamp * 1000).format('LLLL')}>
<span class="line-clamp-1">{formatDate(message.timestamp * 1000)}</span>
</Tooltip>
</div>

View File

@@ -11,8 +11,10 @@
import Tooltip from '$lib/components/common/Tooltip.svelte';
import { error } from '@sveltejs/kit';
import EditMemoryModal from './EditMemoryModal.svelte';
import localizedFormat from 'dayjs/plugin/localizedFormat';
const i18n = getContext('i18n');
dayjs.extend(localizedFormat);
export let show = false;
@@ -84,9 +86,7 @@
</td>
<td class=" px-3 py-1 hidden md:flex h-[2.5rem]">
<div class="my-auto whitespace-nowrap">
{dayjs(memory.updated_at * 1000).format(
$i18n.t('MMMM DD, YYYY hh:mm:ss A')
)}
{dayjs(memory.updated_at * 1000).format('LLL')}
</div>
</td>
<td class="px-3 py-1">

View File

@@ -4,6 +4,9 @@
import { toast } from 'svelte-sonner';
import dayjs from 'dayjs';
import { getContext, createEventDispatcher } from 'svelte';
import localizedFormat from 'dayjs/plugin/localizedFormat';
dayjs.extend(localizedFormat);
const dispatch = createEventDispatcher();
@@ -159,7 +162,7 @@
<td class=" px-3 py-1 hidden md:flex h-[2.5rem]">
<div class="my-auto">
{dayjs(chat.created_at * 1000).format($i18n.t('MMMM DD, YYYY HH:mm'))}
{dayjs(chat.created_at * 1000).format('LLL')}
</div>
</td>

View File

@@ -112,7 +112,10 @@
<div class="mt-2">
<div class="px-3 py-2 bg-gray-50 dark:bg-gray-950 rounded-lg">
<AccessControl bind:accessControl />
<AccessControl
bind:accessControl
accessRoles={['read', 'write']}
/>
</div>
</div>

View File

@@ -531,7 +531,10 @@
<div class="my-2">
<div class="px-3 py-2 bg-gray-50 dark:bg-gray-950 rounded-lg">
<AccessControl bind:accessControl />
<AccessControl
bind:accessControl
accessRoles={['read', 'write']}
/>
</div>
</div>

View File

@@ -767,7 +767,7 @@
"Reset": "",
"Reset All Models": "",
"Reset Upload Directory": "アップロードディレクトリをリセット",
"Reset Vector Storage/Knowledge": "ベクターストレージとナレッジべーうをリセット",
"Reset Vector Storage/Knowledge": "ベクターストレージとナレッジベースをリセット",
"Reset view": "",
"Response notifications cannot be activated as the website permissions have been denied. Please visit your browser settings to grant the necessary access.": "",
"Response splitting": "応答の分割",

View File

@@ -935,7 +935,7 @@
"This will delete all models including custom models and cannot be undone.": "這將刪除所有模型,包括自訂模型,且無法復原。",
"This will reset the knowledge base and sync all files. Do you wish to continue?": "這將重設知識庫並同步所有檔案。您確定要繼續嗎?",
"Thorough explanation": "詳細解釋",
"Thought for {{DURATION}}": "",
"Thought for {{DURATION}}": "{{DURATION}} 思考中",
"Tika": "Tika",
"Tika Server URL required.": "需要 Tika 伺服器 URL。",
"Tiktoken": "Tiktoken",

View File

@@ -5,10 +5,12 @@ import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import isToday from 'dayjs/plugin/isToday';
import isYesterday from 'dayjs/plugin/isYesterday';
import localizedFormat from 'dayjs/plugin/localizedFormat';
dayjs.extend(relativeTime);
dayjs.extend(isToday);
dayjs.extend(isYesterday);
dayjs.extend(localizedFormat);
import { WEBUI_BASE_URL } from '$lib/constants';
import { TTS_RESPONSE_SPLIT } from '$lib/types';
@@ -295,11 +297,11 @@ export const formatDate = (inputDate) => {
const now = dayjs();
if (date.isToday()) {
return `Today at ${date.format('HH:mm')}`;
return `Today at ${date.format('LT')}`;
} else if (date.isYesterday()) {
return `Yesterday at ${date.format('HH:mm')}`;
return `Yesterday at ${date.format('LT')}`;
} else {
return `${date.format('DD/MM/YYYY')} at ${date.format('HH:mm')}`;
return `${date.format('L')} at ${date.format('LT')}`;
}
};

View File

@@ -16,8 +16,10 @@
import { getUserById } from '$lib/apis/users';
import { getModels } from '$lib/apis';
import { toast } from 'svelte-sonner';
import localizedFormat from 'dayjs/plugin/localizedFormat';
const i18n = getContext('i18n');
dayjs.extend(localizedFormat);
let loaded = false;
@@ -138,7 +140,7 @@
<div class="flex text-sm justify-between items-center mt-1">
<div class="text-gray-400">
{dayjs(chat.chat.timestamp).format($i18n.t('MMMM DD, YYYY'))}
{dayjs(chat.chat.timestamp).format('LLL')}
</div>
</div>
</div>