fix: prompts delete

This commit is contained in:
Timothy Jaeryang Baek
2026-02-18 14:58:39 -06:00
parent 9b55343509
commit 094ed0b48c
4 changed files with 113 additions and 32 deletions

View File

@@ -259,7 +259,6 @@ class PromptsTable:
# Join with User table for user filtering and sorting
query = db.query(Prompt, User).outerjoin(User, User.id == Prompt.user_id)
query = query.filter(Prompt.is_active == True)
if filter:
query_key = filter.get("query")
@@ -562,43 +561,24 @@ class PromptsTable:
except Exception:
return None
def delete_prompt_by_command(
self, command: str, db: Optional[Session] = None
) -> bool:
"""Soft delete a prompt by setting is_active to False."""
try:
with get_db_context(db) as db:
prompt = db.query(Prompt).filter_by(command=command).first()
if prompt:
PromptHistories.delete_history_by_prompt_id(prompt.id, db=db)
AccessGrants.revoke_all_access("prompt", prompt.id, db=db)
prompt.is_active = False
prompt.updated_at = int(time.time())
db.commit()
return True
return False
except Exception:
return False
def delete_prompt_by_id(self, prompt_id: str, db: Optional[Session] = None) -> bool:
"""Soft delete a prompt by setting is_active to False."""
def toggle_prompt_active(
self, prompt_id: str, db: Optional[Session] = None
) -> Optional[PromptModel]:
"""Toggle the is_active flag on a prompt."""
try:
with get_db_context(db) as db:
prompt = db.query(Prompt).filter_by(id=prompt_id).first()
if prompt:
PromptHistories.delete_history_by_prompt_id(prompt.id, db=db)
AccessGrants.revoke_all_access("prompt", prompt.id, db=db)
prompt.is_active = False
prompt.is_active = not prompt.is_active
prompt.updated_at = int(time.time())
db.commit()
return True
return False
db.refresh(prompt)
return self._to_prompt_model(prompt, db=db)
return None
except Exception:
return False
return None
def hard_delete_prompt_by_command(
def delete_prompt_by_command(
self, command: str, db: Optional[Session] = None
) -> bool:
"""Permanently delete a prompt and its history."""
@@ -609,8 +589,23 @@ class PromptsTable:
PromptHistories.delete_history_by_prompt_id(prompt.id, db=db)
AccessGrants.revoke_all_access("prompt", prompt.id, db=db)
# Delete prompt
db.query(Prompt).filter_by(command=command).delete()
db.delete(prompt)
db.commit()
return True
return False
except Exception:
return False
def delete_prompt_by_id(self, prompt_id: str, db: Optional[Session] = None) -> bool:
"""Permanently delete a prompt and its history."""
try:
with get_db_context(db) as db:
prompt = db.query(Prompt).filter_by(id=prompt_id).first()
if prompt:
PromptHistories.delete_history_by_prompt_id(prompt.id, db=db)
AccessGrants.revoke_all_access("prompt", prompt.id, db=db)
db.delete(prompt)
db.commit()
return True
return False

View File

@@ -497,6 +497,48 @@ async def update_prompt_access_by_id(
return Prompts.get_prompt_by_id(prompt_id, db=db)
############################
# TogglePromptActiveById
############################
@router.post("/id/{prompt_id}/toggle", response_model=Optional[PromptModel])
async def toggle_prompt_active(
prompt_id: str, user=Depends(get_verified_user), db: Session = Depends(get_session)
):
prompt = Prompts.get_prompt_by_id(prompt_id, db=db)
if not prompt:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=ERROR_MESSAGES.NOT_FOUND,
)
if (
prompt.user_id != user.id
and not AccessGrants.has_access(
user_id=user.id,
resource_type="prompt",
resource_id=prompt.id,
permission="write",
db=db,
)
and user.role != "admin"
):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
)
result = Prompts.toggle_prompt_active(prompt.id, db=db)
if result:
return result
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT(),
)
############################
# DeletePromptById
############################

View File

@@ -395,6 +395,34 @@ export const setProductionPromptVersion = async (
return res;
};
export const togglePromptById = async (token: string, promptId: string) => {
let error = null;
const res = await fetch(`${WEBUI_API_BASE_URL}/prompts/id/${promptId}/toggle`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
authorization: `Bearer ${token}`
}
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
error = err.detail;
console.error(err);
return null;
});
if (error) {
throw error;
}
return res;
};
export const deletePromptById = async (token: string, promptId: string) => {
let error = null;

View File

@@ -10,6 +10,7 @@
import {
createNewPrompt,
deletePromptById,
togglePromptById,
getPrompts,
getPromptItems,
getPromptTags
@@ -31,6 +32,7 @@
import ViewSelector from './common/ViewSelector.svelte';
import TagSelector from './common/TagSelector.svelte';
import Badge from '$lib/components/common/Badge.svelte';
import Switch from '../common/Switch.svelte';
import Pagination from '../common/Pagination.svelte';
let shiftKey = false;
@@ -398,6 +400,9 @@
<div class="text-xs overflow-hidden text-ellipsis line-clamp-1 text-gray-500">
/{prompt.command}
</div>
{#if prompt.is_active === false}
<Badge type="muted" content={$i18n.t('Inactive')} />
{/if}
</div>
{#if !prompt.write_access}
<Badge type="muted" content={$i18n.t('Read Only')} />
@@ -484,6 +489,17 @@
<EllipsisHorizontal className="size-5" />
</button>
</PromptMenu>
<button on:click|stopPropagation|preventDefault>
<Tooltip content={prompt.is_active !== false ? $i18n.t('Enabled') : $i18n.t('Disabled')}>
<Switch
bind:state={prompt.is_active}
on:change={async () => {
togglePromptById(localStorage.token, prompt.id);
}}
/>
</Tooltip>
</button>
{/if}
</div>
</a>