mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-09 03:04:54 -04:00
feat: additional recipe sort behavior (#1858)
* changed default sort direction for certain attrs * added workaround for filtering out null datetimes * filtered out null-valued results for certain sorts * removed unecessary parse * used minyear instead of 1900
This commit is contained in:
parent
33dffccaa5
commit
1b9ff454fb
@ -243,7 +243,10 @@ export default defineComponent({
|
|||||||
cookbook.value,
|
cookbook.value,
|
||||||
category.value,
|
category.value,
|
||||||
tag.value,
|
tag.value,
|
||||||
tool.value
|
tool.value,
|
||||||
|
|
||||||
|
// filter out recipes that have a null value for the property we're sorting by
|
||||||
|
preferences.value.filterNull && preferences.value.orderBy ? `${preferences.value.orderBy} <> null` : null
|
||||||
);
|
);
|
||||||
|
|
||||||
// since we doubled the first call, we also need to advance the page
|
// since we doubled the first call, we also need to advance the page
|
||||||
@ -270,7 +273,10 @@ export default defineComponent({
|
|||||||
cookbook.value,
|
cookbook.value,
|
||||||
category.value,
|
category.value,
|
||||||
tag.value,
|
tag.value,
|
||||||
tool.value
|
tool.value,
|
||||||
|
|
||||||
|
// filter out recipes that have a null value for the property we're sorting by
|
||||||
|
preferences.value.filterNull && preferences.value.orderBy ? `${preferences.value.orderBy} <> null` : null
|
||||||
);
|
);
|
||||||
if (!newRecipes.length) {
|
if (!newRecipes.length) {
|
||||||
hasMore.value = false;
|
hasMore.value = false;
|
||||||
@ -287,10 +293,11 @@ export default defineComponent({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setter(orderBy: string, ascIcon: string, descIcon: string) {
|
function setter(orderBy: string, ascIcon: string, descIcon: string, defaultOrderDirection = "asc", filterNull = false) {
|
||||||
if (preferences.value.orderBy !== orderBy) {
|
if (preferences.value.orderBy !== orderBy) {
|
||||||
preferences.value.orderBy = orderBy;
|
preferences.value.orderBy = orderBy;
|
||||||
preferences.value.orderDirection = "asc";
|
preferences.value.orderDirection = defaultOrderDirection;
|
||||||
|
preferences.value.filterNull = filterNull;
|
||||||
} else {
|
} else {
|
||||||
preferences.value.orderDirection = preferences.value.orderDirection === "asc" ? "desc" : "asc";
|
preferences.value.orderDirection = preferences.value.orderDirection === "asc" ? "desc" : "asc";
|
||||||
}
|
}
|
||||||
@ -299,19 +306,19 @@ export default defineComponent({
|
|||||||
|
|
||||||
switch (sortType) {
|
switch (sortType) {
|
||||||
case EVENTS.az:
|
case EVENTS.az:
|
||||||
setter("name", $globals.icons.sortAlphabeticalAscending, $globals.icons.sortAlphabeticalDescending);
|
setter("name", $globals.icons.sortAlphabeticalAscending, $globals.icons.sortAlphabeticalDescending, "asc", false);
|
||||||
break;
|
break;
|
||||||
case EVENTS.rating:
|
case EVENTS.rating:
|
||||||
setter("rating", $globals.icons.sortAscending, $globals.icons.sortDescending);
|
setter("rating", $globals.icons.sortAscending, $globals.icons.sortDescending, "desc", true);
|
||||||
break;
|
break;
|
||||||
case EVENTS.created:
|
case EVENTS.created:
|
||||||
setter("created_at", $globals.icons.sortCalendarAscending, $globals.icons.sortCalendarDescending);
|
setter("created_at", $globals.icons.sortCalendarAscending, $globals.icons.sortCalendarDescending, "desc", false);
|
||||||
break;
|
break;
|
||||||
case EVENTS.updated:
|
case EVENTS.updated:
|
||||||
setter("update_at", $globals.icons.sortClockAscending, $globals.icons.sortClockDescending);
|
setter("update_at", $globals.icons.sortClockAscending, $globals.icons.sortClockDescending, "desc", false);
|
||||||
break;
|
break;
|
||||||
case EVENTS.lastMade:
|
case EVENTS.lastMade:
|
||||||
setter("last_made", $globals.icons.sortCalendarAscending, $globals.icons.sortCalendarDescending);
|
setter("last_made", $globals.icons.sortCalendarAscending, $globals.icons.sortCalendarDescending, "desc", true);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.log("Unknown Event", sortType);
|
console.log("Unknown Event", sortType);
|
||||||
@ -335,7 +342,10 @@ export default defineComponent({
|
|||||||
cookbook.value,
|
cookbook.value,
|
||||||
category.value,
|
category.value,
|
||||||
tag.value,
|
tag.value,
|
||||||
tool.value
|
tool.value,
|
||||||
|
|
||||||
|
// filter out recipes that have a null value for the property we're sorting by
|
||||||
|
preferences.value.filterNull && preferences.value.orderBy ? `${preferences.value.orderBy} <> null` : null
|
||||||
);
|
);
|
||||||
context.emit(REPLACE_RECIPES_EVENT, newRecipes);
|
context.emit(REPLACE_RECIPES_EVENT, newRecipes);
|
||||||
|
|
||||||
|
@ -19,7 +19,8 @@ export const useLazyRecipes = function () {
|
|||||||
cookbook: string | null = null,
|
cookbook: string | null = null,
|
||||||
category: string | null = null,
|
category: string | null = null,
|
||||||
tag: string | null = null,
|
tag: string | null = null,
|
||||||
tool: string | null = null
|
tool: string | null = null,
|
||||||
|
queryFilter: string | null = null,
|
||||||
) {
|
) {
|
||||||
const { data } = await api.recipes.getAll(page, perPage, {
|
const { data } = await api.recipes.getAll(page, perPage, {
|
||||||
orderBy,
|
orderBy,
|
||||||
@ -28,6 +29,7 @@ export const useLazyRecipes = function () {
|
|||||||
categories: category,
|
categories: category,
|
||||||
tags: tag,
|
tags: tag,
|
||||||
tools: tool,
|
tools: tool,
|
||||||
|
queryFilter,
|
||||||
});
|
});
|
||||||
return data ? data.items : [];
|
return data ? data.items : [];
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import { useLocalStorage } from "@vueuse/core";
|
|||||||
export interface UserRecipePreferences {
|
export interface UserRecipePreferences {
|
||||||
orderBy: string;
|
orderBy: string;
|
||||||
orderDirection: string;
|
orderDirection: string;
|
||||||
|
filterNull: boolean;
|
||||||
sortIcon: string;
|
sortIcon: string;
|
||||||
useMobileCards: boolean;
|
useMobileCards: boolean;
|
||||||
}
|
}
|
||||||
@ -16,6 +17,7 @@ export function useUserSortPreferences(): Ref<UserRecipePreferences> {
|
|||||||
{
|
{
|
||||||
orderBy: "name",
|
orderBy: "name",
|
||||||
orderDirection: "asc",
|
orderDirection: "asc",
|
||||||
|
filterNull: false,
|
||||||
sortIcon: $globals.icons.sortAlphabeticalAscending,
|
sortIcon: $globals.icons.sortAlphabeticalAscending,
|
||||||
useMobileCards: false,
|
useMobileCards: false,
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import datetime
|
||||||
import re
|
import re
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Any, TypeVar, cast
|
from typing import Any, TypeVar, cast
|
||||||
@ -96,13 +97,20 @@ class QueryFilter:
|
|||||||
value: Any = component.value
|
value: Any = component.value
|
||||||
|
|
||||||
if isinstance(attr.type, (sqltypes.Date, sqltypes.DateTime)):
|
if isinstance(attr.type, (sqltypes.Date, sqltypes.DateTime)):
|
||||||
try:
|
# TODO: add support for IS NULL and IS NOT NULL
|
||||||
value = date_parser.parse(component.value)
|
# in the meantime, this will work for the specific usecase of non-null dates/datetimes
|
||||||
|
if value in ["none", "null"] and component.relational_operator == RelationalOperator.NOTEQ:
|
||||||
|
component.relational_operator = RelationalOperator.GTE
|
||||||
|
value = datetime.datetime(datetime.MINYEAR, 1, 1)
|
||||||
|
|
||||||
except ParserError as e:
|
else:
|
||||||
raise ValueError(
|
try:
|
||||||
f"invalid query string: unknown date or datetime format '{component.value}'"
|
value = date_parser.parse(component.value)
|
||||||
) from e
|
|
||||||
|
except ParserError as e:
|
||||||
|
raise ValueError(
|
||||||
|
f"invalid query string: unknown date or datetime format '{component.value}'"
|
||||||
|
) from e
|
||||||
|
|
||||||
if isinstance(attr.type, sqltypes.Boolean):
|
if isinstance(attr.type, sqltypes.Boolean):
|
||||||
try:
|
try:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user