refac: shared chat
This commit is contained in:
@@ -953,6 +953,77 @@ export const deleteSharedChatById = async (token: string, id: string) => {
|
||||
return res;
|
||||
};
|
||||
|
||||
export const updateChatAccessGrants = async (
|
||||
token: string,
|
||||
id: string,
|
||||
accessGrants: object[]
|
||||
) => {
|
||||
let error = null;
|
||||
|
||||
const res = await fetch(`${WEBUI_API_BASE_URL}/chats/shared/${id}/access/update`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
...(token && { authorization: `Bearer ${token}` })
|
||||
},
|
||||
body: JSON.stringify({
|
||||
access_grants: accessGrants
|
||||
})
|
||||
})
|
||||
.then(async (res) => {
|
||||
if (!res.ok) throw await res.json();
|
||||
return res.json();
|
||||
})
|
||||
.then((json) => {
|
||||
return json;
|
||||
})
|
||||
.catch((err) => {
|
||||
error = err;
|
||||
|
||||
console.error(err);
|
||||
return null;
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
export const getChatAccessGrants = async (token: string, id: string) => {
|
||||
let error = null;
|
||||
|
||||
const res = await fetch(`${WEBUI_API_BASE_URL}/chats/shared/${id}/access`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
...(token && { authorization: `Bearer ${token}` })
|
||||
}
|
||||
})
|
||||
.then(async (res) => {
|
||||
if (!res.ok) throw await res.json();
|
||||
return res.json();
|
||||
})
|
||||
.then((json) => {
|
||||
return json;
|
||||
})
|
||||
.catch((err) => {
|
||||
error = err;
|
||||
|
||||
console.error(err);
|
||||
return null;
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
export const updateChatById = async (token: string, id: string, chat: object) => {
|
||||
let error = null;
|
||||
|
||||
|
||||
@@ -3,24 +3,32 @@
|
||||
import { models, config } from '$lib/stores';
|
||||
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { deleteSharedChatById, getChatById, shareChatById } from '$lib/apis/chats';
|
||||
import {
|
||||
deleteSharedChatById,
|
||||
getChatById,
|
||||
shareChatById,
|
||||
getChatAccessGrants,
|
||||
updateChatAccessGrants
|
||||
} from '$lib/apis/chats';
|
||||
import { copyToClipboard } from '$lib/utils';
|
||||
|
||||
import Modal from '../common/Modal.svelte';
|
||||
import Link from '../icons/Link.svelte';
|
||||
import XMark from '$lib/components/icons/XMark.svelte';
|
||||
import AccessControl from '$lib/components/workspace/common/AccessControl.svelte';
|
||||
|
||||
export let chatId;
|
||||
|
||||
let chat = null;
|
||||
let shareUrl = null;
|
||||
let accessGrants: any[] = [];
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
const shareLocalChat = async () => {
|
||||
const _chat = chat;
|
||||
|
||||
const sharedChat = await shareChatById(localStorage.token, chatId);
|
||||
shareUrl = `${window.location.origin}/s/${sharedChat.id}`;
|
||||
shareUrl = `${window.location.origin}/s/${sharedChat.share_id}`;
|
||||
console.log(shareUrl);
|
||||
chat = await getChatById(localStorage.token, chatId);
|
||||
|
||||
@@ -54,6 +62,25 @@
|
||||
);
|
||||
};
|
||||
|
||||
const loadAccessGrants = async () => {
|
||||
if (!chatId) return;
|
||||
try {
|
||||
accessGrants = (await getChatAccessGrants(localStorage.token, chatId)) ?? [];
|
||||
} catch (e) {
|
||||
console.error('Failed to load access grants', e);
|
||||
accessGrants = [];
|
||||
}
|
||||
};
|
||||
|
||||
const saveAccessGrants = async () => {
|
||||
try {
|
||||
await updateChatAccessGrants(localStorage.token, chatId, accessGrants);
|
||||
toast.success($i18n.t('Access updated'));
|
||||
} catch (e) {
|
||||
toast.error(`${e}`);
|
||||
}
|
||||
};
|
||||
|
||||
export let show = false;
|
||||
|
||||
const isDifferentChat = (_chat) => {
|
||||
@@ -73,8 +100,10 @@
|
||||
if (isDifferentChat(_chat)) {
|
||||
chat = _chat;
|
||||
}
|
||||
await loadAccessGrants();
|
||||
} else {
|
||||
chat = null;
|
||||
accessGrants = [];
|
||||
console.log(chat);
|
||||
}
|
||||
})();
|
||||
@@ -97,8 +126,8 @@
|
||||
</div>
|
||||
|
||||
{#if chat}
|
||||
<div class="px-5 pt-4 pb-5 w-full flex flex-col justify-center">
|
||||
<div class=" text-sm dark:text-gray-300 mb-1">
|
||||
<div class="px-5 pt-4 pb-5 w-full flex flex-col">
|
||||
<div class="text-sm dark:text-gray-300">
|
||||
{#if chat.share_id}
|
||||
<a href="/s/{chat.share_id}" target="_blank"
|
||||
>{$i18n.t('You have shared this chat')}
|
||||
@@ -124,70 +153,73 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end">
|
||||
<div class="flex flex-col items-end space-x-1 mt-3">
|
||||
<div class="flex gap-1">
|
||||
{#if $config?.features.enable_community_sharing}
|
||||
<button
|
||||
class="self-center flex items-center gap-1 px-3.5 py-2 text-sm font-medium bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:text-white dark:hover:bg-gray-800 transition rounded-full"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
shareChat();
|
||||
show = false;
|
||||
}}
|
||||
>
|
||||
{$i18n.t('Share to Open WebUI Community')}
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<button
|
||||
class="self-center flex items-center gap-1 px-3.5 py-2 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"
|
||||
id="copy-and-share-chat-button"
|
||||
on:click={async () => {
|
||||
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||
|
||||
if (isSafari) {
|
||||
// Oh, Safari, you're so special, let's give you some extra love and attention
|
||||
console.log('isSafari');
|
||||
|
||||
const getUrlPromise = async () => {
|
||||
const url = await shareLocalChat();
|
||||
return new Blob([url], { type: 'text/plain' });
|
||||
};
|
||||
|
||||
navigator.clipboard
|
||||
.write([
|
||||
new ClipboardItem({
|
||||
'text/plain': getUrlPromise()
|
||||
})
|
||||
])
|
||||
.then(() => {
|
||||
console.log('Async: Copying to clipboard was successful!');
|
||||
return true;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Async: Could not copy text: ', error);
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
copyToClipboard(await shareLocalChat());
|
||||
}
|
||||
|
||||
toast.success($i18n.t('Copied shared chat URL to clipboard!'));
|
||||
show = false;
|
||||
}}
|
||||
>
|
||||
<Link />
|
||||
|
||||
{#if chat.share_id}
|
||||
{$i18n.t('Update and Copy Link')}
|
||||
{:else}
|
||||
{$i18n.t('Copy Link')}
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
{#if chat.share_id}
|
||||
<div class="mt-3">
|
||||
<AccessControl
|
||||
bind:accessGrants
|
||||
accessRoles={['read']}
|
||||
onChange={saveAccessGrants}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="flex justify-end gap-1 mt-3">
|
||||
{#if $config?.features.enable_community_sharing}
|
||||
<button
|
||||
class="flex items-center gap-1 px-3.5 py-2 text-sm font-medium bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:text-white dark:hover:bg-gray-800 transition rounded-full"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
shareChat();
|
||||
}}
|
||||
>
|
||||
{$i18n.t('Share to Open WebUI Community')}
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<button
|
||||
class="flex items-center gap-1 px-3.5 py-2 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"
|
||||
id="copy-and-share-chat-button"
|
||||
on:click={async () => {
|
||||
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||
|
||||
if (isSafari) {
|
||||
console.log('isSafari');
|
||||
|
||||
const getUrlPromise = async () => {
|
||||
const url = await shareLocalChat();
|
||||
return new Blob([url], { type: 'text/plain' });
|
||||
};
|
||||
|
||||
navigator.clipboard
|
||||
.write([
|
||||
new ClipboardItem({
|
||||
'text/plain': getUrlPromise()
|
||||
})
|
||||
])
|
||||
.then(() => {
|
||||
console.log('Async: Copying to clipboard was successful!');
|
||||
return true;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Async: Could not copy text: ', error);
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
copyToClipboard(await shareLocalChat());
|
||||
}
|
||||
|
||||
toast.success($i18n.t('Copied shared chat URL to clipboard!'));
|
||||
}}
|
||||
>
|
||||
<Link />
|
||||
|
||||
{#if chat.share_id}
|
||||
{$i18n.t('Update and Copy Link')}
|
||||
{:else}
|
||||
{$i18n.t('Copy Link')}
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user