mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-15 13:55:19 +00:00
enh/refac: show read only kbs
This commit is contained in:
parent
a6ef82c5ed
commit
693636d971
4 changed files with 154 additions and 125 deletions
|
|
@ -41,7 +41,11 @@ router = APIRouter()
|
|||
############################
|
||||
|
||||
|
||||
@router.get("/", response_model=list[KnowledgeUserResponse])
|
||||
class KnowledgeAccessResponse(KnowledgeUserResponse):
|
||||
write_access: Optional[bool] = False
|
||||
|
||||
|
||||
@router.get("/", response_model=list[KnowledgeAccessResponse])
|
||||
async def get_knowledge(user=Depends(get_verified_user)):
|
||||
# Return knowledge bases with read access
|
||||
knowledge_bases = []
|
||||
|
|
@ -51,27 +55,29 @@ async def get_knowledge(user=Depends(get_verified_user)):
|
|||
knowledge_bases = Knowledges.get_knowledge_bases_by_user_id(user.id, "read")
|
||||
|
||||
return [
|
||||
KnowledgeUserResponse(
|
||||
KnowledgeAccessResponse(
|
||||
**knowledge_base.model_dump(),
|
||||
files=Knowledges.get_file_metadatas_by_id(knowledge_base.id),
|
||||
write_access=has_access(user.id, "write", knowledge_base.access_control),
|
||||
)
|
||||
for knowledge_base in knowledge_bases
|
||||
]
|
||||
|
||||
|
||||
@router.get("/list", response_model=list[KnowledgeUserResponse])
|
||||
@router.get("/list", response_model=list[KnowledgeAccessResponse])
|
||||
async def get_knowledge_list(user=Depends(get_verified_user)):
|
||||
# Return knowledge bases with write access
|
||||
knowledge_bases = []
|
||||
if user.role == "admin" and BYPASS_ADMIN_ACCESS_CONTROL:
|
||||
knowledge_bases = Knowledges.get_knowledge_bases()
|
||||
else:
|
||||
knowledge_bases = Knowledges.get_knowledge_bases_by_user_id(user.id, "write")
|
||||
knowledge_bases = Knowledges.get_knowledge_bases_by_user_id(user.id, "read")
|
||||
|
||||
return [
|
||||
KnowledgeUserResponse(
|
||||
KnowledgeAccessResponse(
|
||||
**knowledge_base.model_dump(),
|
||||
files=Knowledges.get_file_metadatas_by_id(knowledge_base.id),
|
||||
write_access=has_access(user.id, "write", knowledge_base.access_control),
|
||||
)
|
||||
for knowledge_base in knowledge_bases
|
||||
]
|
||||
|
|
@ -187,6 +193,7 @@ async def reindex_knowledge_files(request: Request, user=Depends(get_verified_us
|
|||
|
||||
class KnowledgeFilesResponse(KnowledgeResponse):
|
||||
files: list[FileMetadataResponse]
|
||||
write_access: Optional[bool] = False
|
||||
|
||||
|
||||
@router.get("/{id}", response_model=Optional[KnowledgeFilesResponse])
|
||||
|
|
@ -203,6 +210,7 @@ async def get_knowledge_by_id(id: str, user=Depends(get_verified_user)):
|
|||
return KnowledgeFilesResponse(
|
||||
**knowledge.model_dump(),
|
||||
files=Knowledges.get_file_metadatas_by_id(knowledge.id),
|
||||
write_access=has_access(user.id, "write", knowledge.access_control),
|
||||
)
|
||||
else:
|
||||
raise HTTPException(
|
||||
|
|
|
|||
|
|
@ -196,7 +196,6 @@
|
|||
<!-- The Aleph dreams itself into being, and the void learns its own name -->
|
||||
<div class=" my-2 px-3 grid grid-cols-1 lg:grid-cols-2 gap-2">
|
||||
{#each filteredItems as item}
|
||||
<Tooltip content={item?.description ?? item.name}>
|
||||
<button
|
||||
class=" flex space-x-4 cursor-pointer text-left w-full px-3 py-2.5 dark:hover:bg-gray-850/50 hover:bg-gray-50 transition rounded-2xl"
|
||||
on:click={() => {
|
||||
|
|
@ -214,19 +213,16 @@
|
|||
<div class=" w-full">
|
||||
<div class=" self-center flex-1">
|
||||
<div class="flex items-center justify-between -my-1">
|
||||
<div class=" flex gap-2 items-center">
|
||||
<div class=" flex gap-2 items-center justify-between w-full">
|
||||
<div>
|
||||
{#if item?.meta?.document}
|
||||
<Badge type="muted" content={$i18n.t('Document')} />
|
||||
{:else}
|
||||
<Badge type="success" content={$i18n.t('Collection')} />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class=" text-xs text-gray-500 line-clamp-1">
|
||||
{$i18n.t('Updated')}
|
||||
{dayjs(item.updated_at * 1000).fromNow()}
|
||||
{#if !item?.write_access}
|
||||
<div>
|
||||
<Badge type="muted" content={$i18n.t('Read Only')} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
|
|
@ -242,11 +238,20 @@
|
|||
</div>
|
||||
|
||||
<div class=" flex items-center gap-1 justify-between px-1.5">
|
||||
<Tooltip content={item?.description ?? item.name}>
|
||||
<div class=" flex items-center gap-2">
|
||||
<div class=" text-sm font-medium line-clamp-1 capitalize">{item.name}</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<Tooltip content={dayjs(item.updated_at * 1000).format('LLLL')}>
|
||||
<div class=" text-xs text-gray-500 line-clamp-1">
|
||||
{$i18n.t('Updated')}
|
||||
{dayjs(item.updated_at * 1000).fromNow()}
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
<div>
|
||||
<div class="text-xs text-gray-500">
|
||||
<Tooltip
|
||||
content={item?.user?.email ?? $i18n.t('Deleted User')}
|
||||
|
|
@ -265,7 +270,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</Tooltip>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
|
|
|
|||
|
|
@ -429,7 +429,7 @@
|
|||
});
|
||||
|
||||
if (res) {
|
||||
knowledge = res;
|
||||
fileItems = [];
|
||||
toast.success($i18n.t('Knowledge reset successfully.'));
|
||||
|
||||
// Upload directory
|
||||
|
|
@ -747,6 +747,7 @@
|
|||
class="text-left w-full font-medium text-lg font-primary bg-transparent outline-hidden flex-1"
|
||||
bind:value={knowledge.name}
|
||||
placeholder={$i18n.t('Knowledge Name')}
|
||||
disabled={!knowledge?.write_access}
|
||||
on:input={() => {
|
||||
changeDebounceHandler();
|
||||
}}
|
||||
|
|
@ -763,6 +764,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{#if knowledge?.write_access}
|
||||
<div class="self-center shrink-0">
|
||||
<button
|
||||
class="bg-gray-50 hover:bg-gray-100 text-black dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-white transition px-2 py-1 rounded-full flex gap-1 items-center"
|
||||
|
|
@ -778,6 +780,11 @@
|
|||
</div>
|
||||
</button>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="text-xs shrink-0 text-gray-500">
|
||||
{$i18n.t('Read Only')}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex w-full">
|
||||
|
|
@ -786,6 +793,7 @@
|
|||
class="text-left text-xs w-full text-gray-500 bg-transparent outline-hidden"
|
||||
bind:value={knowledge.description}
|
||||
placeholder={$i18n.t('Knowledge Description')}
|
||||
disabled={!knowledge?.write_access}
|
||||
on:input={() => {
|
||||
changeDebounceHandler();
|
||||
}}
|
||||
|
|
@ -812,6 +820,7 @@
|
|||
}}
|
||||
/>
|
||||
|
||||
{#if knowledge?.write_access}
|
||||
<div>
|
||||
<AddContentMenu
|
||||
on:upload={(e) => {
|
||||
|
|
@ -828,6 +837,7 @@
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -896,6 +906,7 @@
|
|||
<div class=" flex overflow-y-auto h-full w-full scrollbar-hidden text-xs">
|
||||
<Files
|
||||
files={fileItems}
|
||||
{knowledge}
|
||||
{selectedFileId}
|
||||
onClick={(fileId) => {
|
||||
selectedFileId = fileId;
|
||||
|
|
@ -959,6 +970,7 @@
|
|||
{selectedFile?.meta?.name}
|
||||
</div>
|
||||
|
||||
{#if knowledge?.write_access}
|
||||
<div>
|
||||
<button
|
||||
class="flex self-center w-fit text-sm py-1 px-2.5 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-lg disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
|
|
@ -975,12 +987,14 @@
|
|||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#key selectedFile.id}
|
||||
<textarea
|
||||
class="w-full h-full text-sm outline-none resize-none px-3 py-2"
|
||||
bind:value={selectedFileContent}
|
||||
disabled={!knowledge?.write_access}
|
||||
placeholder={$i18n.t('Add content here')}
|
||||
/>
|
||||
{/key}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
import XMark from '$lib/components/icons/XMark.svelte';
|
||||
import Spinner from '$lib/components/common/Spinner.svelte';
|
||||
|
||||
export let knowledge = null;
|
||||
export let selectedFileId = null;
|
||||
export let files = [];
|
||||
|
||||
|
|
@ -79,6 +80,7 @@
|
|||
</div>
|
||||
</button>
|
||||
|
||||
{#if knowledge?.write_access}
|
||||
<div class="flex items-center">
|
||||
<Tooltip content={$i18n.t('Delete')}>
|
||||
<button
|
||||
|
|
@ -92,6 +94,7 @@
|
|||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue