forked from open-webui/open-webui
Merge pull request #643 from ollama-webui/export-all-user-chats
feat: export all chats from db
This commit is contained in:
commit
e2f92f11d7
4 changed files with 103 additions and 9 deletions
|
@ -70,9 +70,9 @@ class ChatTable:
|
||||||
**{
|
**{
|
||||||
"id": id,
|
"id": id,
|
||||||
"user_id": user_id,
|
"user_id": user_id,
|
||||||
"title": form_data.chat["title"]
|
"title": (
|
||||||
if "title" in form_data.chat
|
form_data.chat["title"] if "title" in form_data.chat else "New Chat"
|
||||||
else "New Chat",
|
),
|
||||||
"chat": json.dumps(form_data.chat),
|
"chat": json.dumps(form_data.chat),
|
||||||
"timestamp": int(time.time()),
|
"timestamp": int(time.time()),
|
||||||
}
|
}
|
||||||
|
@ -131,6 +131,12 @@ class ChatTable:
|
||||||
.order_by(Chat.timestamp.desc())
|
.order_by(Chat.timestamp.desc())
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def get_all_chats(self) -> List[ChatModel]:
|
||||||
|
return [
|
||||||
|
ChatModel(**model_to_dict(chat))
|
||||||
|
for chat in Chat.select().order_by(Chat.timestamp.desc())
|
||||||
|
]
|
||||||
|
|
||||||
def get_all_chats_by_user_id(self, user_id: str) -> List[ChatModel]:
|
def get_all_chats_by_user_id(self, user_id: str) -> List[ChatModel]:
|
||||||
return [
|
return [
|
||||||
ChatModel(**model_to_dict(chat))
|
ChatModel(**model_to_dict(chat))
|
||||||
|
|
|
@ -54,6 +54,25 @@ async def get_all_user_chats(user=Depends(get_current_user)):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
############################
|
||||||
|
# GetAllChatsInDB
|
||||||
|
############################
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/all/db", response_model=List[ChatResponse])
|
||||||
|
async def get_all_user_chats_in_db(user=Depends(get_current_user)):
|
||||||
|
if user.role == "admin":
|
||||||
|
return [
|
||||||
|
ChatResponse(**{**chat.model_dump(), "chat": json.loads(chat.chat)})
|
||||||
|
for chat in Chats.get_all_chats()
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
############################
|
############################
|
||||||
# CreateNewChat
|
# CreateNewChat
|
||||||
############################
|
############################
|
||||||
|
|
|
@ -93,6 +93,37 @@ export const getAllChats = async (token: string) => {
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getAllUserChats = async (token: string) => {
|
||||||
|
let error = null;
|
||||||
|
|
||||||
|
const res = await fetch(`${WEBUI_API_BASE_URL}/chats/all/db`, {
|
||||||
|
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.log(err);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
export const getAllChatTags = async (token: string) => {
|
export const getAllChatTags = async (token: string) => {
|
||||||
let error = null;
|
let error = null;
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,13 @@
|
||||||
deleteModel
|
deleteModel
|
||||||
} from '$lib/apis/ollama';
|
} from '$lib/apis/ollama';
|
||||||
import { updateUserPassword } from '$lib/apis/auths';
|
import { updateUserPassword } from '$lib/apis/auths';
|
||||||
import { createNewChat, deleteAllChats, getAllChats, getChatList } from '$lib/apis/chats';
|
import {
|
||||||
|
createNewChat,
|
||||||
|
deleteAllChats,
|
||||||
|
getAllChats,
|
||||||
|
getAllUserChats,
|
||||||
|
getChatList
|
||||||
|
} from '$lib/apis/chats';
|
||||||
import { WEB_UI_VERSION, WEBUI_API_BASE_URL } from '$lib/constants';
|
import { WEB_UI_VERSION, WEBUI_API_BASE_URL } from '$lib/constants';
|
||||||
|
|
||||||
import { config, models, voices, settings, user, chats } from '$lib/stores';
|
import { config, models, voices, settings, user, chats } from '$lib/stores';
|
||||||
|
@ -179,6 +185,13 @@
|
||||||
saveAs(blob, `chat-export-${Date.now()}.json`);
|
saveAs(blob, `chat-export-${Date.now()}.json`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const exportAllUserChats = async () => {
|
||||||
|
let blob = new Blob([JSON.stringify(await getAllUserChats(localStorage.token))], {
|
||||||
|
type: 'application/json'
|
||||||
|
});
|
||||||
|
saveAs(blob, `all-chats-export-${Date.now()}.json`);
|
||||||
|
};
|
||||||
|
|
||||||
const deleteChats = async () => {
|
const deleteChats = async () => {
|
||||||
await goto('/');
|
await goto('/');
|
||||||
await deleteAllChats(localStorage.token);
|
await deleteAllChats(localStorage.token);
|
||||||
|
@ -1962,23 +1975,48 @@
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
class="w-4 h-4"
|
class="w-4 h-4"
|
||||||
>
|
>
|
||||||
<path
|
|
||||||
d="M2 3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3Z"
|
|
||||||
/>
|
|
||||||
<path
|
<path
|
||||||
fill-rule="evenodd"
|
fill-rule="evenodd"
|
||||||
d="M13 6H3v6a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V6ZM5.72 7.47a.75.75 0 0 1 1.06 0L8 8.69l1.22-1.22a.75.75 0 1 1 1.06 1.06L9.06 9.75l1.22 1.22a.75.75 0 1 1-1.06 1.06L8 10.81l-1.22 1.22a.75.75 0 0 1-1.06-1.06l1.22-1.22-1.22-1.22a.75.75 0 0 1 0-1.06Z"
|
d="M4 2a1.5 1.5 0 0 0-1.5 1.5v9A1.5 1.5 0 0 0 4 14h8a1.5 1.5 0 0 0 1.5-1.5V6.621a1.5 1.5 0 0 0-.44-1.06L9.94 2.439A1.5 1.5 0 0 0 8.878 2H4Zm7 7a.75.75 0 0 1-.75.75h-4.5a.75.75 0 0 1 0-1.5h4.5A.75.75 0 0 1 11 9Z"
|
||||||
clip-rule="evenodd"
|
clip-rule="evenodd"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div class=" self-center text-sm font-medium">Delete All Chats</div>
|
<div class=" self-center text-sm font-medium">Delete Chats</div>
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if $user?.role === 'admin'}
|
{#if $user?.role === 'admin'}
|
||||||
<hr class=" dark:border-gray-700" />
|
<hr class=" dark:border-gray-700" />
|
||||||
|
|
||||||
|
<button
|
||||||
|
class=" flex rounded-md py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
|
||||||
|
on:click={() => {
|
||||||
|
exportAllUserChats();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div class=" self-center mr-3">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
fill="currentColor"
|
||||||
|
class="w-4 h-4"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M2 3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M13 6H3v6a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V6ZM8.75 7.75a.75.75 0 0 0-1.5 0v2.69L6.03 9.22a.75.75 0 0 0-1.06 1.06l2.5 2.5a.75.75 0 0 0 1.06 0l2.5-2.5a.75.75 0 1 0-1.06-1.06l-1.22 1.22V7.75Z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class=" self-center text-sm font-medium">Export All Chats (All Users)</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<hr class=" dark:border-gray-700" />
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class=" flex rounded-md py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
|
class=" flex rounded-md py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
|
|
Loading…
Reference in a new issue