fixed times cooked in saved serarch and improved frontend query binding

This commit is contained in:
vabene1111
2025-11-19 21:02:16 +01:00
parent dd56bb4b35
commit 14696e3ce8
3 changed files with 35 additions and 13 deletions

View File

@@ -324,9 +324,9 @@ class RecipeSearch():
self._queryset = self._queryset.annotate(recent=Coalesce(Max(Case(When(pk__in=num_recent_recipes.values('recipe'), then='viewlog__pk'))), Value(0)))
def _favorite_recipes(self):
if self._sort_includes('favorite') or self._timescooked or self._timescooked_gte or self._timescooked_lte:
if self._sort_includes('favorite') or self._timescooked is not None or self._timescooked_gte is not None or self._timescooked_lte is not None:
less_than = self._timescooked_lte and not self._sort_includes('-favorite')
if less_than or self._timescooked == 0:
if less_than:
default = 1000
else:
default = 0
@@ -338,11 +338,11 @@ class RecipeSearch():
)
self._queryset = self._queryset.annotate(favorite=Coalesce(Subquery(favorite_recipes), default))
if self._timescooked:
if self._timescooked is not None:
self._queryset = self._queryset.filter(favorite=self._timescooked)
elif self._timescooked_lte:
elif self._timescooked_lte is not None:
self._queryset = self._queryset.filter(favorite__lte=int(self._timescooked_lte)).exclude(favorite=0)
elif self._timescooked_gte:
elif self._timescooked_gte is not None:
self._queryset = self._queryset.filter(favorite__gte=int(self._timescooked_gte))
def keyword_filters(self, **kwargs):

View File

@@ -184,7 +184,7 @@ import RecipeCard from "@/components/display/RecipeCard.vue";
import {useDisplay} from "vuetify";
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
import {useRouteQuery} from "@vueuse/router";
import {routeQueryDateTransformer, stringToBool, toNumberArray} from "@/utils/utils";
import {numberOrUndefinedTransformer, routeQueryDateTransformer, stringToBool, toNumberArray} from "@/utils/utils";
import RandomIcon from "@/components/display/RandomIcon.vue";
import {VSelect, VTextField, VNumberInput} from "vuetify/components";
import RatingField from "@/components/inputs/RatingField.vue";
@@ -759,27 +759,30 @@ const filters = ref({
label: `${t('Rating')} (${t('exact')})`,
hint: '',
enabled: false,
clearable: true,
default: undefined,
is: RatingField,
modelValue: useRouteQuery('rating', undefined, {transform: Number}),
modelValue: useRouteQuery('rating', undefined, {transform: numberOrUndefinedTransformer}),
},
ratingGte: {
id: 'ratingGte',
label: `${t('Rating')} (>=)`,
hint: '',
enabled: false,
clearable: true,
default: undefined,
is: RatingField,
modelValue: useRouteQuery('ratingGte', undefined, {transform: Number}),
modelValue: useRouteQuery('ratingGte', undefined, {transform: numberOrUndefinedTransformer}),
},
ratingLte: {
id: 'ratingLte',
label: `${t('Rating')} (<=)`,
hint: '',
enabled: false,
clearable: true,
default: undefined,
is: RatingField,
modelValue: useRouteQuery('ratingLte', undefined, {transform: Number}),
modelValue: useRouteQuery('ratingLte', undefined, {transform: numberOrUndefinedTransformer}),
},
timescooked: {
id: 'timescooked',
@@ -787,26 +790,29 @@ const filters = ref({
hint: 'Recipes that were cooked at least X times',
enabled: false,
default: undefined,
clearable: true,
is: VNumberInput,
modelValue: useRouteQuery('timescooked', undefined, {transform: Number}),
modelValue: useRouteQuery('timescooked', undefined, {transform: numberOrUndefinedTransformer}),
},
timescookedGte: {
id: 'timescookedGte',
label: `${t('times_cooked')} (>=)`,
hint: '',
enabled: false,
clearable: true,
default: undefined,
is: VNumberInput,
modelValue: useRouteQuery('timescookedGte', undefined, {transform: Number}),
modelValue: useRouteQuery('timescookedGte', undefined, {transform: numberOrUndefinedTransformer}),
},
timescookedLte: {
id: 'timescookedLte',
label: `${t('times_cooked')} (<=)`,
hint: '',
enabled: false,
clearable: true,
default: undefined,
is: VNumberInput,
modelValue: useRouteQuery('timescookedLte', undefined, {transform: Number}),
modelValue: useRouteQuery('timescookedLte', undefined, {transform: numberOrUndefinedTransformer}),
},
makenow: {
id: 'makenow',

View File

@@ -79,4 +79,20 @@ export function stringToBool(param: string): boolean | undefined {
export const routeQueryDateTransformer = {
get: (value: string | null | Date) => ((value == null) ? null : (new Date(value))),
set: (value: string | null | Date) => ((value == null) ? null : (DateTime.fromJSDate(new Date(value)).toISODate()))
}
}
/**
* routeQueryParam transformer for boolean fields converting string bools to real bools
*/
export const boolOrUndefinedTransformer = {
get: (value: string | null | undefined) => ((value == null) ? undefined : value == 'true'),
set: (value: boolean | null | undefined) => ((value == null) ? undefined : value.toString())
}
/**
* routeQueryParam transformer for number fields converting string numbers to real numbers and allowing undefined for resettable parameters
*/
export const numberOrUndefinedTransformer = {
get: (value: string | null | undefined) => ((value == null) ? undefined : Number(value)),
set: (value: string | null | undefined) => ((value == null) ? undefined : value.toString())
}