mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-03 21:37:49 -05:00
added ability to delete external recipe file
This commit is contained in:
@@ -1449,6 +1449,22 @@ class RecipeViewSet(LoggingMixin, viewsets.ModelViewSet):
|
||||
|
||||
return Response(serializer.errors, 400)
|
||||
|
||||
@extend_schema(responses=RecipeSerializer(many=False))
|
||||
@decorators.action(detail=True, pagination_class=None, methods=['PATCH'], serializer_class=RecipeSerializer)
|
||||
def delete_external(self, request, pk):
|
||||
obj = self.get_object()
|
||||
if obj.get_space() != request.space and has_group_permission(request.user, ['user']):
|
||||
raise PermissionDenied(detail='You do not have the required permission to perform this action', code=403)
|
||||
|
||||
if obj.storage:
|
||||
get_recipe_provider(obj).delete_file(obj)
|
||||
obj.storage = None
|
||||
obj.file_path = ''
|
||||
obj.file_uid = ''
|
||||
obj.save()
|
||||
|
||||
return Response(self.serializer_class(obj, many=False, context={'request': request}).data)
|
||||
|
||||
|
||||
@extend_schema_view(list=extend_schema(
|
||||
parameters=[OpenApiParameter(name='food_id', description='ID of food to filter for', type=int),
|
||||
|
||||
@@ -83,8 +83,10 @@
|
||||
<v-icon icon="fa-solid fa-arrow-down-1-9"></v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn prepend-icon="fa-solid fa-maximize" @click="handleSplitAllSteps" :disabled="editingObj.steps.length < 1"><span v-if="!mobile">{{ $t('Split') }}</span></v-btn>
|
||||
<v-btn prepend-icon="fa-solid fa-minimize" @click="handleMergeAllSteps" :disabled="editingObj.steps.length < 2"><span v-if="!mobile">{{ $t('Merge') }}</span></v-btn>
|
||||
<v-btn prepend-icon="fa-solid fa-maximize" @click="handleSplitAllSteps" :disabled="editingObj.steps.length < 1"><span
|
||||
v-if="!mobile">{{ $t('Split') }}</span></v-btn>
|
||||
<v-btn prepend-icon="fa-solid fa-minimize" @click="handleMergeAllSteps" :disabled="editingObj.steps.length < 2"><span
|
||||
v-if="!mobile">{{ $t('Merge') }}</span></v-btn>
|
||||
</v-btn-group>
|
||||
|
||||
|
||||
@@ -109,6 +111,15 @@
|
||||
<model-select mode="tags" model="User" :label="$t('Share')" persistent-hint v-model="editingObj.shared"
|
||||
append-to-body v-if="editingObj._private"></model-select>
|
||||
|
||||
<div class="mt-2" v-if="editingObj.filePath">
|
||||
{{ $t('ExternalRecipe') }}
|
||||
<v-text-field readonly v-model="editingObj.filePath"></v-text-field>
|
||||
|
||||
<v-btn prepend-icon="$delete" color="error" :loading="loading">{{ $t('delete_title', {type: $t('ExternalRecipe')}) }}
|
||||
<delete-confirm-dialog :object-name="editingObj.filePath" :model-name="$t('ExternalRecipe')" @delete="deleteExternalFile()"></delete-confirm-dialog>
|
||||
</v-btn>
|
||||
</div>
|
||||
|
||||
</v-form>
|
||||
</v-tabs-window-item>
|
||||
</v-tabs-window>
|
||||
@@ -143,7 +154,7 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {onMounted, PropType, ref, shallowRef, watch} from "vue";
|
||||
import {Ingredient, Recipe, Step} from "@/openapi";
|
||||
import {ApiApi, Ingredient, Recipe, Step} from "@/openapi";
|
||||
import ModelEditorBase from "@/components/model_editors/ModelEditorBase.vue";
|
||||
import {useModelEditorFunctions} from "@/composables/useModelEditorFunctions";
|
||||
import ModelSelect from "@/components/inputs/ModelSelect.vue";
|
||||
@@ -156,8 +167,9 @@ import ClosableHelpAlert from "@/components/display/ClosableHelpAlert.vue";
|
||||
import {useDisplay} from "vuetify";
|
||||
import {isSpaceAtRecipeLimit} from "@/utils/logic_utils";
|
||||
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
|
||||
import SpaceSettings from "@/components/settings/SpaceSettings.vue";
|
||||
import {mergeAllSteps, splitAllSteps} from "@/utils/step_utils.ts";
|
||||
import DeleteConfirmDialog from "@/components/dialogs/DeleteConfirmDialog.vue";
|
||||
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore.ts";
|
||||
|
||||
|
||||
const props = defineProps({
|
||||
@@ -267,6 +279,21 @@ function handleSplitAllSteps(): void {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes the external file for the recipe
|
||||
*/
|
||||
function deleteExternalFile() {
|
||||
let api = new ApiApi()
|
||||
loading.value = true
|
||||
api.apiRecipeDeleteExternalPartialUpdate({id: editingObj.value.id!, patchedRecipe: editingObj.value}).then(r => {
|
||||
editingObj.value = r
|
||||
}).catch(err => {
|
||||
useMessageStore().addError(ErrorMessageType.DELETE_ERROR, err)
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -759,6 +759,11 @@ export interface ApiEnterpriseSocialRecipeCreateRequest {
|
||||
recipe: Omit<Recipe, 'image'|'createdBy'|'createdAt'|'updatedAt'|'foodProperties'|'rating'|'lastCooked'>;
|
||||
}
|
||||
|
||||
export interface ApiEnterpriseSocialRecipeDeleteExternalPartialUpdateRequest {
|
||||
id: number;
|
||||
patchedRecipe?: Omit<PatchedRecipe, 'image'|'createdBy'|'createdAt'|'updatedAt'|'foodProperties'|'rating'|'lastCooked'>;
|
||||
}
|
||||
|
||||
export interface ApiEnterpriseSocialRecipeDestroyRequest {
|
||||
id: number;
|
||||
}
|
||||
@@ -1512,6 +1517,11 @@ export interface ApiRecipeCreateRequest {
|
||||
recipe: Omit<Recipe, 'image'|'createdBy'|'createdAt'|'updatedAt'|'foodProperties'|'rating'|'lastCooked'>;
|
||||
}
|
||||
|
||||
export interface ApiRecipeDeleteExternalPartialUpdateRequest {
|
||||
id: number;
|
||||
patchedRecipe?: Omit<PatchedRecipe, 'image'|'createdBy'|'createdAt'|'updatedAt'|'foodProperties'|'rating'|'lastCooked'>;
|
||||
}
|
||||
|
||||
export interface ApiRecipeDestroyRequest {
|
||||
id: number;
|
||||
}
|
||||
@@ -4411,6 +4421,46 @@ export class ApiApi extends runtime.BaseAPI {
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiEnterpriseSocialRecipeDeleteExternalPartialUpdateRaw(requestParameters: ApiEnterpriseSocialRecipeDeleteExternalPartialUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Recipe>> {
|
||||
if (requestParameters['id'] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
'id',
|
||||
'Required parameter "id" was null or undefined when calling apiEnterpriseSocialRecipeDeleteExternalPartialUpdate().'
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
headerParameters['Content-Type'] = 'application/json';
|
||||
|
||||
if (this.configuration && this.configuration.apiKey) {
|
||||
headerParameters["Authorization"] = await this.configuration.apiKey("Authorization"); // ApiKeyAuth authentication
|
||||
}
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/enterprise-social-recipe/{id}/delete_external/`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))),
|
||||
method: 'PATCH',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
body: PatchedRecipeToJSON(requestParameters['patchedRecipe']),
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => RecipeFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiEnterpriseSocialRecipeDeleteExternalPartialUpdate(requestParameters: ApiEnterpriseSocialRecipeDeleteExternalPartialUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Recipe> {
|
||||
const response = await this.apiEnterpriseSocialRecipeDeleteExternalPartialUpdateRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
@@ -10819,6 +10869,46 @@ export class ApiApi extends runtime.BaseAPI {
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiRecipeDeleteExternalPartialUpdateRaw(requestParameters: ApiRecipeDeleteExternalPartialUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Recipe>> {
|
||||
if (requestParameters['id'] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
'id',
|
||||
'Required parameter "id" was null or undefined when calling apiRecipeDeleteExternalPartialUpdate().'
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
headerParameters['Content-Type'] = 'application/json';
|
||||
|
||||
if (this.configuration && this.configuration.apiKey) {
|
||||
headerParameters["Authorization"] = await this.configuration.apiKey("Authorization"); // ApiKeyAuth authentication
|
||||
}
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/recipe/{id}/delete_external/`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))),
|
||||
method: 'PATCH',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
body: PatchedRecipeToJSON(requestParameters['patchedRecipe']),
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => RecipeFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiRecipeDeleteExternalPartialUpdate(requestParameters: ApiRecipeDeleteExternalPartialUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Recipe> {
|
||||
const response = await this.apiRecipeDeleteExternalPartialUpdateRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user