mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-11 00:58:32 -05:00
food batch update dialog and first api functions
This commit is contained in:
@@ -1198,6 +1198,26 @@ class FoodBatchUpdateSerializer(serializers.Serializer):
|
||||
|
||||
category = serializers.IntegerField(required=False, allow_null=True)
|
||||
|
||||
substitute_add = serializers.ListField(child=serializers.IntegerField())
|
||||
substitute_remove = serializers.ListField(child=serializers.IntegerField())
|
||||
substitute_set = serializers.ListField(child=serializers.IntegerField())
|
||||
substitute_remove_all = serializers.BooleanField(default=False)
|
||||
|
||||
inherit_fields_add = serializers.ListField(child=serializers.IntegerField())
|
||||
inherit_fields_remove = serializers.ListField(child=serializers.IntegerField())
|
||||
inherit_fields_set = serializers.ListField(child=serializers.IntegerField())
|
||||
inherit_fields_remove_all = serializers.BooleanField(default=False)
|
||||
|
||||
child_inherit_fields_add = serializers.ListField(child=serializers.IntegerField())
|
||||
child_inherit_fields_remove = serializers.ListField(child=serializers.IntegerField())
|
||||
child_inherit_fields_set = serializers.ListField(child=serializers.IntegerField())
|
||||
child_inherit_fields_remove_all = serializers.BooleanField(default=False)
|
||||
|
||||
substitute_children = serializers.BooleanField(required=False, allow_null=True)
|
||||
substitute_siblings = serializers.BooleanField(required=False, allow_null=True)
|
||||
ignore_shopping = serializers.BooleanField(required=False, allow_null=True)
|
||||
on_hand = serializers.BooleanField(required=False, allow_null=True)
|
||||
|
||||
|
||||
class CustomFilterSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
|
||||
shared = UserSerializer(many=True, required=False)
|
||||
|
||||
@@ -946,10 +946,50 @@ class FoodViewSet(LoggingMixin, TreeMixin):
|
||||
|
||||
if serializer.is_valid():
|
||||
foods = Food.objects.filter(id__in=serializer.validated_data['foods'], space=self.request.space)
|
||||
# safe_food_ids = Food.objects.filter(id__in=serializer.validated_data['foods'], space=self.request.space).values_list('id', flat=True)
|
||||
safe_food_ids = Food.objects.filter(id__in=serializer.validated_data['foods'], space=self.request.space).values_list('id', flat=True)
|
||||
|
||||
if 'category' in serializer.validated_data:
|
||||
foods.update(category_id=serializer.validated_data['category'])
|
||||
foods.update(supermarket_category_id=serializer.validated_data['category'])
|
||||
|
||||
|
||||
if 'ignore_shopping' in serializer.validated_data and serializer.validated_data['ignore_shopping'] is not None:
|
||||
foods.update(ignore_shopping=serializer.validated_data['ignore_shopping'])
|
||||
|
||||
if 'on_hand' in serializer.validated_data and serializer.validated_data['on_hand'] is not None:
|
||||
if serializer.validated_data['on_hand']:
|
||||
user_relation = []
|
||||
for f in safe_food_ids:
|
||||
user_relation.append(Food.onhand_users.through(food_id=f, user_id=request.user.id))
|
||||
Food.onhand_users.through.objects.bulk_create(user_relation, ignore_conflicts=True, unique_fields=('food_id', 'user_id',))
|
||||
else:
|
||||
Food.onhand_users.through.objects.filter(food_id__in=safe_food_ids, user_id=request.user.id).delete()
|
||||
|
||||
if 'substitutes_add' in serializer.validated_data:
|
||||
substitute_relation = []
|
||||
for f in safe_food_ids:
|
||||
for s in serializer.validated_data['substitutes_add']:
|
||||
substitute_relation.append(Food.substitute.through(from_food_id=f, to_food_id=s))
|
||||
Food.substitute.through.objects.bulk_create(substitute_relation, ignore_conflicts=True, unique_fields=('from_food_id', 'to_food_id',))
|
||||
|
||||
if 'substitute_remove' in serializer.validated_data:
|
||||
for s in serializer.validated_data['substitute_remove']:
|
||||
Food.substitute.through.objects.filter(from_food_id=safe_food_ids, to_food_id=s).delete()
|
||||
|
||||
if 'substitute_set' in serializer.validated_data and len(serializer.validated_data['substitute_set']) > 0:
|
||||
substitute_relation = []
|
||||
Food.substitute.through.objects.filter(from_food_id=safe_food_ids).delete()
|
||||
for f in safe_food_ids:
|
||||
for s in serializer.validated_data['substitute_set']:
|
||||
substitute_relation.append(Food.substitute.through(from_food_id=f, to_food_id=s))
|
||||
Food.substitute.through.objects.bulk_create(substitute_relation, ignore_conflicts=True, unique_fields=('from_food_id', 'to_food_id',))
|
||||
|
||||
if 'substitute_remove_all' in serializer.validated_data and serializer.validated_data['substitute_remove_all']:
|
||||
Food.substitute.through.objects.filter(from_food_id=safe_food_ids).delete()
|
||||
|
||||
|
||||
def add_substitute(relation_model, base_field, base_ids, related_field_name, related_ids ):
|
||||
pass
|
||||
|
||||
|
||||
return Response({}, 200)
|
||||
|
||||
|
||||
178
vue3/src/components/dialogs/BatchEditFoodDialog.vue
Normal file
178
vue3/src/components/dialogs/BatchEditFoodDialog.vue
Normal file
@@ -0,0 +1,178 @@
|
||||
<template>
|
||||
<v-dialog max-width="1200px" :activator="props.activator" v-model="dialog">
|
||||
<v-card :loading="loading">
|
||||
<v-closable-card-title
|
||||
:title="$t('BatchEdit')"
|
||||
:sub-title="$t('BatchEditUpdatingItemsCount', {type: $t('Foods'), count: updateItems.length})"
|
||||
:icon="TFood.icon"
|
||||
v-model="dialog"
|
||||
></v-closable-card-title>
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-card-text>
|
||||
|
||||
<v-form>
|
||||
<v-row>
|
||||
<v-col cols="12" md="6">
|
||||
<v-card :title="$t('Miscellaneous')" prepend-icon="fa-solid fa-list" variant="flat">
|
||||
<v-card-text>
|
||||
<model-select model="SupermarketCategory" v-model="batchUpdateRequest.foodBatchUpdate.category" :object="false" allow-create mode="single">
|
||||
</model-select>
|
||||
|
||||
<v-select :items="boolUpdateOptions" :label="$t('Ignore_Shopping')" clearable v-model="batchUpdateRequest.foodBatchUpdate.ignoreShopping"></v-select>
|
||||
<v-select :items="boolUpdateOptions" :label="$t('OnHand')" clearable v-model="batchUpdateRequest.foodBatchUpdate.onHand"></v-select>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
<v-label :text="$t('Substitutes')"></v-label>
|
||||
<model-select model="Food" v-model="batchUpdateRequest.foodBatchUpdate.substituteAdd" :object="false" allow-create mode="tags">
|
||||
<template #prepend>
|
||||
<v-icon icon="fa-solid fa-add"></v-icon>
|
||||
</template>
|
||||
</model-select>
|
||||
<model-select model="Food" v-model="batchUpdateRequest.foodBatchUpdate.substituteRemove" :object="false" allow-create mode="tags">
|
||||
<template #prepend>
|
||||
<v-icon icon="fa-solid fa-minus"></v-icon>
|
||||
</template>
|
||||
</model-select>
|
||||
<model-select model="Food" v-model="batchUpdateRequest.foodBatchUpdate.substituteSet" :object="false" allow-create mode="tags">
|
||||
<template #prepend>
|
||||
<v-icon icon="fa-solid fa-equals"></v-icon>
|
||||
</template>
|
||||
</model-select>
|
||||
<v-checkbox :label="$t('RemoveAllType', {type: $t('Substitutes')})" hide-details
|
||||
v-model="batchUpdateRequest.foodBatchUpdate.substituteRemoveAll"></v-checkbox>
|
||||
|
||||
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" md="6">
|
||||
<v-card :title="$t('Hierarchy')" prepend-icon="fa-solid fa-folder-tree" variant="flat">
|
||||
<v-card-text>
|
||||
<v-select :items="boolUpdateOptions" :label="$t('substitute_siblings')" clearable v-model="batchUpdateRequest.foodBatchUpdate.substituteChildren"></v-select>
|
||||
<v-select :items="boolUpdateOptions" :label="$t('substitute_children')" clearable v-model="batchUpdateRequest.foodBatchUpdate.substituteSiblings"></v-select>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
|
||||
<v-label :text="$t('InheritFields')"></v-label>
|
||||
<model-select model="FoodInheritField" v-model="batchUpdateRequest.foodBatchUpdate.inheritFieldsAdd" :object="false" allow-create mode="tags">
|
||||
<template #prepend>
|
||||
<v-icon icon="fa-solid fa-add"></v-icon>
|
||||
</template>
|
||||
</model-select>
|
||||
<model-select model="FoodInheritField" v-model="batchUpdateRequest.foodBatchUpdate.inheritFieldsRemove" :object="false" allow-create mode="tags">
|
||||
<template #prepend>
|
||||
<v-icon icon="fa-solid fa-minus"></v-icon>
|
||||
</template>
|
||||
</model-select>
|
||||
<model-select model="FoodInheritField" v-model="batchUpdateRequest.foodBatchUpdate.inheritFieldsSet" :object="false" allow-create mode="tags">
|
||||
<template #prepend>
|
||||
<v-icon icon="fa-solid fa-equals"></v-icon>
|
||||
</template>
|
||||
</model-select>
|
||||
<v-checkbox :label="$t('RemoveAllType', {type: $t('InheritFields')})" hide-details
|
||||
v-model="batchUpdateRequest.foodBatchUpdate.inheritFieldsRemoveAll"></v-checkbox>
|
||||
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
<v-label :text="$t('ChildInheritFields')"></v-label>
|
||||
|
||||
<model-select model="FoodInheritField" v-model="batchUpdateRequest.foodBatchUpdate.childInheritFieldsAdd" :object="false" allow-create mode="tags">
|
||||
<template #prepend>
|
||||
<v-icon icon="fa-solid fa-add"></v-icon>
|
||||
</template>
|
||||
</model-select>
|
||||
<model-select model="FoodInheritField" v-model="batchUpdateRequest.foodBatchUpdate.childInheritFieldsRemove" :object="false" allow-create mode="tags">
|
||||
<template #prepend>
|
||||
<v-icon icon="fa-solid fa-minus"></v-icon>
|
||||
</template>
|
||||
</model-select>
|
||||
<model-select model="FoodInheritField" v-model="batchUpdateRequest.foodBatchUpdate.childInheritFieldsSet" :object="false" allow-create mode="tags">
|
||||
<template #prepend>
|
||||
<v-icon icon="fa-solid fa-equals"></v-icon>
|
||||
</template>
|
||||
</model-select>
|
||||
<v-checkbox :label="$t('RemoveAllType', {type: $t('ChildInheritFields')})" hide-details
|
||||
v-model="batchUpdateRequest.foodBatchUpdate.childInheritFieldsRemoveAll"></v-checkbox>
|
||||
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
</v-row>
|
||||
|
||||
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn :disabled="loading" @click="dialog = false">{{ $t('Cancel') }}</v-btn>
|
||||
<v-btn color="warning" :loading="loading" @click="batchUpdateFoods()" :disabled="updateItems.length < 1">{{ $t('Update') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
import {onMounted, PropType, ref, watch} from "vue";
|
||||
import {EditorSupportedModels, EditorSupportedTypes, getGenericModelFromString, TFood, TKeyword, TRecipe} from "@/types/Models.ts";
|
||||
import VClosableCardTitle from "@/components/dialogs/VClosableCardTitle.vue";
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {ApiApi, ApiFoodBatchUpdateUpdateRequest, ApiRecipeBatchUpdateUpdateRequest, Food, Recipe, RecipeOverview} from "@/openapi";
|
||||
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore.ts";
|
||||
import ModelSelect from "@/components/inputs/ModelSelect.vue";
|
||||
|
||||
const emit = defineEmits(['change'])
|
||||
|
||||
const props = defineProps({
|
||||
items: {type: Array as PropType<Array<Food>>, required: true},
|
||||
activator: {type: String, default: 'parent'},
|
||||
})
|
||||
|
||||
const {t} = useI18n()
|
||||
|
||||
const dialog = defineModel<boolean>({default: false})
|
||||
const loading = ref(false)
|
||||
|
||||
const updateItems = ref([] as Food[])
|
||||
const batchUpdateRequest = ref({foodBatchUpdate: {}} as ApiFoodBatchUpdateUpdateRequest)
|
||||
|
||||
const boolUpdateOptions = ref([
|
||||
{value: true, title: t('Yes')},
|
||||
{value: false, title: t('No')},
|
||||
])
|
||||
|
||||
/**
|
||||
* copy prop when dialog opens so that items remain when parent is updated after change is emitted
|
||||
*/
|
||||
watch(dialog, (newValue, oldValue) => {
|
||||
if (!oldValue && newValue && props.items != undefined) {
|
||||
batchUpdateRequest.value.foodBatchUpdate.foods = props.items.flatMap(r => r.id!)
|
||||
updateItems.value = JSON.parse(JSON.stringify(props.items))
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* perform batch request to update recipes
|
||||
*/
|
||||
function batchUpdateFoods() {
|
||||
let api = new ApiApi()
|
||||
loading.value = true
|
||||
|
||||
api.apiFoodBatchUpdateUpdate(batchUpdateRequest.value).then(r => {
|
||||
|
||||
}).catch(err => {
|
||||
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
|
||||
}).finally(() => {
|
||||
emit('change')
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -54,7 +54,7 @@
|
||||
<properties-editor v-model="editingObj.properties" :amount-for="propertiesAmountFor"></properties-editor>
|
||||
|
||||
<!-- TODO remove once append to body for model select is working properly -->
|
||||
<v-spacer style="margin-top: 60px;"></v-spacer>
|
||||
<v-spacer style="margin-top: 80px;"></v-spacer>
|
||||
</v-form>
|
||||
</v-tabs-window-item>
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
</v-card>
|
||||
</v-form>
|
||||
<!-- TODO remove once append to body for model select is working properly -->
|
||||
<v-spacer style="margin-top: 60px;"></v-spacer>
|
||||
<v-spacer style="margin-top: 80px;"></v-spacer>
|
||||
</v-tabs-window-item>
|
||||
|
||||
<v-tabs-window-item value="hierarchy">
|
||||
@@ -119,6 +119,9 @@
|
||||
mode="tags"></ModelSelect>
|
||||
<ModelSelect model="FoodInheritField" v-model="editingObj.childInheritFields" :label="$t('ChildInheritFields')" :hint="$t('ChildInheritFields_help')"
|
||||
mode="tags"></ModelSelect>
|
||||
|
||||
<!-- TODO remove once append to body for model select is working properly -->
|
||||
<v-spacer style="margin-top: 100px;"></v-spacer>
|
||||
</v-tabs-window-item>
|
||||
|
||||
<v-tabs-window-item value="misc">
|
||||
|
||||
@@ -29,6 +29,7 @@ models/ExportRequest.ts
|
||||
models/FdcQuery.ts
|
||||
models/FdcQueryFoods.ts
|
||||
models/Food.ts
|
||||
models/FoodBatchUpdate.ts
|
||||
models/FoodInheritField.ts
|
||||
models/FoodShoppingUpdate.ts
|
||||
models/FoodSimple.ts
|
||||
|
||||
@@ -30,6 +30,7 @@ import type {
|
||||
ExportRequest,
|
||||
FdcQuery,
|
||||
Food,
|
||||
FoodBatchUpdate,
|
||||
FoodInheritField,
|
||||
FoodShoppingUpdate,
|
||||
Group,
|
||||
@@ -212,6 +213,8 @@ import {
|
||||
FdcQueryToJSON,
|
||||
FoodFromJSON,
|
||||
FoodToJSON,
|
||||
FoodBatchUpdateFromJSON,
|
||||
FoodBatchUpdateToJSON,
|
||||
FoodInheritFieldFromJSON,
|
||||
FoodInheritFieldToJSON,
|
||||
FoodShoppingUpdateFromJSON,
|
||||
@@ -962,6 +965,10 @@ export interface ApiFdcSearchRetrieveRequest {
|
||||
query?: string;
|
||||
}
|
||||
|
||||
export interface ApiFoodBatchUpdateUpdateRequest {
|
||||
foodBatchUpdate: FoodBatchUpdate;
|
||||
}
|
||||
|
||||
export interface ApiFoodCreateRequest {
|
||||
food: Omit<Food, 'shopping'|'parent'|'numchild'|'fullName'|'substituteOnhand'>;
|
||||
}
|
||||
@@ -5956,6 +5963,46 @@ export class ApiApi extends runtime.BaseAPI {
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiFoodBatchUpdateUpdateRaw(requestParameters: ApiFoodBatchUpdateUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<FoodBatchUpdate>> {
|
||||
if (requestParameters['foodBatchUpdate'] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
'foodBatchUpdate',
|
||||
'Required parameter "foodBatchUpdate" was null or undefined when calling apiFoodBatchUpdateUpdate().'
|
||||
);
|
||||
}
|
||||
|
||||
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/food/batch_update/`,
|
||||
method: 'PUT',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
body: FoodBatchUpdateToJSON(requestParameters['foodBatchUpdate']),
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => FoodBatchUpdateFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiFoodBatchUpdateUpdate(requestParameters: ApiFoodBatchUpdateUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<FoodBatchUpdate> {
|
||||
const response = await this.apiFoodBatchUpdateUpdateRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
|
||||
206
vue3/src/openapi/models/FoodBatchUpdate.ts
Normal file
206
vue3/src/openapi/models/FoodBatchUpdate.ts
Normal file
@@ -0,0 +1,206 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Tandoor
|
||||
* Tandoor API Docs
|
||||
*
|
||||
* The version of the OpenAPI document: 0.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface FoodBatchUpdate
|
||||
*/
|
||||
export interface FoodBatchUpdate {
|
||||
/**
|
||||
*
|
||||
* @type {Array<number>}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
foods: Array<number>;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
category?: number;
|
||||
/**
|
||||
*
|
||||
* @type {Array<number>}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
substituteAdd: Array<number>;
|
||||
/**
|
||||
*
|
||||
* @type {Array<number>}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
substituteRemove: Array<number>;
|
||||
/**
|
||||
*
|
||||
* @type {Array<number>}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
substituteSet: Array<number>;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
substituteRemoveAll?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {Array<number>}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
inheritFieldsAdd: Array<number>;
|
||||
/**
|
||||
*
|
||||
* @type {Array<number>}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
inheritFieldsRemove: Array<number>;
|
||||
/**
|
||||
*
|
||||
* @type {Array<number>}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
inheritFieldsSet: Array<number>;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
inheritFieldsRemoveAll?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {Array<number>}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
childInheritFieldsAdd: Array<number>;
|
||||
/**
|
||||
*
|
||||
* @type {Array<number>}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
childInheritFieldsRemove: Array<number>;
|
||||
/**
|
||||
*
|
||||
* @type {Array<number>}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
childInheritFieldsSet: Array<number>;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
childInheritFieldsRemoveAll?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
substituteChildren?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
substituteSiblings?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
ignoreShopping?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof FoodBatchUpdate
|
||||
*/
|
||||
onHand?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the FoodBatchUpdate interface.
|
||||
*/
|
||||
export function instanceOfFoodBatchUpdate(value: object): value is FoodBatchUpdate {
|
||||
if (!('foods' in value) || value['foods'] === undefined) return false;
|
||||
if (!('substituteAdd' in value) || value['substituteAdd'] === undefined) return false;
|
||||
if (!('substituteRemove' in value) || value['substituteRemove'] === undefined) return false;
|
||||
if (!('substituteSet' in value) || value['substituteSet'] === undefined) return false;
|
||||
if (!('inheritFieldsAdd' in value) || value['inheritFieldsAdd'] === undefined) return false;
|
||||
if (!('inheritFieldsRemove' in value) || value['inheritFieldsRemove'] === undefined) return false;
|
||||
if (!('inheritFieldsSet' in value) || value['inheritFieldsSet'] === undefined) return false;
|
||||
if (!('childInheritFieldsAdd' in value) || value['childInheritFieldsAdd'] === undefined) return false;
|
||||
if (!('childInheritFieldsRemove' in value) || value['childInheritFieldsRemove'] === undefined) return false;
|
||||
if (!('childInheritFieldsSet' in value) || value['childInheritFieldsSet'] === undefined) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function FoodBatchUpdateFromJSON(json: any): FoodBatchUpdate {
|
||||
return FoodBatchUpdateFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function FoodBatchUpdateFromJSONTyped(json: any, ignoreDiscriminator: boolean): FoodBatchUpdate {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'foods': json['foods'],
|
||||
'category': json['category'] == null ? undefined : json['category'],
|
||||
'substituteAdd': json['substitute_add'],
|
||||
'substituteRemove': json['substitute_remove'],
|
||||
'substituteSet': json['substitute_set'],
|
||||
'substituteRemoveAll': json['substitute_remove_all'] == null ? undefined : json['substitute_remove_all'],
|
||||
'inheritFieldsAdd': json['inherit_fields_add'],
|
||||
'inheritFieldsRemove': json['inherit_fields_remove'],
|
||||
'inheritFieldsSet': json['inherit_fields_set'],
|
||||
'inheritFieldsRemoveAll': json['inherit_fields_remove_all'] == null ? undefined : json['inherit_fields_remove_all'],
|
||||
'childInheritFieldsAdd': json['child_inherit_fields_add'],
|
||||
'childInheritFieldsRemove': json['child_inherit_fields_remove'],
|
||||
'childInheritFieldsSet': json['child_inherit_fields_set'],
|
||||
'childInheritFieldsRemoveAll': json['child_inherit_fields_remove_all'] == null ? undefined : json['child_inherit_fields_remove_all'],
|
||||
'substituteChildren': json['substitute_children'] == null ? undefined : json['substitute_children'],
|
||||
'substituteSiblings': json['substitute_siblings'] == null ? undefined : json['substitute_siblings'],
|
||||
'ignoreShopping': json['ignore_shopping'] == null ? undefined : json['ignore_shopping'],
|
||||
'onHand': json['on_hand'] == null ? undefined : json['on_hand'],
|
||||
};
|
||||
}
|
||||
|
||||
export function FoodBatchUpdateToJSON(value?: FoodBatchUpdate | null): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
return {
|
||||
|
||||
'foods': value['foods'],
|
||||
'category': value['category'],
|
||||
'substitute_add': value['substituteAdd'],
|
||||
'substitute_remove': value['substituteRemove'],
|
||||
'substitute_set': value['substituteSet'],
|
||||
'substitute_remove_all': value['substituteRemoveAll'],
|
||||
'inherit_fields_add': value['inheritFieldsAdd'],
|
||||
'inherit_fields_remove': value['inheritFieldsRemove'],
|
||||
'inherit_fields_set': value['inheritFieldsSet'],
|
||||
'inherit_fields_remove_all': value['inheritFieldsRemoveAll'],
|
||||
'child_inherit_fields_add': value['childInheritFieldsAdd'],
|
||||
'child_inherit_fields_remove': value['childInheritFieldsRemove'],
|
||||
'child_inherit_fields_set': value['childInheritFieldsSet'],
|
||||
'child_inherit_fields_remove_all': value['childInheritFieldsRemoveAll'],
|
||||
'substitute_children': value['substituteChildren'],
|
||||
'substitute_siblings': value['substituteSiblings'],
|
||||
'ignore_shopping': value['ignoreShopping'],
|
||||
'on_hand': value['onHand'],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ export * from './ExportRequest';
|
||||
export * from './FdcQuery';
|
||||
export * from './FdcQueryFoods';
|
||||
export * from './Food';
|
||||
export * from './FoodBatchUpdate';
|
||||
export * from './FoodInheritField';
|
||||
export * from './FoodShoppingUpdate';
|
||||
export * from './FoodSimple';
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
</v-card-actions>
|
||||
|
||||
<v-card-text v-if="genericModel.model.name == 'AiLog'">
|
||||
{{$t('MonthlyCreditsUsed')}} ({{ useUserPreferenceStore().activeSpace.aiMonthlyCreditsUsed }} / {{ useUserPreferenceStore().activeSpace.aiCreditsMonthly }})
|
||||
{{$t('AiCreditsBalance')}} : {{useUserPreferenceStore().activeSpace.aiCreditsBalance}}
|
||||
{{ $t('MonthlyCreditsUsed') }} ({{ useUserPreferenceStore().activeSpace.aiMonthlyCreditsUsed }} / {{ useUserPreferenceStore().activeSpace.aiCreditsMonthly }})
|
||||
{{ $t('AiCreditsBalance') }} : {{ useUserPreferenceStore().activeSpace.aiCreditsBalance }}
|
||||
<v-progress-linear :model-value="useUserPreferenceStore().activeSpace.aiMonthlyCreditsUsed" :max="useUserPreferenceStore().activeSpace.aiCreditsMonthly"></v-progress-linear>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
@@ -65,6 +65,9 @@
|
||||
<v-icon icon="fa-solid fa-ellipsis-v"></v-icon>
|
||||
<v-menu activator="parent" close-on-content-click>
|
||||
<v-list density="compact" class="pt-1 pb-1" activatable>
|
||||
<v-list-item prepend-icon="fa-solid fa-list-check" @click="batchEditDialog = true" v-if="genericModel.model.name == 'Food'">
|
||||
{{ $t('BatchEdit') }}
|
||||
</v-list-item>
|
||||
<v-list-item prepend-icon="fa-solid fa-arrows-to-dot" @click="batchMergeDialog = true" v-if="genericModel.model.isMerge">
|
||||
{{ $t('Merge') }}
|
||||
</v-list-item>
|
||||
@@ -76,8 +79,8 @@
|
||||
</v-btn>
|
||||
</template>
|
||||
<template v-slot:item.space="{ item }" v-if="genericModel.model.name == 'AiProvider'">
|
||||
<v-chip label v-if="item.space == null" color="success">{{$t('Global')}}</v-chip>
|
||||
<v-chip label v-else color="info">{{$t('Space')}}</v-chip>
|
||||
<v-chip label v-if="item.space == null" color="success">{{ $t('Global') }}</v-chip>
|
||||
<v-chip label v-else color="info">{{ $t('Space') }}</v-chip>
|
||||
</template>
|
||||
<template v-slot:item.action="{ item }">
|
||||
<v-btn class="float-right" icon="$menu" variant="plain">
|
||||
@@ -117,10 +120,13 @@
|
||||
</v-row>
|
||||
|
||||
<batch-delete-dialog :items="selectedItems" :model="props.model" v-model="batchDeleteDialog" activator="model"
|
||||
@change="loadItems({page: page, itemsPerPage: pageSize, search: query})"></batch-delete-dialog>
|
||||
@change="loadItems({page: page, itemsPerPage: pageSize, search: query})"></batch-delete-dialog>
|
||||
|
||||
<model-merge-dialog :model="model" :source="selectedItems" v-model="batchMergeDialog" activator="model"
|
||||
@change="loadItems({page: page, itemsPerPage: pageSize, search: query})"></model-merge-dialog>
|
||||
<model-merge-dialog :model="model" :source="selectedItems" v-model="batchMergeDialog" activator="model"
|
||||
@change="loadItems({page: page, itemsPerPage: pageSize, search: query})"></model-merge-dialog>
|
||||
|
||||
<batch-edit-food-dialog :items="selectedItems" v-model="batchEditDialog" v-if="model == 'Food'" activator="model"
|
||||
@change="loadItems({page: page, itemsPerPage: pageSize, search: query})"></batch-edit-food-dialog>
|
||||
|
||||
</v-container>
|
||||
</template>
|
||||
@@ -144,6 +150,7 @@ import RecipeShareDialog from "@/components/dialogs/RecipeShareDialog.vue";
|
||||
import AddToShoppingDialog from "@/components/dialogs/AddToShoppingDialog.vue";
|
||||
import BatchDeleteDialog from "@/components/dialogs/BatchDeleteDialog.vue";
|
||||
import {useRouteQuery} from "@vueuse/router";
|
||||
import BatchEditFoodDialog from "@/components/dialogs/BatchEditFoodDialog.vue";
|
||||
|
||||
const {t} = useI18n()
|
||||
const router = useRouter()
|
||||
@@ -172,6 +179,7 @@ const selectedItems = ref([] as EditorSupportedTypes[])
|
||||
|
||||
const batchDeleteDialog = ref(false)
|
||||
const batchMergeDialog = ref(false)
|
||||
const batchEditDialog = ref(false)
|
||||
|
||||
// data
|
||||
const loading = ref(false);
|
||||
@@ -215,7 +223,7 @@ function loadItems(options: VDataTableUpdateOptions) {
|
||||
page.value = options.page
|
||||
pageSize.value = options.itemsPerPage
|
||||
|
||||
genericModel.value.list({ query: query.value, page: options.page, pageSize: pageSize.value }).then((r: any) => {
|
||||
genericModel.value.list({query: query.value, page: options.page, pageSize: pageSize.value}).then((r: any) => {
|
||||
items.value = r.results
|
||||
itemCount.value = r.count
|
||||
}).catch((err: any) => {
|
||||
|
||||
Reference in New Issue
Block a user