From 6224e38138dcde352357c7f90e661bddbde20449 Mon Sep 17 00:00:00 2001 From: smilerz Date: Fri, 23 Feb 2024 13:27:59 -0600 Subject: [PATCH] add filter for automation type on automation API --- cookbook/views/api.py | 119 +++++++++++++++++++++-------------- vue/src/utils/models.js | 2 +- vue/src/utils/openapi/api.ts | 38 ++++++----- 3 files changed, 97 insertions(+), 62 deletions(-) diff --git a/cookbook/views/api.py b/cookbook/views/api.py index bd38483a2..88d492ecc 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -30,7 +30,6 @@ from django.http import FileResponse, HttpResponse, JsonResponse from django.shortcuts import get_object_or_404, redirect from django.urls import reverse from django.utils import timezone -from django.utils.timezone import make_aware from django.utils.translation import gettext as _ from django_scopes import scopes_disabled from icalendar import Calendar, Event @@ -58,56 +57,36 @@ from cookbook.helper.HelperFunctions import str2bool from cookbook.helper.image_processing import handle_image from cookbook.helper.ingredient_parser import IngredientParser from cookbook.helper.open_data_importer import OpenDataImporter -from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsOwner, CustomIsOwnerReadOnly, - CustomIsShared, CustomIsSpaceOwner, CustomIsUser, - CustomRecipePermission, CustomTokenHasReadWriteScope, - CustomTokenHasScope, CustomUserPermission, - IsReadOnlyDRF, above_space_limit, group_required, - has_group_permission, is_space_owner, - switch_user_active_space) +from cookbook.helper.permission_helper import ( + CustomIsAdmin, CustomIsOwner, CustomIsOwnerReadOnly, CustomIsShared, CustomIsSpaceOwner, CustomIsUser, CustomRecipePermission, CustomTokenHasReadWriteScope, + CustomTokenHasScope, CustomUserPermission, IsReadOnlyDRF, above_space_limit, group_required, has_group_permission, is_space_owner, switch_user_active_space, +) from cookbook.helper.recipe_search import RecipeSearch -from cookbook.helper.recipe_url_import import (clean_dict, get_from_youtube_scraper, - get_images_from_soup) +from cookbook.helper.recipe_url_import import clean_dict, get_from_youtube_scraper, get_images_from_soup from cookbook.helper.scrapers.scrapers import text_scraper from cookbook.helper.shopping_helper import RecipeShoppingEditor, shopping_helper -from cookbook.models import (Automation, BookmarkletImport, CookLog, CustomFilter, ExportLog, Food, - FoodInheritField, FoodProperty, ImportLog, Ingredient, InviteLink, - Keyword, MealPlan, MealType, Property, PropertyType, Recipe, - RecipeBook, RecipeBookEntry, ShareLink, ShoppingList, - ShoppingListEntry, ShoppingListRecipe, Space, Step, Storage, - Supermarket, SupermarketCategory, SupermarketCategoryRelation, Sync, - SyncLog, Unit, UnitConversion, UserFile, UserPreference, UserSpace, - ViewLog) +from cookbook.models import ( + Automation, BookmarkletImport, CookLog, CustomFilter, ExportLog, Food, FoodInheritField, FoodProperty, ImportLog, Ingredient, InviteLink, Keyword, MealPlan, MealType, + Property, PropertyType, Recipe, RecipeBook, RecipeBookEntry, ShareLink, ShoppingList, ShoppingListEntry, ShoppingListRecipe, Space, Step, Storage, Supermarket, + SupermarketCategory, SupermarketCategoryRelation, Sync, SyncLog, Unit, UnitConversion, UserFile, UserPreference, UserSpace, ViewLog, +) from cookbook.provider.dropbox import Dropbox from cookbook.provider.local import Local from cookbook.provider.nextcloud import Nextcloud from cookbook.schemas import FilterSchema, QueryParam, QueryParamAutoSchema, TreeSchema -from cookbook.serializer import (AccessTokenSerializer, AutomationSerializer, - AutoMealPlanSerializer, BookmarkletImportListSerializer, - BookmarkletImportSerializer, CookLogSerializer, - CustomFilterSerializer, ExportLogSerializer, - FoodInheritFieldSerializer, FoodSerializer, - FoodShoppingUpdateSerializer, FoodSimpleSerializer, - GroupSerializer, ImportLogSerializer, IngredientSerializer, - IngredientSimpleSerializer, InviteLinkSerializer, - KeywordSerializer, MealPlanSerializer, MealTypeSerializer, - PropertySerializer, PropertyTypeSerializer, - RecipeBookEntrySerializer, RecipeBookSerializer, - RecipeExportSerializer, RecipeFromSourceSerializer, - RecipeImageSerializer, RecipeOverviewSerializer, RecipeSerializer, - RecipeShoppingUpdateSerializer, RecipeSimpleSerializer, - ShoppingListAutoSyncSerializer, ShoppingListEntrySerializer, - ShoppingListRecipeSerializer, ShoppingListSerializer, - SpaceSerializer, StepSerializer, StorageSerializer, - SupermarketCategoryRelationSerializer, - SupermarketCategorySerializer, SupermarketSerializer, - SyncLogSerializer, SyncSerializer, UnitConversionSerializer, - UnitSerializer, UserFileSerializer, UserPreferenceSerializer, - UserSerializer, UserSpaceSerializer, ViewLogSerializer, - ShoppingListEntryBulkSerializer) +from cookbook.serializer import ( + AccessTokenSerializer, AutomationSerializer, AutoMealPlanSerializer, BookmarkletImportListSerializer, BookmarkletImportSerializer, CookLogSerializer, CustomFilterSerializer, + ExportLogSerializer, FoodInheritFieldSerializer, FoodSerializer, FoodShoppingUpdateSerializer, FoodSimpleSerializer, GroupSerializer, ImportLogSerializer, + IngredientSerializer, IngredientSimpleSerializer, InviteLinkSerializer, KeywordSerializer, MealPlanSerializer, MealTypeSerializer, PropertySerializer, PropertyTypeSerializer, + RecipeBookEntrySerializer, RecipeBookSerializer, RecipeExportSerializer, RecipeFromSourceSerializer, RecipeImageSerializer, RecipeOverviewSerializer, RecipeSerializer, + RecipeShoppingUpdateSerializer, RecipeSimpleSerializer, ShoppingListAutoSyncSerializer, ShoppingListEntryBulkSerializer, ShoppingListEntrySerializer, + ShoppingListRecipeSerializer, ShoppingListSerializer, SpaceSerializer, StepSerializer, StorageSerializer, SupermarketCategoryRelationSerializer, SupermarketCategorySerializer, + SupermarketSerializer, SyncLogSerializer, SyncSerializer, UnitConversionSerializer, UnitSerializer, UserFileSerializer, UserPreferenceSerializer, UserSerializer, + UserSpaceSerializer, ViewLogSerializer, +) from cookbook.views.import_export import get_integration from recipes import settings -from recipes.settings import FDC_API_KEY, DRF_THROTTLE_RECIPE_URL_IMPORT +from recipes.settings import DRF_THROTTLE_RECIPE_URL_IMPORT, FDC_API_KEY class StandardFilterMixin(ViewSetMixin): @@ -612,14 +591,19 @@ class FoodViewSet(viewsets.ModelViewSet, TreeMixin): response = requests.get(f'https://api.nal.usda.gov/fdc/v1/food/{food.fdc_id}?api_key={FDC_API_KEY}') if response.status_code == 429: - return JsonResponse({'msg': 'API Key Rate Limit reached/exceeded, see https://api.data.gov/docs/rate-limits/ for more information. Configure your key in Tandoor using environment FDC_API_KEY variable.'}, status=429, + return JsonResponse({'msg': 'API Key Rate Limit reached/exceeded, see https://api.data.gov/docs/rate-limits/ for more information. \ + Configure your key in Tandoor using environment FDC_API_KEY variable.'}, + status=429, json_dumps_params={'indent': 4}) if response.status_code != 200: return JsonResponse({'msg': f'Error while requesting FDC data using url https://api.nal.usda.gov/fdc/v1/food/{food.fdc_id}?api_key=****'}, status=response.status_code, json_dumps_params={'indent': 4}) food.properties_food_amount = 100 - food.properties_food_unit = Unit.objects.get_or_create(base_unit__iexact='g', space=self.request.space, defaults={'name': 'g', 'base_unit': 'g', 'space': self.request.space})[0] + food.properties_food_unit = Unit.objects.get_or_create( + base_unit__iexact='g', + space=self.request.space, + defaults={'name': 'g', 'base_unit': 'g', 'space': self.request.space})[0] food.save() try: @@ -1153,7 +1137,10 @@ class ShoppingListEntryViewSet(viewsets.ModelViewSet): permission_classes = [(CustomIsOwner | CustomIsShared) & CustomTokenHasReadWriteScope] query_params = [ QueryParam(name='id', description=_('Returns the shopping list entry with a primary key of id. Multiple values allowed.'), qtype='integer'), - QueryParam(name='checked', description=_('Filter shopping list entries on checked. [''true'', ''false'', ''both'', ''recent'']
- ''recent'' includes unchecked items and recently completed items.') + QueryParam( + name='checked', + description=_('Filter shopping list entries on checked. [''true'', ''false'', ''both'', ''recent'']
\ + - ''recent'' includes unchecked items and recently completed items.') ), QueryParam(name='supermarket', description=_('Returns the shopping list entries sorted by supermarket category order.'), qtype='integer'), ] @@ -1198,7 +1185,7 @@ class ShoppingListEntryViewSet(viewsets.ModelViewSet): if last_autosync: last_autosync = datetime.datetime.fromtimestamp(int(last_autosync) / 1000, datetime.timezone.utc) self.queryset = self.queryset.filter(updated_at__gte=last_autosync) - except: + except Exception: traceback.print_exc() # TODO once old shopping list is removed this needs updated to sharing users in preferences @@ -1323,12 +1310,52 @@ class UserFileViewSet(viewsets.ModelViewSet, StandardFilterMixin): class AutomationViewSet(viewsets.ModelViewSet, StandardFilterMixin): + """ + list: + optional parameters + + - **automation_type**: Return the Automations matching the automation type. Multiple values allowed. + + *Automation Types:* + - FS: Food Alias + - UA: Unit Alias + - KA: Keyword Alias + - DR: Description Replace + - IR: Instruction Replace + - NU: Never Unit + - TW: Transpose Words + - FR: Food Replace + - UR: Unit Replace + - NR: Name Replace + """ + queryset = Automation.objects serializer_class = AutomationSerializer permission_classes = [CustomIsUser & CustomTokenHasReadWriteScope] pagination_class = DefaultPagination + query_params = [ + QueryParam(name='automation_type', description=_('Return the Automations matching the automation type. Multiple values allowed.'), qtype='string'), + ] + schema = QueryParamAutoSchema() + + auto_type = { + 'FS': 'FOOD_ALIAS', + 'UA': 'UNIT_ALIAS', + 'KA': 'KEYWORD_ALIAS', + 'DR': 'DESCRIPTION_REPLACE', + 'IR': 'INSTRUCTION_REPLACE', + 'NU': 'NEVER_UNIT', + 'TW': 'TRANSPOSE_WORDS', + 'FR': 'FOOD_REPLACE', + 'UR': 'UNIT_REPLACE', + 'NR': 'NAME_REPLACE' + } + def get_queryset(self): + automation_type = self.request.query_params.getlist('automation_type', []) + if automation_type: + self.queryset = self.queryset.filter(type__in=[self.auto_type[x.upper()] for x in automation_type]) self.queryset = self.queryset.filter(space=self.request.space).all() return super().get_queryset() diff --git a/vue/src/utils/models.js b/vue/src/utils/models.js index 87278d9dc..42182baf8 100644 --- a/vue/src/utils/models.js +++ b/vue/src/utils/models.js @@ -518,7 +518,7 @@ export class Models { header_component: { name: "BetaWarning", }, - params: ["page", "pageSize", "options"], + params: ["automation_type", "page", "pageSize", "options"], }, create: { params: [["name", "description", "type", "param_1", "param_2", "param_3", "order", "disabled"]], diff --git a/vue/src/utils/openapi/api.ts b/vue/src/utils/openapi/api.ts index 69ace31e4..a508927da 100644 --- a/vue/src/utils/openapi/api.ts +++ b/vue/src/utils/openapi/api.ts @@ -6979,13 +6979,14 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration) }; }, /** - * + * optional parameters - **automation_type**: Return the Automations matching the automation type. Multiple values allowed. *Automation Types:* - FS: Food Alias - UA: Unit Alias - KA: Keyword Alias - DR: Description Replace - IR: Instruction Replace - NU: Never Unit - TW: Transpose Words - FR: Food Replace - UR: Unit Replace - NR: Name Replace + * @param {string} [automationType] Return the Automations matching the automation type. Multiple values allowed. * @param {number} [page] A page number within the paginated result set. * @param {number} [pageSize] Number of results to return per page. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - listAutomations: async (page?: number, pageSize?: number, options: any = {}): Promise => { + listAutomations: async (automationType?: string, page?: number, pageSize?: number, options: any = {}): Promise => { const localVarPath = `/api/automation/`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -6998,6 +6999,10 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration) const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; + if (automationType !== undefined) { + localVarQueryParameter['automation_type'] = automationType; + } + if (page !== undefined) { localVarQueryParameter['page'] = page; } @@ -7802,7 +7807,7 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration) /** * * @param {number} [id] Returns the shopping list entry with a primary key of id. Multiple values allowed. - * @param {string} [checked] Filter shopping list entries on checked. [true, false, both, <b>recent</b>]<br> - recent includes unchecked items and recently completed items. + * @param {string} [checked] Filter shopping list entries on checked. [true, false, both, <b>recent</b>]<br> - recent includes unchecked items and recently completed items. * @param {number} [supermarket] Returns the shopping list entries sorted by supermarket category order. * @param {*} [options] Override http request option. * @throws {RequiredError} @@ -13394,14 +13399,15 @@ export const ApiApiFp = function(configuration?: Configuration) { return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** - * + * optional parameters - **automation_type**: Return the Automations matching the automation type. Multiple values allowed. *Automation Types:* - FS: Food Alias - UA: Unit Alias - KA: Keyword Alias - DR: Description Replace - IR: Instruction Replace - NU: Never Unit - TW: Transpose Words - FR: Food Replace - UR: Unit Replace - NR: Name Replace + * @param {string} [automationType] Return the Automations matching the automation type. Multiple values allowed. * @param {number} [page] A page number within the paginated result set. * @param {number} [pageSize] Number of results to return per page. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async listAutomations(page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.listAutomations(page, pageSize, options); + async listAutomations(automationType?: string, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.listAutomations(automationType, page, pageSize, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** @@ -13621,7 +13627,7 @@ export const ApiApiFp = function(configuration?: Configuration) { /** * * @param {number} [id] Returns the shopping list entry with a primary key of id. Multiple values allowed. - * @param {string} [checked] Filter shopping list entries on checked. [true, false, both, <b>recent</b>]<br> - recent includes unchecked items and recently completed items. + * @param {string} [checked] Filter shopping list entries on checked. [true, false, both, <b>recent</b>]<br> - recent includes unchecked items and recently completed items. * @param {number} [supermarket] Returns the shopping list entries sorted by supermarket category order. * @param {*} [options] Override http request option. * @throws {RequiredError} @@ -15709,14 +15715,15 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?: return localVarFp.listAccessTokens(options).then((request) => request(axios, basePath)); }, /** - * + * optional parameters - **automation_type**: Return the Automations matching the automation type. Multiple values allowed. *Automation Types:* - FS: Food Alias - UA: Unit Alias - KA: Keyword Alias - DR: Description Replace - IR: Instruction Replace - NU: Never Unit - TW: Transpose Words - FR: Food Replace - UR: Unit Replace - NR: Name Replace + * @param {string} [automationType] Return the Automations matching the automation type. Multiple values allowed. * @param {number} [page] A page number within the paginated result set. * @param {number} [pageSize] Number of results to return per page. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - listAutomations(page?: number, pageSize?: number, options?: any): AxiosPromise { - return localVarFp.listAutomations(page, pageSize, options).then((request) => request(axios, basePath)); + listAutomations(automationType?: string, page?: number, pageSize?: number, options?: any): AxiosPromise { + return localVarFp.listAutomations(automationType, page, pageSize, options).then((request) => request(axios, basePath)); }, /** * @@ -15917,7 +15924,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?: /** * * @param {number} [id] Returns the shopping list entry with a primary key of id. Multiple values allowed. - * @param {string} [checked] Filter shopping list entries on checked. [true, false, both, <b>recent</b>]<br> - recent includes unchecked items and recently completed items. + * @param {string} [checked] Filter shopping list entries on checked. [true, false, both, <b>recent</b>]<br> - recent includes unchecked items and recently completed items. * @param {number} [supermarket] Returns the shopping list entries sorted by supermarket category order. * @param {*} [options] Override http request option. * @throws {RequiredError} @@ -18010,15 +18017,16 @@ export class ApiApi extends BaseAPI { } /** - * + * optional parameters - **automation_type**: Return the Automations matching the automation type. Multiple values allowed. *Automation Types:* - FS: Food Alias - UA: Unit Alias - KA: Keyword Alias - DR: Description Replace - IR: Instruction Replace - NU: Never Unit - TW: Transpose Words - FR: Food Replace - UR: Unit Replace - NR: Name Replace + * @param {string} [automationType] Return the Automations matching the automation type. Multiple values allowed. * @param {number} [page] A page number within the paginated result set. * @param {number} [pageSize] Number of results to return per page. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ApiApi */ - public listAutomations(page?: number, pageSize?: number, options?: any) { - return ApiApiFp(this.configuration).listAutomations(page, pageSize, options).then((request) => request(this.axios, this.basePath)); + public listAutomations(automationType?: string, page?: number, pageSize?: number, options?: any) { + return ApiApiFp(this.configuration).listAutomations(automationType, page, pageSize, options).then((request) => request(this.axios, this.basePath)); } /** @@ -18256,7 +18264,7 @@ export class ApiApi extends BaseAPI { /** * * @param {number} [id] Returns the shopping list entry with a primary key of id. Multiple values allowed. - * @param {string} [checked] Filter shopping list entries on checked. [true, false, both, <b>recent</b>]<br> - recent includes unchecked items and recently completed items. + * @param {string} [checked] Filter shopping list entries on checked. [true, false, both, <b>recent</b>]<br> - recent includes unchecked items and recently completed items. * @param {number} [supermarket] Returns the shopping list entries sorted by supermarket category order. * @param {*} [options] Override http request option. * @throws {RequiredError}