mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-09 16:18:00 -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)
|
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(
|
@extend_schema_view(list=extend_schema(
|
||||||
parameters=[OpenApiParameter(name='food_id', description='ID of food to filter for', type=int),
|
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-icon icon="fa-solid fa-arrow-down-1-9"></v-icon>
|
||||||
</v-btn>
|
</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-maximize" @click="handleSplitAllSteps" :disabled="editingObj.steps.length < 1"><span
|
||||||
<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-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>
|
</v-btn-group>
|
||||||
|
|
||||||
|
|
||||||
@@ -109,6 +111,15 @@
|
|||||||
<model-select mode="tags" model="User" :label="$t('Share')" persistent-hint v-model="editingObj.shared"
|
<model-select mode="tags" model="User" :label="$t('Share')" persistent-hint v-model="editingObj.shared"
|
||||||
append-to-body v-if="editingObj._private"></model-select>
|
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-form>
|
||||||
</v-tabs-window-item>
|
</v-tabs-window-item>
|
||||||
</v-tabs-window>
|
</v-tabs-window>
|
||||||
@@ -143,7 +154,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
import {onMounted, PropType, ref, shallowRef, watch} from "vue";
|
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 ModelEditorBase from "@/components/model_editors/ModelEditorBase.vue";
|
||||||
import {useModelEditorFunctions} from "@/composables/useModelEditorFunctions";
|
import {useModelEditorFunctions} from "@/composables/useModelEditorFunctions";
|
||||||
import ModelSelect from "@/components/inputs/ModelSelect.vue";
|
import ModelSelect from "@/components/inputs/ModelSelect.vue";
|
||||||
@@ -156,8 +167,9 @@ import ClosableHelpAlert from "@/components/display/ClosableHelpAlert.vue";
|
|||||||
import {useDisplay} from "vuetify";
|
import {useDisplay} from "vuetify";
|
||||||
import {isSpaceAtRecipeLimit} from "@/utils/logic_utils";
|
import {isSpaceAtRecipeLimit} from "@/utils/logic_utils";
|
||||||
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
|
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
|
||||||
import SpaceSettings from "@/components/settings/SpaceSettings.vue";
|
|
||||||
import {mergeAllSteps, splitAllSteps} from "@/utils/step_utils.ts";
|
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({
|
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>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -759,6 +759,11 @@ export interface ApiEnterpriseSocialRecipeCreateRequest {
|
|||||||
recipe: Omit<Recipe, 'image'|'createdBy'|'createdAt'|'updatedAt'|'foodProperties'|'rating'|'lastCooked'>;
|
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 {
|
export interface ApiEnterpriseSocialRecipeDestroyRequest {
|
||||||
id: number;
|
id: number;
|
||||||
}
|
}
|
||||||
@@ -1512,6 +1517,11 @@ export interface ApiRecipeCreateRequest {
|
|||||||
recipe: Omit<Recipe, 'image'|'createdBy'|'createdAt'|'updatedAt'|'foodProperties'|'rating'|'lastCooked'>;
|
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 {
|
export interface ApiRecipeDestroyRequest {
|
||||||
id: number;
|
id: number;
|
||||||
}
|
}
|
||||||
@@ -4411,6 +4421,46 @@ export class ApiApi extends runtime.BaseAPI {
|
|||||||
return await response.value();
|
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/
|
* logs request counts to redis cache total/per user/
|
||||||
*/
|
*/
|
||||||
@@ -10819,6 +10869,46 @@ export class ApiApi extends runtime.BaseAPI {
|
|||||||
return await response.value();
|
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/
|
* logs request counts to redis cache total/per user/
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user