WIP search page

This commit is contained in:
vabene1111
2025-03-30 00:08:25 +01:00
parent 77195718d8
commit dd1975817e
5 changed files with 109 additions and 23 deletions

View File

@@ -49,7 +49,11 @@ class RecipeSearch():
self._search_prefs = SearchPreference()
self._string = self._params.get('query').strip(
) if self._params.get('query', None) else None
self._rating = self._params.get('rating', None)
self._rating_gte = self._params.get('rating_gte', None)
self._rating_lte = self._params.get('rating_lte', None)
self._keywords = {
'or': self._params.get('keywords_or', None) or self._params.get('keywords', None),
'and': self._params.get('keywords_and', None),
@@ -140,7 +144,7 @@ class RecipeSearch():
self.keyword_filters(**self._keywords)
self.food_filters(**self._foods)
self.book_filters(**self._books)
self.rating_filter(rating=self._rating)
self.rating_filter()
self.internal_filter(internal=self._internal)
self.step_filters(steps=self._steps)
self.unit_filters(units=self._units)
@@ -413,25 +417,16 @@ class RecipeSearch():
units = [units]
self._queryset = self._queryset.filter(steps__ingredients__unit__in=units)
def rating_filter(self, rating=None):
if rating or self._sort_includes('rating'):
lessthan = '-' in (rating or [])
reverse = 'rating' in (self._sort_order or []) and '-rating' not in (self._sort_order or [])
if lessthan or reverse:
default = 100
else:
default = 0
# TODO make ratings a settings user-only vs all-users
self._queryset = self._queryset.annotate(rating=Round(Avg(Case(When(cooklog__created_by=self._request.user, then='cooklog__rating'), default=default))))
if rating is None:
return
def rating_filter(self):
if self._rating or self._rating_lte or self._rating_gte or self._sort_includes('rating'):
self._queryset = self._queryset.annotate(rating=Round(Avg(Case(When(cooklog__created_by=self._request.user, then='cooklog__rating'), default=0))))
if rating == '0':
self._queryset = self._queryset.filter(rating=0)
elif lessthan:
self._queryset = self._queryset.filter(rating__lte=int(rating[1:])).exclude(rating=0)
else:
self._queryset = self._queryset.filter(rating__gte=int(rating))
if self._rating:
self._queryset = self._queryset.filter(rating=round(int(self._rating)))
elif self._rating_gte:
self._queryset = self._queryset.filter(rating__gte=int(self._rating_gte))
elif self._rating_lte:
self._queryset = self._queryset.filter(rating__gte=int(self._rating_lte)).exclude(rating=0)
def internal_filter(self, internal=None):
if not internal:

View File

@@ -1110,9 +1110,6 @@ class RecipePagination(PageNumberPagination):
OpenApiParameter(name='foods_and_not',
description=_('Food IDs, repeat for multiple. Exclude recipes with all of the foods.'), type=int,
many=True),
OpenApiParameter(name='units', description=_('ID of unit a recipe should have.'), type=int),
OpenApiParameter(name='rating', description=_(
'Rating a recipe should have or greater. [0 - 5] Negative value filters rating less than.'), type=int),
OpenApiParameter(name='books', description=_('ID of book a recipe should be in. For multiple repeat parameter.'),
type=int, many=True),
OpenApiParameter(name='books_or',
@@ -1127,9 +1124,15 @@ class RecipePagination(PageNumberPagination):
OpenApiParameter(name='books_and_not',
description=_('Book IDs, repeat for multiple. Exclude recipes with all of the books.'), type=int,
many=True),
OpenApiParameter(name='units', description=_('ID of unit a recipe should have.'), type=int),
OpenApiParameter(name='internal',
description=_('If only internal recipes should be returned. [''true''/''<b>false</b>'']'),
type=bool),
OpenApiParameter(name='rating', description=_( 'Exact rating of recipe'), type=int),
OpenApiParameter(name='rating_gte', description=_( 'Rating a recipe should have or greater. '), type=int),
OpenApiParameter(name='rating_lte', description=_( 'Rating a recipe should have or smaller.'), type=int),
OpenApiParameter(name='random',
description=_('Returns the results in randomized order. [''true''/''<b>false</b>'']')),
OpenApiParameter(name='new',

View File

@@ -0,0 +1,26 @@
<template>
<v-input label="Test" hint="Test hint" persistent-hint>
<template #prepend v-if="$slots.prepend">
<slot name="prepend">
</slot>
</template>
<v-rating v-model="model"></v-rating>
<template #append v-if="$slots.append">
<slot name="append">
</slot>
</template>
</v-input>
</template>
<script setup lang="ts">
const model = defineModel<boolean>({required: true})
</script>
<style scoped>
</style>

View File

@@ -1217,6 +1217,8 @@ export interface ApiRecipeListRequest {
query?: string;
random?: string;
rating?: number;
ratingGte?: number;
ratingLte?: number;
timescooked?: number;
units?: number;
updatedon?: string;
@@ -8880,6 +8882,14 @@ export class ApiApi extends runtime.BaseAPI {
queryParameters['rating'] = requestParameters['rating'];
}
if (requestParameters['ratingGte'] != null) {
queryParameters['rating_gte'] = requestParameters['ratingGte'];
}
if (requestParameters['ratingLte'] != null) {
queryParameters['rating_lte'] = requestParameters['ratingLte'];
}
if (requestParameters['timescooked'] != null) {
queryParameters['timescooked'] = requestParameters['timescooked'];
}

View File

@@ -154,12 +154,14 @@ import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
import {useRouteQuery} from "@vueuse/router";
import {toNumberArray} from "@/utils/utils";
import RandomIcon from "@/components/display/RandomIcon.vue";
import {VRating, VSelect} from "vuetify/components";
import RatingField from "@/components/inputs/RatingField.vue";
const {t} = useI18n()
const router = useRouter()
const {mdAndUp} = useDisplay()
const query = useRouteQuery('query', "",)
const query = useRouteQuery('query', "")
const page = useRouteQuery('page', 1, {transform: Number})
const pageSize = useRouteQuery('pageSize', useUserPreferenceStore().deviceSettings.general_tableItemsPerPage, {transform: Number})
@@ -323,6 +325,56 @@ const filters = ref({
object: false,
searchOnLoad: true
},
units: {
value: 'units',
label: 'Unit (any)',
hint: 'Recipes that contain any of the given units',
enabled: false,
default: [],
is: ModelSelect,
model: 'Unit',
modelValue: useRouteQuery('units', [], {transform: toNumberArray}),
mode: 'tags',
object: false,
searchOnLoad: true
},
internal: {
value: 'internal',
label: 'Hide External',
hint: 'Hide external recipes',
enabled: false,
default: [],
is: VSelect,
items: [{value: true, title: 'Yes'}, {value: false, title: 'No'}],
modelValue: useRouteQuery('internal ', "false"),
},
rating: {
value: 'rating',
label: 'Rating (exact)',
hint: 'Recipes with the exact rating',
enabled: false,
default: 0,
is: RatingField,
modelValue: useRouteQuery('rating ', 0),
},
rating_gte: {
value: 'rating_gte',
label: 'Rating (>=)',
hint: 'Recipes with the given or a greater rating',
enabled: false,
default: 0,
is: RatingField,
modelValue: useRouteQuery('rating_gte ', 0),
},
rating_lte: {
value: 'rating_lte',
label: 'Rating (<=)',
hint: 'Recipes with the given or a smaller rating',
enabled: false,
default: 0,
is: RatingField,
modelValue: useRouteQuery('rating_lte ', 0),
},
})
/**