From 2b5aec5d0aaa50dc8638e995913fad1888510253 Mon Sep 17 00:00:00 2001 From: smilerz Date: Fri, 18 Feb 2022 09:08:36 -0600 Subject: [PATCH] resolved loading custom filter when not in expert mode --- cookbook/helper/recipe_search.py | 35 ++++++++------ .../RecipeSearchView/RecipeSearchView.vue | 46 +++++-------------- 2 files changed, 32 insertions(+), 49 deletions(-) diff --git a/cookbook/helper/recipe_search.py b/cookbook/helper/recipe_search.py index 98a137458..4ef2edaa0 100644 --- a/cookbook/helper/recipe_search.py +++ b/cookbook/helper/recipe_search.py @@ -74,13 +74,16 @@ class RecipeSearch(): self._createdon = self._params.get('createdon', None) self._updatedon = self._params.get('updatedon', None) self._viewedon = self._params.get('viewedon', None) + self._makenow = self._params.get('makenow', None) # this supports hidden feature to find recipes missing X ingredients - try: - self._makenow = int(makenow := self._params.get('makenow', None)) - except (ValueError, TypeError): - if str2bool(makenow): - self._makenow = 0 - else: + if type(self._makenow) == bool and self._makenow == True: + self._makenow = 0 + elif type(self._makenow) == str and self._makenow in ["yes", "true"]: + self._makenow = 0 + else: + try: + self._makenow = int(self._makenow) + except (ValueError, TypeError): self._makenow = None self._search_type = self._search_prefs.search or 'plain' @@ -495,21 +498,23 @@ class RecipeSearch(): self._filters += [Q(pk__in=self._fuzzy_match.values('pk'))] def _makenow_filter(self, missing=None): - if missing is None: + if missing is None or (type(missing) == bool and missing == False): return shopping_users = [*self._request.user.get_shopping_share(), self._request.user] onhand_filter = ( - Q(steps__ingredients__food__onhand_users__in=shopping_users, steps__ingredients__food__ignore_shopping=False) # food onhand - | Q(steps__ingredients__food__substitute__onhand_users__in=shopping_users, steps__ingredients__food__substitute__ignore_shopping=False) # or substitute food onhand + Q(steps__ingredients__food__onhand_users__in=shopping_users) # food onhand + | Q(steps__ingredients__food__substitute__onhand_users__in=shopping_users) # or substitute food onhand | Q(steps__ingredients__food__in=self.__children_substitute_filter(shopping_users)) | Q(steps__ingredients__food__in=self.__sibling_substitute_filter(shopping_users)) ) makenow_recipes = Recipe.objects.annotate( - count_food=Count('steps__ingredients__food', filter=Q(steps__ingredients__food__ignore_shopping=False, steps__ingredients__food__isnull=False), distinct=True), - count_onhand=Count('pk', filter=onhand_filter) - ).annotate(missingfood=F('count_food')-F('count_onhand')).filter(missingfood=missing) - self._queryset = self._queryset.filter(id__in=makenow_recipes.values('id')) + count_food=Count('steps__ingredients__food__pk', filter=Q(steps__ingredients__food__isnull=False), distinct=True), + count_onhand=Count('steps__ingredients__food__pk', filter=onhand_filter, distinct=True), + count_ignore_shopping=Count('steps__ingredients__food__pk', filter=Q(steps__ingredients__food__ignore_shopping=True, + steps__ingredients__food__recipe__isnull=True), distinct=True), + ).annotate(missingfood=F('count_food')-F('count_onhand')-F('count_ignore_shopping')).filter(missingfood=missing) + self._queryset = self._queryset.distinct().filter(id__in=makenow_recipes.values('id')) @staticmethod def __children_substitute_filter(shopping_users=None): @@ -520,7 +525,7 @@ class RecipeSearch(): ).annotate(child_onhand=Count((Substr(OuterRef('path'), 1, Food.steplen*OuterRef('depth'))), distinct=True)).values('child_onhand') return Food.objects.exclude( # list of foods that are onhand and children of: foods that are not onhand and are set to use children as substitutes Q(onhand_users__in=shopping_users) - | Q(ignore_shopping=True) + | Q(ignore_shopping=True, recipe__isnull=True) | Q(substitute__onhand_users__in=shopping_users) ).exclude(depth=1, numchild=0).filter(substitute_children=True ).annotate(child_onhand=Coalesce(Subquery(children_onhand_subquery), 0)) @@ -534,7 +539,7 @@ class RecipeSearch(): ).annotate(sibling_onhand=Count(Substr(OuterRef('path'), 1, Food.steplen*(OuterRef('depth')-1)), distinct=True)).values('sibling_onhand') return Food.objects.exclude( # list of foods that are onhand and siblings of: foods that are not onhand and are set to use siblings as substitutes Q(onhand_users__in=shopping_users) - | Q(ignore_shopping=True) + | Q(ignore_shopping=True, recipe__isnull=True) | Q(substitute__onhand_users__in=shopping_users) ).exclude(depth=1, numchild=0).filter(substitute_siblings=True ).annotate(sibling_onhand=Coalesce(Subquery(sibling_onhand_subquery), 0)) diff --git a/vue/src/apps/RecipeSearchView/RecipeSearchView.vue b/vue/src/apps/RecipeSearchView/RecipeSearchView.vue index 70b73e45b..bae535a62 100644 --- a/vue/src/apps/RecipeSearchView/RecipeSearchView.vue +++ b/vue/src/apps/RecipeSearchView/RecipeSearchView.vue @@ -1029,7 +1029,7 @@ export default { } // if selecting a filter, reset all current selections if (obj.var === "search_filter") { - this.resetSearch(this.search.search_filter) + this.resetSearch(true) } else { this.refreshData(false) } @@ -1057,36 +1057,14 @@ export default { this.search.createdon = undefined this.search.updatedon = undefined - let fieldnum = { - keywords: 1, - foods: 1, - books: 1, - } + this.search.keywords_fields = 1 + this.search.foods_fields = 1 + this.search.books_fields = 1 - if (filter) { - // this can be simplified by calling recipe API {query: {filter: filter_id}} but you lose loading all of the params into the UI - filter = JSON.parse(filter.search) - let fields = ["keywords", "foods", "books"] - let operators = ["_or", "_and", "_or_not", "_and_not"] - fields.forEach((field) => { - let x = 0 - operators.forEach((operator) => { - if (filter[`${field}${operator}`].length > 0) { - this.search[`search_${field}`][x].items = filter[`${field}${operator}`] - this.search[`search_${field}`][x].operator = operator.includes("or") - this.search[`search_${field}`][x].not = operator.includes("not") - x = x + 1 - } - }) - fieldnum[field] = fieldnum[field] + x - }) - } else { + if (!filter) { this.search.search_filter = undefined } - this.search.keywords_fields = fieldnum["keywords"] - this.search.foods_fields = fieldnum["foods"] - this.search.books_fields = fieldnum["books"] // this.search.rating_fields = 1 // this.search.units_fields = 1 this.refreshData(false) @@ -1150,6 +1128,11 @@ export default { return }, buildParams: function (random) { + let params = { options: { query: {} }, page: this.search.pagination_page, pageSize: this.ui.page_size } + if (this.search.search_filter) { + params.options.query.filter = this.search.search_filter.id + return params + } this.random_search = random let rating = this.search.search_rating if (rating !== undefined && !this.search.search_rating_gte) { @@ -1178,8 +1161,8 @@ export default { timescooked = timescooked * -1 } // when a filter is selected - added search params will be added to the filter - let params = { - options: { query: {} }, + params = { + ...params, ...this.addFields("keywords"), ...this.addFields("foods"), ...this.addFields("books"), @@ -1194,8 +1177,6 @@ export default { createdon: createdon, updatedon: updatedon, viewedon: viewedon, - page: this.search.pagination_page, - pageSize: this.ui.page_size, } params.options.query = { @@ -1206,9 +1187,6 @@ export default { params.options.query.num_recent = this.ui.recently_viewed //TODO refactor as num_recent params._new = this.ui.sort_by_new } - if (this.search.search_filter) { - params.options.query.filter = this.search.search_filter.id - } return params }, searchFiltered: function (ignore_string = false) {