Merge pull request #1374 from smilerz/patch-updated-search
fix sort by new and show recent recipes
This commit is contained in:
commit
890817ef6d
@ -85,6 +85,7 @@ class RecipeSearch():
|
|||||||
self._queryset = queryset
|
self._queryset = queryset
|
||||||
self.recently_viewed_recipes(self._last_viewed)
|
self.recently_viewed_recipes(self._last_viewed)
|
||||||
self._favorite_recipes()
|
self._favorite_recipes()
|
||||||
|
self._new_recipes()
|
||||||
# self._last_viewed()
|
# self._last_viewed()
|
||||||
# self._last_cooked()
|
# self._last_cooked()
|
||||||
self.keyword_filters(keywords=self._keywords, operator=self._keywords_or)
|
self.keyword_filters(keywords=self._keywords, operator=self._keywords_or)
|
||||||
@ -110,6 +111,8 @@ class RecipeSearch():
|
|||||||
order = [] # TODO add user preferences here: name, date cooked, rating, times cooked, date created, date viewed, random
|
order = [] # TODO add user preferences here: name, date cooked, rating, times cooked, date created, date viewed, random
|
||||||
if '-recent' in self.orderby and self._last_viewed:
|
if '-recent' in self.orderby and self._last_viewed:
|
||||||
order += ['-recent']
|
order += ['-recent']
|
||||||
|
if '-new_recipe' in self.orderby and self._new:
|
||||||
|
order += ['-new_recipe']
|
||||||
|
|
||||||
if '-rank' in self.orderby and '-simularity' in self.orderby:
|
if '-rank' in self.orderby and '-simularity' in self.orderby:
|
||||||
self._queryset = self._queryset.annotate(score=Sum(F('rank')+F('simularity')))
|
self._queryset = self._queryset.annotate(score=Sum(F('rank')+F('simularity')))
|
||||||
@ -153,6 +156,16 @@ class RecipeSearch():
|
|||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.filter(name__icontains=self._string)
|
self._queryset = self._queryset.filter(name__icontains=self._string)
|
||||||
|
|
||||||
|
def _new_recipes(self, new_days=7):
|
||||||
|
# TODO make new days a user-setting
|
||||||
|
if not self._new:
|
||||||
|
return
|
||||||
|
self._queryset = (
|
||||||
|
self._queryset.annotate(new_recipe=Case(
|
||||||
|
When(created_at__gte=(timezone.now() - timedelta(days=new_days)), then=('pk')), default=Value(0), ))
|
||||||
|
)
|
||||||
|
self.orderby += ['-new_recipe']
|
||||||
|
|
||||||
def recently_viewed_recipes(self, last_viewed=None):
|
def recently_viewed_recipes(self, last_viewed=None):
|
||||||
if not last_viewed:
|
if not last_viewed:
|
||||||
return
|
return
|
||||||
|
@ -502,7 +502,6 @@ class NutritionInformationSerializer(serializers.ModelSerializer):
|
|||||||
proteins = CustomDecimalField()
|
proteins = CustomDecimalField()
|
||||||
calories = CustomDecimalField()
|
calories = CustomDecimalField()
|
||||||
|
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
validated_data['space'] = self.context['request'].space
|
validated_data['space'] = self.context['request'].space
|
||||||
return super().create(validated_data)
|
return super().create(validated_data)
|
||||||
@ -534,7 +533,7 @@ class RecipeBaseSerializer(WritableNestedModelSerializer):
|
|||||||
|
|
||||||
# TODO make days of new recipe a setting
|
# TODO make days of new recipe a setting
|
||||||
def is_recipe_new(self, obj):
|
def is_recipe_new(self, obj):
|
||||||
if obj.created_at > (timezone.now() - timedelta(days=7)):
|
if getattr(obj, 'new_recipe', None) or obj.created_at > (timezone.now() - timedelta(days=7)):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
@ -16,17 +16,17 @@
|
|||||||
<b-button variant="light" v-b-tooltip.hover :title="$t('Random Recipes')" @click="openRandom()">
|
<b-button variant="light" v-b-tooltip.hover :title="$t('Random Recipes')" @click="openRandom()">
|
||||||
<i class="fas fa-dice-five" style="font-size: 1.5em"></i>
|
<i class="fas fa-dice-five" style="font-size: 1.5em"></i>
|
||||||
</b-button>
|
</b-button>
|
||||||
<b-button v-b-toggle.collapse_advanced_search v-b-tooltip.hover :title="$t('Advanced Settings')" v-bind:variant="searchFiltered(true) ? 'primary' : 'danger'">
|
<b-button v-b-toggle.collapse_advanced_search v-b-tooltip.hover :title="$t('Advanced Settings')" v-bind:variant="!searchFiltered(true) ? 'primary' : 'danger'">
|
||||||
<!-- TODO consider changing this icon to a filter -->
|
<!-- TODO consider changing this icon to a filter -->
|
||||||
<i class="fas fa-caret-down" v-if="!ui.advanced_search_visible"></i>
|
<i class="fas fa-caret-down" v-if="!search.advanced_search_visible"></i>
|
||||||
<i class="fas fa-caret-up" v-if="ui.advanced_search_visible"></i>
|
<i class="fas fa-caret-up" v-if="search.advanced_search_visible"></i>
|
||||||
</b-button>
|
</b-button>
|
||||||
</b-input-group-append>
|
</b-input-group-append>
|
||||||
</b-input-group>
|
</b-input-group>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<b-collapse id="collapse_advanced_search" class="mt-2 shadow-sm" v-model="ui.advanced_search_visible">
|
<b-collapse id="collapse_advanced_search" class="mt-2 shadow-sm" v-model="search.advanced_search_visible">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body p-4">
|
<div class="card-body p-4">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -250,7 +250,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col col-md-12">
|
<div class="col col-md-12">
|
||||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); grid-gap: 0.8rem">
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); grid-gap: 0.8rem">
|
||||||
<template v-if="!searchFiltered">
|
<template v-if="!searchFiltered()">
|
||||||
<recipe-card v-bind:key="`mp_${m.id}`" v-for="m in meal_plans" :recipe="m.recipe" :meal_plan="m" :footer_text="m.meal_type_name" footer_icon="far fa-calendar-alt"></recipe-card>
|
<recipe-card v-bind:key="`mp_${m.id}`" v-for="m in meal_plans" :recipe="m.recipe" :meal_plan="m" :footer_text="m.meal_type_name" footer_icon="far fa-calendar-alt"></recipe-card>
|
||||||
</template>
|
</template>
|
||||||
<recipe-card v-for="r in recipes" v-bind:key="r.id" :recipe="r" :footer_text="isRecentOrNew(r)[0]" :footer_icon="isRecentOrNew(r)[1]"> </recipe-card>
|
<recipe-card v-for="r in recipes" v-bind:key="r.id" :recipe="r" :footer_text="isRecentOrNew(r)[0]" :footer_icon="isRecentOrNew(r)[1]"> </recipe-card>
|
||||||
@ -309,6 +309,7 @@ export default {
|
|||||||
last_viewed_recipes: [],
|
last_viewed_recipes: [],
|
||||||
|
|
||||||
search: {
|
search: {
|
||||||
|
advanced_search_visible: false,
|
||||||
search_input: "",
|
search_input: "",
|
||||||
search_internal: false,
|
search_internal: false,
|
||||||
search_keywords: [],
|
search_keywords: [],
|
||||||
@ -321,7 +322,6 @@ export default {
|
|||||||
pagination_page: 1,
|
pagination_page: 1,
|
||||||
},
|
},
|
||||||
ui: {
|
ui: {
|
||||||
advanced_search_visible: false,
|
|
||||||
show_meal_plan: true,
|
show_meal_plan: true,
|
||||||
meal_plan_days: 0,
|
meal_plan_days: 0,
|
||||||
recently_viewed: 5,
|
recently_viewed: 5,
|
||||||
@ -419,7 +419,6 @@ export default {
|
|||||||
},
|
},
|
||||||
"ui.tree_select": function () {
|
"ui.tree_select": function () {
|
||||||
if (this.ui.tree_select && !this.facets?.Keywords && !this.facets?.Foods) {
|
if (this.ui.tree_select && !this.facets?.Keywords && !this.facets?.Foods) {
|
||||||
console.log("i changed to true")
|
|
||||||
this.getFacets(this.facets?.hash)
|
this.getFacets(this.facets?.hash)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -436,30 +435,7 @@ export default {
|
|||||||
// this.genericAPI inherited from ApiMixin
|
// this.genericAPI inherited from ApiMixin
|
||||||
refreshData: function (random) {
|
refreshData: function (random) {
|
||||||
this.random_search = random
|
this.random_search = random
|
||||||
let params = {
|
let params = this.buildParams()
|
||||||
query: this.search.search_input,
|
|
||||||
keywords: this.search.search_keywords.map(function (A) {
|
|
||||||
return A?.["id"] ?? A
|
|
||||||
}),
|
|
||||||
foods: this.search.search_foods.map(function (A) {
|
|
||||||
return A?.["id"] ?? A
|
|
||||||
}),
|
|
||||||
rating: this.search.search_ratings,
|
|
||||||
books: this.search.search_books.map(function (A) {
|
|
||||||
return A["id"]
|
|
||||||
}),
|
|
||||||
keywordsOr: this.search.search_keywords_or,
|
|
||||||
foodsOr: this.search.search_foods_or,
|
|
||||||
booksOr: this.search.search_books_or,
|
|
||||||
internal: this.search.search_internal,
|
|
||||||
random: this.random_search,
|
|
||||||
_new: this.ui.sort_by_new,
|
|
||||||
page: this.search.pagination_page,
|
|
||||||
pageSize: this.search.page_size,
|
|
||||||
}
|
|
||||||
if (!this.searchFiltered) {
|
|
||||||
params.options = { query: { last_viewed: this.ui.recently_viewed } }
|
|
||||||
}
|
|
||||||
this.genericAPI(this.Models.RECIPE, this.Actions.LIST, params)
|
this.genericAPI(this.Models.RECIPE, this.Actions.LIST, params)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
window.scrollTo(0, 0)
|
window.scrollTo(0, 0)
|
||||||
@ -467,7 +443,7 @@ export default {
|
|||||||
|
|
||||||
this.facets = result.data.facets
|
this.facets = result.data.facets
|
||||||
this.recipes = this.removeDuplicates(result.data.results, (recipe) => recipe.id)
|
this.recipes = this.removeDuplicates(result.data.results, (recipe) => recipe.id)
|
||||||
if (!this.searchFiltered) {
|
if (!this.searchFiltered()) {
|
||||||
// if meal plans are being shown - filter out any meal plan recipes from the recipe list
|
// if meal plans are being shown - filter out any meal plan recipes from the recipe list
|
||||||
let mealPlans = []
|
let mealPlans = []
|
||||||
this.meal_plans.forEach((x) => mealPlans.push(x.recipe.id))
|
this.meal_plans.forEach((x) => mealPlans.push(x.recipe.id))
|
||||||
@ -555,11 +531,33 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
showSQL: function () {
|
showSQL: function () {
|
||||||
// TODO refactor this so that it isn't a total copy of refreshData
|
let params = this.buildParams()
|
||||||
|
this.genericAPI(this.Models.RECIPE, this.Actions.LIST, params).then((result) => {})
|
||||||
|
},
|
||||||
|
// TODO refactor to combine with load KeywordChildren
|
||||||
|
loadFoodChildren({ action, parentNode, callback }) {
|
||||||
|
if (action === LOAD_CHILDREN_OPTIONS) {
|
||||||
|
if (this.facets?.cache_key) {
|
||||||
|
this.getFacets(this.facets.cache_key, "food", parentNode.id).then(callback())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
loadKeywordChildren({ action, parentNode, callback }) {
|
||||||
|
if (action === LOAD_CHILDREN_OPTIONS) {
|
||||||
|
if (this.facets?.cache_key) {
|
||||||
|
this.getFacets(this.facets.cache_key, "keyword", parentNode.id).then(callback())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
buildParams: function () {
|
||||||
let params = {
|
let params = {
|
||||||
query: this.search.search_input,
|
query: this.search.search_input,
|
||||||
keywords: this.search.search_keywords,
|
keywords: this.search.search_keywords.map(function (A) {
|
||||||
foods: this.search.search_foods,
|
return A?.["id"] ?? A
|
||||||
|
}),
|
||||||
|
foods: this.search.search_foods.map(function (A) {
|
||||||
|
return A?.["id"] ?? A
|
||||||
|
}),
|
||||||
rating: this.search.search_ratings,
|
rating: this.search.search_ratings,
|
||||||
books: this.search.search_books.map(function (A) {
|
books: this.search.search_books.map(function (A) {
|
||||||
return A["id"]
|
return A["id"]
|
||||||
@ -573,41 +571,22 @@ export default {
|
|||||||
page: this.search.pagination_page,
|
page: this.search.pagination_page,
|
||||||
pageSize: this.ui.page_size,
|
pageSize: this.ui.page_size,
|
||||||
}
|
}
|
||||||
if (!this.searchFiltered) {
|
if (!this.searchFiltered()) {
|
||||||
params.options = { query: { last_viewed: this.ui.recently_viewed, debug: true } }
|
params.options = { query: { last_viewed: this.ui.recently_viewed } }
|
||||||
} else {
|
|
||||||
params.options = { query: { debug: true } }
|
|
||||||
}
|
|
||||||
this.genericAPI(this.Models.RECIPE, this.Actions.LIST, params).then((result) => {})
|
|
||||||
},
|
|
||||||
// TODO remove
|
|
||||||
loadFoodChildren({ action, parentNode, callback }) {
|
|
||||||
if (action === LOAD_CHILDREN_OPTIONS) {
|
|
||||||
if (this.facets?.cache_key) {
|
|
||||||
this.getFacets(this.facets.cache_key, "food", parentNode.id).then(callback())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// TODO remove
|
|
||||||
loadKeywordChildren({ action, parentNode, callback }) {
|
|
||||||
if (action === LOAD_CHILDREN_OPTIONS) {
|
|
||||||
if (this.facets?.cache_key) {
|
|
||||||
this.getFacets(this.facets.cache_key, "keyword", parentNode.id).then(callback())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return params
|
||||||
},
|
},
|
||||||
searchFiltered: function (ignore_string = false) {
|
searchFiltered: function (ignore_string = false) {
|
||||||
let filtered =
|
let filtered =
|
||||||
this.search?.search_keywords?.length === 0 &&
|
this.search?.search_keywords?.length === 0 &&
|
||||||
this.search?.search_foods?.length === 0 &&
|
this.search?.search_foods?.length === 0 &&
|
||||||
this.search?.search_books?.length === 0 &&
|
this.search?.search_books?.length === 0 &&
|
||||||
// this.settings?.pagination_page === 1 &&
|
|
||||||
!this.random_search &&
|
!this.random_search &&
|
||||||
this.search?.search_ratings === undefined
|
this.search?.search_ratings === undefined
|
||||||
if (ignore_string) {
|
if (ignore_string) {
|
||||||
return filtered
|
return !filtered
|
||||||
} else {
|
} else {
|
||||||
return filtered && this.search?.search_input === ""
|
return !filtered && this.search?.search_input !== ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user