mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-11 00:58:32 -05:00
WIP
This commit is contained in:
@@ -33,12 +33,11 @@ class RecipeSearch():
|
|||||||
self._params = {**(params or {})}
|
self._params = {**(params or {})}
|
||||||
else:
|
else:
|
||||||
self._params = {**(params or {})}
|
self._params = {**(params or {})}
|
||||||
self._query = self._params.get('query', {}) or {}
|
|
||||||
if self._request.user.is_authenticated:
|
if self._request.user.is_authenticated:
|
||||||
self._search_prefs = request.user.searchpreference
|
self._search_prefs = request.user.searchpreference
|
||||||
else:
|
else:
|
||||||
self._search_prefs = SearchPreference()
|
self._search_prefs = SearchPreference()
|
||||||
self._string = params.get('string').strip() if params.get('string', None) else None
|
self._string = params.get('query').strip() if params.get('query', None) else None
|
||||||
self._rating = self._params.get('rating', None)
|
self._rating = self._params.get('rating', None)
|
||||||
self._keywords = {
|
self._keywords = {
|
||||||
'or': self._params.get('keywords_or', None) or self._params.get('keywords', None),
|
'or': self._params.get('keywords_or', None) or self._params.get('keywords', None),
|
||||||
@@ -62,14 +61,15 @@ class RecipeSearch():
|
|||||||
self._units = self._params.get('units', None)
|
self._units = self._params.get('units', None)
|
||||||
# TODO add created by
|
# TODO add created by
|
||||||
# TODO image exists
|
# TODO image exists
|
||||||
self._sort_order = self._params.get('sort_order', None) or self._query.get('sort_order', 0)
|
self._sort_order = self._params.get('sort_order', None)
|
||||||
self._internal = str2bool(self._params.get('internal', False))
|
self._internal = str2bool(self._params.get('internal', False))
|
||||||
self._random = str2bool(self._params.get('random', False))
|
self._random = str2bool(self._params.get('random', False))
|
||||||
self._new = str2bool(self._params.get('new', False))
|
self._new = str2bool(self._params.get('new', False))
|
||||||
self._last_viewed = int(self._params.get('last_viewed', 0) or self._query.get('last_viewed', 0))
|
self._last_viewed = int(self._params.get('last_viewed', 0))
|
||||||
|
self._include_children = str2bool(self._params.get('include_children', None))
|
||||||
self._timescooked = self._params.get('timescooked', None)
|
self._timescooked = self._params.get('timescooked', None)
|
||||||
self._lastcooked = self._params.get('lastcooked', None)
|
self._lastcooked = self._params.get('lastcooked', None)
|
||||||
self._makenow = self._params.get('makenow', None)
|
self._makenow = str2bool(self._params.get('makenow', None))
|
||||||
|
|
||||||
self._search_type = self._search_prefs.search or 'plain'
|
self._search_type = self._search_prefs.search or 'plain'
|
||||||
if self._string:
|
if self._string:
|
||||||
@@ -254,18 +254,25 @@ class RecipeSearch():
|
|||||||
|
|
||||||
keywords = Keyword.objects.filter(pk__in=kwargs[kw_filter])
|
keywords = Keyword.objects.filter(pk__in=kwargs[kw_filter])
|
||||||
if 'or' in kw_filter:
|
if 'or' in kw_filter:
|
||||||
f = Q(keywords__in=Keyword.include_descendants(keywords))
|
if self._include_children:
|
||||||
if 'not' in kw_filter:
|
f_or = Q(keywords__in=Keyword.include_descendants(keywords))
|
||||||
self._queryset = self._queryset.exclude(f)
|
|
||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.filter(f)
|
f_or = Q(keywords__in=keywords)
|
||||||
|
if 'not' in kw_filter:
|
||||||
|
self._queryset = self._queryset.exclude(f_or)
|
||||||
|
else:
|
||||||
|
self._queryset = self._queryset.filter(f_or)
|
||||||
elif 'and' in kw_filter:
|
elif 'and' in kw_filter:
|
||||||
recipes = Recipe.objects.all()
|
recipes = Recipe.objects.all()
|
||||||
for kw in keywords:
|
for kw in keywords:
|
||||||
if 'not' in kw_filter:
|
if self._include_children:
|
||||||
recipes = recipes.filter(keywords__in=kw.get_descendants_and_self())
|
f_and = Q(keywords__in=kw.get_descendants_and_self())
|
||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.filter(keywords__in=kw.get_descendants_and_self())
|
f_and = Q(keywords=kw)
|
||||||
|
if 'not' in kw_filter:
|
||||||
|
recipes = recipes.filter(f_and)
|
||||||
|
else:
|
||||||
|
self._queryset = self._queryset.filter(f_and)
|
||||||
if 'not' in kw_filter:
|
if 'not' in kw_filter:
|
||||||
self._queryset = self._queryset.exclude(id__in=recipes.values('id'))
|
self._queryset = self._queryset.exclude(id__in=recipes.values('id'))
|
||||||
|
|
||||||
@@ -280,18 +287,26 @@ class RecipeSearch():
|
|||||||
|
|
||||||
foods = Food.objects.filter(pk__in=kwargs[fd_filter])
|
foods = Food.objects.filter(pk__in=kwargs[fd_filter])
|
||||||
if 'or' in fd_filter:
|
if 'or' in fd_filter:
|
||||||
f = Q(steps__ingredients__food__in=Food.include_descendants(foods))
|
if self._include_children:
|
||||||
if 'not' in fd_filter:
|
f_or = Q(steps__ingredients__food__in=Food.include_descendants(foods))
|
||||||
self._queryset = self._queryset.exclude(f)
|
|
||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.filter(f)
|
f_or = Q(steps__ingredients__food__in=foods)
|
||||||
|
|
||||||
|
if 'not' in fd_filter:
|
||||||
|
self._queryset = self._queryset.exclude(f_or)
|
||||||
|
else:
|
||||||
|
self._queryset = self._queryset.filter(f_or)
|
||||||
elif 'and' in fd_filter:
|
elif 'and' in fd_filter:
|
||||||
recipes = Recipe.objects.all()
|
recipes = Recipe.objects.all()
|
||||||
for food in foods:
|
for food in foods:
|
||||||
if 'not' in fd_filter:
|
if self._include_children:
|
||||||
recipes = recipes.filter(steps__ingredients__food__in=food.get_descendants_and_self())
|
f_and = Q(steps__ingredients__food__in=food.get_descendants_and_self())
|
||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.filter(steps__ingredients__food__in=food.get_descendants_and_self())
|
f_and = Q(steps__ingredients__food=food)
|
||||||
|
if 'not' in fd_filter:
|
||||||
|
recipes = recipes.filter(f_and)
|
||||||
|
else:
|
||||||
|
self._queryset = self._queryset.filter(f_and)
|
||||||
if 'not' in fd_filter:
|
if 'not' in fd_filter:
|
||||||
self._queryset = self._queryset.exclude(id__in=recipes.values('id'))
|
self._queryset = self._queryset.exclude(id__in=recipes.values('id'))
|
||||||
|
|
||||||
|
|||||||
@@ -632,7 +632,7 @@ class RecipeViewSet(viewsets.ModelViewSet):
|
|||||||
pagination_class = RecipePagination
|
pagination_class = RecipePagination
|
||||||
|
|
||||||
query_params = [
|
query_params = [
|
||||||
QueryParam(name='string', description=_('Query string matched (fuzzy) against recipe name. In the future also fulltext search.')),
|
QueryParam(name='query', description=_('Query string matched (fuzzy) against recipe name. In the future also fulltext search.')),
|
||||||
QueryParam(name='keywords', description=_('ID of keyword a recipe should have. For multiple repeat parameter. Equivalent to keywords_or'), qtype='int'),
|
QueryParam(name='keywords', description=_('ID of keyword a recipe should have. For multiple repeat parameter. Equivalent to keywords_or'), qtype='int'),
|
||||||
QueryParam(name='keywords_or', description=_('Keyword IDs, repeat for multiple. Return recipes with any of the keywords'), qtype='int'),
|
QueryParam(name='keywords_or', description=_('Keyword IDs, repeat for multiple. Return recipes with any of the keywords'), qtype='int'),
|
||||||
QueryParam(name='keywords_and', description=_('Keyword IDs, repeat for multiple. Return recipes with all of the keywords.'), qtype='int'),
|
QueryParam(name='keywords_and', description=_('Keyword IDs, repeat for multiple. Return recipes with all of the keywords.'), qtype='int'),
|
||||||
@@ -668,10 +668,7 @@ class RecipeViewSet(viewsets.ModelViewSet):
|
|||||||
if not (share and self.detail):
|
if not (share and self.detail):
|
||||||
self.queryset = self.queryset.filter(space=self.request.space)
|
self.queryset = self.queryset.filter(space=self.request.space)
|
||||||
|
|
||||||
if filter := (self.request.GET.get('query', {}) or {}).get('filter', None):
|
params = {x: self.request.GET.get(x) if len({**self.request.GET}[x]) == 1 else self.request.GET.getlist(x) for x in list(self.request.GET)}
|
||||||
params = {'filter': filter}
|
|
||||||
else:
|
|
||||||
params = {x: self.request.GET.get(x) if len({**self.request.GET}[x]) == 1 else self.request.GET.getlist(x) for x in list(self.request.GET)}
|
|
||||||
search = RecipeSearch(self.request, **params)
|
search = RecipeSearch(self.request, **params)
|
||||||
self.queryset = search.get_queryset(self.queryset).prefetch_related('cooklog_set')
|
self.queryset = search.get_queryset(self.queryset).prefetch_related('cooklog_set')
|
||||||
return self.queryset
|
return self.queryset
|
||||||
|
|||||||
@@ -474,7 +474,7 @@
|
|||||||
|
|
||||||
<div class="row align-content-center">
|
<div class="row align-content-center">
|
||||||
<div class="col col-md-6" style="margin-top: 2vh">
|
<div class="col col-md-6" style="margin-top: 2vh">
|
||||||
<b-dropdown id="sortby" split :text="$t('sort_by')" variant="link" class="m-0 p-0">
|
<b-dropdown id="sortby" :text="$t('sort_by')" variant="link" toggle-class="text-decoration-none " class="m-0 p-0">
|
||||||
<div v-for="o in sortOptions" :key="o.id">
|
<div v-for="o in sortOptions" :key="o.id">
|
||||||
<b-dropdown-item
|
<b-dropdown-item
|
||||||
v-on:click="
|
v-on:click="
|
||||||
@@ -490,7 +490,7 @@
|
|||||||
<div class="col col-md-6 text-right" style="margin-top: 2vh">
|
<div class="col col-md-6 text-right" style="margin-top: 2vh">
|
||||||
<span class="text-muted">
|
<span class="text-muted">
|
||||||
{{ $t("Page") }} {{ search.pagination_page }}/{{ Math.ceil(pagination_count / ui.page_size) }}
|
{{ $t("Page") }} {{ search.pagination_page }}/{{ Math.ceil(pagination_count / ui.page_size) }}
|
||||||
<a href="#" @click="resetSearch"><i class="fas fa-times-circle"></i> {{ $t("Reset") }}</a>
|
<a href="#" @click="resetSearch()"><i class="fas fa-times-circle"></i> {{ $t("Reset") }}</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -616,6 +616,7 @@ export default {
|
|||||||
show_timescooked: false,
|
show_timescooked: false,
|
||||||
show_makenow: false,
|
show_makenow: false,
|
||||||
show_lastcooked: false,
|
show_lastcooked: false,
|
||||||
|
include_children: true,
|
||||||
},
|
},
|
||||||
pagination_count: 0,
|
pagination_count: 0,
|
||||||
random_search: false,
|
random_search: false,
|
||||||
@@ -799,6 +800,19 @@ export default {
|
|||||||
"ui.page_size": _debounce(function () {
|
"ui.page_size": _debounce(function () {
|
||||||
this.refreshData(false)
|
this.refreshData(false)
|
||||||
}, 300),
|
}, 300),
|
||||||
|
expertMode: function (newVal, oldVal) {
|
||||||
|
if (!newVal) {
|
||||||
|
this.search.search_keywords = this.search.search_keywords.map((x) => {
|
||||||
|
return { ...x, not: false }
|
||||||
|
})
|
||||||
|
this.search.search_foods = this.search.search_foods.map((x) => {
|
||||||
|
return { ...x, not: false }
|
||||||
|
})
|
||||||
|
this.search.search_books = this.search.search_books.map((x) => {
|
||||||
|
return { ...x, not: false }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// this.genericAPI inherited from ApiMixin
|
// this.genericAPI inherited from ApiMixin
|
||||||
@@ -817,7 +831,6 @@ export default {
|
|||||||
this.meal_plans.forEach((x) => mealPlans.push(x.recipe.id))
|
this.meal_plans.forEach((x) => mealPlans.push(x.recipe.id))
|
||||||
this.recipes = this.recipes.filter((recipe) => !mealPlans.includes(recipe.id))
|
this.recipes = this.recipes.filter((recipe) => !mealPlans.includes(recipe.id))
|
||||||
}
|
}
|
||||||
console.log(result.data)
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.$nextTick(function () {
|
this.$nextTick(function () {
|
||||||
@@ -997,7 +1010,7 @@ export default {
|
|||||||
...this.addFields("foods"),
|
...this.addFields("foods"),
|
||||||
...this.addFields("books"),
|
...this.addFields("books"),
|
||||||
units: this.search.search_units,
|
units: this.search.search_units,
|
||||||
string: this.search.search_input,
|
query: this.search.search_input,
|
||||||
rating: rating,
|
rating: rating,
|
||||||
internal: this.search.search_internal,
|
internal: this.search.search_internal,
|
||||||
random: this.random_search,
|
random: this.random_search,
|
||||||
@@ -1011,6 +1024,7 @@ export default {
|
|||||||
|
|
||||||
params.options.query = {
|
params.options.query = {
|
||||||
sort_order: this.search.sort_order.map((x) => x.value),
|
sort_order: this.search.sort_order.map((x) => x.value),
|
||||||
|
include_children: this.ui.include_children,
|
||||||
}
|
}
|
||||||
if (!this.searchFiltered()) {
|
if (!this.searchFiltered()) {
|
||||||
params.options.query.last_viewed = this.ui.recently_viewed
|
params.options.query.last_viewed = this.ui.recently_viewed
|
||||||
@@ -1068,10 +1082,12 @@ export default {
|
|||||||
;["page", "pageSize"].forEach((key) => {
|
;["page", "pageSize"].forEach((key) => {
|
||||||
delete search[key]
|
delete search[key]
|
||||||
})
|
})
|
||||||
|
search = { ...search, ...search.options.query }
|
||||||
let params = {
|
let params = {
|
||||||
name: filtername,
|
name: filtername,
|
||||||
search: JSON.stringify(search),
|
search: JSON.stringify(search),
|
||||||
}
|
}
|
||||||
|
console.log("saved search", search)
|
||||||
|
|
||||||
this.genericAPI(this.Models.CUSTOM_FILTER, this.Actions.CREATE, params)
|
this.genericAPI(this.Models.CUSTOM_FILTER, this.Actions.CREATE, params)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
|
|||||||
@@ -325,5 +325,6 @@
|
|||||||
"search_rank": "Search Rank",
|
"search_rank": "Search Rank",
|
||||||
"make_now": "Make Now",
|
"make_now": "Make Now",
|
||||||
"recipe_filter": "Recipe Filter",
|
"recipe_filter": "Recipe Filter",
|
||||||
"book_filter_help": "Include recipes from recipe filter instead of assigning each recipe"
|
"book_filter_help": "Include recipes from recipe filter instead of assigning each recipe",
|
||||||
|
"filter": "Filter"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -441,7 +441,7 @@ export class Models {
|
|||||||
apiName: "Recipe",
|
apiName: "Recipe",
|
||||||
list: {
|
list: {
|
||||||
params: [
|
params: [
|
||||||
"string",
|
"query",
|
||||||
"keywords",
|
"keywords",
|
||||||
"keywords_or",
|
"keywords_or",
|
||||||
"keywords_and",
|
"keywords_and",
|
||||||
|
|||||||
Reference in New Issue
Block a user