Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Filter Recipes By Household (and a ton of bug fixes) #4207

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
87abe4c
added public household routes
michael-genson Sep 11, 2024
a54f11e
dev:generate
michael-genson Sep 12, 2024
a080612
added household routes to frontend
michael-genson Sep 12, 2024
47d4d56
refactor stores to reuse less code
michael-genson Sep 12, 2024
22ffed6
explicitly set data table sort
michael-genson Sep 12, 2024
e6051c8
Merge remote-tracking branch 'upstream/mealie-next' into feat/filter-…
michael-genson Sep 12, 2024
931b496
fixed sort value
michael-genson Sep 12, 2024
e9f84ca
rename store classes
michael-genson Sep 12, 2024
1d4967d
re-organized household routes
michael-genson Sep 12, 2024
4791f63
dev:generate
michael-genson Sep 12, 2024
d7ee937
re-organized frontend household routes and migrated household CRUD to…
michael-genson Sep 12, 2024
a278a23
added household readonly stores (finally)
michael-genson Sep 12, 2024
7ee8e8e
added households filter to recipe get_all
michael-genson Sep 12, 2024
6824bb7
added households filter to public routes
michael-genson Sep 12, 2024
fd5135f
fixed households not using correct routes
michael-genson Sep 12, 2024
6e0c649
added missing store index
michael-genson Sep 12, 2024
b117866
added household support to search frontend
michael-genson Sep 12, 2024
da3b194
add support for radio buttons on search filter
michael-genson Sep 12, 2024
df8c716
added household filter to explore page
michael-genson Sep 12, 2024
ea53cf6
fixed selection jank
michael-genson Sep 12, 2024
dbbab53
removed over-hydration
michael-genson Sep 13, 2024
44f4ec8
removed jank transition when selecting filters
michael-genson Sep 13, 2024
e78a538
fixed several infinite scroll bugs
michael-genson Sep 13, 2024
edb429b
fixed queryFilter being ignored
michael-genson Sep 13, 2024
64eed51
better hasMore calc
michael-genson Sep 13, 2024
51592cd
converted recipes page to use lazyRecipes
michael-genson Sep 13, 2024
1ec3281
fix reset
michael-genson Sep 13, 2024
7ee0069
fix bad user-ratings calls
michael-genson Sep 13, 2024
4e7951e
fixed bad indentation
michael-genson Sep 13, 2024
1f04a4a
test types
michael-genson Sep 13, 2024
d5272bc
added missing cookbook tests
michael-genson Sep 13, 2024
125f156
added new household tests
michael-genson Sep 14, 2024
3783f14
added household filter test
michael-genson Sep 14, 2024
d177634
hide households filter if there's only one household
michael-genson Sep 14, 2024
3c5e5df
lint
michael-genson Sep 14, 2024
adda825
reverted food_id change in page_all
michael-genson Sep 14, 2024
6fa79a0
Merge remote-tracking branch 'upstream/mealie-next' into feat/filter-…
michael-genson Sep 18, 2024
ba17825
fix/add tests
michael-genson Sep 18, 2024
ec63943
Merge branch 'mealie-next' into feat/filter-recipes-by-household
michael-genson Sep 18, 2024
a6df1a9
Update frontend/components/Domain/Recipe/RecipeCardSection.vue
michael-genson Sep 18, 2024
69e3bb7
Update frontend/components/Domain/SearchFilter.vue
michael-genson Sep 18, 2024
bbc88d1
sorted by createdAt and formatted date on CRUD tables
michael-genson Sep 19, 2024
5966f10
Merge branch 'mealie-next' into feat/filter-recipes-by-household
michael-genson Sep 19, 2024
72df89f
Merge branch 'mealie-next' into feat/filter-recipes-by-household
michael-genson Sep 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 71 additions & 57 deletions frontend/components/Domain/Recipe/RecipeCardSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,50 +69,52 @@
@toggle-dense-view="toggleMobileCards()"
/>
</v-app-bar>
<div v-if="recipes" class="mt-2">
<v-row v-if="!useMobileCards">
<v-col v-for="(recipe, index) in recipes" :key="recipe.slug + index" :sm="6" :md="6" :lg="4" :xl="3">
<v-lazy>
<RecipeCard
:name="recipe.name"
:description="recipe.description"
:slug="recipe.slug"
:rating="recipe.rating"
:image="recipe.image"
:tags="recipe.tags"
:recipe-id="recipe.id"
/>
</v-lazy>
</v-col>
</v-row>
<v-row v-else dense>
<v-col
v-for="recipe in recipes"
:key="recipe.name"
cols="12"
:sm="singleColumn ? '12' : '12'"
:md="singleColumn ? '12' : '6'"
:lg="singleColumn ? '12' : '4'"
:xl="singleColumn ? '12' : '3'"
>
<v-lazy>
<RecipeCardMobile
:name="recipe.name"
:description="recipe.description"
:slug="recipe.slug"
:rating="recipe.rating"
:image="recipe.image"
:tags="recipe.tags"
:recipe-id="recipe.id"
/>
</v-lazy>
</v-col>
</v-row>
<div v-if="recipes && ready">
<div class="mt-2">
<v-row v-if="!useMobileCards">
<v-col v-for="(recipe, index) in recipes" :key="recipe.slug + index" :sm="6" :md="6" :lg="4" :xl="3">
<v-lazy>
<RecipeCard
:name="recipe.name"
:description="recipe.description"
:slug="recipe.slug"
:rating="recipe.rating"
:image="recipe.image"
:tags="recipe.tags"
:recipe-id="recipe.id"
/>
</v-lazy>
</v-col>
</v-row>
<v-row v-else dense>
<v-col
v-for="recipe in recipes"
:key="recipe.name"
cols="12"
:sm="singleColumn ? '12' : '12'"
:md="singleColumn ? '12' : '6'"
:lg="singleColumn ? '12' : '4'"
:xl="singleColumn ? '12' : '3'"
>
<v-lazy>
<RecipeCardMobile
:name="recipe.name"
:description="recipe.description"
:slug="recipe.slug"
:rating="recipe.rating"
:image="recipe.image"
:tags="recipe.tags"
:recipe-id="recipe.id"
/>
</v-lazy>
</v-col>
</v-row>
</div>
<v-card v-intersect="infiniteScroll"></v-card>
<v-fade-transition>
<AppLoader v-if="loading" :loading="loading" />
</v-fade-transition>
</div>
<v-card v-intersect="infiniteScroll"></v-card>
<v-fade-transition>
<AppLoader v-if="loading" :loading="loading" />
</v-fade-transition>
</div>
</template>

Expand Down Expand Up @@ -223,36 +225,42 @@ export default defineComponent({

const queryFilter = computed(() => {
const orderBy = props.query?.orderBy || preferences.value.orderBy;
return preferences.value.filterNull && orderBy ? `${orderBy} IS NOT NULL` : null;
const orderByFilter = preferences.value.filterNull && orderBy ? `${orderBy} IS NOT NULL` : null;

if (props.query.queryFilter && orderByFilter) {
return `(${props.query.queryFilter}) AND ${orderByFilter}`;
} else if (props.query.queryFilter) {
return props.query.queryFilter;
} else {
return orderByFilter;
}
});

async function fetchRecipes(pageCount = 1) {
return await fetchMore(
page.value,
// we double-up the first call to avoid a bug with large screens that render the entire first page without scrolling, preventing additional loading
perPage * pageCount,
props.query?.orderBy || preferences.value.orderBy,
props.query?.orderDirection || preferences.value.orderDirection,
props.query,
// filter out recipes that have a null value for the property we're sorting by
// we use a computed queryFilter to filter out recipes that have a null value for the property we're sorting by
queryFilter.value
);
}

onMounted(async () => {
if (props.query) {
await initRecipes();
ready.value = true;
}
await initRecipes();
ready.value = true;
});

let lastQuery: string | undefined;
let lastQuery: string | undefined = JSON.stringify(props.query);
watch(
() => props.query,
async (newValue: RecipeSearchQuery | undefined) => {
const newValueString = JSON.stringify(newValue)
if (newValue && (!ready.value || lastQuery !== newValueString)) {
if (lastQuery !== newValueString) {
lastQuery = newValueString;
ready.value = false;
await initRecipes();
ready.value = true;
}
Expand All @@ -261,8 +269,12 @@ export default defineComponent({

async function initRecipes() {
page.value = 1;
const newRecipes = await fetchRecipes(2);
if (!newRecipes.length) {
hasMore.value = true;

// we double-up the first call to avoid a bug with large screens that render
// the entire first page without scrolling, preventing additional loading
const newRecipes = await fetchRecipes(page.value + 1);
if (newRecipes.length < perPage) {
hasMore.value = false;
}

Expand All @@ -274,17 +286,18 @@ export default defineComponent({

const infiniteScroll = useThrottleFn(() => {
useAsync(async () => {
if (!ready.value || !hasMore.value || loading.value) {
if (!hasMore.value || loading.value) {
return;
}

loading.value = true;
page.value = page.value + 1;

const newRecipes = await fetchRecipes();
if (!newRecipes.length) {
if (newRecipes.length < perPage) {
hasMore.value = false;
} else {
}
if (newRecipes.length) {
context.emit(APPEND_RECIPES_EVENT, newRecipes);
}

Expand Down Expand Up @@ -379,6 +392,7 @@ export default defineComponent({
displayTitleIcon,
EVENTS,
infiniteScroll,
ready,
loading,
navigateRandom,
preferences,
Expand Down
14 changes: 14 additions & 0 deletions frontend/components/Domain/Recipe/RecipeDataTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
v-model="selected"
item-key="id"
show-select
sort-by="dateAdded"
sort-desc
:headers="headers"
:items="recipes"
:items-per-page="15"
Expand Down Expand Up @@ -39,6 +41,9 @@
</v-list-item-content>
</v-list-item>
</template>
<template #item.dateAdded="{ item }">
{{ formatDate(item.dateAdded) }}
</template>
</v-data-table>
</template>

Expand Down Expand Up @@ -132,6 +137,14 @@ export default defineComponent({
return hdrs;
});

function formatDate(date: string) {
try {
return i18n.d(Date.parse(date), "medium");
} catch {
return "";
}
}

// ============
// Group Members
const api = useUserApi();
Expand Down Expand Up @@ -160,6 +173,7 @@ export default defineComponent({
groupSlug,
setValue,
headers,
formatDate,
members,
getMember,
};
Expand Down
Loading
Loading