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: Add Household Filter to Meal Plan Rules #4231

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 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
985cbfd
added households filter to meal plan rule table
michael-genson Sep 18, 2024
9ce9562
update plan rules schema
michael-genson Sep 18, 2024
1110e55
simplify get random meal route and added households filter
michael-genson Sep 18, 2024
1c79199
fixes
michael-genson Sep 18, 2024
02a616b
added tests
michael-genson Sep 18, 2024
5581150
better naming
michael-genson Sep 18, 2024
d779357
dev:generate
michael-genson Sep 18, 2024
895095a
added household selection to frontend
michael-genson Sep 18, 2024
1691d3e
Merge remote-tracking branch 'upstream/mealie-next' into feat/add-hou…
michael-genson Sep 22, 2024
301a7af
Merge branch 'mealie-next' into feat/add-household-filter-to-mealplan…
michael-genson Sep 25, 2024
21696b8
Update mealie/routes/households/controller_mealplan.py
michael-genson Sep 25, 2024
4f195c0
Merge branch 'mealie-next' into feat/add-household-filter-to-mealplan…
michael-genson Sep 27, 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""add households filter to meal plans

Revision ID: 1fe4bd37ccc8
Revises: be568e39ffdf
Create Date: 2024-09-18 14:52:55.831540

"""

import sqlalchemy as sa

import mealie.db.migration_types
from alembic import op

# revision identifiers, used by Alembic.
revision = "1fe4bd37ccc8"
down_revision: str | None = "be568e39ffdf"
branch_labels: str | tuple[str, ...] | None = None
depends_on: str | tuple[str, ...] | None = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"plan_rules_to_households",
sa.Column("group_plan_rule_id", mealie.db.migration_types.GUID(), nullable=True),
sa.Column("household_id", mealie.db.migration_types.GUID(), nullable=True),
sa.ForeignKeyConstraint(
["group_plan_rule_id"],
["group_meal_plan_rules.id"],
),
sa.ForeignKeyConstraint(
["household_id"],
["households.id"],
),
sa.UniqueConstraint("group_plan_rule_id", "household_id", name="group_plan_rule_id_household_id_key"),
)
with op.batch_alter_table("plan_rules_to_households", schema=None) as batch_op:
batch_op.create_index(
batch_op.f("ix_plan_rules_to_households_group_plan_rule_id"), ["group_plan_rule_id"], unique=False
)
batch_op.create_index(batch_op.f("ix_plan_rules_to_households_household_id"), ["household_id"], unique=False)

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table("plan_rules_to_households", schema=None) as batch_op:
batch_op.drop_index(batch_op.f("ix_plan_rules_to_households_household_id"))
batch_op.drop_index(batch_op.f("ix_plan_rules_to_households_group_plan_rule_id"))

op.drop_table("plan_rules_to_households")
# ### end Alembic commands ###
91 changes: 91 additions & 0 deletions frontend/components/Domain/Household/GroupHouseholdSelector.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<template>
<v-select
v-model="selected"
:items="households"
:label="label"
:hint="description"
:persistent-hint="!!description"
item-text="name"
:multiple="multiselect"
:prepend-inner-icon="$globals.icons.household"
return-object
>
<template #selection="data">
<v-chip
:key="data.index"
class="ma-1"
:input-value="data.selected"
small
close
label
color="accent"
dark
@click:close="removeByIndex(data.index)"
>
{{ data.item.name || data.item }}
</v-chip>
</template>
</v-select>
</template>

<script lang="ts">
import { computed, defineComponent, onMounted, useContext } from "@nuxtjs/composition-api";
import { useHouseholdStore } from "~/composables/store/use-household-store";

interface HouseholdLike {
id: string;
name: string;
}

export default defineComponent({
props: {
value: {
type: Array as () => HouseholdLike[],
required: true,
},
multiselect: {
type: Boolean,
default: false,
},
description: {
type: String,
default: "",
},
},
setup(props, context) {
const selected = computed({
get: () => props.value,
set: (val) => {
context.emit("input", val);
},
});

onMounted(() => {
if (selected.value === undefined) {
selected.value = [];
}
});

const { i18n } = useContext();
const label = computed(
() => props.multiselect ? i18n.tc("household.households") : i18n.tc("household.household")
);

const { store: households } = useHouseholdStore();
function removeByIndex(index: number) {
if (selected.value === undefined) {
return;
}
const newSelected = selected.value.filter((_, i) => i !== index);
selected.value = [...newSelected];
}

return {
selected,
label,
households,
removeByIndex,
};
},
});
</script>
33 changes: 28 additions & 5 deletions frontend/components/Domain/Household/GroupMealPlanRuleForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,15 @@
<v-select v-model="inputEntryType" :items="MEAL_TYPE_OPTIONS" :label="$t('meal-plan.meal-type')"></v-select>
</div>

<RecipeOrganizerSelector v-model="inputCategories" selector-type="categories" />
<RecipeOrganizerSelector v-model="inputTags" selector-type="tags" />
<div class="mb-5">
<RecipeOrganizerSelector v-model="inputCategories" selector-type="categories" />
<RecipeOrganizerSelector v-model="inputTags" selector-type="tags" />
<GroupHouseholdSelector
v-model="inputHouseholds"
multiselect
:description="$tc('meal-plan.mealplan-households-description')"
/>
</div>

<!-- TODO: proper pluralization of inputDay -->
{{ $t('meal-plan.this-rule-will-apply', {
Expand All @@ -18,11 +25,13 @@

<script lang="ts">
import { defineComponent, computed, useContext } from "@nuxtjs/composition-api";
import GroupHouseholdSelector from "~/components/Domain/Household/GroupHouseholdSelector.vue";
import RecipeOrganizerSelector from "~/components/Domain/Recipe/RecipeOrganizerSelector.vue";
import { RecipeTag, RecipeCategory } from "~/lib/api/types/recipe";
import { PlanCategory, PlanHousehold, PlanTag } from "~/lib/api/types/meal-plan";

export default defineComponent({
components: {
GroupHouseholdSelector,
RecipeOrganizerSelector,
},
props: {
Expand All @@ -35,11 +44,15 @@ export default defineComponent({
default: "unset",
},
categories: {
type: Array as () => RecipeCategory[],
type: Array as () => PlanCategory[],
default: () => [],
},
tags: {
type: Array as () => RecipeTag[],
type: Array as () => PlanTag[],
default: () => [],
},
households: {
type: Array as () => PlanHousehold[],
default: () => [],
},
showHelp: {
Expand Down Expand Up @@ -105,13 +118,23 @@ export default defineComponent({
},
});

const inputHouseholds = computed({
get: () => {
return props.households;
},
set: (val) => {
context.emit("update:households", val);
},
});

return {
MEAL_TYPE_OPTIONS,
MEAL_DAY_OPTIONS,
inputDay,
inputEntryType,
inputCategories,
inputTags,
inputHouseholds,
};
},
});
Expand Down
4 changes: 4 additions & 0 deletions frontend/lang/messages/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,10 @@
"mealplan-settings": "Mealplan Settings",
"mealplan-update-failed": "Mealplan update failed",
"mealplan-updated": "Mealplan Updated",
"mealplan-households-description": "If no household is selected, recipes can be added from any household",
"any-category": "Any Category",
"any-tag": "Any Tag",
"any-household": "Any Household",
"no-meal-plan-defined-yet": "No meal plan defined yet",
"no-meal-planned-for-today": "No meal planned for today",
"numberOfDays-hint": "Number of days on page load",
Expand Down
27 changes: 20 additions & 7 deletions frontend/lib/api/types/meal-plan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,31 +31,44 @@ export interface ListItem {
quantity?: number;
checked?: boolean;
}
export interface PlanCategory {
id: string;
name: string;
slug: string;
}
michael-genson marked this conversation as resolved.
Show resolved Hide resolved
export interface PlanHousehold {
id: string;
name: string;
slug: string;
}
export interface PlanRulesCreate {
day?: PlanRulesDay & string;
entryType?: PlanRulesType & string;
categories?: Category[];
tags?: Tag[];
categories?: PlanCategory[];
tags?: PlanTag[];
households?: PlanHousehold[];
}
export interface Tag {
export interface PlanTag {
id: string;
name: string;
slug: string;
}
export interface PlanRulesOut {
day?: PlanRulesDay & string;
entryType?: PlanRulesType & string;
categories?: Category[];
tags?: Tag[];
categories?: PlanCategory[];
tags?: PlanTag[];
households?: PlanHousehold[];
groupId: string;
householdId: string;
id: string;
}
export interface PlanRulesSave {
day?: PlanRulesDay & string;
entryType?: PlanRulesType & string;
categories?: Category[];
tags?: Tag[];
categories?: PlanCategory[];
tags?: PlanTag[];
households?: PlanHousehold[];
groupId: string;
householdId: string;
}
Expand Down
54 changes: 52 additions & 2 deletions frontend/pages/household/mealplan/settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
:entry-type.sync="createData.entryType"
:categories.sync="createData.categories"
:tags.sync="createData.tags"
:households.sync="createData.households"
/>
</v-card-text>
<v-card-actions class="justify-end">
Expand Down Expand Up @@ -58,12 +59,58 @@
<template v-if="!editState[rule.id]">
<div v-if="rule.categories">
<h4 class="py-1">{{ $t("category.categories") }}:</h4>
<RecipeChips :items="rule.categories" small />
<RecipeChips v-if="rule.categories.length" :items="rule.categories" small class="pb-3" />
<v-card-text
v-else
label
class="ma-0 px-0 pt-0 pb-3"
text-color="accent"
small
dark
>
{{ $tc("meal-plan.any-category") }}
</v-card-text>
</div>

<div v-if="rule.tags">
<h4 class="py-1">{{ $t("tag.tags") }}:</h4>
<RecipeChips :items="rule.tags" url-prefix="tags" small />
<RecipeChips v-if="rule.tags.length" :items="rule.tags" url-prefix="tags" small class="pb-3" />
<v-card-text
v-else
label
class="ma-0 px-0 pt-0 pb-3"
text-color="accent"
small
dark
>
{{ $tc("meal-plan.any-tag") }}
</v-card-text>
</div>
<div v-if="rule.households">
<h4 class="py-1">{{ $t("household.households") }}:</h4>
<div v-if="rule.households.length">
<v-chip
v-for="household in rule.households"
:key="household.id"
label
class="ma-1"
color="accent"
small
dark
>
{{ household.name }}
</v-chip>
</div>
<v-card-text
v-else
label
class="ma-0 px-0 pt-0 pb-3"
text-color="accent"
small
dark
>
{{ $tc("meal-plan.any-household") }}
</v-card-text>
</div>
</template>
<template v-else>
Expand All @@ -72,6 +119,7 @@
:entry-type.sync="allRules[idx].entryType"
:categories.sync="allRules[idx].categories"
:tags.sync="allRules[idx].tags"
:households.sync="allRules[idx].households"
/>
<div class="d-flex justify-end">
<BaseButton update @click="updateRule(rule)" />
Expand Down Expand Up @@ -138,6 +186,7 @@ export default defineComponent({
day: "unset",
categories: [],
tags: [],
households: [],
});

async function createRule() {
Expand All @@ -149,6 +198,7 @@ export default defineComponent({
day: "unset",
categories: [],
tags: [],
households: [],
};
}
}
Expand Down
Loading
Loading