This commit is contained in:
Tom Nowell 2025-06-13 12:00:24 +02:00 committed by GitHub
commit 544279729f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 48 additions and 4 deletions

View file

@ -9,7 +9,7 @@
{{ $t("general.image") }} {{ $t("general.image") }}
</v-btn> </v-btn>
</template> </template>
<v-card width="400"> <v-card width="450">
<v-card-title class="headline flex mb-0"> <v-card-title class="headline flex mb-0">
<div> <div>
{{ $t("recipe.recipe-image") }} {{ $t("recipe.recipe-image") }}
@ -22,6 +22,10 @@
:post="false" :post="false"
@uploaded="uploadImage" @uploaded="uploadImage"
/> />
<v-btn class="ml-2" color="error" :loading="loading" :disabled="!slug" @click="deleteImage">
<v-icon> {{ $globals.icons.delete }} </v-icon>
{{ $t("general.delete") }}
</v-btn>
</v-card-title> </v-card-title>
<v-card-text class="mt-n5"> <v-card-text class="mt-n5">
<div> <div>
@ -45,6 +49,7 @@ import { useUserApi } from "~/composables/api";
const REFRESH_EVENT = "refresh"; const REFRESH_EVENT = "refresh";
const UPLOAD_EVENT = "upload"; const UPLOAD_EVENT = "upload";
const DELETE_EVENT = "delete";
export default defineComponent({ export default defineComponent({
props: { props: {
@ -65,6 +70,11 @@ export default defineComponent({
state.menu = false; state.menu = false;
} }
function deleteImage() {
context.emit(DELETE_EVENT);
state.menu = false;
}
const api = useUserApi(); const api = useUserApi();
async function getImageFromURL() { async function getImageFromURL() {
state.loading = true; state.loading = true;
@ -81,6 +91,7 @@ export default defineComponent({
return { return {
...toRefs(state), ...toRefs(state),
uploadImage, uploadImage,
deleteImage,
getImageFromURL, getImageFromURL,
messages, messages,
}; };

View file

@ -1,6 +1,6 @@
<template> <template>
<div class="d-flex justify-start align-top py-2"> <div class="d-flex justify-start align-top py-2">
<RecipeImageUploadBtn class="my-1" :slug="recipe.slug" @upload="uploadImage" @refresh="imageKey++" /> <RecipeImageUploadBtn class="my-1" :slug="recipe.slug" @upload="uploadImage" @delete = "deleteImage" @refresh="imageKey++" />
<RecipeSettingsMenu <RecipeSettingsMenu
class="my-1 mx-1" class="my-1 mx-1"
:value="recipe.settings" :value="recipe.settings"
@ -59,7 +59,6 @@ export default defineComponent({
const { user } = usePageUser(); const { user } = usePageUser();
const api = useUserApi(); const api = useUserApi();
const { imageKey } = usePageState(props.recipe.slug); const { imageKey } = usePageState(props.recipe.slug);
const canEditOwner = computed(() => { const canEditOwner = computed(() => {
return user.id === props.recipe.userId || user.admin; return user.id === props.recipe.userId || user.admin;
}) })
@ -86,10 +85,21 @@ export default defineComponent({
imageKey.value++; imageKey.value++;
} }
async function deleteImage() {
if (props.recipe.image == null) {
return;
}
const response = await api.recipes.deleteImage(props.recipe.slug);
if (response) {
props.recipe.image = null
}
}
return { return {
user, user,
canEditOwner, canEditOwner,
uploadImage, uploadImage,
deleteImage,
imageKey, imageKey,
allUsers, allUsers,
ownerHousehold, ownerHousehold,

View file

@ -137,6 +137,10 @@ export class RecipeAPI extends BaseCRUDAPI<CreateRecipe, Recipe, Recipe> {
return this.requests.put<UpdateImageResponse, FormData>(routes.recipesRecipeSlugImage(slug), formData); return this.requests.put<UpdateImageResponse, FormData>(routes.recipesRecipeSlugImage(slug), formData);
} }
deleteImage(slug: string) {
return this.requests.delete<UpdateImageResponse>(routes.recipesRecipeSlugImage(slug));
}
updateImagebyURL(slug: string, url: string) { updateImagebyURL(slug: string, url: string) {
return this.requests.post<UpdateImageResponse>(routes.recipesRecipeSlugImage(slug), { url }); return this.requests.post<UpdateImageResponse>(routes.recipesRecipeSlugImage(slug), { url });
} }

View file

@ -152,7 +152,12 @@ class RepositoryRecipes(HouseholdRepositoryGeneric[Recipe, RecipeModel]):
entry: RecipeModel = self._query_one(match_value=slug) entry: RecipeModel = self._query_one(match_value=slug)
entry.image = randint(0, 255) entry.image = randint(0, 255)
self.session.commit() self.session.commit()
return entry.image
def delete_image(self, slug: str) -> None:
entry: RecipeModel = self._query_one(match_value=slug)
entry.image = None
self.session.commit()
return entry.image return entry.image
def count_uncategorized(self, count=True, override_schema=None): def count_uncategorized(self, count=True, override_schema=None):

View file

@ -526,10 +526,16 @@ class RecipeController(BaseRecipeController):
recipe = self.mixins.get_one(slug) recipe = self.mixins.get_one(slug)
data_service = RecipeDataService(recipe.id) data_service = RecipeDataService(recipe.id)
data_service.write_image(image, extension) data_service.write_image(image, extension)
new_version = self.recipes.update_image(slug, extension) new_version = self.recipes.update_image(slug, extension)
return UpdateImageResponse(image=new_version) return UpdateImageResponse(image=new_version)
@router.delete("/{slug}/image", tags=["Recipe: Images and Assets"])
def delete_recipe_image(self, slug: str):
recipe = self.mixins.get_one(slug)
data_service = RecipeDataService(recipe.id)
data_service.delete_image()
self.recipes.delete_image(slug)
@router.post("/{slug}/assets", response_model=RecipeAsset, tags=["Recipe: Images and Assets"]) @router.post("/{slug}/assets", response_model=RecipeAsset, tags=["Recipe: Images and Assets"])
def upload_recipe_asset( def upload_recipe_asset(
self, self,

View file

@ -104,6 +104,14 @@ class RecipeDataService(BaseService):
return image_path return image_path
def delete_image(self) -> None:
image_dir = self.dir_image
try:
shutil.rmtree(image_dir)
except Exception as e:
self.logger.exception(f"Failed to delete image data: {e}")
async def scrape_image(self, image_url: str | dict[str, str] | list[str]) -> None: async def scrape_image(self, image_url: str | dict[str, str] | list[str]) -> None:
self.logger.info(f"Image URL: {image_url}") self.logger.info(f"Image URL: {image_url}")
user_agent = get_user_agents_manager().user_agents[0] user_agent = get_user_agents_manager().user_agents[0]