Skip to content

Commit

Permalink
Merge branch 'mealie-next' into persist-img-exif-data-iss-4681
Browse files Browse the repository at this point in the history
  • Loading branch information
hay-kot authored Jan 14, 2025
2 parents 32f814c + d7f460b commit 9ad5f67
Show file tree
Hide file tree
Showing 151 changed files with 5,532 additions and 2,510 deletions.
14 changes: 0 additions & 14 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,6 @@
-->

## What type of PR is this?

_(REQUIRED)_

<!--
Delete any of the following that do not apply:
-->

- feature
- bug
- documentation
- cleanup
- dev (Internal development)

## What this PR does / why we need it:

_(REQUIRED)_
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ repos:
exclude: ^tests/data/
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.8.4
rev: v0.9.0
hooks:
- id: ruff
- id: ruff-format
28 changes: 28 additions & 0 deletions docs/docs/documentation/getting-started/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,24 @@ Do the following for each recipe you want to intelligently handle ingredients.

Scaling up this recipe or adding it to a Shopping List will now smartly take care of ingredient amounts and duplicate combinations.

## How do I enable Nutritional Values?
Mealie can store Nutritional Information for Recipes. Please note that the values you enter are static for the recipe and no scaling is being done when changing Servings / Yield.

Do the following to enable Nutritional Values on individual Recipes, or to modify your Household Recipe Preferences

### Show Nutritional Values on a Single Recipe
1. Go to a recipe
2. Click the Edit button/icon
3. Click the Recipe Settings gear and select `Show Nutritional Values`
4. Scroll down to manually fill out the Nutritional Values
5. Save

### Show Nutritional Values by default
1. Click your username in the top left
2. Click the 'Household Settings' button
3. Under 'Household Recipe Preferences', click to select 'Show nutrition information'
4. Click 'Update'

## Is it safe to upgrade Mealie?

Yes. If you are using the v1 branches (including beta), you can upgrade to the latest version of Mealie without performing a site Export/Restore. This process was required in previous versions of Mealie, however we've automated the database migration process to make it easier to upgrade. Note that if you were using the v0.5.x version, you CANNOT upgrade to the latest version automatically. You must follow the migration instructions in the documentation.
Expand Down Expand Up @@ -84,6 +102,16 @@ docker exec -it mealie bash
python /app/mealie/scripts/reset_locked_users.py
```

## How can I reset admin privileges for my account?

If you've lost admin privileges and no other admin can restore them, you can use the Command Line Interface (CLI) to grant admin access.

```shell
docker exec -it mealie bash

python /app/mealie/scripts/make_admin.py
```

## How can I change my password?

You can change your password by going to the user profile page and clicking the "Change Password" button. Alternatively you can use the following script to change your password via the CLI if you are locked out of your account.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ To deploy mealie on your local network, it is highly recommended to use Docker t
We've gone through a few versions of Mealie v1 deployment targets. We have settled on a single container deployment, and we've begun publishing the nightly container on github containers. If you're looking to move from the old nightly (split containers _or_ the omni image) to the new nightly, there are a few things you need to do:

1. Take a backup just in case!
2. Replace the image for the API container with `ghcr.io/mealie-recipes/mealie:v2.4.1`
2. Replace the image for the API container with `ghcr.io/mealie-recipes/mealie:v2.4.2`
3. Take the external port from the frontend container and set that as the port mapped to port `9000` on the new container. The frontend is now served on port 9000 from the new container, so it will need to be mapped for you to have access.
4. Restart the container

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ PostgreSQL might be considered if you need to support many concurrent users. In
```yaml
services:
mealie:
image: ghcr.io/mealie-recipes/mealie:v2.4.1 # (3)
image: ghcr.io/mealie-recipes/mealie:v2.4.2 # (3)
container_name: mealie
restart: always
ports:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ SQLite is a popular, open source, self-contained, zero-configuration database th
```yaml
services:
mealie:
image: ghcr.io/mealie-recipes/mealie:v2.4.1 # (3)
image: ghcr.io/mealie-recipes/mealie:v2.4.2 # (3)
container_name: mealie
restart: always
ports:
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/overrides/api.html

Large diffs are not rendered by default.

Binary file removed frontend/assets/audio/kitchen_alarm.mp3
Binary file not shown.
9 changes: 1 addition & 8 deletions frontend/components/Domain/Recipe/RecipeActionMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@
</v-tooltip>
</div>

<RecipeTimerMenu
fab
color="info"
class="ml-1"
/>

<RecipeContextMenu
show-print
:menu-top="false"
Expand Down Expand Up @@ -88,7 +82,6 @@
import { defineComponent, ref, useContext } from "@nuxtjs/composition-api";
import RecipeContextMenu from "./RecipeContextMenu.vue";
import RecipeFavoriteBadge from "./RecipeFavoriteBadge.vue";
import RecipeTimerMenu from "./RecipeTimerMenu.vue";
import RecipeTimelineBadge from "./RecipeTimelineBadge.vue";
import { Recipe } from "~/lib/api/types/recipe";
Expand All @@ -98,7 +91,7 @@ const CLOSE_EVENT = "close";
const JSON_EVENT = "json";
export default defineComponent({
components: { RecipeContextMenu, RecipeFavoriteBadge, RecipeTimerMenu, RecipeTimelineBadge },
components: { RecipeContextMenu, RecipeFavoriteBadge, RecipeTimelineBadge },
props: {
recipe: {
required: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ export default defineComponent({
shoppingListShowAllToggled: false,
});
const userHousehold = computed(() => {
return $auth.user?.householdSlug || "";
});
const shoppingListChoices = computed(() => {
return props.shoppingLists.filter((list) => preferences.value.viewAllLists || list.userId === $auth.user?.id);
});
Expand Down Expand Up @@ -248,8 +252,9 @@ export default defineComponent({
}
const shoppingListIngredients: ShoppingListIngredient[] = recipe.recipeIngredient.map((ing) => {
const householdsWithFood = (ing.food?.householdsWithIngredientFood || []);
return {
checked: !ing.food?.onHand,
checked: !householdsWithFood.includes(userHousehold.value),
ingredient: ing,
disableAmount: recipe.settings?.disableAmount || false,
}
Expand All @@ -276,7 +281,8 @@ export default defineComponent({
}
// Store the on-hand ingredients for later
if (ing.ingredient.food?.onHand) {
const householdsWithFood = (ing.ingredient.food?.householdsWithIngredientFood || []);
if (householdsWithFood.includes(userHousehold.value)) {
onHandIngs.push(ing);
return sections;
}
Expand Down
35 changes: 25 additions & 10 deletions frontend/components/Domain/Recipe/RecipeLastMade.vue
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,12 @@
<v-icon left>
{{ $globals.icons.calendar }}
</v-icon>
{{ $t('recipe.last-made-date', { date: value ? new Date(value).toLocaleDateString($i18n.locale) : $t("general.never") } ) }}
<div v-if="lastMadeReady">
{{ $t('recipe.last-made-date', { date: lastMade ? new Date(lastMade).toLocaleDateString($i18n.locale) : $t("general.never") } ) }}
</div>
<div v-else>
<AppLoader tiny />
</div>
</v-chip>
</div>
<div class="d-flex justify-center flex-wrap mt-1">
Expand All @@ -110,7 +115,7 @@
</template>

<script lang="ts">
import { computed, defineComponent, reactive, ref, toRefs, useContext } from "@nuxtjs/composition-api";
import { computed, defineComponent, onMounted, reactive, ref, toRefs, useContext } from "@nuxtjs/composition-api";
import { whenever } from "@vueuse/core";
import { VForm } from "~/types/vuetify";
import { useUserApi } from "~/composables/api";
Expand All @@ -119,10 +124,6 @@ import { Recipe, RecipeTimelineEventIn } from "~/lib/api/types/recipe";
export default defineComponent({
props: {
value: {
type: String,
default: null,
},
recipe: {
type: Object as () => Recipe,
required: true,
Expand All @@ -146,6 +147,20 @@ export default defineComponent({
const newTimelineEventImagePreviewUrl = ref<string>();
const newTimelineEventTimestamp = ref<string>();
const lastMade = ref(props.recipe.lastMade);
const lastMadeReady = ref(false);
onMounted(async () => {
if (!$auth.user?.householdSlug) {
lastMade.value = props.recipe.lastMade;
} else {
const { data } = await userApi.households.getCurrentUserHouseholdRecipe(props.recipe.slug || "");
lastMade.value = data?.lastMade;
}
lastMadeReady.value = true;
});
whenever(
() => madeThisDialog.value,
() => {
Expand Down Expand Up @@ -195,11 +210,9 @@ export default defineComponent({
const newEvent = eventResponse.data;
// we also update the recipe's last made value
if (!props.value || newTimelineEvent.value.timestamp > props.value) {
if (!lastMade.value || newTimelineEvent.value.timestamp > lastMade.value) {
lastMade.value = newTimelineEvent.value.timestamp;
await userApi.recipes.updateLastMade(props.recipe.slug, newTimelineEvent.value.timestamp);
// update recipe in parent so the user can see it
context.emit("input", newTimelineEvent.value.timestamp);
}
// update the image, if provided
Expand Down Expand Up @@ -234,6 +247,8 @@ export default defineComponent({
newTimelineEventImage,
newTimelineEventImagePreviewUrl,
newTimelineEventTimestamp,
lastMade,
lastMadeReady,
createTimelineEvent,
clearImage,
uploadImage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
:logged-in="isOwnGroup"
:open="isEditMode"
:recipe-id="recipe.id"
class="ml-auto mt-n8 pb-4"
class="ml-auto mt-n2 pb-4"
@close="setMode(PageMode.VIEW)"
@json="toggleEditMode()"
@edit="setMode(PageMode.EDIT)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
<v-col cols="12" class="d-flex flex-wrap justify-center">
<RecipeLastMade
v-if="isOwnGroup"
:value="recipe.lastMade"
:recipe="recipe"
:class="true ? undefined : 'force-bottom'"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<h2 class="mb-2 mt-4">{{ $t('tool.required-tools') }}</h2>
<v-list-item v-for="(tool, index) in recipe.tools" :key="index" dense>
<v-checkbox
v-model="recipe.tools[index].onHand"
v-model="recipeTools[index].onHand"
hide-details
class="pt-0 my-auto py-auto"
color="secondary"
Expand All @@ -26,14 +26,18 @@
</template>

<script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api";
import { computed, defineComponent } from "@nuxtjs/composition-api";
import { useLoggedInState } from "~/composables/use-logged-in-state";
import { usePageState, usePageUser } from "~/composables/recipe-page/shared-state";
import { useToolStore } from "~/composables/store";
import { NoUndefinedField } from "~/lib/api/types/non-generated";
import { Recipe } from "~/lib/api/types/recipe";
import { Recipe, RecipeTool } from "~/lib/api/types/recipe";
import RecipeIngredients from "~/components/Domain/Recipe/RecipeIngredients.vue";
interface RecipeToolWithOnHand extends RecipeTool {
onHand: boolean;
}
export default defineComponent({
components: {
RecipeIngredients,
Expand All @@ -59,16 +63,39 @@ export default defineComponent({
const { user } = usePageUser();
const { isEditMode } = usePageState(props.recipe.slug);
const recipeTools = computed(() => {
if (!(user.householdSlug && toolStore)) {
return props.recipe.tools.map((tool) => ({ ...tool, onHand: false }) as RecipeToolWithOnHand);
} else {
return props.recipe.tools.map((tool) => {
const onHand = tool.householdsWithTool?.includes(user.householdSlug) || false;
return { ...tool, onHand } as RecipeToolWithOnHand;
});
}
})
function updateTool(index: number) {
if (user.id && toolStore) {
toolStore.actions.updateOne(props.recipe.tools[index]);
if (user.id && user.householdSlug && toolStore) {
const tool = recipeTools.value[index];
if (tool.onHand && !tool.householdsWithTool?.includes(user.householdSlug)) {
if (!tool.householdsWithTool) {
tool.householdsWithTool = [user.householdSlug];
} else {
tool.householdsWithTool.push(user.householdSlug);
}
} else if (!tool.onHand && tool.householdsWithTool?.includes(user.householdSlug)) {
tool.householdsWithTool = tool.householdsWithTool.filter((household) => household !== user.householdSlug);
}
toolStore.actions.updateOne(tool);
} else {
console.log("no user, skipping server update");
}
}
return {
toolStore,
recipeTools,
isEditMode,
updateTool,
};
Expand Down
13 changes: 10 additions & 3 deletions frontend/components/Domain/Recipe/RecipeScaleEditButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@
<div>
<v-menu v-model="menu" :disabled="!canEditScale" offset-y top nudge-top="6" :close-on-content-click="false">
<template #activator="{ on, attrs }">
<v-card class="pa-1 px-2" dark color="secondary darken-1" small v-bind="attrs" v-on="on">
<v-icon small class="mr-2">{{ $globals.icons.edit }}</v-icon>
<v-card
class="pa-1 px-2"
dark
color="secondary darken-1"
small
v-bind="attrs"
:style="{ cursor: canEditScale ? '' : 'default' }"
v-on="on"
>
<v-icon v-if="canEditScale" small class="mr-2">{{ $globals.icons.edit }}</v-icon>
<!-- eslint-disable-next-line vue/no-v-html -->
<span v-html="yieldDisplay"></span>

</v-card>
</template>
<v-card min-width="300px">
Expand Down
Loading

0 comments on commit 9ad5f67

Please sign in to comment.