implemented all filters in frontend

This commit is contained in:
vabene1111
2025-03-31 08:58:32 +02:00
parent 988dcd1522
commit f7eabfe458
2 changed files with 381 additions and 317 deletions

View File

@@ -261,49 +261,41 @@ class RecipeSearch():
if self._cookedon_lte:
self._queryset = self._queryset.filter(lastcooked__date__lte=self._cookedon_lte).exclude(lastcooked=default)
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):
if created_date is None:
return
lessthan = '-' in created_date[:1]
created_date = date(*[int(x) for x in created_date.split('-') if x != ''])
if lessthan:
self._queryset = self._queryset.filter(created_at__date__lte=created_date)
else:
self._queryset = self._queryset.filter(created_at__date__gte=created_date)
def _viewed_on_filter(self, viewed_date=None):
if self._sort_includes('lastviewed') or self._viewedon_gte or self._viewedon_lte:
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 self._viewedon_lte:
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):
if created_by_user_id is None:
return
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):
# TODO make new days a user-setting
if not self._new:

View File

@@ -158,9 +158,8 @@ import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
import {useRouteQuery} from "@vueuse/router";
import {routeQueryDateTransformer, stringToBool, toNumberArray} from "@/utils/utils";
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 {DateTime} from "luxon";
const {t} = useI18n()
const router = useRouter()
@@ -170,278 +169,6 @@ const query = useRouteQuery('query', "")
const page = useRouteQuery('page', 1, {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
*/
@@ -885,6 +612,351 @@ function apiRecipeListRequestToCustomFilter() {
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>
<style scoped>