mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-08-05 05:25:26 +02:00
Merge branch 'mealie-next' into feat-frontend-access-controll
This commit is contained in:
commit
058d968833
193 changed files with 1808 additions and 990 deletions
|
@ -19,11 +19,11 @@
|
|||
</div>
|
||||
</v-card-text>
|
||||
<v-list v-if="showViewer" dense class="mt-0 pt-0">
|
||||
<v-list-item v-for="(item, key, index) in labels" :key="index" style="min-height: 25px" dense>
|
||||
<v-list-item v-for="(item, key, index) in renderedList" :key="index" style="min-height: 25px" dense>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title class="pl-4 caption flex row">
|
||||
<div>{{ item.label }}</div>
|
||||
<div class="ml-auto mr-1">{{ value[key] }}</div>
|
||||
<div class="ml-auto mr-1">{{ item.value }}</div>
|
||||
<div>{{ item.suffix }}</div>
|
||||
</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
|
@ -37,6 +37,14 @@
|
|||
import { computed, defineComponent, useContext } from "@nuxtjs/composition-api";
|
||||
import { Nutrition } from "~/lib/api/types/recipe";
|
||||
|
||||
type NutritionLabelType = {
|
||||
[key: string]: {
|
||||
label: string;
|
||||
suffix: string;
|
||||
value?: string;
|
||||
};
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
value: {
|
||||
|
@ -50,34 +58,34 @@ export default defineComponent({
|
|||
},
|
||||
setup(props, context) {
|
||||
const { i18n } = useContext();
|
||||
const labels = {
|
||||
const labels = <NutritionLabelType>{
|
||||
calories: {
|
||||
label: i18n.t("recipe.calories"),
|
||||
suffix: i18n.t("recipe.calories-suffix"),
|
||||
label: i18n.tc("recipe.calories"),
|
||||
suffix: i18n.tc("recipe.calories-suffix"),
|
||||
},
|
||||
fatContent: {
|
||||
label: i18n.t("recipe.fat-content"),
|
||||
suffix: i18n.t("recipe.grams"),
|
||||
label: i18n.tc("recipe.fat-content"),
|
||||
suffix: i18n.tc("recipe.grams"),
|
||||
},
|
||||
fiberContent: {
|
||||
label: i18n.t("recipe.fiber-content"),
|
||||
suffix: i18n.t("recipe.grams"),
|
||||
label: i18n.tc("recipe.fiber-content"),
|
||||
suffix: i18n.tc("recipe.grams"),
|
||||
},
|
||||
proteinContent: {
|
||||
label: i18n.t("recipe.protein-content"),
|
||||
suffix: i18n.t("recipe.grams"),
|
||||
label: i18n.tc("recipe.protein-content"),
|
||||
suffix: i18n.tc("recipe.grams"),
|
||||
},
|
||||
sodiumContent: {
|
||||
label: i18n.t("recipe.sodium-content"),
|
||||
suffix: i18n.t("recipe.milligrams"),
|
||||
label: i18n.tc("recipe.sodium-content"),
|
||||
suffix: i18n.tc("recipe.milligrams"),
|
||||
},
|
||||
sugarContent: {
|
||||
label: i18n.t("recipe.sugar-content"),
|
||||
suffix: i18n.t("recipe.grams"),
|
||||
label: i18n.tc("recipe.sugar-content"),
|
||||
suffix: i18n.tc("recipe.grams"),
|
||||
},
|
||||
carbohydrateContent: {
|
||||
label: i18n.t("recipe.carbohydrate-content"),
|
||||
suffix: i18n.t("recipe.grams"),
|
||||
label: i18n.tc("recipe.carbohydrate-content"),
|
||||
suffix: i18n.tc("recipe.grams"),
|
||||
},
|
||||
};
|
||||
const valueNotNull = computed(() => {
|
||||
|
@ -96,11 +104,25 @@ export default defineComponent({
|
|||
context.emit("input", { ...props.value, [key]: event });
|
||||
}
|
||||
|
||||
// Build a new list that only contains nutritional information that has a value
|
||||
const renderedList = computed(() => {
|
||||
return Object.entries(labels).reduce((item: NutritionLabelType, [key, label]) => {
|
||||
if (props.value[key]?.trim()) {
|
||||
item[key] = {
|
||||
...label,
|
||||
value: props.value[key],
|
||||
};
|
||||
}
|
||||
return item;
|
||||
}, {});
|
||||
});
|
||||
|
||||
return {
|
||||
labels,
|
||||
valueNotNull,
|
||||
showViewer,
|
||||
updateValue,
|
||||
renderedList,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -200,7 +200,7 @@
|
|||
"created-on-date": "Създадено на {0}",
|
||||
"unsaved-changes": "Имате незапазени промени. Желаете ли да ги запазите преди да излезете? Натиснете Ок за запазване и Отказ за отхвърляне на промените.",
|
||||
"clipboard-copy-failure": "Линкът към рецептата е копиран в клипборда.",
|
||||
"confirm-delete-generic-items": "Are you sure you want to delete the following items?"
|
||||
"confirm-delete-generic-items": "Сигурни ли сте, че желаете да изтриете следните елементи?"
|
||||
},
|
||||
"group": {
|
||||
"are-you-sure-you-want-to-delete-the-group": "Сигурни ли сте, че искате да изтриете <b>{groupName}<b/>?",
|
||||
|
@ -259,7 +259,7 @@
|
|||
},
|
||||
"meal-plan": {
|
||||
"create-a-new-meal-plan": "Създаване на нов хранителен план",
|
||||
"update-this-meal-plan": "Update this Meal Plan",
|
||||
"update-this-meal-plan": "Обнови този План за хранене",
|
||||
"dinner-this-week": "Вечеря тази седмица",
|
||||
"dinner-today": "Вечеря Днес",
|
||||
"dinner-tonight": "Вечеря ТАЗИ ВЕЧЕР",
|
||||
|
@ -474,11 +474,11 @@
|
|||
"add-to-timeline": "Добави към времевата линия",
|
||||
"recipe-added-to-list": "Рецептата е добавена към списъка",
|
||||
"recipes-added-to-list": "Рецептите са добавени към списъка",
|
||||
"successfully-added-to-list": "Successfully added to list",
|
||||
"successfully-added-to-list": "Успешно добавено в списъка",
|
||||
"recipe-added-to-mealplan": "Рецептата е добавена към хранителния план",
|
||||
"failed-to-add-recipes-to-list": "Неуспешно добавяне на рецепта към списъка",
|
||||
"failed-to-add-recipe-to-mealplan": "Рецептата не беше добавена към хранителния план",
|
||||
"failed-to-add-to-list": "Failed to add to list",
|
||||
"failed-to-add-to-list": "Неуспешно добавяне към списъка",
|
||||
"yield": "Добив",
|
||||
"quantity": "Количество",
|
||||
"choose-unit": "Избери единица",
|
||||
|
@ -537,8 +537,8 @@
|
|||
"new-recipe-names-must-be-unique": "Името на рецептата трябва да бъде уникално",
|
||||
"scrape-recipe": "Обхождане на рецепта",
|
||||
"scrape-recipe-description": "Обходи рецепта по линк. Предоставете линк за сайт, който искате да бъде обходен. Mealie ще опита да обходи рецептата от този сайт и да я добави във Вашата колекция.",
|
||||
"scrape-recipe-have-a-lot-of-recipes": "Have a lot of recipes you want to scrape at once?",
|
||||
"scrape-recipe-suggest-bulk-importer": "Try out the bulk importer",
|
||||
"scrape-recipe-have-a-lot-of-recipes": "Имате много рецепти, които искате да обходите наведнъж?",
|
||||
"scrape-recipe-suggest-bulk-importer": "Пробвайте масовото импорторане",
|
||||
"import-original-keywords-as-tags": "Импортирай оригиналните ключови думи като тагове",
|
||||
"stay-in-edit-mode": "Остани в режим на редакция",
|
||||
"import-from-zip": "Импортирай от Zip",
|
||||
|
@ -562,7 +562,7 @@
|
|||
"upload-image": "Качване на изображение",
|
||||
"screen-awake": "Запази екрана активен",
|
||||
"remove-image": "Премахване на изображение",
|
||||
"nextStep": "Next step"
|
||||
"nextStep": "Следваща стъпка"
|
||||
},
|
||||
"search": {
|
||||
"advanced-search": "Разширено търсене",
|
||||
|
@ -1187,7 +1187,7 @@
|
|||
"require-all-tools": "Изискване на всички инструменти",
|
||||
"cookbook-name": "Име на книгата с рецепти",
|
||||
"cookbook-with-name": "Книга с рецепти {0}",
|
||||
"create-a-cookbook": "Create a Cookbook",
|
||||
"cookbook": "Cookbook"
|
||||
"create-a-cookbook": "Създай Готварска книга",
|
||||
"cookbook": "Готварска книга"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -200,7 +200,7 @@
|
|||
"created-on-date": "נוצר ב-{0}",
|
||||
"unsaved-changes": "יש שינויים שלא נשמרו. לצאת לפני שמירה? אשר לשמירה, בטל למחיקת שינויים.",
|
||||
"clipboard-copy-failure": "כשלון בהעתקה ללוח ההדבקה.",
|
||||
"confirm-delete-generic-items": "Are you sure you want to delete the following items?"
|
||||
"confirm-delete-generic-items": "האם אתה בטוח שברצונך למחוק את הפריטים הנבחרים?"
|
||||
},
|
||||
"group": {
|
||||
"are-you-sure-you-want-to-delete-the-group": "האם את/ה בטוח/ה שברצונך למחוק את <b>{groupName}<b/>?",
|
||||
|
@ -259,7 +259,7 @@
|
|||
},
|
||||
"meal-plan": {
|
||||
"create-a-new-meal-plan": "יצירת תכנית ארוחות חדשה",
|
||||
"update-this-meal-plan": "Update this Meal Plan",
|
||||
"update-this-meal-plan": "עדכן את תכנון הארוחות",
|
||||
"dinner-this-week": "ארוחות ערב השבוע",
|
||||
"dinner-today": "ארוחת ערב היום",
|
||||
"dinner-tonight": "ארוחת ערב היום",
|
||||
|
@ -474,11 +474,11 @@
|
|||
"add-to-timeline": "הוסף לציר הזמן",
|
||||
"recipe-added-to-list": "מתכון נוסף לרשימה",
|
||||
"recipes-added-to-list": "מתכונים הוספו לרשימה",
|
||||
"successfully-added-to-list": "Successfully added to list",
|
||||
"successfully-added-to-list": "נוסף לרשימה בהצלחה",
|
||||
"recipe-added-to-mealplan": "מתכון נוסף לתכנון ארוחות",
|
||||
"failed-to-add-recipes-to-list": "כשלון בהוספת מתכון לרשימה",
|
||||
"failed-to-add-recipe-to-mealplan": "הוספת מתכון לתכנון ארוחות נכשלה",
|
||||
"failed-to-add-to-list": "Failed to add to list",
|
||||
"failed-to-add-to-list": "כשלון בהוספה לרשימה",
|
||||
"yield": "תשואה",
|
||||
"quantity": "כמות",
|
||||
"choose-unit": "בחירת יחידת מידה",
|
||||
|
@ -515,7 +515,7 @@
|
|||
"how-did-it-turn-out": "איך יצא?",
|
||||
"user-made-this": "{user} הכין את זה",
|
||||
"last-made-date": "נעשה לאחרונה ב{date}",
|
||||
"api-extras-description": "Recipes extras are a key feature of the Mealie API. They allow you to create custom JSON key/value pairs within a recipe, to reference from 3rd party applications. You can use these keys to provide information, for example to trigger automations or custom messages to relay to your desired device.",
|
||||
"api-extras-description": "מתכונים נוספים הם יכולת מפתח של Mealie API. הם מאפשרים ליצור צמדי key/value בצורת JSON על מנת לקרוא אותם בתוכנת צד שלישית. תוכלו להשתמש בצמדים האלה כדי לספק מידע, לדוגמא להפעיל אוטומציות או הודעות מותאמות אישית למכשירים מסויימים.",
|
||||
"message-key": "מפתח הודעה",
|
||||
"parse": "ניתוח",
|
||||
"attach-images-hint": "הוסף תמונות ע\"י גרירה ושחרור אל תוך העורך",
|
||||
|
@ -537,8 +537,8 @@
|
|||
"new-recipe-names-must-be-unique": "שם מתכון חדש חייב להיות ייחודי",
|
||||
"scrape-recipe": "קריאת מתכון",
|
||||
"scrape-recipe-description": "קריאת מתכון בעזרת לינק. ספק את הלינק של האתר שברצונך לקרוא, ומילי תנסה לקרוא את המתכון מהאתר ולהוסיף אותו לאוסף.",
|
||||
"scrape-recipe-have-a-lot-of-recipes": "Have a lot of recipes you want to scrape at once?",
|
||||
"scrape-recipe-suggest-bulk-importer": "Try out the bulk importer",
|
||||
"scrape-recipe-have-a-lot-of-recipes": "יש לך הרבה מתכונים שאתה רוצה לקרוא בבת אחת?",
|
||||
"scrape-recipe-suggest-bulk-importer": "נסה את יכולת קריאת רשימה",
|
||||
"import-original-keywords-as-tags": "ייבא שמות מפתח מקוריות כתגיות",
|
||||
"stay-in-edit-mode": "השאר במצב עריכה",
|
||||
"import-from-zip": "ייבא מקובץ",
|
||||
|
@ -562,7 +562,7 @@
|
|||
"upload-image": "העלה תמונה",
|
||||
"screen-awake": "השאר את המסך פעיל",
|
||||
"remove-image": "האם למחוק את התמונה?",
|
||||
"nextStep": "Next step"
|
||||
"nextStep": "השלב הבא"
|
||||
},
|
||||
"search": {
|
||||
"advanced-search": "חיפוש מתקדם",
|
||||
|
@ -797,7 +797,7 @@
|
|||
"untagged-count": "לא מתוייג {count}",
|
||||
"create-a-tag": "צור תגית",
|
||||
"tag-name": "שם תגית",
|
||||
"tag": "Tag"
|
||||
"tag": "תגית"
|
||||
},
|
||||
"tool": {
|
||||
"tools": "כלים",
|
||||
|
@ -807,7 +807,7 @@
|
|||
"create-new-tool": "יצירת כלי חדש",
|
||||
"on-hand-checkbox-label": "הראה מה יש לי במטבח",
|
||||
"required-tools": "צריך כלים",
|
||||
"tool": "Tool"
|
||||
"tool": "כלי"
|
||||
},
|
||||
"user": {
|
||||
"admin": "אדמין",
|
||||
|
@ -898,10 +898,10 @@
|
|||
"user-can-organize-group-data": "משתמש יכול לשנות מידע של קבוצה",
|
||||
"enable-advanced-features": "אפשר אפשרויות מתקדמות",
|
||||
"it-looks-like-this-is-your-first-time-logging-in": "נראה שזו ההתחברות הראשונה שלך.",
|
||||
"dont-want-to-see-this-anymore-be-sure-to-change-your-email": "Don't want to see this anymore? Be sure to change your email in your user settings!",
|
||||
"dont-want-to-see-this-anymore-be-sure-to-change-your-email": "לא רוצה לראות את זה יותר? דאג לשנות את המייל של בהגדרות המשתמש!",
|
||||
"forgot-password": "שכחתי סיסמא",
|
||||
"forgot-password-text": "Please enter your email address and we will send you a link to reset your password.",
|
||||
"changes-reflected-immediately": "Changes to this user will be reflected immediately."
|
||||
"forgot-password-text": "נא לספק כתובת דוא\"ל. אנו נשלח לך הודעת דוא\"ל לצורך איפוס הסיסמה שלך.",
|
||||
"changes-reflected-immediately": "השינויים למשתמש זה יבוצעו מיידית."
|
||||
},
|
||||
"language-dialog": {
|
||||
"translated": "תורגם",
|
||||
|
@ -923,8 +923,8 @@
|
|||
"food-label": "תוית אוכל",
|
||||
"edit-food": "עריכת מזון",
|
||||
"food-data": "נתוני אוכל",
|
||||
"example-food-singular": "ex: Onion",
|
||||
"example-food-plural": "ex: Onions"
|
||||
"example-food-singular": "דוגמא: בצל",
|
||||
"example-food-plural": "דוגמא: בצלים"
|
||||
},
|
||||
"units": {
|
||||
"seed-dialog-text": "אכלס את מסד הנתונים עם יחידות מדידה בהתאם לשפה המקומית שלך.",
|
||||
|
@ -935,7 +935,7 @@
|
|||
"merging-unit-into-unit": "ממזג את {0} לתוך {1}",
|
||||
"create-unit": "יצירת יחידה",
|
||||
"abbreviation": "קיצור",
|
||||
"plural-abbreviation": "Plural Abbreviation",
|
||||
"plural-abbreviation": "צורת הרבית",
|
||||
"description": "תיאור",
|
||||
"display-as-fraction": "הצגה כשבר",
|
||||
"use-abbreviation": "השתמש בקיצור",
|
||||
|
@ -943,10 +943,10 @@
|
|||
"unit-data": "נתוני יחידה",
|
||||
"use-abbv": "השתמש בקיצור",
|
||||
"fraction": "שבר",
|
||||
"example-unit-singular": "ex: Tablespoon",
|
||||
"example-unit-plural": "ex: Tablespoons",
|
||||
"example-unit-abbreviation-singular": "ex: Tbsp",
|
||||
"example-unit-abbreviation-plural": "ex: Tbsps"
|
||||
"example-unit-singular": "דוגמא: כפית",
|
||||
"example-unit-plural": "דוגמא: כפיות",
|
||||
"example-unit-abbreviation-singular": "דוגמא: כף",
|
||||
"example-unit-abbreviation-plural": "דוגמא: כפות"
|
||||
},
|
||||
"labels": {
|
||||
"seed-dialog-text": "אכלס את מסד הנתונים בתגיות נפוצות בהתאם לשפה המקומית שלך.",
|
||||
|
@ -1187,7 +1187,7 @@
|
|||
"require-all-tools": "זקוק לכל הכלים",
|
||||
"cookbook-name": "שם ספר בישול",
|
||||
"cookbook-with-name": "ספר בישול {0}",
|
||||
"create-a-cookbook": "Create a Cookbook",
|
||||
"cookbook": "Cookbook"
|
||||
"create-a-cookbook": "צור ספר בישול חדש",
|
||||
"cookbook": "ספר בישול"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -200,7 +200,7 @@
|
|||
"created-on-date": "Gemaakt op {0}",
|
||||
"unsaved-changes": "Er zijn niet-opgeslagen wijzigingen. Wil je eerst opslaan voordat je vertrekt? Okay om op te slaan, Annuleren om wijzigingen ongedaan te maken.",
|
||||
"clipboard-copy-failure": "Kopiëren naar klembord mislukt.",
|
||||
"confirm-delete-generic-items": "Are you sure you want to delete the following items?"
|
||||
"confirm-delete-generic-items": "Weet u zeker dat u de volgende items wilt verwijderen?"
|
||||
},
|
||||
"group": {
|
||||
"are-you-sure-you-want-to-delete-the-group": "Weet je zeker dat je <b>{groupName}<b/> wil verwijderen?",
|
||||
|
|
|
@ -707,7 +707,7 @@
|
|||
"email-configured": "Email настроен",
|
||||
"email-test-results": "Результаты теста Email",
|
||||
"ready": "Готово",
|
||||
"not-ready": "Не готово - Проверьте переменные окружающей среды",
|
||||
"not-ready": "Не готово - Проверьте переменные окружения",
|
||||
"succeeded": "Выполнено успешно",
|
||||
"failed": "Ошибка",
|
||||
"general-about": "Общая информация",
|
||||
|
|
|
@ -31,7 +31,24 @@
|
|||
<BaseButton type="button" :loading="generatingToken" create @click.prevent="handlePasswordReset">
|
||||
{{ $t("user.generate-password-reset-link") }}
|
||||
</BaseButton>
|
||||
<AppButtonCopy v-if="resetUrl" :copy-text="resetUrl"></AppButtonCopy>
|
||||
</div>
|
||||
<div v-if="resetUrl" class="mb-2">
|
||||
<v-card-text>
|
||||
<p class="text-center pb-0">
|
||||
{{ resetUrl }}
|
||||
</p>
|
||||
</v-card-text>
|
||||
<v-card-actions class="align-center pt-0" style="gap: 4px">
|
||||
<BaseButton cancel @click="resetUrl = ''"> {{ $t("general.close") }} </BaseButton>
|
||||
<v-spacer></v-spacer>
|
||||
<BaseButton v-if="user.email" color="info" class="mr-1" @click="sendResetEmail">
|
||||
<template #icon>
|
||||
{{ $globals.icons.email }}
|
||||
</template>
|
||||
{{ $t("user.email") }}
|
||||
</BaseButton>
|
||||
<AppButtonCopy :icon="false" color="info" :copy-text="resetUrl" />
|
||||
</v-card-actions>
|
||||
</div>
|
||||
|
||||
<AutoForm v-model="user" :items="userForm" update-mode :disabled-fields="disabledFields" />
|
||||
|
@ -46,7 +63,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, useRoute, onMounted, ref, useContext } from "@nuxtjs/composition-api";
|
||||
import { useAdminApi } from "~/composables/api";
|
||||
import { useAdminApi, useUserApi } from "~/composables/api";
|
||||
import { useGroups } from "~/composables/use-groups";
|
||||
import { alert } from "~/composables/use-toast";
|
||||
import { useUserForm } from "~/composables/use-users";
|
||||
|
@ -118,6 +135,17 @@ export default defineComponent({
|
|||
generatingToken.value = false;
|
||||
}
|
||||
|
||||
const userApi = useUserApi();
|
||||
async function sendResetEmail() {
|
||||
if (!user.value?.email) return;
|
||||
const { response } = await userApi.email.sendForgotPassword({ email: user.value.email });
|
||||
if (response && response.status === 200) {
|
||||
alert.success(i18n.tc("profile.email-sent"));
|
||||
} else {
|
||||
alert.error(i18n.tc("profile.error-sending-email"));
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
disabledFields,
|
||||
|
@ -130,6 +158,7 @@ export default defineComponent({
|
|||
handlePasswordReset,
|
||||
resetUrl,
|
||||
generatingToken,
|
||||
sendResetEmail,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue