mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-06 14:48:02 -05:00
implemented all filters in frontend
This commit is contained in:
@@ -206,9 +206,9 @@ class RecipeSearch():
|
|||||||
else:
|
else:
|
||||||
order += default_order
|
order += default_order
|
||||||
order[:] = [Lower('name').asc() if x ==
|
order[:] = [Lower('name').asc() if x ==
|
||||||
'name' else x for x in order]
|
'name' else x for x in order]
|
||||||
order[:] = [Lower('name').desc() if x ==
|
order[:] = [Lower('name').desc() if x ==
|
||||||
'-name' else x for x in order]
|
'-name' else x for x in order]
|
||||||
self.orderby = order
|
self.orderby = order
|
||||||
|
|
||||||
def string_filters(self, string=None):
|
def string_filters(self, string=None):
|
||||||
@@ -261,49 +261,41 @@ class RecipeSearch():
|
|||||||
if self._cookedon_lte:
|
if self._cookedon_lte:
|
||||||
self._queryset = self._queryset.filter(lastcooked__date__lte=self._cookedon_lte).exclude(lastcooked=default)
|
self._queryset = self._queryset.filter(lastcooked__date__lte=self._cookedon_lte).exclude(lastcooked=default)
|
||||||
elif self._cookedon_gte:
|
elif self._cookedon_gte:
|
||||||
self._queryset = self._queryset.filter(lastcooked__date__gte=self._cookedon_gte ).exclude(lastcooked=default)
|
self._queryset = self._queryset.filter(lastcooked__date__gte=self._cookedon_gte).exclude(lastcooked=default)
|
||||||
|
|
||||||
def _created_on_filter(self, created_date=None):
|
def _viewed_on_filter(self, viewed_date=None):
|
||||||
if created_date is None:
|
if self._sort_includes('lastviewed') or self._viewedon_gte or self._viewedon_lte:
|
||||||
return
|
longTimeAgo = timezone.now() - timedelta(days=100000)
|
||||||
lessthan = '-' in created_date[:1]
|
self._queryset = self._queryset.annotate(
|
||||||
created_date = date(*[int(x) for x in created_date.split('-') if x != ''])
|
lastviewed=Coalesce(Max(Case(When(viewlog__created_by=self._request.user, viewlog__space=self._request.space, then='viewlog__created_at'))), Value(longTimeAgo))
|
||||||
if lessthan:
|
)
|
||||||
self._queryset = self._queryset.filter(created_at__date__lte=created_date)
|
|
||||||
else:
|
if self._viewedon_lte:
|
||||||
self._queryset = self._queryset.filter(created_at__date__gte=created_date)
|
self._queryset = self._queryset.filter(lastviewed__date__lte=self._viewedon_lte).exclude(lastviewed=longTimeAgo)
|
||||||
|
elif self._viewedon_gte:
|
||||||
|
self._queryset = self._queryset.filter(lastviewed__date__gte=self._viewedon_gte).exclude(lastviewed=longTimeAgo)
|
||||||
|
|
||||||
|
def _created_on_filter(self):
|
||||||
|
if self._createdon:
|
||||||
|
self._queryset = self._queryset.filter(created_at__date=self._createdon)
|
||||||
|
elif self._createdon_lte:
|
||||||
|
self._queryset = self._queryset.filter(created_at__date__lte=self._createdon_lte)
|
||||||
|
elif self._createdon_gte:
|
||||||
|
self._queryset = self._queryset.filter(created_at__date__gte=self._createdon_gte)
|
||||||
|
|
||||||
|
def _updated_on_filter(self):
|
||||||
|
if self._updatedon:
|
||||||
|
self._queryset = self._queryset.filter(updated_at__date__date=self._updatedon)
|
||||||
|
elif self._updatedon_lte:
|
||||||
|
self._queryset = self._queryset.filter(updated_at__date__lte=self._updatedon_lte)
|
||||||
|
elif self._updatedon_gte:
|
||||||
|
self._queryset = self._queryset.filter(updated_at__date__gte=self._updatedon_gte)
|
||||||
|
|
||||||
def _created_by_filter(self, created_by_user_id=None):
|
def _created_by_filter(self, created_by_user_id=None):
|
||||||
if created_by_user_id is None:
|
if created_by_user_id is None:
|
||||||
return
|
return
|
||||||
self._queryset = self._queryset.filter(created_by__id=created_by_user_id)
|
self._queryset = self._queryset.filter(created_by__id=created_by_user_id)
|
||||||
|
|
||||||
def _updated_on_filter(self, updated_date=None):
|
|
||||||
if updated_date is None:
|
|
||||||
return
|
|
||||||
lessthan = '-' in updated_date[:1]
|
|
||||||
updated_date = date(*[int(x)for x in updated_date.split('-') if x != ''])
|
|
||||||
if lessthan:
|
|
||||||
self._queryset = self._queryset.filter(updated_at__date__lte=updated_date)
|
|
||||||
else:
|
|
||||||
self._queryset = self._queryset.filter(updated_at__date__gte=updated_date)
|
|
||||||
|
|
||||||
def _viewed_on_filter(self, viewed_date=None):
|
|
||||||
if self._sort_includes('lastviewed') or viewed_date:
|
|
||||||
longTimeAgo = timezone.now() - timedelta(days=100000)
|
|
||||||
self._queryset = self._queryset.annotate(
|
|
||||||
lastviewed=Coalesce(Max(Case(When(viewlog__created_by=self._request.user, viewlog__space=self._request.space, then='viewlog__created_at'))), Value(longTimeAgo))
|
|
||||||
)
|
|
||||||
if viewed_date is None:
|
|
||||||
return
|
|
||||||
lessthan = '-' in viewed_date[:1]
|
|
||||||
viewed_date = date(*[int(x)for x in viewed_date.split('-') if x != ''])
|
|
||||||
|
|
||||||
if lessthan:
|
|
||||||
self._queryset = self._queryset.filter(lastviewed__date__lte=viewed_date).exclude(lastviewed=longTimeAgo)
|
|
||||||
else:
|
|
||||||
self._queryset = self._queryset.filter(lastviewed__date__gte=viewed_date).exclude(lastviewed=longTimeAgo)
|
|
||||||
|
|
||||||
def _new_recipes(self, new_days=7):
|
def _new_recipes(self, new_days=7):
|
||||||
# TODO make new days a user-setting
|
# TODO make new days a user-setting
|
||||||
if not self._new:
|
if not self._new:
|
||||||
@@ -545,11 +537,11 @@ class RecipeSearch():
|
|||||||
shopping_users = [*self._request.user.get_shopping_share(), self._request.user]
|
shopping_users = [*self._request.user.get_shopping_share(), self._request.user]
|
||||||
|
|
||||||
onhand_filter = (
|
onhand_filter = (
|
||||||
Q(steps__ingredients__food__onhand_users__in=shopping_users) # food onhand
|
Q(steps__ingredients__food__onhand_users__in=shopping_users) # food onhand
|
||||||
# or substitute food onhand
|
# or substitute food onhand
|
||||||
| Q(steps__ingredients__food__substitute__onhand_users__in=shopping_users)
|
| Q(steps__ingredients__food__substitute__onhand_users__in=shopping_users)
|
||||||
| Q(steps__ingredients__food__in=self.__children_substitute_filter(shopping_users))
|
| Q(steps__ingredients__food__in=self.__children_substitute_filter(shopping_users))
|
||||||
| Q(steps__ingredients__food__in=self.__sibling_substitute_filter(shopping_users))
|
| Q(steps__ingredients__food__in=self.__sibling_substitute_filter(shopping_users))
|
||||||
)
|
)
|
||||||
makenow_recipes = Recipe.objects.annotate(
|
makenow_recipes = Recipe.objects.annotate(
|
||||||
count_food=Count('steps__ingredients__food__pk', filter=Q(steps__ingredients__food__isnull=False), distinct=True),
|
count_food=Count('steps__ingredients__food__pk', filter=Q(steps__ingredients__food__isnull=False), distinct=True),
|
||||||
|
|||||||
@@ -158,9 +158,8 @@ import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
|
|||||||
import {useRouteQuery} from "@vueuse/router";
|
import {useRouteQuery} from "@vueuse/router";
|
||||||
import {routeQueryDateTransformer, stringToBool, toNumberArray} from "@/utils/utils";
|
import {routeQueryDateTransformer, stringToBool, toNumberArray} from "@/utils/utils";
|
||||||
import RandomIcon from "@/components/display/RandomIcon.vue";
|
import RandomIcon from "@/components/display/RandomIcon.vue";
|
||||||
import {VRating, VSelect, VTextField} from "vuetify/components";
|
import {VSelect, VTextField} from "vuetify/components";
|
||||||
import RatingField from "@/components/inputs/RatingField.vue";
|
import RatingField from "@/components/inputs/RatingField.vue";
|
||||||
import {DateTime} from "luxon";
|
|
||||||
|
|
||||||
const {t} = useI18n()
|
const {t} = useI18n()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -170,278 +169,6 @@ const query = useRouteQuery('query', "")
|
|||||||
const page = useRouteQuery('page', 1, {transform: Number})
|
const page = useRouteQuery('page', 1, {transform: Number})
|
||||||
const pageSize = useRouteQuery('pageSize', useUserPreferenceStore().deviceSettings.general_tableItemsPerPage, {transform: Number})
|
const pageSize = useRouteQuery('pageSize', useUserPreferenceStore().deviceSettings.general_tableItemsPerPage, {transform: Number})
|
||||||
|
|
||||||
/**
|
|
||||||
* all filters available to enable
|
|
||||||
*/
|
|
||||||
const filters = ref({
|
|
||||||
keywords: {
|
|
||||||
id: 'keywords',
|
|
||||||
label: 'Keyword (any)',
|
|
||||||
hint: 'Any of the given keywords',
|
|
||||||
enabled: false,
|
|
||||||
default: [],
|
|
||||||
is: ModelSelect,
|
|
||||||
model: 'Keyword',
|
|
||||||
modelValue: useRouteQuery('keywords', [], {transform: toNumberArray}),
|
|
||||||
mode: 'tags',
|
|
||||||
object: false,
|
|
||||||
searchOnLoad: true
|
|
||||||
},
|
|
||||||
keywordsAnd: {
|
|
||||||
id: 'keywordsAnd',
|
|
||||||
label: 'Keyword (all)',
|
|
||||||
hint: 'All of the given keywords',
|
|
||||||
enabled: false,
|
|
||||||
default: [],
|
|
||||||
is: ModelSelect,
|
|
||||||
model: 'Keyword',
|
|
||||||
modelValue: useRouteQuery('keywordsAnd', [], {transform: toNumberArray}),
|
|
||||||
mode: 'tags',
|
|
||||||
object: false,
|
|
||||||
searchOnLoad: true
|
|
||||||
},
|
|
||||||
keywordsOrNot: {
|
|
||||||
id: 'keywordsOrNot',
|
|
||||||
label: 'Keyword exclude (any)',
|
|
||||||
hint: 'Exclude recipes with any of the given keywords',
|
|
||||||
enabled: false,
|
|
||||||
default: [],
|
|
||||||
is: ModelSelect,
|
|
||||||
model: 'Keyword',
|
|
||||||
modelValue: useRouteQuery('keywordsOrNot', [], {transform: toNumberArray}),
|
|
||||||
mode: 'tags',
|
|
||||||
object: false,
|
|
||||||
searchOnLoad: true
|
|
||||||
},
|
|
||||||
keywordsAndNot: {
|
|
||||||
id: 'keywordsAndNot',
|
|
||||||
label: 'Keyword exclude (all)',
|
|
||||||
hint: 'Exclude recipes with all of the given keywords',
|
|
||||||
enabled: false,
|
|
||||||
default: [],
|
|
||||||
is: ModelSelect,
|
|
||||||
model: 'Keyword',
|
|
||||||
modelValue: useRouteQuery('keywordsAndNot', [], {transform: toNumberArray}),
|
|
||||||
mode: 'tags',
|
|
||||||
object: false,
|
|
||||||
searchOnLoad: true
|
|
||||||
},
|
|
||||||
foods: {
|
|
||||||
id: 'foods',
|
|
||||||
label: 'Foods (any)',
|
|
||||||
hint: 'Any of the given foods',
|
|
||||||
enabled: false,
|
|
||||||
default: [],
|
|
||||||
is: ModelSelect,
|
|
||||||
model: 'Food',
|
|
||||||
modelValue: useRouteQuery('foods', [], {transform: toNumberArray}),
|
|
||||||
mode: 'tags',
|
|
||||||
object: false,
|
|
||||||
searchOnLoad: true
|
|
||||||
},
|
|
||||||
foodsAnd: {
|
|
||||||
id: 'foodsAnd',
|
|
||||||
label: 'Food (all)',
|
|
||||||
hint: 'All of the given foods',
|
|
||||||
enabled: false,
|
|
||||||
default: [],
|
|
||||||
is: ModelSelect,
|
|
||||||
model: 'Food',
|
|
||||||
modelValue: useRouteQuery('foodsAnd', [], {transform: toNumberArray}),
|
|
||||||
mode: 'tags',
|
|
||||||
object: false,
|
|
||||||
searchOnLoad: true
|
|
||||||
},
|
|
||||||
foodsOrNot: {
|
|
||||||
id: 'foodsOrNot',
|
|
||||||
label: 'Food exclude (any)',
|
|
||||||
hint: 'Exclude recipes with any of the given foods',
|
|
||||||
enabled: false,
|
|
||||||
default: [],
|
|
||||||
is: ModelSelect,
|
|
||||||
model: 'Food',
|
|
||||||
modelValue: useRouteQuery('foodsOrNot', [], {transform: toNumberArray}),
|
|
||||||
mode: 'tags',
|
|
||||||
object: false,
|
|
||||||
searchOnLoad: true
|
|
||||||
},
|
|
||||||
foodsAndNot: {
|
|
||||||
id: 'foodsAndNot',
|
|
||||||
label: 'Food exclude (all)',
|
|
||||||
hint: 'Exclude recipes with all of the given foods',
|
|
||||||
enabled: false,
|
|
||||||
default: [],
|
|
||||||
is: ModelSelect,
|
|
||||||
model: 'Food',
|
|
||||||
modelValue: useRouteQuery('foodsAndNot', [], {transform: toNumberArray}),
|
|
||||||
mode: 'tags',
|
|
||||||
object: false,
|
|
||||||
searchOnLoad: true
|
|
||||||
},
|
|
||||||
books: {
|
|
||||||
id: 'books',
|
|
||||||
label: 'Book (any)',
|
|
||||||
hint: 'Recipes that are in any of the given books',
|
|
||||||
enabled: false,
|
|
||||||
default: [],
|
|
||||||
is: ModelSelect,
|
|
||||||
model: 'RecipeBook',
|
|
||||||
modelValue: useRouteQuery('books', [], {transform: toNumberArray}),
|
|
||||||
mode: 'tags',
|
|
||||||
object: false,
|
|
||||||
searchOnLoad: true
|
|
||||||
},
|
|
||||||
booksAnd: {
|
|
||||||
id: 'booksAnd',
|
|
||||||
label: 'Book (all)',
|
|
||||||
hint: 'Recipes that are in all of the given books',
|
|
||||||
enabled: false,
|
|
||||||
default: [],
|
|
||||||
is: ModelSelect,
|
|
||||||
model: 'RecipeBook',
|
|
||||||
modelValue: useRouteQuery('booksAnd', [], {transform: toNumberArray}),
|
|
||||||
mode: 'tags',
|
|
||||||
object: false,
|
|
||||||
searchOnLoad: true
|
|
||||||
},
|
|
||||||
booksOrNot: {
|
|
||||||
id: 'booksOrNot',
|
|
||||||
label: 'Book exclude (any)',
|
|
||||||
hint: 'Exclude recipes with any of the given books',
|
|
||||||
enabled: false,
|
|
||||||
default: [],
|
|
||||||
is: ModelSelect,
|
|
||||||
model: 'RecipeBook',
|
|
||||||
modelValue: useRouteQuery('booksOrNot', [], {transform: toNumberArray}),
|
|
||||||
mode: 'tags',
|
|
||||||
object: false,
|
|
||||||
searchOnLoad: true
|
|
||||||
},
|
|
||||||
booksAndNot: {
|
|
||||||
id: 'booksAndNot',
|
|
||||||
label: 'Book exclude (all)',
|
|
||||||
hint: 'Exclude recipes with all of the given books',
|
|
||||||
enabled: false,
|
|
||||||
default: [],
|
|
||||||
is: ModelSelect,
|
|
||||||
model: 'RecipeBook',
|
|
||||||
modelValue: useRouteQuery('booksAndNot', [], {transform: toNumberArray}),
|
|
||||||
mode: 'tags',
|
|
||||||
object: false,
|
|
||||||
searchOnLoad: true
|
|
||||||
},
|
|
||||||
createdby: {
|
|
||||||
id: 'createdby',
|
|
||||||
label: 'Created By',
|
|
||||||
hint: 'Recipes created by the selected user',
|
|
||||||
enabled: false,
|
|
||||||
default: undefined,
|
|
||||||
is: ModelSelect,
|
|
||||||
model: 'User',
|
|
||||||
modelValue: useRouteQuery('createdby', undefined, {transform: Number}),
|
|
||||||
mode: 'single',
|
|
||||||
object: false,
|
|
||||||
searchOnLoad: true
|
|
||||||
},
|
|
||||||
units: {
|
|
||||||
id: '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: {
|
|
||||||
id: 'internal',
|
|
||||||
label: 'Hide External',
|
|
||||||
hint: 'Hide external recipes',
|
|
||||||
enabled: false,
|
|
||||||
default: "false",
|
|
||||||
is: VSelect,
|
|
||||||
items: [{value: "true", title: 'Yes'}, {value: "false", title: 'No'}],
|
|
||||||
modelValue: useRouteQuery('internal', "false"),
|
|
||||||
},
|
|
||||||
rating: {
|
|
||||||
id: 'rating',
|
|
||||||
label: 'Rating (exact)',
|
|
||||||
hint: 'Recipes with the exact rating',
|
|
||||||
enabled: false,
|
|
||||||
default: undefined,
|
|
||||||
is: RatingField,
|
|
||||||
modelValue: useRouteQuery('rating', undefined, {transform: Number}),
|
|
||||||
},
|
|
||||||
ratingGte: {
|
|
||||||
id: 'ratingGte',
|
|
||||||
label: 'Rating (>=)',
|
|
||||||
hint: 'Recipes with the given or a greater rating',
|
|
||||||
enabled: false,
|
|
||||||
default: undefined,
|
|
||||||
is: RatingField,
|
|
||||||
modelValue: useRouteQuery('ratingGte', undefined, {transform: Number}),
|
|
||||||
},
|
|
||||||
ratingLte: {
|
|
||||||
id: 'ratingLte',
|
|
||||||
label: 'Rating (<=)',
|
|
||||||
hint: 'Recipes with the given or a smaller rating',
|
|
||||||
enabled: false,
|
|
||||||
default: undefined,
|
|
||||||
is: RatingField,
|
|
||||||
modelValue: useRouteQuery('ratingLte', undefined, {transform: Number}),
|
|
||||||
},
|
|
||||||
timescookedGte: {
|
|
||||||
id: 'timescookedGte',
|
|
||||||
label: 'Times Cooked (>=)',
|
|
||||||
hint: 'Recipes that were cooked at least X times',
|
|
||||||
enabled: false,
|
|
||||||
default: undefined,
|
|
||||||
is: VNumberInput,
|
|
||||||
modelValue: useRouteQuery('timescookedGte', undefined, {transform: Number}),
|
|
||||||
},
|
|
||||||
timescookedLte: {
|
|
||||||
id: 'timescookedLte',
|
|
||||||
label: 'Times Cooked (<=)',
|
|
||||||
hint: 'Recipes that were cooked at most X times',
|
|
||||||
enabled: false,
|
|
||||||
default: undefined,
|
|
||||||
is: VNumberInput,
|
|
||||||
modelValue: useRouteQuery('timescookedLte', undefined, {transform: Number}),
|
|
||||||
},
|
|
||||||
makenow: {
|
|
||||||
id: 'makenow',
|
|
||||||
label: 'Foods on Hand',
|
|
||||||
hint: 'Only recipes were all foods (or its substitutes) are marked as on hand',
|
|
||||||
enabled: false,
|
|
||||||
default: "false",
|
|
||||||
is: VSelect,
|
|
||||||
items: [{value: "true", title: 'Yes'}, {value: "false", title: 'No'}],
|
|
||||||
modelValue: useRouteQuery('makenow', "false"),
|
|
||||||
},
|
|
||||||
|
|
||||||
cookedonGte: {
|
|
||||||
id: 'cookedonGte',
|
|
||||||
label: 'Cooked after',
|
|
||||||
hint: 'Only recipes that were cooked on or after the given date.',
|
|
||||||
enabled: false,
|
|
||||||
default: null,
|
|
||||||
is: VDateInput,
|
|
||||||
modelValue: useRouteQuery('cookedonGte', null, {transform: routeQueryDateTransformer}),
|
|
||||||
},
|
|
||||||
cookedonLte: {
|
|
||||||
id: 'cookedonLte',
|
|
||||||
label: 'Cooked before',
|
|
||||||
hint: 'Only recipes that were cooked on or before the given date.',
|
|
||||||
enabled: false,
|
|
||||||
default: null,
|
|
||||||
is: VDateInput,
|
|
||||||
modelValue: useRouteQuery('cookedonLte', null, {transform: routeQueryDateTransformer}),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* filters that are not yet enabled
|
* filters that are not yet enabled
|
||||||
*/
|
*/
|
||||||
@@ -885,6 +612,351 @@ function apiRecipeListRequestToCustomFilter() {
|
|||||||
return customFilterParams
|
return customFilterParams
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* all filters available to enable
|
||||||
|
*/
|
||||||
|
const filters = ref({
|
||||||
|
keywords: {
|
||||||
|
id: 'keywords',
|
||||||
|
label: 'Keyword (any)',
|
||||||
|
hint: 'Any of the given keywords',
|
||||||
|
enabled: false,
|
||||||
|
default: [],
|
||||||
|
is: ModelSelect,
|
||||||
|
model: 'Keyword',
|
||||||
|
modelValue: useRouteQuery('keywords', [], {transform: toNumberArray}),
|
||||||
|
mode: 'tags',
|
||||||
|
object: false,
|
||||||
|
searchOnLoad: true
|
||||||
|
},
|
||||||
|
keywordsAnd: {
|
||||||
|
id: 'keywordsAnd',
|
||||||
|
label: 'Keyword (all)',
|
||||||
|
hint: 'All of the given keywords',
|
||||||
|
enabled: false,
|
||||||
|
default: [],
|
||||||
|
is: ModelSelect,
|
||||||
|
model: 'Keyword',
|
||||||
|
modelValue: useRouteQuery('keywordsAnd', [], {transform: toNumberArray}),
|
||||||
|
mode: 'tags',
|
||||||
|
object: false,
|
||||||
|
searchOnLoad: true
|
||||||
|
},
|
||||||
|
keywordsOrNot: {
|
||||||
|
id: 'keywordsOrNot',
|
||||||
|
label: 'Keyword exclude (any)',
|
||||||
|
hint: 'Exclude recipes with any of the given keywords',
|
||||||
|
enabled: false,
|
||||||
|
default: [],
|
||||||
|
is: ModelSelect,
|
||||||
|
model: 'Keyword',
|
||||||
|
modelValue: useRouteQuery('keywordsOrNot', [], {transform: toNumberArray}),
|
||||||
|
mode: 'tags',
|
||||||
|
object: false,
|
||||||
|
searchOnLoad: true
|
||||||
|
},
|
||||||
|
keywordsAndNot: {
|
||||||
|
id: 'keywordsAndNot',
|
||||||
|
label: 'Keyword exclude (all)',
|
||||||
|
hint: 'Exclude recipes with all of the given keywords',
|
||||||
|
enabled: false,
|
||||||
|
default: [],
|
||||||
|
is: ModelSelect,
|
||||||
|
model: 'Keyword',
|
||||||
|
modelValue: useRouteQuery('keywordsAndNot', [], {transform: toNumberArray}),
|
||||||
|
mode: 'tags',
|
||||||
|
object: false,
|
||||||
|
searchOnLoad: true
|
||||||
|
},
|
||||||
|
foods: {
|
||||||
|
id: 'foods',
|
||||||
|
label: 'Foods (any)',
|
||||||
|
hint: 'Any of the given foods',
|
||||||
|
enabled: false,
|
||||||
|
default: [],
|
||||||
|
is: ModelSelect,
|
||||||
|
model: 'Food',
|
||||||
|
modelValue: useRouteQuery('foods', [], {transform: toNumberArray}),
|
||||||
|
mode: 'tags',
|
||||||
|
object: false,
|
||||||
|
searchOnLoad: true
|
||||||
|
},
|
||||||
|
foodsAnd: {
|
||||||
|
id: 'foodsAnd',
|
||||||
|
label: 'Food (all)',
|
||||||
|
hint: 'All of the given foods',
|
||||||
|
enabled: false,
|
||||||
|
default: [],
|
||||||
|
is: ModelSelect,
|
||||||
|
model: 'Food',
|
||||||
|
modelValue: useRouteQuery('foodsAnd', [], {transform: toNumberArray}),
|
||||||
|
mode: 'tags',
|
||||||
|
object: false,
|
||||||
|
searchOnLoad: true
|
||||||
|
},
|
||||||
|
foodsOrNot: {
|
||||||
|
id: 'foodsOrNot',
|
||||||
|
label: 'Food exclude (any)',
|
||||||
|
hint: 'Exclude recipes with any of the given foods',
|
||||||
|
enabled: false,
|
||||||
|
default: [],
|
||||||
|
is: ModelSelect,
|
||||||
|
model: 'Food',
|
||||||
|
modelValue: useRouteQuery('foodsOrNot', [], {transform: toNumberArray}),
|
||||||
|
mode: 'tags',
|
||||||
|
object: false,
|
||||||
|
searchOnLoad: true
|
||||||
|
},
|
||||||
|
foodsAndNot: {
|
||||||
|
id: 'foodsAndNot',
|
||||||
|
label: 'Food exclude (all)',
|
||||||
|
hint: 'Exclude recipes with all of the given foods',
|
||||||
|
enabled: false,
|
||||||
|
default: [],
|
||||||
|
is: ModelSelect,
|
||||||
|
model: 'Food',
|
||||||
|
modelValue: useRouteQuery('foodsAndNot', [], {transform: toNumberArray}),
|
||||||
|
mode: 'tags',
|
||||||
|
object: false,
|
||||||
|
searchOnLoad: true
|
||||||
|
},
|
||||||
|
books: {
|
||||||
|
id: 'books',
|
||||||
|
label: 'Book (any)',
|
||||||
|
hint: 'Recipes that are in any of the given books',
|
||||||
|
enabled: false,
|
||||||
|
default: [],
|
||||||
|
is: ModelSelect,
|
||||||
|
model: 'RecipeBook',
|
||||||
|
modelValue: useRouteQuery('books', [], {transform: toNumberArray}),
|
||||||
|
mode: 'tags',
|
||||||
|
object: false,
|
||||||
|
searchOnLoad: true
|
||||||
|
},
|
||||||
|
booksAnd: {
|
||||||
|
id: 'booksAnd',
|
||||||
|
label: 'Book (all)',
|
||||||
|
hint: 'Recipes that are in all of the given books',
|
||||||
|
enabled: false,
|
||||||
|
default: [],
|
||||||
|
is: ModelSelect,
|
||||||
|
model: 'RecipeBook',
|
||||||
|
modelValue: useRouteQuery('booksAnd', [], {transform: toNumberArray}),
|
||||||
|
mode: 'tags',
|
||||||
|
object: false,
|
||||||
|
searchOnLoad: true
|
||||||
|
},
|
||||||
|
booksOrNot: {
|
||||||
|
id: 'booksOrNot',
|
||||||
|
label: 'Book exclude (any)',
|
||||||
|
hint: 'Exclude recipes with any of the given books',
|
||||||
|
enabled: false,
|
||||||
|
default: [],
|
||||||
|
is: ModelSelect,
|
||||||
|
model: 'RecipeBook',
|
||||||
|
modelValue: useRouteQuery('booksOrNot', [], {transform: toNumberArray}),
|
||||||
|
mode: 'tags',
|
||||||
|
object: false,
|
||||||
|
searchOnLoad: true
|
||||||
|
},
|
||||||
|
booksAndNot: {
|
||||||
|
id: 'booksAndNot',
|
||||||
|
label: 'Book exclude (all)',
|
||||||
|
hint: 'Exclude recipes with all of the given books',
|
||||||
|
enabled: false,
|
||||||
|
default: [],
|
||||||
|
is: ModelSelect,
|
||||||
|
model: 'RecipeBook',
|
||||||
|
modelValue: useRouteQuery('booksAndNot', [], {transform: toNumberArray}),
|
||||||
|
mode: 'tags',
|
||||||
|
object: false,
|
||||||
|
searchOnLoad: true
|
||||||
|
},
|
||||||
|
createdby: {
|
||||||
|
id: 'createdby',
|
||||||
|
label: 'Created By',
|
||||||
|
hint: 'Recipes created by the selected user',
|
||||||
|
enabled: false,
|
||||||
|
default: undefined,
|
||||||
|
is: ModelSelect,
|
||||||
|
model: 'User',
|
||||||
|
modelValue: useRouteQuery('createdby', undefined, {transform: Number}),
|
||||||
|
mode: 'single',
|
||||||
|
object: false,
|
||||||
|
searchOnLoad: true
|
||||||
|
},
|
||||||
|
units: {
|
||||||
|
id: '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: {
|
||||||
|
id: 'internal',
|
||||||
|
label: 'Hide External',
|
||||||
|
hint: 'Hide external recipes',
|
||||||
|
enabled: false,
|
||||||
|
default: "false",
|
||||||
|
is: VSelect,
|
||||||
|
items: [{value: "true", title: 'Yes'}, {value: "false", title: 'No'}],
|
||||||
|
modelValue: useRouteQuery('internal', "false"),
|
||||||
|
},
|
||||||
|
rating: {
|
||||||
|
id: 'rating',
|
||||||
|
label: 'Rating (exact)',
|
||||||
|
hint: 'Recipes with the exact rating',
|
||||||
|
enabled: false,
|
||||||
|
default: undefined,
|
||||||
|
is: RatingField,
|
||||||
|
modelValue: useRouteQuery('rating', undefined, {transform: Number}),
|
||||||
|
},
|
||||||
|
ratingGte: {
|
||||||
|
id: 'ratingGte',
|
||||||
|
label: 'Rating (>=)',
|
||||||
|
hint: 'Recipes with the given or a greater rating',
|
||||||
|
enabled: false,
|
||||||
|
default: undefined,
|
||||||
|
is: RatingField,
|
||||||
|
modelValue: useRouteQuery('ratingGte', undefined, {transform: Number}),
|
||||||
|
},
|
||||||
|
ratingLte: {
|
||||||
|
id: 'ratingLte',
|
||||||
|
label: 'Rating (<=)',
|
||||||
|
hint: 'Recipes with the given or a smaller rating',
|
||||||
|
enabled: false,
|
||||||
|
default: undefined,
|
||||||
|
is: RatingField,
|
||||||
|
modelValue: useRouteQuery('ratingLte', undefined, {transform: Number}),
|
||||||
|
},
|
||||||
|
timescookedGte: {
|
||||||
|
id: 'timescookedGte',
|
||||||
|
label: 'Times Cooked (>=)',
|
||||||
|
hint: 'Recipes that were cooked at least X times',
|
||||||
|
enabled: false,
|
||||||
|
default: undefined,
|
||||||
|
is: VNumberInput,
|
||||||
|
modelValue: useRouteQuery('timescookedGte', undefined, {transform: Number}),
|
||||||
|
},
|
||||||
|
timescookedLte: {
|
||||||
|
id: 'timescookedLte',
|
||||||
|
label: 'Times Cooked (<=)',
|
||||||
|
hint: 'Recipes that were cooked at most X times',
|
||||||
|
enabled: false,
|
||||||
|
default: undefined,
|
||||||
|
is: VNumberInput,
|
||||||
|
modelValue: useRouteQuery('timescookedLte', undefined, {transform: Number}),
|
||||||
|
},
|
||||||
|
makenow: {
|
||||||
|
id: 'makenow',
|
||||||
|
label: 'Foods on Hand',
|
||||||
|
hint: 'Only recipes were all foods (or its substitutes) are marked as on hand',
|
||||||
|
enabled: false,
|
||||||
|
default: "false",
|
||||||
|
is: VSelect,
|
||||||
|
items: [{value: "true", title: 'Yes'}, {value: "false", title: 'No'}],
|
||||||
|
modelValue: useRouteQuery('makenow', "false"),
|
||||||
|
},
|
||||||
|
|
||||||
|
cookedonGte: {
|
||||||
|
id: 'cookedonGte',
|
||||||
|
label: 'Cooked after',
|
||||||
|
hint: 'Only recipes that were cooked on or after the given date.',
|
||||||
|
enabled: false,
|
||||||
|
default: null,
|
||||||
|
is: VDateInput,
|
||||||
|
modelValue: useRouteQuery('cookedonGte', null, {transform: routeQueryDateTransformer}),
|
||||||
|
},
|
||||||
|
cookedonLte: {
|
||||||
|
id: 'cookedonLte',
|
||||||
|
label: 'Cooked before',
|
||||||
|
hint: 'Only recipes that were cooked on or before the given date.',
|
||||||
|
enabled: false,
|
||||||
|
default: null,
|
||||||
|
is: VDateInput,
|
||||||
|
modelValue: useRouteQuery('cookedonLte', null, {transform: routeQueryDateTransformer}),
|
||||||
|
},
|
||||||
|
viewedonGte: {
|
||||||
|
id: 'viewedonGte',
|
||||||
|
label: 'Viewed after',
|
||||||
|
hint: 'Only recipes that were viewed on or after the given date.',
|
||||||
|
enabled: false,
|
||||||
|
default: null,
|
||||||
|
is: VDateInput,
|
||||||
|
modelValue: useRouteQuery('viewedonGte', null, {transform: routeQueryDateTransformer}),
|
||||||
|
},
|
||||||
|
viewedonLte: {
|
||||||
|
id: 'viewedonLte',
|
||||||
|
label: 'Viewed before',
|
||||||
|
hint: 'Only recipes that were viewed on or before the given date.',
|
||||||
|
enabled: false,
|
||||||
|
default: null,
|
||||||
|
is: VDateInput,
|
||||||
|
modelValue: useRouteQuery('viewedonLte', null, {transform: routeQueryDateTransformer}),
|
||||||
|
},
|
||||||
|
|
||||||
|
createdon: {
|
||||||
|
id: 'createdon',
|
||||||
|
label: 'Created on',
|
||||||
|
hint: 'Only recipes that were created on the given date.',
|
||||||
|
enabled: false,
|
||||||
|
default: null,
|
||||||
|
is: VDateInput,
|
||||||
|
modelValue: useRouteQuery('createdon', null, {transform: routeQueryDateTransformer}),
|
||||||
|
},
|
||||||
|
createdonGte: {
|
||||||
|
id: 'createdonGte',
|
||||||
|
label: 'Created on/after',
|
||||||
|
hint: 'Only recipes that were created on or after the given date.',
|
||||||
|
enabled: false,
|
||||||
|
default: null,
|
||||||
|
is: VDateInput,
|
||||||
|
modelValue: useRouteQuery('createdonGte', null, {transform: routeQueryDateTransformer}),
|
||||||
|
},
|
||||||
|
createdonLte: {
|
||||||
|
id: 'createdonLte',
|
||||||
|
label: 'Created on/before',
|
||||||
|
hint: 'Only recipes that were created on or before the given date.',
|
||||||
|
enabled: false,
|
||||||
|
default: null,
|
||||||
|
is: VDateInput,
|
||||||
|
modelValue: useRouteQuery('createdonLte', null, {transform: routeQueryDateTransformer}),
|
||||||
|
},
|
||||||
|
updatedon: {
|
||||||
|
id: 'updatedon',
|
||||||
|
label: 'Updated on',
|
||||||
|
hint: 'Only recipes that were updated on the given date.',
|
||||||
|
enabled: false,
|
||||||
|
default: null,
|
||||||
|
is: VDateInput,
|
||||||
|
modelValue: useRouteQuery('updatedon', null, {transform: routeQueryDateTransformer}),
|
||||||
|
},
|
||||||
|
updatedonGte: {
|
||||||
|
id: 'updatedonGte',
|
||||||
|
label: 'Updated on/after',
|
||||||
|
hint: 'Only recipes that were updated on or after the given date.',
|
||||||
|
enabled: false,
|
||||||
|
default: null,
|
||||||
|
is: VDateInput,
|
||||||
|
modelValue: useRouteQuery('updatedonGte', null, {transform: routeQueryDateTransformer}),
|
||||||
|
},
|
||||||
|
updatedonLte: {
|
||||||
|
id: 'updatedonLte',
|
||||||
|
label: 'Updated on/before',
|
||||||
|
hint: 'Only recipes that were updated on or before the given date.',
|
||||||
|
enabled: false,
|
||||||
|
default: null,
|
||||||
|
is: VDateInput,
|
||||||
|
modelValue: useRouteQuery('updatedonLte', null, {transform: routeQueryDateTransformer}),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
Reference in New Issue
Block a user