mirror of
https://github.com/open-webui/open-webui
synced 2025-03-24 14:40:51 +00:00
refac
This commit is contained in:
parent
c2732a0990
commit
1b7d363d32
@ -2,6 +2,7 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
import uuid
|
||||||
|
|
||||||
from open_webui.apps.webui.internal.db import Base, get_db
|
from open_webui.apps.webui.internal.db import Base, get_db
|
||||||
from open_webui.env import SRC_LOG_LEVELS
|
from open_webui.env import SRC_LOG_LEVELS
|
||||||
@ -65,7 +66,6 @@ class ProjectResponse(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class ProjectForm(BaseModel):
|
class ProjectForm(BaseModel):
|
||||||
id: str
|
|
||||||
name: str
|
name: str
|
||||||
description: str
|
description: str
|
||||||
data: Optional[dict] = None
|
data: Optional[dict] = None
|
||||||
@ -79,6 +79,7 @@ class ProjectTable:
|
|||||||
project = ProjectModel(
|
project = ProjectModel(
|
||||||
**{
|
**{
|
||||||
**form_data.model_dump(),
|
**form_data.model_dump(),
|
||||||
|
"id": str(uuid.uuid4()),
|
||||||
"user_id": user_id,
|
"user_id": user_id,
|
||||||
"created_at": int(time.time()),
|
"created_at": int(time.time()),
|
||||||
"updated_at": int(time.time()),
|
"updated_at": int(time.time()),
|
||||||
|
@ -46,8 +46,6 @@ async def get_projects(id: Optional[str] = None, user=Depends(get_verified_user)
|
|||||||
|
|
||||||
@router.post("/create", response_model=Optional[ProjectResponse])
|
@router.post("/create", response_model=Optional[ProjectResponse])
|
||||||
async def create_new_project(form_data: ProjectForm, user=Depends(get_admin_user)):
|
async def create_new_project(form_data: ProjectForm, user=Depends(get_admin_user)):
|
||||||
project = Projects.get_project_by_id(form_data.id)
|
|
||||||
if project is None:
|
|
||||||
project = Projects.insert_new_project(user.id, form_data)
|
project = Projects.insert_new_project(user.id, form_data)
|
||||||
|
|
||||||
if project:
|
if project:
|
||||||
@ -57,10 +55,23 @@ async def create_new_project(form_data: ProjectForm, user=Depends(get_admin_user
|
|||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
detail=ERROR_MESSAGES.FILE_EXISTS,
|
detail=ERROR_MESSAGES.FILE_EXISTS,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
############################
|
||||||
|
# GetProjectById
|
||||||
|
############################
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/{id}", response_model=Optional[ProjectResponse])
|
||||||
|
async def get_projects(id: str, user=Depends(get_verified_user)):
|
||||||
|
project = Projects.get_project_by_id(id=id)
|
||||||
|
|
||||||
|
if project:
|
||||||
|
return project
|
||||||
else:
|
else:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
detail=ERROR_MESSAGES.ID_TAKEN,
|
detail=ERROR_MESSAGES.NOT_FOUND,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -69,8 +80,9 @@ async def create_new_project(form_data: ProjectForm, user=Depends(get_admin_user
|
|||||||
############################
|
############################
|
||||||
|
|
||||||
|
|
||||||
@router.post("/update", response_model=Optional[ProjectResponse])
|
@router.post("/{id}/update", response_model=Optional[ProjectResponse])
|
||||||
async def update_project_by_id(
|
async def update_project_by_id(
|
||||||
|
id: str,
|
||||||
form_data: ProjectForm,
|
form_data: ProjectForm,
|
||||||
user=Depends(get_admin_user),
|
user=Depends(get_admin_user),
|
||||||
):
|
):
|
||||||
@ -89,7 +101,7 @@ async def update_project_by_id(
|
|||||||
############################
|
############################
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/delete", response_model=bool)
|
@router.delete("/{id}/delete", response_model=bool)
|
||||||
async def delete_project_by_id(id: str, user=Depends(get_admin_user)):
|
async def delete_project_by_id(id: str, user=Depends(get_admin_user)):
|
||||||
result = Projects.delete_project_by_id(id=id)
|
result = Projects.delete_project_by_id(id=id)
|
||||||
return result
|
return result
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { WEBUI_API_BASE_URL } from '$lib/constants';
|
import { WEBUI_API_BASE_URL } from '$lib/constants';
|
||||||
|
|
||||||
export const createNewProject = async (token: string, id: string, name: string) => {
|
export const createNewProject = async (token: string, name: string, description: string) => {
|
||||||
let error = null;
|
let error = null;
|
||||||
|
|
||||||
const res = await fetch(`${WEBUI_API_BASE_URL}/projects/create`, {
|
const res = await fetch(`${WEBUI_API_BASE_URL}/projects/create`, {
|
||||||
@ -11,8 +11,8 @@ export const createNewProject = async (token: string, id: string, name: string)
|
|||||||
authorization: `Bearer ${token}`
|
authorization: `Bearer ${token}`
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
id: id,
|
name: name,
|
||||||
name: name
|
description: description
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { getRAGConfig, updateRAGConfig } from '$lib/apis/retrieval';
|
import { getRAGConfig, updateRAGConfig } from '$lib/apis/retrieval';
|
||||||
import Switch from '$lib/components/common/Switch.svelte';
|
import Switch from '$lib/components/common/Switch.svelte';
|
||||||
|
|
||||||
import { documents, models } from '$lib/stores';
|
import { models } from '$lib/stores';
|
||||||
import { onMount, getContext } from 'svelte';
|
import { onMount, getContext } from 'svelte';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
|
import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
|
||||||
|
@ -114,7 +114,7 @@
|
|||||||
files = [
|
files = [
|
||||||
...files,
|
...files,
|
||||||
{
|
{
|
||||||
type: e?.detail?.type ?? 'file',
|
type: e?.detail?.meta?.legacy ? 'file' : 'project',
|
||||||
...e.detail,
|
...e.detail,
|
||||||
status: 'processed'
|
status: 'processed'
|
||||||
}
|
}
|
||||||
|
@ -111,12 +111,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class=" dark:border-gray-850 my-2.5" />
|
<hr class=" border-gray-50 dark:border-gray-850 my-2.5" />
|
||||||
|
|
||||||
<div class="my-3 mb-5 grid md:grid-cols-2 gap-2">
|
<div class="my-3 mb-5 grid md:grid-cols-2 gap-2">
|
||||||
{#each filteredProjects as project}
|
{#each filteredProjects as project}
|
||||||
|
{JSON.stringify(project)}
|
||||||
<button
|
<button
|
||||||
class=" flex space-x-4 cursor-pointer text-left w-full px-4 py-3 border dark:border-gray-850 dark:hover:bg-gray-850 rounded-xl"
|
class=" flex space-x-4 cursor-pointer text-left w-full px-4 py-3 border border-gray-50 dark:border-gray-850 hover:bg-gray-50 dark:hover:bg-gray-850 rounded-xl"
|
||||||
>
|
>
|
||||||
<div class=" w-full">
|
<div class=" w-full">
|
||||||
<div class="flex items-center justify-between -mt-1">
|
<div class="flex items-center justify-between -mt-1">
|
||||||
@ -147,7 +148,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div
|
<div
|
||||||
class="bg-green-500/20 text-green-700 dark:text-green-200 rounded uppercase text-xs px-1"
|
class="bg-green-500/20 text-green-700 dark:text-green-200 rounded uppercase text-xs font-bold px-1"
|
||||||
>
|
>
|
||||||
{$i18n.t('Project')}
|
{$i18n.t('Project')}
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,138 @@
|
|||||||
|
<script>
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
import { getContext } from 'svelte';
|
||||||
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
|
import { createNewProject, getProjects } from '$lib/apis/projects';
|
||||||
|
import { toast } from 'svelte-sonner';
|
||||||
|
import { projects } from '$lib/stores';
|
||||||
|
|
||||||
|
let loading = false;
|
||||||
|
|
||||||
|
let name = '';
|
||||||
|
let description = '';
|
||||||
|
|
||||||
|
const submitHandler = async () => {
|
||||||
|
loading = true;
|
||||||
|
|
||||||
|
const res = await createNewProject(localStorage.token, name, description).catch((e) => {
|
||||||
|
toast.error(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
toast.success($i18n.t('Project created successfully.'));
|
||||||
|
projects.set(await getProjects(localStorage.token));
|
||||||
|
goto(`/workspace/projects/${res.id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
loading = false;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="w-full max-h-full">
|
||||||
|
<button
|
||||||
|
class="flex space-x-1"
|
||||||
|
on:click={() => {
|
||||||
|
goto('/workspace/projects');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div class=" self-center">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
class="w-4 h-4"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M17 10a.75.75 0 01-.75.75H5.612l4.158 3.96a.75.75 0 11-1.04 1.08l-5.5-5.25a.75.75 0 010-1.08l5.5-5.25a.75.75 0 111.04 1.08L5.612 9.25H16.25A.75.75 0 0117 10z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class=" self-center font-medium text-sm">{$i18n.t('Back')}</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<form
|
||||||
|
class="flex flex-col max-w-lg mx-auto mt-10 mb-10"
|
||||||
|
on:submit|preventDefault={() => {
|
||||||
|
submitHandler();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div class=" w-full flex flex-col justify-center">
|
||||||
|
<div class=" text-2xl font-medium font-primary mb-2.5">Create a project</div>
|
||||||
|
|
||||||
|
<div class="w-full flex flex-col gap-2.5">
|
||||||
|
<div class="w-full">
|
||||||
|
<div class=" text-sm mb-2">What are you working on?</div>
|
||||||
|
|
||||||
|
<div class="w-full mt-1">
|
||||||
|
<input
|
||||||
|
class="w-full rounded-lg py-2 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-none"
|
||||||
|
type="text"
|
||||||
|
bind:value={name}
|
||||||
|
placeholder={`Name your project`}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="text-sm mb-2">What are you trying to achieve?</div>
|
||||||
|
|
||||||
|
<div class=" w-full mt-1">
|
||||||
|
<textarea
|
||||||
|
class="w-full resize-none rounded-lg py-2 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-none"
|
||||||
|
rows="4"
|
||||||
|
bind:value={description}
|
||||||
|
placeholder={`Describe your project, its goals, and objectives`}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-end mt-2">
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
class=" text-sm px-4 py-2 transition rounded-lg {loading
|
||||||
|
? ' cursor-not-allowed bg-gray-100 dark:bg-gray-800'
|
||||||
|
: ' bg-gray-50 hover:bg-gray-100 dark:bg-gray-850 dark:hover:bg-gray-800'} flex"
|
||||||
|
type="submit"
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
<div class=" self-center font-medium">{$i18n.t('Create Project')}</div>
|
||||||
|
|
||||||
|
{#if loading}
|
||||||
|
<div class="ml-1.5 self-center">
|
||||||
|
<svg
|
||||||
|
class=" w-4 h-4"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
><style>
|
||||||
|
.spinner_ajPY {
|
||||||
|
transform-origin: center;
|
||||||
|
animation: spinner_AtaB 0.75s infinite linear;
|
||||||
|
}
|
||||||
|
@keyframes spinner_AtaB {
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style><path
|
||||||
|
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z"
|
||||||
|
opacity=".25"
|
||||||
|
/><path
|
||||||
|
d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z"
|
||||||
|
class="spinner_ajPY"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
@ -99,7 +99,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class=" my-2 dark:border-gray-850" />
|
<hr class=" my-2 border-gray-100 dark:border-gray-850" />
|
||||||
|
|
||||||
<div class=" py-1 px-5 flex-1 max-h-full overflow-y-auto">
|
<div class=" py-1 px-5 flex-1 max-h-full overflow-y-auto">
|
||||||
<slot />
|
<slot />
|
||||||
|
7
src/routes/(app)/workspace/projects/[id]/+page.svelte
Normal file
7
src/routes/(app)/workspace/projects/[id]/+page.svelte
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
import { page } from '$app/stores';
|
||||||
|
|
||||||
|
import Project from '$lib/components/workspace/Projects/Project.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Project />
|
@ -1,5 +0,0 @@
|
|||||||
<script>
|
|
||||||
import EditProject from '$lib/components/workspace/Projects/EditProject.svelte';
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<EditProject />
|
|
Loading…
Reference in New Issue
Block a user