mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 06:23:34 -07:00
Merge remote-tracking branch 'upstream/dev' into localization
This commit is contained in:
commit
a7f7a742bb
73 changed files with 1330 additions and 1004 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -9,6 +9,7 @@ mealie/temp/*
|
||||||
mealie/temp/api.html
|
mealie/temp/api.html
|
||||||
.temp/
|
.temp/
|
||||||
.secret
|
.secret
|
||||||
|
!*/components/Recipe/Parts
|
||||||
|
|
||||||
dev/data/backups/*
|
dev/data/backups/*
|
||||||
dev/data/debug/*
|
dev/data/debug/*
|
||||||
|
@ -159,3 +160,4 @@ scratch.py
|
||||||
dev/data/backups/dev_sample_data*.zip
|
dev/data/backups/dev_sample_data*.zip
|
||||||
dev/data/backups/dev_sample_data*.zip
|
dev/data/backups/dev_sample_data*.zip
|
||||||
!dev/data/backups/test*.zip
|
!dev/data/backups/test*.zip
|
||||||
|
dev/data/recipes/*
|
||||||
|
|
|
@ -16,6 +16,7 @@ const recipeURLs = {
|
||||||
delete: slug => prefix + slug,
|
delete: slug => prefix + slug,
|
||||||
recipeImage: slug => `${prefix}${slug}/image`,
|
recipeImage: slug => `${prefix}${slug}/image`,
|
||||||
updateImage: slug => `${prefix}${slug}/image`,
|
updateImage: slug => `${prefix}${slug}/image`,
|
||||||
|
createAsset: slug => `${prefix}${slug}/asset`,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const recipeAPI = {
|
export const recipeAPI = {
|
||||||
|
@ -78,26 +79,16 @@ export const recipeAPI = {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
updateImagebyURL(slug, url) {
|
async updateImagebyURL(slug, url) {
|
||||||
return apiReq.post(
|
const response = apiReq.post(recipeURLs.updateImage(slug), { url: url });
|
||||||
recipeURLs.updateImage(slug),
|
return response;
|
||||||
{ url: url },
|
|
||||||
function() { return i18n.t('general.image-upload-failed'); },
|
|
||||||
function() { return i18n.t('recipe.recipe-image-updated'); }
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async update(data) {
|
async update(data) {
|
||||||
let response = await apiReq.put(
|
console.log(data)
|
||||||
recipeURLs.update(data.slug),
|
let response = await apiReq.put(recipeURLs.update(data.slug), data);
|
||||||
data,
|
store.dispatch("patchRecipe", response.data);
|
||||||
function() { return i18n.t('recipe.recipe-update-failed'); },
|
return response.data.slug; // ! Temporary until I rewrite to refresh page without additional request
|
||||||
function() { return i18n.t('recipe.recipe-updated'); }
|
|
||||||
);
|
|
||||||
if(response) {
|
|
||||||
store.dispatch("patchRecipe", response.data);
|
|
||||||
return response.data.slug; // ! Temporary until I rewrite to refresh page without additional request
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async patch(data) {
|
async patch(data) {
|
||||||
|
|
160
frontend/src/components/Recipe/Parts/Assets.vue
Normal file
160
frontend/src/components/Recipe/Parts/Assets.vue
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
<template>
|
||||||
|
<div v-if="value.length > 0 || edit">
|
||||||
|
<v-card class="mt-2">
|
||||||
|
<v-card-title class="py-2">
|
||||||
|
{{ $t("recipe.assets") }}
|
||||||
|
</v-card-title>
|
||||||
|
<v-divider class="mx-2"></v-divider>
|
||||||
|
<v-list :flat="!edit" v-if="value.length > 0">
|
||||||
|
<v-list-item v-for="(item, i) in value" :key="i">
|
||||||
|
<v-list-item-icon class="ma-auto">
|
||||||
|
<v-icon v-text="item.icon"></v-icon>
|
||||||
|
</v-list-item-icon>
|
||||||
|
<v-list-item-content>
|
||||||
|
<v-list-item-title
|
||||||
|
class="pl-2"
|
||||||
|
v-text="item.name"
|
||||||
|
></v-list-item-title>
|
||||||
|
</v-list-item-content>
|
||||||
|
<v-list-item-action>
|
||||||
|
<v-btn
|
||||||
|
v-if="!edit"
|
||||||
|
color="primary"
|
||||||
|
icon
|
||||||
|
:href="`/api/recipes/${slug}/asset?file_name=${item.fileName}`"
|
||||||
|
target="_blank"
|
||||||
|
top
|
||||||
|
>
|
||||||
|
<v-icon> mdi-download</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
<v-btn v-else color="error" icon @click="deleteAsset(i)" top>
|
||||||
|
<v-icon>mdi-delete</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</v-list-item-action>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-card>
|
||||||
|
<div class="d-flex ml-auto mt-2">
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<base-dialog
|
||||||
|
@submit="addAsset"
|
||||||
|
title="New Asset"
|
||||||
|
:title-icon="newAsset.icon"
|
||||||
|
>
|
||||||
|
<template v-slot:open="{ open }">
|
||||||
|
<v-btn color="secondary" dark @click="open" v-if="edit">
|
||||||
|
<v-icon>mdi-plus</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
<v-card-text class="pt-2">
|
||||||
|
<v-text-field
|
||||||
|
dense
|
||||||
|
v-model="newAsset.name"
|
||||||
|
:label="$t('general.name')"
|
||||||
|
></v-text-field>
|
||||||
|
<div class="d-flex justify-space-between">
|
||||||
|
<v-select
|
||||||
|
dense
|
||||||
|
:prepend-icon="newAsset.icon"
|
||||||
|
v-model="newAsset.icon"
|
||||||
|
:items="iconOptions"
|
||||||
|
class="mr-2"
|
||||||
|
>
|
||||||
|
<template v-slot:item="{ item }">
|
||||||
|
<v-list-item-avatar>
|
||||||
|
<v-icon class="mr-auto">
|
||||||
|
{{ item }}
|
||||||
|
</v-icon>
|
||||||
|
</v-list-item-avatar>
|
||||||
|
{{ item }}
|
||||||
|
</template>
|
||||||
|
</v-select>
|
||||||
|
<TheUploadBtn
|
||||||
|
@uploaded="setFileObject"
|
||||||
|
:post="false"
|
||||||
|
file-name="file"
|
||||||
|
:text-btn="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{{ fileObject.name }}
|
||||||
|
</v-card-text>
|
||||||
|
</base-dialog>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import TheUploadBtn from "@/components/UI/Buttons/TheUploadBtn";
|
||||||
|
import BaseDialog from "@/components/UI/Dialogs/BaseDialog";
|
||||||
|
import { api } from "@/api";
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
BaseDialog,
|
||||||
|
TheUploadBtn,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
slug: String,
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
edit: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
fileObject: {},
|
||||||
|
newAsset: {
|
||||||
|
name: "",
|
||||||
|
icon: "mdi-file",
|
||||||
|
},
|
||||||
|
iconOptions: [
|
||||||
|
"mdi-file",
|
||||||
|
"mdi-file-pdf-box",
|
||||||
|
"mdi-file-image",
|
||||||
|
"mdi-code-json",
|
||||||
|
"mdi-silverware-fork-knife",
|
||||||
|
],
|
||||||
|
menu: [
|
||||||
|
{
|
||||||
|
title: "Link 1",
|
||||||
|
icon: "mdi-file",
|
||||||
|
action: "Do Something",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Link 1",
|
||||||
|
icon: "mdi-file",
|
||||||
|
action: "Do Something",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Link 1",
|
||||||
|
icon: "mdi-file",
|
||||||
|
action: "Do Something",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setFileObject(obj) {
|
||||||
|
this.fileObject = obj;
|
||||||
|
},
|
||||||
|
async addAsset() {
|
||||||
|
const serverAsset = await api.recipes.createAsset(
|
||||||
|
this.slug,
|
||||||
|
this.fileObject,
|
||||||
|
this.newAsset.name,
|
||||||
|
this.newAsset.icon
|
||||||
|
);
|
||||||
|
this.value.push(serverAsset.data);
|
||||||
|
this.newAsset = { name: "", icon: "mdi-file" };
|
||||||
|
},
|
||||||
|
deleteAsset(index) {
|
||||||
|
this.value.splice(index, 1);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
|
@ -3,7 +3,7 @@
|
||||||
<v-dialog v-model="dialog" width="600">
|
<v-dialog v-model="dialog" width="600">
|
||||||
<template v-slot:activator="{ on, attrs }">
|
<template v-slot:activator="{ on, attrs }">
|
||||||
<v-btn
|
<v-btn
|
||||||
text
|
|
||||||
color="secondary lighten-2"
|
color="secondary lighten-2"
|
||||||
dark
|
dark
|
||||||
v-bind="attrs"
|
v-bind="attrs"
|
|
@ -3,13 +3,16 @@
|
||||||
<v-menu offset-y top nudge-top="6" :close-on-content-click="false">
|
<v-menu offset-y top nudge-top="6" :close-on-content-click="false">
|
||||||
<template v-slot:activator="{ on, attrs }">
|
<template v-slot:activator="{ on, attrs }">
|
||||||
<v-btn color="accent" dark v-bind="attrs" v-on="on">
|
<v-btn color="accent" dark v-bind="attrs" v-on="on">
|
||||||
{{$t('general.image')}}
|
<v-icon left>
|
||||||
|
mdi-image
|
||||||
|
</v-icon>
|
||||||
|
{{ $t("general.image") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
<v-card width="400">
|
<v-card width="400">
|
||||||
<v-card-title class="headline flex mb-0">
|
<v-card-title class="headline flex mb-0">
|
||||||
<div>
|
<div>
|
||||||
{{$t('recipe.recipe-image')}}
|
{{ $t("recipe.recipe-image") }}
|
||||||
</div>
|
</div>
|
||||||
<TheUploadBtn
|
<TheUploadBtn
|
||||||
class="ml-auto"
|
class="ml-auto"
|
||||||
|
@ -22,7 +25,12 @@
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
<v-card-text class="mt-n5">
|
<v-card-text class="mt-n5">
|
||||||
<div>
|
<div>
|
||||||
<v-text-field :label="$t('general.url')" class="pt-5" clearable v-model="url">
|
<v-text-field
|
||||||
|
:label="$t('general.url')"
|
||||||
|
class="pt-5"
|
||||||
|
clearable
|
||||||
|
v-model="url"
|
||||||
|
>
|
||||||
<template v-slot:append-outer>
|
<template v-slot:append-outer>
|
||||||
<v-btn
|
<v-btn
|
||||||
class="ml-2"
|
class="ml-2"
|
||||||
|
@ -30,7 +38,7 @@
|
||||||
@click="getImageFromURL"
|
@click="getImageFromURL"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
>
|
>
|
||||||
{{$t('general.get')}}
|
{{ $t("general.get") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
</v-text-field>
|
</v-text-field>
|
137
frontend/src/components/Recipe/Parts/Ingredients.vue
Normal file
137
frontend/src/components/Recipe/Parts/Ingredients.vue
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2 class="mb-4">{{ $t("recipe.ingredients") }}</h2>
|
||||||
|
<div v-if="edit">
|
||||||
|
<draggable
|
||||||
|
:value="value"
|
||||||
|
@input="updateIndex"
|
||||||
|
@start="drag = true"
|
||||||
|
@end="drag = false"
|
||||||
|
handle=".handle"
|
||||||
|
>
|
||||||
|
<transition-group type="transition" :name="!drag ? 'flip-list' : null">
|
||||||
|
<div
|
||||||
|
v-for="(ingredient, index) in value"
|
||||||
|
:key="generateKey('ingredient', index)"
|
||||||
|
>
|
||||||
|
<v-row align="center">
|
||||||
|
<v-textarea
|
||||||
|
class="mr-2"
|
||||||
|
:label="$t('recipe.ingredient')"
|
||||||
|
v-model="value[index]"
|
||||||
|
mdi-move-resize
|
||||||
|
auto-grow
|
||||||
|
solo
|
||||||
|
dense
|
||||||
|
rows="1"
|
||||||
|
>
|
||||||
|
<template slot="append-outer">
|
||||||
|
<v-icon class="handle">mdi-arrow-up-down</v-icon>
|
||||||
|
</template>
|
||||||
|
<v-icon
|
||||||
|
class="mr-n1"
|
||||||
|
slot="prepend"
|
||||||
|
color="error"
|
||||||
|
@click="removeByIndex(value, index)"
|
||||||
|
>
|
||||||
|
mdi-delete
|
||||||
|
</v-icon>
|
||||||
|
</v-textarea>
|
||||||
|
</v-row>
|
||||||
|
</div>
|
||||||
|
</transition-group>
|
||||||
|
</draggable>
|
||||||
|
|
||||||
|
<div class="d-flex row justify-end">
|
||||||
|
<BulkAdd @bulk-data="addIngredient" class="mr-2" />
|
||||||
|
<v-btn color="secondary" dark @click="addIngredient" class="mr-4">
|
||||||
|
<v-icon>mdi-plus</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<v-list-item
|
||||||
|
dense
|
||||||
|
v-for="(ingredient, index) in value"
|
||||||
|
:key="generateKey('ingredient', index)"
|
||||||
|
@click="toggleChecked(index)"
|
||||||
|
>
|
||||||
|
<v-checkbox
|
||||||
|
hide-details
|
||||||
|
:value="checked[index]"
|
||||||
|
class="pt-0 my-auto py-auto"
|
||||||
|
color="secondary"
|
||||||
|
>
|
||||||
|
</v-checkbox>
|
||||||
|
|
||||||
|
<v-list-item-content>
|
||||||
|
<vue-markdown
|
||||||
|
class="ma-0 pa-0 text-subtitle-1 dense-markdown"
|
||||||
|
:source="ingredient"
|
||||||
|
>
|
||||||
|
</vue-markdown>
|
||||||
|
</v-list-item-content>
|
||||||
|
</v-list-item>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import BulkAdd from "@/components/Recipe/Parts/Helpers/BulkAdd";
|
||||||
|
import VueMarkdown from "@adapttive/vue-markdown";
|
||||||
|
import draggable from "vuedraggable";
|
||||||
|
import utils from "@/utils";
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
BulkAdd,
|
||||||
|
draggable,
|
||||||
|
VueMarkdown,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
|
||||||
|
edit: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
drag: false,
|
||||||
|
checked: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.checked = this.value.map(() => false);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addIngredient(ingredients = null) {
|
||||||
|
if (ingredients.length) {
|
||||||
|
this.value.push(...ingredients);
|
||||||
|
} else {
|
||||||
|
this.value.push("");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
generateKey(item, index) {
|
||||||
|
return utils.generateUniqueKey(item, index);
|
||||||
|
},
|
||||||
|
updateIndex(data) {
|
||||||
|
this.$emit("input", data);
|
||||||
|
},
|
||||||
|
toggleChecked(index) {
|
||||||
|
this.$set(this.checked, index, !this.checked[index]);
|
||||||
|
},
|
||||||
|
removeByIndex(list, index) {
|
||||||
|
list.splice(index, 1);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style >
|
||||||
|
.dense-markdown p {
|
||||||
|
margin: auto !important;
|
||||||
|
}
|
||||||
|
</style>
|
148
frontend/src/components/Recipe/Parts/Instructions.vue
Normal file
148
frontend/src/components/Recipe/Parts/Instructions.vue
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2 class="mb-4">{{ $t("recipe.instructions") }}</h2>
|
||||||
|
<div>
|
||||||
|
<div v-for="(step, index) in value" :key="index">
|
||||||
|
<v-app-bar
|
||||||
|
v-if="showTitleEditor[index]"
|
||||||
|
class="primary mx-1 mt-6"
|
||||||
|
dark
|
||||||
|
dense
|
||||||
|
rounded
|
||||||
|
>
|
||||||
|
<v-toolbar-title class="headline" v-if="!edit">
|
||||||
|
<v-app-bar-title v-text="step.title"> </v-app-bar-title>
|
||||||
|
</v-toolbar-title>
|
||||||
|
<v-text-field
|
||||||
|
v-if="edit"
|
||||||
|
class="headline pa-0 mt-5"
|
||||||
|
v-model="step.title"
|
||||||
|
dense
|
||||||
|
solo
|
||||||
|
flat
|
||||||
|
placeholder="Section Title"
|
||||||
|
background-color="primary"
|
||||||
|
>
|
||||||
|
</v-text-field>
|
||||||
|
</v-app-bar>
|
||||||
|
<v-hover v-slot="{ hover }">
|
||||||
|
<v-card
|
||||||
|
class="ma-1"
|
||||||
|
:class="[{ 'on-hover': hover }, isDisabled(index)]"
|
||||||
|
:elevation="hover ? 12 : 2"
|
||||||
|
:ripple="!edit"
|
||||||
|
@click="toggleDisabled(index)"
|
||||||
|
>
|
||||||
|
<v-card-title>
|
||||||
|
<v-btn
|
||||||
|
v-if="edit"
|
||||||
|
fab
|
||||||
|
x-small
|
||||||
|
color="white"
|
||||||
|
class="mr-2"
|
||||||
|
elevation="0"
|
||||||
|
@click="removeByIndex(value, index)"
|
||||||
|
>
|
||||||
|
<v-icon size="24" color="error">mdi-delete</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
{{ $t("recipe.step-index", { step: index + 1 }) }}
|
||||||
|
<v-btn
|
||||||
|
v-if="edit"
|
||||||
|
text
|
||||||
|
color="primary"
|
||||||
|
class="ml-auto"
|
||||||
|
@click="toggleShowTitle(index)"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
!showTitleEditor[index] ? "Insert Section" : "Remove Section"
|
||||||
|
}}
|
||||||
|
</v-btn>
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text v-if="edit">
|
||||||
|
<v-textarea
|
||||||
|
auto-grow
|
||||||
|
dense
|
||||||
|
v-model="value[index]['text']"
|
||||||
|
:key="generateKey('instructions', index)"
|
||||||
|
rows="4"
|
||||||
|
>
|
||||||
|
</v-textarea>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-text v-else>
|
||||||
|
<vue-markdown :source="step.text"> </vue-markdown>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-hover>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import VueMarkdown from "@adapttive/vue-markdown";
|
||||||
|
import utils from "@/utils";
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
VueMarkdown,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
|
||||||
|
edit: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
disabledSteps: [],
|
||||||
|
showTitleEditor: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.showTitleEditor = this.value.map(x => this.validateTitle(x.title));
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
generateKey(item, index) {
|
||||||
|
return utils.generateUniqueKey(item, index);
|
||||||
|
},
|
||||||
|
removeByIndex(list, index) {
|
||||||
|
list.splice(index, 1);
|
||||||
|
},
|
||||||
|
validateTitle(title) {
|
||||||
|
return !(title === null || title === "");
|
||||||
|
},
|
||||||
|
toggleDisabled(stepIndex) {
|
||||||
|
if (this.edit) return;
|
||||||
|
if (this.disabledSteps.includes(stepIndex)) {
|
||||||
|
let index = this.disabledSteps.indexOf(stepIndex);
|
||||||
|
if (index !== -1) {
|
||||||
|
this.disabledSteps.splice(index, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.disabledSteps.push(stepIndex);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isDisabled(stepIndex) {
|
||||||
|
if (this.disabledSteps.includes(stepIndex) && !this.edit) {
|
||||||
|
return "disabled-card";
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toggleShowTitle(index) {
|
||||||
|
const newVal = !this.showTitleEditor[index];
|
||||||
|
if (!newVal) {
|
||||||
|
this.value[index].title = "";
|
||||||
|
}
|
||||||
|
this.$set(this.showTitleEditor, index, newVal);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
87
frontend/src/components/Recipe/Parts/Notes.vue
Normal file
87
frontend/src/components/Recipe/Parts/Notes.vue
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
<template>
|
||||||
|
<div v-if="value.length > 0 || edit">
|
||||||
|
<h2 class="my-4">{{ $t("recipe.note") }}</h2>
|
||||||
|
<v-card
|
||||||
|
class="mt-1"
|
||||||
|
v-for="(note, index) in value"
|
||||||
|
:key="generateKey('note', index)"
|
||||||
|
>
|
||||||
|
<div v-if="edit">
|
||||||
|
<v-card-text>
|
||||||
|
<v-row align="center">
|
||||||
|
<v-btn
|
||||||
|
fab
|
||||||
|
x-small
|
||||||
|
color="white"
|
||||||
|
class="mr-2"
|
||||||
|
elevation="0"
|
||||||
|
@click="removeByIndex(value, index)"
|
||||||
|
>
|
||||||
|
<v-icon color="error">mdi-delete</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
<v-text-field
|
||||||
|
:label="$t('recipe.title')"
|
||||||
|
v-model="value[index]['title']"
|
||||||
|
></v-text-field>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<v-textarea
|
||||||
|
auto-grow
|
||||||
|
:placeholder="$t('recipe.note')"
|
||||||
|
v-model="value[index]['text']"
|
||||||
|
>
|
||||||
|
</v-textarea>
|
||||||
|
</v-card-text>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<v-card-title class="py-2">
|
||||||
|
{{ note.title }}
|
||||||
|
</v-card-title>
|
||||||
|
<v-divider class="mx-2"></v-divider>
|
||||||
|
<v-card-text>
|
||||||
|
<vue-markdown :source="note.text"> </vue-markdown>
|
||||||
|
</v-card-text>
|
||||||
|
</div>
|
||||||
|
</v-card>
|
||||||
|
|
||||||
|
<div class="d-flex justify-end" v-if="edit">
|
||||||
|
<v-btn class="mt-1" color="secondary" dark @click="addNote">
|
||||||
|
<v-icon>mdi-plus</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import VueMarkdown from "@adapttive/vue-markdown";
|
||||||
|
import utils from "@/utils";
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
VueMarkdown,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
|
||||||
|
edit: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
generateKey(item, index) {
|
||||||
|
return utils.generateUniqueKey(item, index);
|
||||||
|
},
|
||||||
|
addNote() {
|
||||||
|
this.value.push({ text: "" });
|
||||||
|
},
|
||||||
|
removeByIndex(list, index) {
|
||||||
|
list.splice(index, 1);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
101
frontend/src/components/Recipe/Parts/Nutrition.vue
Normal file
101
frontend/src/components/Recipe/Parts/Nutrition.vue
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
<template>
|
||||||
|
<div v-if="valueNotNull || edit">
|
||||||
|
<v-card class="mt-2">
|
||||||
|
<v-card-title class="py-2">
|
||||||
|
{{ $t("recipe.nutrition") }}
|
||||||
|
</v-card-title>
|
||||||
|
<v-divider class="mx-2"></v-divider>
|
||||||
|
<v-card-text v-if="edit">
|
||||||
|
<div v-for="(item, key, index) in value" :key="index">
|
||||||
|
<v-text-field
|
||||||
|
dense
|
||||||
|
:value="value[key]"
|
||||||
|
:label="labels[key].label"
|
||||||
|
:suffix="labels[key].suffix"
|
||||||
|
type="number"
|
||||||
|
autocomplete="off"
|
||||||
|
@input="updateValue(key, $event)"
|
||||||
|
></v-text-field>
|
||||||
|
</div>
|
||||||
|
</v-card-text>
|
||||||
|
<v-list dense v-if="showViewer" class="mt-0 pt-0">
|
||||||
|
<v-list-item v-for="(item, key, index) in labels" :key="index">
|
||||||
|
<v-list-item-content>
|
||||||
|
<v-list-item-title class="pl-4 text-subtitle-1 flex row ">
|
||||||
|
<div>{{ item.label }}</div>
|
||||||
|
<div class="ml-auto mr-1">{{ value[key] }}</div>
|
||||||
|
<div>{{ item.suffix }}</div>
|
||||||
|
</v-list-item-title>
|
||||||
|
</v-list-item-content>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
value: {},
|
||||||
|
edit: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
labels: {
|
||||||
|
calories: {
|
||||||
|
label: this.$t("recipe.calories"),
|
||||||
|
suffix: this.$t("recipe.calories-suffix"),
|
||||||
|
},
|
||||||
|
fatContent: {
|
||||||
|
label: this.$t("recipe.fat-content"),
|
||||||
|
suffix: this.$t("recipe.grams"),
|
||||||
|
},
|
||||||
|
fiberContent: {
|
||||||
|
label: this.$t("recipe.fiber-content"),
|
||||||
|
suffix: this.$t("recipe.grams"),
|
||||||
|
},
|
||||||
|
proteinContent: {
|
||||||
|
label: this.$t("recipe.protein-content"),
|
||||||
|
suffix: this.$t("recipe.grams"),
|
||||||
|
},
|
||||||
|
sodiumContent: {
|
||||||
|
label: this.$t("recipe.sodium-content"),
|
||||||
|
suffix: this.$t("recipe.milligrams"),
|
||||||
|
},
|
||||||
|
sugarContent: {
|
||||||
|
label: this.$t("recipe.sugar-content"),
|
||||||
|
suffix: this.$t("recipe.grams"),
|
||||||
|
},
|
||||||
|
carbohydrateContent: {
|
||||||
|
label: this.$t("recipe.carbohydrate-content"),
|
||||||
|
suffix: this.$t("recipe.grams"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
showViewer() {
|
||||||
|
return !this.edit && this.valueNotNull;
|
||||||
|
},
|
||||||
|
valueNotNull() {
|
||||||
|
for (const property in this.value) {
|
||||||
|
const valueProperty = this.value[property];
|
||||||
|
if (valueProperty && valueProperty !== "") return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
updateValue(key, value) {
|
||||||
|
this.$emit("input", { ...this.value, [key]: value });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
|
@ -1,81 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-if="valueNotNull || edit">
|
|
||||||
<h2 class="my-4">{{$t('recipe.nutrition')}}</h2>
|
|
||||||
<div v-if="edit">
|
|
||||||
<div v-for="(item, key, index) in value" :key="index">
|
|
||||||
<v-text-field
|
|
||||||
dense
|
|
||||||
:value="value[key]"
|
|
||||||
:label="labels[key].label"
|
|
||||||
:suffix="labels[key].suffix"
|
|
||||||
type="number"
|
|
||||||
autocomplete="off"
|
|
||||||
@input="updateValue(key, $event)"
|
|
||||||
></v-text-field>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="showViewer">
|
|
||||||
<v-list dense>
|
|
||||||
<v-list-item-group color="primary">
|
|
||||||
<v-list-item v-for="(item, key, index) in labels" :key="index">
|
|
||||||
<v-list-item-content>
|
|
||||||
<v-list-item-title class="pl-4 text-subtitle-1 flex row ">
|
|
||||||
<div>{{ item.label }}</div>
|
|
||||||
<div class="ml-auto mr-1">{{ value[key] }}</div>
|
|
||||||
<div>{{ item.suffix }}</div>
|
|
||||||
</v-list-item-title>
|
|
||||||
</v-list-item-content>
|
|
||||||
</v-list-item>
|
|
||||||
</v-list-item-group>
|
|
||||||
</v-list>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
value: {},
|
|
||||||
edit: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
labels: {
|
|
||||||
calories: {
|
|
||||||
label: this.$t('recipe.calories'),
|
|
||||||
suffix:this.$t('recipe.calories-suffix'),
|
|
||||||
},
|
|
||||||
fatContent: { label: this.$t('recipe.fat-content'), suffix: this.$t('recipe.grams') },
|
|
||||||
fiberContent: { label: this.$t('recipe.fiber-content'), suffix: this.$t('recipe.grams') },
|
|
||||||
proteinContent: { label: this.$t('recipe.protein-content'), suffix: this.$t('recipe.grams') },
|
|
||||||
sodiumContent: { label: this.$t('recipe.sodium-content'), suffix: this.$t('recipe.milligrams') },
|
|
||||||
sugarContent: { label: this.$t('recipe.sugar-content'), suffix: this.$t('recipe.grams') },
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
showViewer() {
|
|
||||||
return !this.edit && this.valueNotNull;
|
|
||||||
},
|
|
||||||
valueNotNull() {
|
|
||||||
for (const property in this.value) {
|
|
||||||
const valueProperty = this.value[property];
|
|
||||||
if (valueProperty && valueProperty !== "") return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
updateValue(key, value) {
|
|
||||||
this.$emit("input", { ...this.value, [key]: value });
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
</style>
|
|
|
@ -3,7 +3,7 @@
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-row dense>
|
<v-row dense>
|
||||||
<ImageUploadBtn
|
<ImageUploadBtn
|
||||||
class="mt-2"
|
class="my-1"
|
||||||
@upload="uploadImage"
|
@upload="uploadImage"
|
||||||
:slug="value.slug"
|
:slug="value.slug"
|
||||||
@refresh="$emit('upload')"
|
@refresh="$emit('upload')"
|
||||||
|
@ -64,50 +64,7 @@
|
||||||
</v-row>
|
</v-row>
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" sm="12" md="4" lg="4">
|
<v-col cols="12" sm="12" md="4" lg="4">
|
||||||
<h2 class="mb-4">{{ $t("recipe.ingredients") }}</h2>
|
<Ingredients :edit="true" v-model="value.recipeIngredient" />
|
||||||
<draggable
|
|
||||||
v-model="value.recipeIngredient"
|
|
||||||
@start="drag = true"
|
|
||||||
@end="drag = false"
|
|
||||||
>
|
|
||||||
<transition-group
|
|
||||||
type="transition"
|
|
||||||
:name="!drag ? 'flip-list' : null"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-for="(ingredient, index) in value.recipeIngredient"
|
|
||||||
:key="generateKey('ingredient', index)"
|
|
||||||
>
|
|
||||||
<v-row align="center">
|
|
||||||
<v-textarea
|
|
||||||
class="mr-2"
|
|
||||||
:label="$t('recipe.ingredient')"
|
|
||||||
v-model="value.recipeIngredient[index]"
|
|
||||||
append-outer-icon="mdi-menu"
|
|
||||||
mdi-move-resize
|
|
||||||
auto-grow
|
|
||||||
solo
|
|
||||||
dense
|
|
||||||
rows="1"
|
|
||||||
>
|
|
||||||
<v-icon
|
|
||||||
class="mr-n1"
|
|
||||||
slot="prepend"
|
|
||||||
color="error"
|
|
||||||
@click="removeByIndex(value.recipeIngredient, index)"
|
|
||||||
>
|
|
||||||
mdi-delete
|
|
||||||
</v-icon>
|
|
||||||
</v-textarea>
|
|
||||||
</v-row>
|
|
||||||
</div>
|
|
||||||
</transition-group>
|
|
||||||
</draggable>
|
|
||||||
|
|
||||||
<v-btn color="secondary" fab dark small @click="addIngredient">
|
|
||||||
<v-icon>mdi-plus</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
<BulkAdd @bulk-data="addIngredient" />
|
|
||||||
|
|
||||||
<h2 class="mt-6">{{ $t("recipe.categories") }}</h2>
|
<h2 class="mt-6">{{ $t("recipe.categories") }}</h2>
|
||||||
<CategoryTagSelector
|
<CategoryTagSelector
|
||||||
|
@ -125,87 +82,23 @@
|
||||||
:tag-selector="true"
|
:tag-selector="true"
|
||||||
:show-label="false"
|
:show-label="false"
|
||||||
/>
|
/>
|
||||||
|
<Nutrition v-model="value.nutrition" :edit="true" />
|
||||||
<h2 class="my-4">{{ $t("recipe.notes") }}</h2>
|
<Assets v-model="value.assets" :edit="true" :slug="value.slug" />
|
||||||
<v-card
|
|
||||||
class="mt-1"
|
|
||||||
v-for="(note, index) in value.notes"
|
|
||||||
:key="generateKey('note', index)"
|
|
||||||
>
|
|
||||||
<v-card-text>
|
|
||||||
<v-row align="center">
|
|
||||||
<v-btn
|
|
||||||
fab
|
|
||||||
x-small
|
|
||||||
color="white"
|
|
||||||
class="mr-2"
|
|
||||||
elevation="0"
|
|
||||||
@click="removeByIndex(value.notes, index)"
|
|
||||||
>
|
|
||||||
<v-icon color="error">mdi-delete</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
<v-text-field
|
|
||||||
:label="$t('recipe.title')"
|
|
||||||
v-model="value.notes[index]['title']"
|
|
||||||
></v-text-field>
|
|
||||||
</v-row>
|
|
||||||
|
|
||||||
<v-textarea
|
|
||||||
auto-grow
|
|
||||||
:label="$t('recipe.note')"
|
|
||||||
v-model="value.notes[index]['text']"
|
|
||||||
>
|
|
||||||
</v-textarea>
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
<v-btn class="mt-1" color="secondary" fab dark small @click="addNote">
|
|
||||||
<v-icon>mdi-plus</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
<NutritionEditor v-model="value.nutrition" :edit="true" />
|
|
||||||
<ExtrasEditor :extras="value.extras" @save="saveExtras" />
|
<ExtrasEditor :extras="value.extras" @save="saveExtras" />
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-divider class="my-divider" :vertical="true"></v-divider>
|
<v-divider class="my-divider" :vertical="true"></v-divider>
|
||||||
|
|
||||||
<v-col cols="12" sm="12" md="8" lg="8">
|
<v-col cols="12" sm="12" md="8" lg="8">
|
||||||
<h2 class="mb-4">{{ $t("recipe.instructions") }}</h2>
|
<Instructions v-model="value.recipeInstructions" :edit="true" />
|
||||||
<div v-for="(step, index) in value.recipeInstructions" :key="index">
|
<div class="d-flex row justify-end mt-2">
|
||||||
<v-hover v-slot="{ hover }">
|
<BulkAdd @bulk-data="appendSteps" class="mr-2" />
|
||||||
<v-card
|
<v-btn color="secondary" dark @click="addStep" class="mr-4">
|
||||||
class="ma-1"
|
<v-icon>mdi-plus</v-icon>
|
||||||
:class="[{ 'on-hover': hover }]"
|
</v-btn>
|
||||||
:elevation="hover ? 12 : 2"
|
|
||||||
>
|
|
||||||
<v-card-title>
|
|
||||||
<v-btn
|
|
||||||
fab
|
|
||||||
x-small
|
|
||||||
color="white"
|
|
||||||
class="mr-2"
|
|
||||||
elevation="0"
|
|
||||||
@click="removeByIndex(value.recipeInstructions, index)"
|
|
||||||
>
|
|
||||||
<v-icon size="24" color="error">mdi-delete</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
{{ $t("recipe.step-index", { step: index + 1 }) }}
|
|
||||||
</v-card-title>
|
|
||||||
<v-card-text>
|
|
||||||
<v-textarea
|
|
||||||
auto-grow
|
|
||||||
dense
|
|
||||||
v-model="value.recipeInstructions[index]['text']"
|
|
||||||
:key="generateKey('instructions', index)"
|
|
||||||
rows="4"
|
|
||||||
>
|
|
||||||
</v-textarea>
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
</v-hover>
|
|
||||||
</div>
|
</div>
|
||||||
<v-btn color="secondary" fab dark small @click="addStep">
|
<Notes :edit="true" v-model="value.notes" />
|
||||||
<v-icon>mdi-plus</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
<BulkAdd @bulk-data="appendSteps" />
|
|
||||||
<v-text-field
|
<v-text-field
|
||||||
v-model="value.orgURL"
|
v-model="value.orgURL"
|
||||||
class="mt-10"
|
class="mt-10"
|
||||||
|
@ -219,22 +112,27 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const UPLOAD_EVENT = "upload";
|
const UPLOAD_EVENT = "upload";
|
||||||
import draggable from "vuedraggable";
|
import BulkAdd from "@/components/Recipe/Parts/Helpers/BulkAdd";
|
||||||
import utils from "@/utils";
|
import ExtrasEditor from "@/components/Recipe/Parts/Helpers/ExtrasEditor";
|
||||||
import BulkAdd from "./BulkAdd";
|
|
||||||
import ExtrasEditor from "./ExtrasEditor";
|
|
||||||
import CategoryTagSelector from "@/components/FormHelpers/CategoryTagSelector";
|
import CategoryTagSelector from "@/components/FormHelpers/CategoryTagSelector";
|
||||||
import NutritionEditor from "./NutritionEditor";
|
import ImageUploadBtn from "@/components/Recipe/Parts/Helpers/ImageUploadBtn";
|
||||||
import ImageUploadBtn from "./ImageUploadBtn.vue";
|
|
||||||
import { validators } from "@/mixins/validators";
|
import { validators } from "@/mixins/validators";
|
||||||
|
import Nutrition from "@/components/Recipe/Parts/Nutrition";
|
||||||
|
import Instructions from "@/components/Recipe/Parts/Instructions";
|
||||||
|
import Ingredients from "@/components/Recipe/Parts/Ingredients";
|
||||||
|
import Assets from "@/components/Recipe/Parts/Assets.vue";
|
||||||
|
import Notes from "@/components/Recipe/Parts/Notes.vue";
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
BulkAdd,
|
BulkAdd,
|
||||||
ExtrasEditor,
|
ExtrasEditor,
|
||||||
draggable,
|
|
||||||
CategoryTagSelector,
|
CategoryTagSelector,
|
||||||
NutritionEditor,
|
Nutrition,
|
||||||
ImageUploadBtn,
|
ImageUploadBtn,
|
||||||
|
Instructions,
|
||||||
|
Ingredients,
|
||||||
|
Assets,
|
||||||
|
Notes,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
value: Object,
|
value: Object,
|
||||||
|
@ -242,7 +140,6 @@ export default {
|
||||||
mixins: [validators],
|
mixins: [validators],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
drag: false,
|
|
||||||
fileObject: null,
|
fileObject: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -250,30 +147,6 @@ export default {
|
||||||
uploadImage(fileObject) {
|
uploadImage(fileObject) {
|
||||||
this.$emit(UPLOAD_EVENT, fileObject);
|
this.$emit(UPLOAD_EVENT, fileObject);
|
||||||
},
|
},
|
||||||
toggleDisabled(stepIndex) {
|
|
||||||
if (this.disabledSteps.includes(stepIndex)) {
|
|
||||||
const index = this.disabledSteps.indexOf(stepIndex);
|
|
||||||
if (index !== -1) {
|
|
||||||
this.disabledSteps.splice(index, 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.disabledSteps.push(stepIndex);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isDisabled(stepIndex) {
|
|
||||||
return this.disabledSteps.includes(stepIndex) ? "disabled-card" : null;
|
|
||||||
},
|
|
||||||
generateKey(item, index) {
|
|
||||||
return utils.generateUniqueKey(item, index);
|
|
||||||
},
|
|
||||||
addIngredient(ingredients = null) {
|
|
||||||
if (ingredients) {
|
|
||||||
this.value.recipeIngredient.push(...ingredients);
|
|
||||||
} else {
|
|
||||||
this.value.recipeIngredient.push("");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
appendSteps(steps) {
|
appendSteps(steps) {
|
||||||
this.value.recipeInstructions.push(
|
this.value.recipeInstructions.push(
|
||||||
...steps.map(x => ({
|
...steps.map(x => ({
|
||||||
|
@ -284,15 +157,9 @@ export default {
|
||||||
addStep() {
|
addStep() {
|
||||||
this.value.recipeInstructions.push({ text: "" });
|
this.value.recipeInstructions.push({ text: "" });
|
||||||
},
|
},
|
||||||
addNote() {
|
|
||||||
this.value.notes.push({ text: "" });
|
|
||||||
},
|
|
||||||
saveExtras(extras) {
|
saveExtras(extras) {
|
||||||
this.value.extras = extras;
|
this.value.extras = extras;
|
||||||
},
|
},
|
||||||
removeByIndex(list, index) {
|
|
||||||
list.splice(index, 1);
|
|
||||||
},
|
|
||||||
validateRecipe() {
|
validateRecipe() {
|
||||||
return this.$refs.form.validate();
|
return this.$refs.form.validate();
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<h2 class="mb-4">{{ $t("recipe.ingredients") }}</h2>
|
|
||||||
<v-list-item
|
|
||||||
dense
|
|
||||||
v-for="(ingredient, index) in ingredients"
|
|
||||||
:key="generateKey('ingredient', index)"
|
|
||||||
@click="toggleChecked(index)"
|
|
||||||
>
|
|
||||||
<v-checkbox
|
|
||||||
hide-details
|
|
||||||
:value="checked[index]"
|
|
||||||
class="pt-0 my-auto py-auto"
|
|
||||||
color="secondary"
|
|
||||||
>
|
|
||||||
</v-checkbox>
|
|
||||||
|
|
||||||
<v-list-item-content>
|
|
||||||
<vue-markdown
|
|
||||||
class="ma-0 pa-0 text-subtitle-1 dense-markdown"
|
|
||||||
:source="ingredient"
|
|
||||||
>
|
|
||||||
</vue-markdown>
|
|
||||||
</v-list-item-content>
|
|
||||||
</v-list-item>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import VueMarkdown from "@adapttive/vue-markdown";
|
|
||||||
import utils from "@/utils";
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
VueMarkdown,
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
ingredients: Array,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
checked: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.checked = this.ingredients.map(() => false);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
generateKey(item, index) {
|
|
||||||
return utils.generateUniqueKey(item, index);
|
|
||||||
},
|
|
||||||
toggleChecked(index) {
|
|
||||||
this.$set(this.checked, index, !this.checked[index]);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style >
|
|
||||||
.dense-markdown p {
|
|
||||||
margin: auto !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,36 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<h2 v-if="notes[0]" class="my-4">{{ $t("recipe.notes") }}</h2>
|
|
||||||
<v-card
|
|
||||||
class="mt-1"
|
|
||||||
v-for="(note, index) in notes"
|
|
||||||
:key="generateKey('note', index)"
|
|
||||||
>
|
|
||||||
<v-card-title> {{ note.title }}</v-card-title>
|
|
||||||
<v-card-text>
|
|
||||||
<vue-markdown :source="note.text"> </vue-markdown>
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import VueMarkdown from "@adapttive/vue-markdown";
|
|
||||||
import utils from "@/utils";
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
notes: Array,
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
VueMarkdown,
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
generateKey(item, index) {
|
|
||||||
return utils.generateUniqueKey(item, index);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
|
@ -1,67 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<h2 class="mb-4">{{ $t("recipe.instructions") }}</h2>
|
|
||||||
<v-hover
|
|
||||||
v-for="(step, index) in steps"
|
|
||||||
:key="generateKey('step', index)"
|
|
||||||
v-slot="{ hover }"
|
|
||||||
>
|
|
||||||
<v-card
|
|
||||||
class="ma-1"
|
|
||||||
:class="[{ 'on-hover': hover }, isDisabled(index)]"
|
|
||||||
:elevation="hover ? 12 : 2"
|
|
||||||
@click="toggleDisabled(index)"
|
|
||||||
>
|
|
||||||
<v-card-title>{{
|
|
||||||
$t("recipe.step-index", { step: index + 1 })
|
|
||||||
}}</v-card-title>
|
|
||||||
<v-card-text>
|
|
||||||
<vue-markdown :source="step.text"> </vue-markdown>
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
</v-hover>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import VueMarkdown from "@adapttive/vue-markdown";
|
|
||||||
import utils from "@/utils";
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
steps: Array,
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
VueMarkdown,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
disabledSteps: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
toggleDisabled(stepIndex) {
|
|
||||||
if (this.disabledSteps.includes(stepIndex)) {
|
|
||||||
let index = this.disabledSteps.indexOf(stepIndex);
|
|
||||||
if (index !== -1) {
|
|
||||||
this.disabledSteps.splice(index, 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.disabledSteps.push(stepIndex);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isDisabled(stepIndex) {
|
|
||||||
if (this.disabledSteps.includes(stepIndex)) {
|
|
||||||
return "disabled-card";
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
generateKey(item, index) {
|
|
||||||
return utils.generateUniqueKey(item, index);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
|
@ -31,16 +31,29 @@
|
||||||
</v-row>
|
</v-row>
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" sm="12" md="4" lg="4">
|
<v-col cols="12" sm="12" md="4" lg="4">
|
||||||
<Ingredients :ingredients="ingredients" />
|
<Ingredients :value="ingredients" :edit="false" />
|
||||||
<div v-if="medium">
|
<div v-if="medium">
|
||||||
<RecipeChips :title="$t('recipe.categories')" :items="categories" />
|
<v-card class="mt-2" v-if="categories.length > 0">
|
||||||
<RecipeChips
|
<v-card-title class="py-2">
|
||||||
:title="$t('recipe.tags')"
|
{{ $t("recipe.categories") }}
|
||||||
:items="tags"
|
</v-card-title>
|
||||||
:isCategory="false"
|
<v-divider class="mx-2"></v-divider>
|
||||||
/>
|
<v-card-text>
|
||||||
<Notes :notes="notes" />
|
<RecipeChips :items="categories" />
|
||||||
<NutritionEditor :value="nutrition" :edit="false" />
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
<v-card class="mt-2" v-if="tags.length > 0">
|
||||||
|
<v-card-title class="py-2">
|
||||||
|
{{ $t("recipe.tags") }}
|
||||||
|
</v-card-title>
|
||||||
|
<v-divider class="mx-2"></v-divider>
|
||||||
|
<v-card-text>
|
||||||
|
<RecipeChips :items="tags" :isCategory="false" />
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
|
||||||
|
<Nutrition :value="nutrition" :edit="false" />
|
||||||
|
<Assets :value="assets" :edit="false" :slug="slug" />
|
||||||
</div>
|
</div>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-divider
|
<v-divider
|
||||||
|
@ -50,14 +63,15 @@
|
||||||
></v-divider>
|
></v-divider>
|
||||||
|
|
||||||
<v-col cols="12" sm="12" md="8" lg="8">
|
<v-col cols="12" sm="12" md="8" lg="8">
|
||||||
<Steps :steps="instructions" />
|
<Instructions :value="instructions" :edit="false" />
|
||||||
|
<Notes :value="notes" :edit="false" />
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
<div v-if="!medium">
|
<div v-if="!medium">
|
||||||
<RecipeChips :title="$t('recipe.categories')" :items="categories" />
|
<RecipeChips :title="$t('recipe.categories')" :items="categories" />
|
||||||
<RecipeChips :title="$t('recipe.tags')" :items="tags" />
|
<RecipeChips :title="$t('recipe.tags')" :items="tags" />
|
||||||
<Notes :notes="notes" />
|
<Nutrition :value="nutrition" :edit="false" />
|
||||||
<NutritionEditor :value="nutrition" :edit="false" />
|
<Assets :value="assets" :edit="false" :slug="slug" />
|
||||||
</div>
|
</div>
|
||||||
<v-row class="mt-2 mb-1">
|
<v-row class="mt-2 mb-1">
|
||||||
<v-col></v-col>
|
<v-col></v-col>
|
||||||
|
@ -82,24 +96,27 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import NutritionEditor from "@/components/Recipe/RecipeEditor/NutritionEditor";
|
import Nutrition from "@/components/Recipe/Parts/Nutrition";
|
||||||
import VueMarkdown from "@adapttive/vue-markdown";
|
import VueMarkdown from "@adapttive/vue-markdown";
|
||||||
import utils from "@/utils";
|
import utils from "@/utils";
|
||||||
import RecipeChips from "./RecipeChips";
|
import RecipeChips from "./RecipeChips";
|
||||||
import Steps from "./Steps";
|
import Notes from "@/components/Recipe/Parts/Notes";
|
||||||
import Notes from "./Notes";
|
import Ingredients from "@/components/Recipe/Parts/Ingredients";
|
||||||
import Ingredients from "./Ingredients";
|
import Instructions from "@/components/Recipe/Parts/Instructions.vue";
|
||||||
|
import Assets from "../Parts/Assets.vue";
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
VueMarkdown,
|
VueMarkdown,
|
||||||
RecipeChips,
|
RecipeChips,
|
||||||
Steps,
|
|
||||||
Notes,
|
Notes,
|
||||||
Ingredients,
|
Ingredients,
|
||||||
NutritionEditor,
|
Nutrition,
|
||||||
|
Instructions,
|
||||||
|
Assets,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
name: String,
|
name: String,
|
||||||
|
slug: String,
|
||||||
description: String,
|
description: String,
|
||||||
ingredients: Array,
|
ingredients: Array,
|
||||||
instructions: Array,
|
instructions: Array,
|
||||||
|
@ -110,6 +127,7 @@ export default {
|
||||||
yields: String,
|
yields: String,
|
||||||
orgURL: String,
|
orgURL: String,
|
||||||
nutrition: Object,
|
nutrition: Object,
|
||||||
|
assets: Array,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
<slot name="open" v-bind="{ open }"> </slot>
|
||||||
<v-dialog
|
<v-dialog
|
||||||
v-model="dialog"
|
v-model="dialog"
|
||||||
:width="modalWidth + 'px'"
|
:width="modalWidth + 'px'"
|
||||||
|
@ -25,7 +26,7 @@
|
||||||
Cancel
|
Cancel
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn color="success" @click="$emit('submit')">
|
<v-btn color="success" @click="submitEvent">
|
||||||
Submit
|
Submit
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</slot>
|
</slot>
|
||||||
|
@ -65,6 +66,10 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
submitEvent() {
|
||||||
|
this.$emit("submit");
|
||||||
|
this.close();
|
||||||
|
},
|
||||||
open() {
|
open() {
|
||||||
this.dialog = true;
|
this.dialog = true;
|
||||||
},
|
},
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Seneste"
|
"recent": "Seneste"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Beskrivelse",
|
"description": "Beskrivelse",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingrediens",
|
"ingredient": "Ingrediens",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Oprindelig opskrift",
|
"original-url": "Oprindelig opskrift",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Opskriftens navn",
|
"recipe-name": "Opskriftens navn",
|
||||||
"servings": "Portioner",
|
"servings": "Portioner",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Trin: {step}",
|
"step-index": "Trin: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Mærker",
|
"tags": "Mærker",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Neueste"
|
"recent": "Neueste"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Schlüssel hinzufügen",
|
"add-key": "Schlüssel hinzufügen",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Kalorien",
|
"calories": "Kalorien",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Bist du dir sicher, dass du dieses Rezept löschen möchtest?",
|
"delete-confirmation": "Bist du dir sicher, dass du dieses Rezept löschen möchtest?",
|
||||||
"delete-recipe": "Rezept löschen",
|
"delete-recipe": "Rezept löschen",
|
||||||
"description": "Beschreibung",
|
"description": "Beschreibung",
|
||||||
"fat-content": "Fettgehalt",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Ballaststoffe",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "g",
|
"grams": "g",
|
||||||
"image": "Bild",
|
"image": "Bild",
|
||||||
"ingredient": "Zutat",
|
"ingredient": "Zutat",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Ursprüngliche URL",
|
"original-url": "Ursprüngliche URL",
|
||||||
"perform-time": "Kochzeit",
|
"perform-time": "Kochzeit",
|
||||||
"prep-time": "Vorbereitung",
|
"prep-time": "Vorbereitung",
|
||||||
"protein-content": "Eiweißgehalt",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Rezeptbild",
|
"recipe-image": "Rezeptbild",
|
||||||
"recipe-name": "Rezeptname",
|
"recipe-name": "Rezeptname",
|
||||||
"servings": "Portionen",
|
"servings": "Portionen",
|
||||||
"sodium-content": "Natriumgehalt",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Schritt {step}:",
|
"step-index": "Schritt {step}:",
|
||||||
"sugar-content": "Zuckergehalt",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Schlagworte",
|
"tags": "Schlagworte",
|
||||||
"title": "Titel",
|
"title": "Titel",
|
||||||
"total-time": "Gesamtzeit",
|
"total-time": "Gesamtzeit",
|
||||||
|
@ -152,7 +154,7 @@
|
||||||
"exclude": "Ausschließen",
|
"exclude": "Ausschließen",
|
||||||
"include": "Einbeziehen",
|
"include": "Einbeziehen",
|
||||||
"or": "Oder",
|
"or": "Oder",
|
||||||
"and": "and",
|
"and": "und",
|
||||||
"search": "Suchen",
|
"search": "Suchen",
|
||||||
"tag-filter": "Schlagwortfilter"
|
"tag-filter": "Schlagwortfilter"
|
||||||
},
|
},
|
||||||
|
@ -221,7 +223,7 @@
|
||||||
},
|
},
|
||||||
"toolbox": {
|
"toolbox": {
|
||||||
"toolbox": "Toolbox",
|
"toolbox": "Toolbox",
|
||||||
"new-name": "New Name",
|
"new-name": "Neuer Name",
|
||||||
"recipes-effected": "Recipes Effected",
|
"recipes-effected": "Recipes Effected",
|
||||||
"title-case-all": "Title Case All",
|
"title-case-all": "Title Case All",
|
||||||
"no-unused-items": "No Unused Items",
|
"no-unused-items": "No Unused Items",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -161,6 +161,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -169,8 +170,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
"ingredients": "Ingredients",
|
"ingredients": "Ingredients",
|
||||||
|
@ -187,7 +189,7 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-created": "Recipe created",
|
"recipe-created": "Recipe created",
|
||||||
"recipe-creation-failed": "Recipe creation failed",
|
"recipe-creation-failed": "Recipe creation failed",
|
||||||
"recipe-deleted": "Recipe deleted",
|
"recipe-deleted": "Recipe deleted",
|
||||||
|
@ -197,9 +199,9 @@
|
||||||
"recipe-update-failed": "Recipe update failed",
|
"recipe-update-failed": "Recipe update failed",
|
||||||
"recipe-updated": "Recipe updated",
|
"recipe-updated": "Recipe updated",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Récent"
|
"recent": "Récent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Ajouter une clé",
|
"add-key": "Ajouter une clé",
|
||||||
"api-extras": "Extras API",
|
"api-extras": "Extras API",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Êtes-vous sûr(e) de vouloir supprimer cette recette ?",
|
"delete-confirmation": "Êtes-vous sûr(e) de vouloir supprimer cette recette ?",
|
||||||
"delete-recipe": "Supprimer la recette",
|
"delete-recipe": "Supprimer la recette",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Lipides",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fibres",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grammes",
|
"grams": "grammes",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingrédient",
|
"ingredient": "Ingrédient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Recette originale",
|
"original-url": "Recette originale",
|
||||||
"perform-time": "Temps de cuisson",
|
"perform-time": "Temps de cuisson",
|
||||||
"prep-time": "Temps de préparation",
|
"prep-time": "Temps de préparation",
|
||||||
"protein-content": "Protéines",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Image de la recette",
|
"recipe-image": "Image de la recette",
|
||||||
"recipe-name": "Nom de la recette",
|
"recipe-name": "Nom de la recette",
|
||||||
"servings": "Portions",
|
"servings": "Portions",
|
||||||
"sodium-content": "Sels",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Étape : {step}",
|
"step-index": "Étape : {step}",
|
||||||
"sugar-content": "Glucides",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Mots-clés",
|
"tags": "Mots-clés",
|
||||||
"title": "Titre",
|
"title": "Titre",
|
||||||
"total-time": "Temps total",
|
"total-time": "Temps total",
|
||||||
|
@ -152,7 +154,7 @@
|
||||||
"exclude": "Exclure",
|
"exclude": "Exclure",
|
||||||
"include": "Inclure",
|
"include": "Inclure",
|
||||||
"or": "Ou",
|
"or": "Ou",
|
||||||
"and": "and",
|
"and": "et",
|
||||||
"search": "Rechercher",
|
"search": "Rechercher",
|
||||||
"tag-filter": "Filtre par mots-clés"
|
"tag-filter": "Filtre par mots-clés"
|
||||||
},
|
},
|
||||||
|
@ -220,14 +222,14 @@
|
||||||
"webhook-url": "Lien du webhook"
|
"webhook-url": "Lien du webhook"
|
||||||
},
|
},
|
||||||
"toolbox": {
|
"toolbox": {
|
||||||
"toolbox": "Toolbox",
|
"toolbox": "Boîte à outils",
|
||||||
"new-name": "New Name",
|
"new-name": "Nouveau nom",
|
||||||
"recipes-effected": "Recipes Effected",
|
"recipes-effected": "Recipes Effected",
|
||||||
"title-case-all": "Title Case All",
|
"title-case-all": "Majuscules partout",
|
||||||
"no-unused-items": "No Unused Items",
|
"no-unused-items": "Aucun élément inutilisé",
|
||||||
"remove-unused": "Remove Unused",
|
"remove-unused": "Supprimer orphelins",
|
||||||
"assign-all": "Assign All",
|
"assign-all": "Assigner tout",
|
||||||
"bulk-assign": "Bulk Assign"
|
"bulk-assign": "Assigner en masse"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent(e)"
|
"recent": "Recent(e)"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Sleutel toevoegen",
|
"add-key": "Sleutel toevoegen",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calorieën",
|
"calories": "Calorieën",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Weet u zeker dat u dit recept wilt verwijderen?",
|
"delete-confirmation": "Weet u zeker dat u dit recept wilt verwijderen?",
|
||||||
"delete-recipe": "Recept verwijderen",
|
"delete-recipe": "Recept verwijderen",
|
||||||
"description": "Omschrijving",
|
"description": "Omschrijving",
|
||||||
"fat-content": "Vetten",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Vezels",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "gram",
|
"grams": "gram",
|
||||||
"image": "Afbeelding",
|
"image": "Afbeelding",
|
||||||
"ingredient": "Ingrediënt",
|
"ingredient": "Ingrediënt",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Oorspronkelijke URL",
|
"original-url": "Oorspronkelijke URL",
|
||||||
"perform-time": "Kook tijd",
|
"perform-time": "Kook tijd",
|
||||||
"prep-time": "Voorbereiding tijd",
|
"prep-time": "Voorbereiding tijd",
|
||||||
"protein-content": "Eiwitten",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recept afbeelding",
|
"recipe-image": "Recept afbeelding",
|
||||||
"recipe-name": "Receptnaam",
|
"recipe-name": "Receptnaam",
|
||||||
"servings": "Porties",
|
"servings": "Porties",
|
||||||
"sodium-content": "Sodium gehalte",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Stap: {step}",
|
"step-index": "Stap: {step}",
|
||||||
"sugar-content": "Suiker gehalte",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Labels",
|
"tags": "Labels",
|
||||||
"title": "Titel",
|
"title": "Titel",
|
||||||
"total-time": "Totale Tijd",
|
"total-time": "Totale Tijd",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -4,65 +4,65 @@
|
||||||
"take-me-home": "Powrót na stronę główną"
|
"take-me-home": "Powrót na stronę główną"
|
||||||
},
|
},
|
||||||
"about": {
|
"about": {
|
||||||
"about-mealie": "About Mealie",
|
"about-mealie": "O Mealie",
|
||||||
"api-docs": "API Docs",
|
"api-docs": "Dokumentacja API",
|
||||||
"api-port": "API Port",
|
"api-port": "Port API",
|
||||||
"application-mode": "Application Mode",
|
"application-mode": "Tryb aplikacji",
|
||||||
"database-type": "Database Type",
|
"database-type": "Rodzaj bazy danych",
|
||||||
"default-group": "Default Group",
|
"default-group": "Domyślna grupa",
|
||||||
"demo": "Demo",
|
"demo": "Demo",
|
||||||
"demo-status": "Demo Status",
|
"demo-status": "Status demo",
|
||||||
"development": "Development",
|
"development": "Wersja testowa",
|
||||||
"not-demo": "Not Demo",
|
"not-demo": "Nie demo",
|
||||||
"production": "Production",
|
"production": "Produkcyjna",
|
||||||
"sqlite-file": "SQLite File",
|
"sqlite-file": "Plik SQLite'a",
|
||||||
"version": "Version"
|
"version": "Wersja"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"apply": "Apply",
|
"apply": "Zastosuj",
|
||||||
"cancel": "Anuluj",
|
"cancel": "Anuluj",
|
||||||
"close": "Zamknij",
|
"close": "Zamknij",
|
||||||
"confirm": "Potwierdź",
|
"confirm": "Potwierdź",
|
||||||
"create": "Utwórz",
|
"create": "Utwórz",
|
||||||
"current-parenthesis": "(Current)",
|
"current-parenthesis": "(Bieżący)",
|
||||||
"delete": "Usuń",
|
"delete": "Usuń",
|
||||||
"disabled": "Disabled",
|
"disabled": "Wyłączone",
|
||||||
"download": "Pobierz",
|
"download": "Pobierz",
|
||||||
"edit": "Edytuj",
|
"edit": "Edytuj",
|
||||||
"enabled": "Włączone",
|
"enabled": "Włączone",
|
||||||
"field-required": "Field Required",
|
"field-required": "Pole jest wymagane",
|
||||||
"filter": "Filter",
|
"filter": "Filtruj",
|
||||||
"friday": "Friday",
|
"friday": "Piątek",
|
||||||
"get": "Get",
|
"get": "Zastosuj",
|
||||||
"groups": "Groups",
|
"groups": "Grupy",
|
||||||
"import": "Importuj",
|
"import": "Importuj",
|
||||||
"monday": "Monday",
|
"monday": "Poniedziałek",
|
||||||
"name": "Nazwa",
|
"name": "Nazwa",
|
||||||
"no": "No",
|
"no": "Nie",
|
||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"options": "Opcje",
|
"options": "Opcje",
|
||||||
"random": "Losowa",
|
"random": "Losowa",
|
||||||
"recent": "Recent",
|
"recent": "Najnowsze",
|
||||||
"recipes": "Przepisy",
|
"recipes": "Przepisy",
|
||||||
"reset": "Reset",
|
"reset": "Resetuj",
|
||||||
"saturday": "Saturday",
|
"saturday": "Sobota",
|
||||||
"save": "Zapisz",
|
"save": "Zapisz",
|
||||||
"settings": "Ustawienia",
|
"settings": "Ustawienia",
|
||||||
"sort": "Sort",
|
"sort": "Sortuj",
|
||||||
"sort-alphabetically": "A-Z",
|
"sort-alphabetically": "A-Z",
|
||||||
"submit": "Zatwierdź",
|
"submit": "Zatwierdź",
|
||||||
"sunday": "Sunday",
|
"sunday": "Niedziela",
|
||||||
"templates": "Szablony",
|
"templates": "Szablony",
|
||||||
"themes": "Motywy",
|
"themes": "Motywy",
|
||||||
"thursday": "Thursday",
|
"thursday": "Czwartek",
|
||||||
"token": "Token",
|
"token": "Token",
|
||||||
"tuesday": "Tuesday",
|
"tuesday": "Wtorek",
|
||||||
"update": "Uaktualnij",
|
"update": "Uaktualnij",
|
||||||
"upload": "Wrzuć",
|
"upload": "Prześlij",
|
||||||
"url": "URL",
|
"url": "URL",
|
||||||
"users": "Users",
|
"users": "Użytkownicy",
|
||||||
"wednesday": "Wednesday",
|
"wednesday": "Środa",
|
||||||
"yes": "Yes"
|
"yes": "Tak"
|
||||||
},
|
},
|
||||||
"meal-plan": {
|
"meal-plan": {
|
||||||
"create-a-new-meal-plan": "Utwórz nowy plan posiłku",
|
"create-a-new-meal-plan": "Utwórz nowy plan posiłku",
|
||||||
|
@ -70,13 +70,13 @@
|
||||||
"dinner-today": "Obiad dziś",
|
"dinner-today": "Obiad dziś",
|
||||||
"edit-meal-plan": "Edytuj plan posiłku",
|
"edit-meal-plan": "Edytuj plan posiłku",
|
||||||
"end-date": "Data zakończenia",
|
"end-date": "Data zakończenia",
|
||||||
"group": "Group (Beta)",
|
"group": "Grupa (Beta)",
|
||||||
"meal-planner": "Meal Planner",
|
"meal-planner": "Plan posiłków",
|
||||||
"meal-plans": "Plany posiłku",
|
"meal-plans": "Plany posiłku",
|
||||||
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Only recipes with these categories will be used in Meal Plans",
|
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Tylko przepisy z tych kategorii będą używane w planach posiłków",
|
||||||
"planner": "Planer",
|
"planner": "Planer",
|
||||||
"quick-week": "Quick Week",
|
"quick-week": "Szybki plan na tydzień",
|
||||||
"shopping-list": "Shopping List",
|
"shopping-list": "Lista zakupów",
|
||||||
"start-date": "Data rozpoczęcia"
|
"start-date": "Data rozpoczęcia"
|
||||||
},
|
},
|
||||||
"migration": {
|
"migration": {
|
||||||
|
@ -93,73 +93,75 @@
|
||||||
},
|
},
|
||||||
"new-recipe": {
|
"new-recipe": {
|
||||||
"bulk-add": "Dodanie zbiorcze",
|
"bulk-add": "Dodanie zbiorcze",
|
||||||
"error-message": "Wygląda na to, że wystąpił błąd. Sprawdź log i debug/last_recipe.json aby zasięgnąć po więcej informacji.",
|
"error-message": "Wygląda na to, że wystąpił błąd. Sprawdź log i debug/last_recipe.json aby sprawdzić co poszło nie tak.",
|
||||||
"from-url": "Z odnośnika",
|
"from-url": "Importuj przepis",
|
||||||
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Przeklej zawartość przepisu. Każda indywidualna linia traktowana będzie jako pozycja na liście",
|
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Wklej zawartość przepisu. Każda indywidualna linia traktowana będzie jako pozycja na liście",
|
||||||
"recipe-url": "Odnośnik przepisu",
|
"recipe-url": "Adres URL przepisu",
|
||||||
"url-form-hint": "Copy and paste a link from your favorite recipe website"
|
"url-form-hint": "Skopiuj i wklej link ze swojej ulubionej strony z przepisami"
|
||||||
},
|
},
|
||||||
"page": {
|
"page": {
|
||||||
"all-recipes": "All Recipes",
|
"all-recipes": "Wszystkie przepisy",
|
||||||
"home-page": "Home Page",
|
"home-page": "Strona Główna",
|
||||||
"recent": "Recent"
|
"recent": "Najnowsze"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Dodaj klucz",
|
"add-key": "Dodaj klucz",
|
||||||
"api-extras": "Dodatki API",
|
"api-extras": "Dodatki API",
|
||||||
"calories": "Calories",
|
"calories": "Kalorie",
|
||||||
"calories-suffix": "calories",
|
"calories-suffix": "kalorie",
|
||||||
"categories": "Kategorie",
|
"categories": "Kategorie",
|
||||||
"delete-confirmation": "Czy jesteś pewien, że chcesz usunąć ten przepis?",
|
"delete-confirmation": "Czy jesteś pewien, że chcesz usunąć ten przepis?",
|
||||||
"delete-recipe": "Usuń przepis",
|
"delete-recipe": "Usuń przepis",
|
||||||
"description": "Opis",
|
"description": "Opis",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
"grams": "grams",
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"image": "Image",
|
"grams": "gram",
|
||||||
|
"image": "Zdjęcie",
|
||||||
"ingredient": "Składnik",
|
"ingredient": "Składnik",
|
||||||
"ingredients": "Składniki",
|
"ingredients": "Składniki",
|
||||||
"instructions": "Instrukcje",
|
"instructions": "Instrukcje",
|
||||||
"key-name-required": "Nazwa klucza jest wymagana",
|
"key-name-required": "Nazwa klucza jest wymagana",
|
||||||
"milligrams": "milligrams",
|
"milligrams": "miligram",
|
||||||
"new-key-name": "Nazwa nowego klucza",
|
"new-key-name": "Nazwa nowego klucza",
|
||||||
"no-white-space-allowed": "Znaki niedrukowalne są niedozwolone",
|
"no-white-space-allowed": "Znaki niedrukowalne są niedozwolone",
|
||||||
"note": "Notatka",
|
"note": "Notatka",
|
||||||
"notes": "Notatki",
|
"notes": "Notatki",
|
||||||
"nutrition": "Nutrition",
|
"nutrition": "Wartości odżywcze",
|
||||||
"object-key": "Klucz obiektu",
|
"object-key": "Klucz obiektu",
|
||||||
"object-value": "Wartość obiektu",
|
"object-value": "Wartość obiektu",
|
||||||
"original-url": "Oryginalny odnośnik",
|
"original-url": "Oryginalny adres URL",
|
||||||
"perform-time": "Czas gotowania",
|
"perform-time": "Czas gotowania",
|
||||||
"prep-time": "Czas przyrządzania",
|
"prep-time": "Czas przyrządzania",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Zdjęcie do przepisu",
|
||||||
"recipe-name": "Nazwa przepisu",
|
"recipe-name": "Nazwa przepisu",
|
||||||
"servings": "Porcje",
|
"servings": "Porcje",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Krok: {step}",
|
"step-index": "Krok: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Etykiety",
|
"tags": "Tagi",
|
||||||
"title": "Tytuł",
|
"title": "Tytuł",
|
||||||
"total-time": "Czas całkowity",
|
"total-time": "Czas całkowity",
|
||||||
"view-recipe": "Wyświetl przepis"
|
"view-recipe": "Wyświetl przepis"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"search-mealie": "Search Mealie (press /)",
|
"search-mealie": "Przeszukaj Mealie (naciśnij /)",
|
||||||
"search-placeholder": "Search...",
|
"search-placeholder": "Szukaj...",
|
||||||
"max-results": "Max Results",
|
"max-results": "Maksymalna liczba wyników",
|
||||||
"category-filter": "Category Filter",
|
"category-filter": "Filtr kategorii",
|
||||||
"exclude": "Exclude",
|
"exclude": "Wyklucz",
|
||||||
"include": "Include",
|
"include": "Dołącz",
|
||||||
"or": "Or",
|
"or": "Lub",
|
||||||
"and": "and",
|
"and": "oraz",
|
||||||
"search": "Search",
|
"search": "Szukaj",
|
||||||
"tag-filter": "Tag Filter"
|
"tag-filter": "Filtr tagów"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"add-a-new-theme": "Dodaj nowy motyw",
|
"add-a-new-theme": "Dodaj nowy motyw",
|
||||||
"admin-settings": "Admin Settings",
|
"admin-settings": "Ustawienia administratora",
|
||||||
"available-backups": "Dostępne kopie zapsowe",
|
"available-backups": "Dostępne kopie zapasowe",
|
||||||
"backup": {
|
"backup": {
|
||||||
"backup-tag": "Etykieta kopii zapasowej",
|
"backup-tag": "Etykieta kopii zapasowej",
|
||||||
"create-heading": "Utwórz kopię zapasową",
|
"create-heading": "Utwórz kopię zapasową",
|
||||||
|
@ -167,43 +169,43 @@
|
||||||
"partial-backup": "Częściowa kopia zapasowa"
|
"partial-backup": "Częściowa kopia zapasowa"
|
||||||
},
|
},
|
||||||
"backup-and-exports": "Kopie zapasowe",
|
"backup-and-exports": "Kopie zapasowe",
|
||||||
"backup-info": "Kopie zapasowe zapisywane są w standardowym formacie JSON wraz ze zdjęciami w systemie plików. W katalogu kopii zapasowej znajdziesz plik z rozszerzeniem .zip zawierający wszystkie przepisy i zdjęcia z bazy danych. Jeśli oznaczone zostały pliki markdown, one także znajdą się w pliku .zip. Aby zaimportować kopię, musi ona znajdować się w folderze kopii zapasowych. Kopie automatyczne tworzone są codziennie o godzinie 03:00.",
|
"backup-info": "Kopie zapasowe zapisywane są w standardowym formacie JSON wraz ze zdjęciami w systemie plików. W katalogu kopii zapasowej znajdziesz plik z rozszerzeniem .zip zawierający wszystkie przepisy i zdjęcia z bazy danych. Jeśli zaznaczone zostały pliki markdown, one także znajdą się w pliku .zip. Aby zaimportować kopię, musi ona znajdować się w folderze kopii zapasowych. Kopie automatyczne tworzone są codziennie o godzinie 03:00.",
|
||||||
"change-password": "Change Password",
|
"change-password": "Zmień hasło",
|
||||||
"current": "Wersja:",
|
"current": "Wersja:",
|
||||||
"custom-pages": "Custom Pages",
|
"custom-pages": "Niestandardowe strony",
|
||||||
"edit-page": "Edit Page",
|
"edit-page": "Edytuj stronę",
|
||||||
"first-day-of-week": "First day of the week",
|
"first-day-of-week": "Pierwszy dzień tygodnia",
|
||||||
"homepage": {
|
"homepage": {
|
||||||
"all-categories": "All Categories",
|
"all-categories": "Wszystkie kategorie",
|
||||||
"card-per-section": "Card Per Section",
|
"card-per-section": "Karty na sekcję",
|
||||||
"home-page": "Home Page",
|
"home-page": "Strona Główna",
|
||||||
"home-page-sections": "Home Page Sections",
|
"home-page-sections": "Sekcje strony głównej",
|
||||||
"show-recent": "Show Recent"
|
"show-recent": "Pokaż najnowsze"
|
||||||
},
|
},
|
||||||
"language": "Język",
|
"language": "Język",
|
||||||
"latest": "Najnowsza",
|
"latest": "Najnowsza",
|
||||||
"local-api": "Lokalne API",
|
"local-api": "Lokalne API",
|
||||||
"locale-settings": "Locale settings",
|
"locale-settings": "Ustawienia językowe",
|
||||||
"manage-users": "Manage Users",
|
"manage-users": "Zarządzaj użytkownikami",
|
||||||
"migrations": "Migrations",
|
"migrations": "Migracje",
|
||||||
"new-page": "New Page",
|
"new-page": "Nowa Strona",
|
||||||
"page-name": "Page Name",
|
"page-name": "Nazwa strony",
|
||||||
"profile": "Profile",
|
"profile": "Profil",
|
||||||
"remove-existing-entries-matching-imported-entries": "Remove existing entries matching imported entries",
|
"remove-existing-entries-matching-imported-entries": "Usuń istniejące wpisy pasujące do importowanych wpisów",
|
||||||
"set-new-time": "Ustaw nowy czas",
|
"set-new-time": "Ustaw nowy czas",
|
||||||
"site-settings": "Site Settings",
|
"site-settings": "Ustawienia strony",
|
||||||
"theme": {
|
"theme": {
|
||||||
"accent": "Akcent",
|
"accent": "Akcent",
|
||||||
"are-you-sure-you-want-to-delete-this-theme": "Czy jesteś pewien, że chcesz usunąć ten motyw?",
|
"are-you-sure-you-want-to-delete-this-theme": "Czy jesteś pewien, że chcesz usunąć ten motyw?",
|
||||||
"choose-how-mealie-looks-to-you-set-your-theme-preference-to-follow-your-system-settings-or-choose-to-use-the-light-or-dark-theme": "Wybierz jak Mealie ma dla Ciebie wyglądać. Dostępne opcje to podążanie za odcieniem systemowym, bądź motyw jasny lub ciemny.",
|
"choose-how-mealie-looks-to-you-set-your-theme-preference-to-follow-your-system-settings-or-choose-to-use-the-light-or-dark-theme": "Wybierz jak Mealie ma dla Ciebie wyglądać. Dostępne opcje to podążanie za odcieniem systemowym, bądź motyw jasny lub ciemny.",
|
||||||
"dark": "Ciemny",
|
"dark": "Ciemny",
|
||||||
"dark-mode": "Ciemny motyw",
|
"dark-mode": "Ciemny motyw",
|
||||||
"default-to-system": "Domyślny dla systemu",
|
"default-to-system": "Motyw systemowy",
|
||||||
"delete-theme": "Usuń motyw",
|
"delete-theme": "Usuń motyw",
|
||||||
"error": "Błąd",
|
"error": "Błąd",
|
||||||
"info": "Informacja",
|
"info": "Informacja",
|
||||||
"light": "Jasny",
|
"light": "Jasny",
|
||||||
"primary": "Pierwszorzędny",
|
"primary": "Podstawowy",
|
||||||
"secondary": "Drugorzędny",
|
"secondary": "Drugorzędny",
|
||||||
"select-a-theme-from-the-dropdown-or-create-a-new-theme-note-that-the-default-theme-will-be-served-to-all-users-who-have-not-set-a-theme-preference": "Wybierz motyw z rozwijanej listy bądź stwórz nowy. Domyślny motyw zostanie użyty dla wszystkich użytkowników którzy nie wybrali własnej preferencji.",
|
"select-a-theme-from-the-dropdown-or-create-a-new-theme-note-that-the-default-theme-will-be-served-to-all-users-who-have-not-set-a-theme-preference": "Wybierz motyw z rozwijanej listy bądź stwórz nowy. Domyślny motyw zostanie użyty dla wszystkich użytkowników którzy nie wybrali własnej preferencji.",
|
||||||
"success": "Powodzenie",
|
"success": "Powodzenie",
|
||||||
|
@ -217,63 +219,63 @@
|
||||||
"meal-planner-webhooks": "Webhooki planera posiłków",
|
"meal-planner-webhooks": "Webhooki planera posiłków",
|
||||||
"test-webhooks": "Testuj webhooki",
|
"test-webhooks": "Testuj webhooki",
|
||||||
"the-urls-listed-below-will-recieve-webhooks-containing-the-recipe-data-for-the-meal-plan-on-its-scheduled-day-currently-webhooks-will-execute-at": "Odnośniki poniżej otrzymają webhook zawierający dane o przepisie dla danego dnia. Aktualnie webhooki zostanę wykonane o",
|
"the-urls-listed-below-will-recieve-webhooks-containing-the-recipe-data-for-the-meal-plan-on-its-scheduled-day-currently-webhooks-will-execute-at": "Odnośniki poniżej otrzymają webhook zawierający dane o przepisie dla danego dnia. Aktualnie webhooki zostanę wykonane o",
|
||||||
"webhook-url": "Odnośnik webhooka"
|
"webhook-url": "URL webhooka"
|
||||||
},
|
},
|
||||||
"toolbox": {
|
"toolbox": {
|
||||||
"toolbox": "Toolbox",
|
"toolbox": "Przybornik",
|
||||||
"new-name": "New Name",
|
"new-name": "Nowa nazwa",
|
||||||
"recipes-effected": "Recipes Effected",
|
"recipes-effected": "Objęte przepisy",
|
||||||
"title-case-all": "Title Case All",
|
"title-case-all": "Wszędzie wielkie litery",
|
||||||
"no-unused-items": "No Unused Items",
|
"no-unused-items": "Brak nieużywanych elementów",
|
||||||
"remove-unused": "Remove Unused",
|
"remove-unused": "Usuń nieużywane",
|
||||||
"assign-all": "Assign All",
|
"assign-all": "Przypisz wszystkie",
|
||||||
"bulk-assign": "Bulk Assign"
|
"bulk-assign": "Masowe przypisanie"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"admin": "Admin",
|
"admin": "Administrator",
|
||||||
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",
|
"are-you-sure-you-want-to-delete-the-group": "Czy na pewno chcesz usunąć <b>{groupName}<b/>?",
|
||||||
"are-you-sure-you-want-to-delete-the-link": "Are you sure you want to delete the link <b>{link}<b/>?",
|
"are-you-sure-you-want-to-delete-the-link": "Czy na pewno chcesz usunąć link <b>{link}<b/>?",
|
||||||
"are-you-sure-you-want-to-delete-the-user": "Are you sure you want to delete the user <b>{activeName} ID: {activeId}<b/>?",
|
"are-you-sure-you-want-to-delete-the-user": "Czy na pewno chcesz usunąć użytkownika <b>{activeName} ID: {activeId}<b/>?",
|
||||||
"confirm-group-deletion": "Confirm Group Deletion",
|
"confirm-group-deletion": "Potwierdź usunięcie grupy",
|
||||||
"confirm-link-deletion": "Confirm Link Deletion",
|
"confirm-link-deletion": "Potwierdź usunięcie linku",
|
||||||
"confirm-password": "Confirm Password",
|
"confirm-password": "Potwierdź hasło",
|
||||||
"confirm-user-deletion": "Confirm User Deletion",
|
"confirm-user-deletion": "Potwierdź usunięcie użytkownika",
|
||||||
"could-not-validate-credentials": "Could Not Validate Credentials",
|
"could-not-validate-credentials": "Nie można zweryfikować danych logowania",
|
||||||
"create-group": "Create Group",
|
"create-group": "Utwórz Grupę",
|
||||||
"create-link": "Create Link",
|
"create-link": "Utwórz link",
|
||||||
"create-user": "Create User",
|
"create-user": "Utwórz użytkownika",
|
||||||
"current-password": "Current Password",
|
"current-password": "Obecne hasło",
|
||||||
"e-mail-must-be-valid": "E-mail must be valid",
|
"e-mail-must-be-valid": "E-mail musi być poprawny",
|
||||||
"edit-user": "Edit User",
|
"edit-user": "Edytuj użytkownika",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"full-name": "Full Name",
|
"full-name": "Imię i nazwisko",
|
||||||
"group": "Group",
|
"group": "Grupa",
|
||||||
"group-id-with-value": "Group ID: {groupID}",
|
"group-id-with-value": "ID grupy: {groupID}",
|
||||||
"group-name": "Group Name",
|
"group-name": "Nazwa grupy",
|
||||||
"groups": "Groups",
|
"groups": "Grupy",
|
||||||
"groups-can-only-be-set-by-administrators": "Groups can only be set by administrators",
|
"groups-can-only-be-set-by-administrators": "Grupy mogą być ustawiane tylko przez administratorów",
|
||||||
"link-id": "Link ID",
|
"link-id": "ID linku",
|
||||||
"link-name": "Link Name",
|
"link-name": "Nazwa linku",
|
||||||
"login": "Login",
|
"login": "Login",
|
||||||
"logout": "Logout",
|
"logout": "Wyloguj się",
|
||||||
"new-password": "New Password",
|
"new-password": "Nowe Hasło",
|
||||||
"new-user": "New User",
|
"new-user": "Nowy użytkownik",
|
||||||
"password": "Hasło",
|
"password": "Hasło",
|
||||||
"password-must-match": "Password must match",
|
"password-must-match": "Hasła muszą być takie same",
|
||||||
"reset-password": "Reset Password",
|
"reset-password": "Zresetuj hasło",
|
||||||
"sign-in": "Zaloguj się",
|
"sign-in": "Zaloguj się",
|
||||||
"sign-up-links": "Sign Up Links",
|
"sign-up-links": "Linki do rejestracji",
|
||||||
"total-mealplans": "Total MealPlans",
|
"total-mealplans": "Ilość planów posiłków",
|
||||||
"total-users": "Total Users",
|
"total-users": "Ilość użytkowników",
|
||||||
"upload-photo": "Upload Photo",
|
"upload-photo": "Prześlij zdjęcie",
|
||||||
"use-8-characters-or-more-for-your-password": "Use 8 characters or more for your password",
|
"use-8-characters-or-more-for-your-password": "Hasło musi składać się z 8 lub więcej znaków",
|
||||||
"user-group": "User Group",
|
"user-group": "Grupa użytkownika",
|
||||||
"user-id": "User ID",
|
"user-id": "ID użytkownika",
|
||||||
"user-id-with-value": "User ID: {id}",
|
"user-id-with-value": "ID użytkownika: {id}",
|
||||||
"user-password": "User Password",
|
"user-password": "Hasło użytkownika",
|
||||||
"users": "Users",
|
"users": "Użytkownicy",
|
||||||
"webhook-time": "Webhook Time",
|
"webhook-time": "Czas webhooka",
|
||||||
"webhooks-enabled": "Webhooks Enabled"
|
"webhooks-enabled": "Webhooki włączone"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Adicionar Chave",
|
"add-key": "Adicionar Chave",
|
||||||
"api-extras": "Extras API",
|
"api-extras": "Extras API",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Tem a certeza que deseja eliminar esta receita?",
|
"delete-confirmation": "Tem a certeza que deseja eliminar esta receita?",
|
||||||
"delete-recipe": "Eliminar Receita",
|
"delete-recipe": "Eliminar Receita",
|
||||||
"description": "Descrição",
|
"description": "Descrição",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingrediente",
|
"ingredient": "Ingrediente",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "URL Original",
|
"original-url": "URL Original",
|
||||||
"perform-time": "Tempo de Cozedura",
|
"perform-time": "Tempo de Cozedura",
|
||||||
"prep-time": "Tempo de Preparação",
|
"prep-time": "Tempo de Preparação",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Nome da Receita",
|
"recipe-name": "Nome da Receita",
|
||||||
"servings": "Porções",
|
"servings": "Porções",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Passo: {step}",
|
"step-index": "Passo: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Etiquetas",
|
"tags": "Etiquetas",
|
||||||
"title": "Título",
|
"title": "Título",
|
||||||
"total-time": "Tempo Total",
|
"total-time": "Tempo Total",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Beskrivning",
|
"description": "Beskrivning",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingrediens",
|
"ingredient": "Ingrediens",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Originalrecept",
|
"original-url": "Originalrecept",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Receptets namn",
|
"recipe-name": "Receptets namn",
|
||||||
"servings": "Portioner",
|
"servings": "Portioner",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Steg: {step}",
|
"step-index": "Steg: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Taggar",
|
"tags": "Taggar",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Delete Recipe",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Ingredient",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "Original URL",
|
"original-url": "Original URL",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Cook Time",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Prep Time",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Recipe Name",
|
||||||
"servings": "Servings",
|
"servings": "Servings",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Step: {step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"total-time": "Total Time",
|
"total-time": "Total Time",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "最近"
|
"recent": "最近"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "您确定要删除此食谱吗?",
|
"delete-confirmation": "您确定要删除此食谱吗?",
|
||||||
"delete-recipe": "删除食谱",
|
"delete-recipe": "删除食谱",
|
||||||
"description": "描述",
|
"description": "描述",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "材料",
|
"ingredient": "材料",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "原食谱链接",
|
"original-url": "原食谱链接",
|
||||||
"perform-time": "烹饪时间",
|
"perform-time": "烹饪时间",
|
||||||
"prep-time": "准备时间",
|
"prep-time": "准备时间",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "食谱名称",
|
"recipe-name": "食谱名称",
|
||||||
"servings": "份量",
|
"servings": "份量",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "步骤:{step}",
|
"step-index": "步骤:{step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "标签",
|
"tags": "标签",
|
||||||
"title": "标题",
|
"title": "标题",
|
||||||
"total-time": "总时间",
|
"total-time": "总时间",
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
"recent": "Recent"
|
"recent": "Recent"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
"assets": "Assets",
|
||||||
"add-key": "Add Key",
|
"add-key": "Add Key",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "API Extras",
|
||||||
"calories": "Calories",
|
"calories": "Calories",
|
||||||
|
@ -113,8 +114,9 @@
|
||||||
"delete-confirmation": "您確定要刪除此食譜嗎?",
|
"delete-confirmation": "您確定要刪除此食譜嗎?",
|
||||||
"delete-recipe": "刪除食譜",
|
"delete-recipe": "刪除食譜",
|
||||||
"description": "描述",
|
"description": "描述",
|
||||||
"fat-content": "Fat Content",
|
"fat-content": "Fat",
|
||||||
"fiber-content": "Fiber Content",
|
"fiber-content": "Fiber",
|
||||||
|
"carbohydrate-content": "Carbohydrate",
|
||||||
"grams": "grams",
|
"grams": "grams",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"ingredient": "材料",
|
"ingredient": "材料",
|
||||||
|
@ -132,13 +134,13 @@
|
||||||
"original-url": "原食譜鏈接",
|
"original-url": "原食譜鏈接",
|
||||||
"perform-time": "烹飪時間 / 執行時間",
|
"perform-time": "烹飪時間 / 執行時間",
|
||||||
"prep-time": "準備時間",
|
"prep-time": "準備時間",
|
||||||
"protein-content": "Protein Content",
|
"protein-content": "Protein",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Recipe Image",
|
||||||
"recipe-name": "食譜名稱",
|
"recipe-name": "食譜名稱",
|
||||||
"servings": "份量",
|
"servings": "份量",
|
||||||
"sodium-content": "Sodium Content",
|
"sodium-content": "Sodium",
|
||||||
"step-index": "步驟:{step}",
|
"step-index": "步驟:{step}",
|
||||||
"sugar-content": "Sugar Content",
|
"sugar-content": "Sugar",
|
||||||
"tags": "標籤",
|
"tags": "標籤",
|
||||||
"title": "標題",
|
"title": "標題",
|
||||||
"total-time": "總時間",
|
"total-time": "總時間",
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<ImportDialog
|
|
||||||
:name="selectedName"
|
|
||||||
:date="selectedDate"
|
|
||||||
ref="import_dialog"
|
|
||||||
@import="importBackup"
|
|
||||||
@delete="deleteBackup"
|
|
||||||
/>
|
|
||||||
<v-row>
|
|
||||||
<v-col
|
|
||||||
:sm="6"
|
|
||||||
:md="6"
|
|
||||||
:lg="4"
|
|
||||||
:xl="4"
|
|
||||||
v-for="backup in backups"
|
|
||||||
:key="backup.name"
|
|
||||||
>
|
|
||||||
<v-card @click="openDialog(backup)">
|
|
||||||
<v-card-text>
|
|
||||||
<v-row align="center">
|
|
||||||
<v-col cols="12" sm="2">
|
|
||||||
<v-icon color="primary"> mdi-backup-restore </v-icon>
|
|
||||||
</v-col>
|
|
||||||
<v-col cols="12" sm="10">
|
|
||||||
<div>
|
|
||||||
<strong>{{ backup.name }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>{{ $d(new Date(backup.date), "medium") }}</div>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import ImportDialog from "./ImportDialog";
|
|
||||||
import { api } from "@/api";
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
backups: Array,
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
ImportDialog,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
selectedName: "",
|
|
||||||
selectedDate: "",
|
|
||||||
loading: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog(backup) {
|
|
||||||
this.selectedDate = backup.date;
|
|
||||||
this.selectedName = backup.name;
|
|
||||||
this.$refs.import_dialog.open();
|
|
||||||
},
|
|
||||||
async importBackup(data) {
|
|
||||||
this.$emit("loading");
|
|
||||||
let response = await api.backups.import(data.name, data);
|
|
||||||
|
|
||||||
let failed = response.data.failed;
|
|
||||||
let succesful = response.data.successful;
|
|
||||||
|
|
||||||
this.$emit("finished", succesful, failed);
|
|
||||||
},
|
|
||||||
deleteBackup(data) {
|
|
||||||
this.$emit("loading");
|
|
||||||
|
|
||||||
api.backups.delete(data.name);
|
|
||||||
this.selectedBackup = null;
|
|
||||||
this.backupLoading = false;
|
|
||||||
|
|
||||||
this.$emit("finished");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
|
@ -71,17 +71,6 @@ export default {
|
||||||
this.availableBackups = response.imports;
|
this.availableBackups = response.imports;
|
||||||
this.availableTemplates = response.templates;
|
this.availableTemplates = response.templates;
|
||||||
},
|
},
|
||||||
deleteBackup() {
|
|
||||||
if (this.$refs.form.validate()) {
|
|
||||||
this.backupLoading = true;
|
|
||||||
|
|
||||||
api.backups.delete(this.selectedBackup);
|
|
||||||
this.getAvailableBackups();
|
|
||||||
|
|
||||||
this.selectedBackup = null;
|
|
||||||
this.backupLoading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
processFinished(data) {
|
processFinished(data) {
|
||||||
this.getAvailableBackups();
|
this.getAvailableBackups();
|
||||||
this.backupLoading = false;
|
this.backupLoading = false;
|
||||||
|
|
|
@ -68,7 +68,6 @@ export default {
|
||||||
},
|
},
|
||||||
async openDialog() {
|
async openDialog() {
|
||||||
this.$refs.deleteDialog.open();
|
this.$refs.deleteDialog.open();
|
||||||
console.log(this.isTags);
|
|
||||||
if (this.isTags) {
|
if (this.isTags) {
|
||||||
this.deleteList = await api.tags.getEmpty();
|
this.deleteList = await api.tags.getEmpty();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
:yields="recipeDetails.recipeYield"
|
:yields="recipeDetails.recipeYield"
|
||||||
:orgURL="recipeDetails.orgURL"
|
:orgURL="recipeDetails.orgURL"
|
||||||
:nutrition="recipeDetails.nutrition"
|
:nutrition="recipeDetails.nutrition"
|
||||||
|
:assets="recipeDetails.assets"
|
||||||
|
:slug="recipeDetails.slug"
|
||||||
/>
|
/>
|
||||||
<VJsoneditor
|
<VJsoneditor
|
||||||
@error="logError()"
|
@error="logError()"
|
||||||
|
|
|
@ -36,7 +36,6 @@ const actions = {
|
||||||
async requestRecentRecipes() {
|
async requestRecentRecipes() {
|
||||||
const payload = await api.recipes.allSummary(0, 30);
|
const payload = await api.recipes.allSummary(0, 30);
|
||||||
payload.sort((a, b) => (a.dateAdded > b.dateAdded ? -1 : 1));
|
payload.sort((a, b) => (a.dateAdded > b.dateAdded ? -1 : 1));
|
||||||
console.log(payload);
|
|
||||||
const hash = Object.fromEntries(payload.map(e => [e.id, e]));
|
const hash = Object.fromEntries(payload.map(e => [e.id, e]));
|
||||||
this.commit("setRecentRecipes", hash);
|
this.commit("setRecentRecipes", hash);
|
||||||
},
|
},
|
||||||
|
@ -44,7 +43,6 @@ const actions = {
|
||||||
const all = getters.getAllRecipes;
|
const all = getters.getAllRecipes;
|
||||||
const payload = await api.recipes.allSummary(all.length, 9999);
|
const payload = await api.recipes.allSummary(all.length, 9999);
|
||||||
const hash = Object.fromEntries([...all, ...payload].map(e => [e.id, e]));
|
const hash = Object.fromEntries([...all, ...payload].map(e => [e.id, e]));
|
||||||
console.log(hash);
|
|
||||||
|
|
||||||
this.commit("setAllRecipes", hash);
|
this.commit("setAllRecipes", hash);
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,13 +2,14 @@ import uvicorn
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
|
|
||||||
from mealie.core import root_logger
|
from mealie.core import root_logger
|
||||||
|
|
||||||
# import utils.startup as startup
|
|
||||||
from mealie.core.config import APP_VERSION, settings
|
from mealie.core.config import APP_VERSION, settings
|
||||||
from mealie.routes import backup_routes, debug_routes, migration_routes, theme_routes, utility_routes
|
from mealie.routes import (backup_routes, debug_routes, migration_routes,
|
||||||
|
theme_routes, utility_routes)
|
||||||
from mealie.routes.groups import groups
|
from mealie.routes.groups import groups
|
||||||
from mealie.routes.mealplans import mealplans
|
from mealie.routes.mealplans import mealplans
|
||||||
from mealie.routes.recipe import all_recipe_routes, category_routes, recipe_crud_routes, tag_routes
|
from mealie.routes.recipe import (all_recipe_routes, category_routes,
|
||||||
|
recipe_assets, recipe_crud_routes,
|
||||||
|
tag_routes)
|
||||||
from mealie.routes.site_settings import all_settings
|
from mealie.routes.site_settings import all_settings
|
||||||
from mealie.routes.users import users
|
from mealie.routes.users import users
|
||||||
|
|
||||||
|
@ -37,6 +38,7 @@ def api_routers():
|
||||||
app.include_router(category_routes.router)
|
app.include_router(category_routes.router)
|
||||||
app.include_router(tag_routes.router)
|
app.include_router(tag_routes.router)
|
||||||
app.include_router(recipe_crud_routes.router)
|
app.include_router(recipe_crud_routes.router)
|
||||||
|
app.include_router(recipe_assets.router)
|
||||||
# Meal Routes
|
# Meal Routes
|
||||||
app.include_router(mealplans.router)
|
app.include_router(mealplans.router)
|
||||||
# Settings Routes
|
# Settings Routes
|
||||||
|
@ -50,11 +52,11 @@ def api_routers():
|
||||||
|
|
||||||
|
|
||||||
api_routers()
|
api_routers()
|
||||||
start_scheduler()
|
|
||||||
|
|
||||||
|
|
||||||
@app.on_event("startup")
|
@app.on_event("startup")
|
||||||
def system_startup():
|
def system_startup():
|
||||||
|
start_scheduler()
|
||||||
logger.info("-----SYSTEM STARTUP----- \n")
|
logger.info("-----SYSTEM STARTUP----- \n")
|
||||||
logger.info("------APP SETTINGS------")
|
logger.info("------APP SETTINGS------")
|
||||||
logger.info(settings.json(indent=4, exclude={"SECRET", "DEFAULT_PASSWORD", "SFTP_PASSWORD", "SFTP_USERNAME"}))
|
logger.info(settings.json(indent=4, exclude={"SECRET", "DEFAULT_PASSWORD", "SFTP_PASSWORD", "SFTP_USERNAME"}))
|
||||||
|
|
|
@ -9,7 +9,7 @@ from mealie.db.models.model_base import BaseMixins, SqlAlchemyBase
|
||||||
class Meal(SqlAlchemyBase):
|
class Meal(SqlAlchemyBase):
|
||||||
__tablename__ = "meal"
|
__tablename__ = "meal"
|
||||||
id = sa.Column(sa.Integer, primary_key=True)
|
id = sa.Column(sa.Integer, primary_key=True)
|
||||||
parent_id = sa.Column(sa.String, sa.ForeignKey("mealplan.uid"))
|
parent_id = sa.Column(sa.Integer, sa.ForeignKey("mealplan.uid"))
|
||||||
slug = sa.Column(sa.String)
|
slug = sa.Column(sa.String)
|
||||||
name = sa.Column(sa.String)
|
name = sa.Column(sa.String)
|
||||||
date = sa.Column(sa.Date)
|
date = sa.Column(sa.Date)
|
||||||
|
|
|
@ -5,7 +5,7 @@ from mealie.db.models.model_base import SqlAlchemyBase
|
||||||
class ApiExtras(SqlAlchemyBase):
|
class ApiExtras(SqlAlchemyBase):
|
||||||
__tablename__ = "api_extras"
|
__tablename__ = "api_extras"
|
||||||
id = sa.Column(sa.Integer, primary_key=True)
|
id = sa.Column(sa.Integer, primary_key=True)
|
||||||
parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id"))
|
parent_id = sa.Column(sa.Integer, sa.ForeignKey("recipes.id"))
|
||||||
key_name = sa.Column(sa.String, unique=True)
|
key_name = sa.Column(sa.String, unique=True)
|
||||||
value = sa.Column(sa.String)
|
value = sa.Column(sa.String)
|
||||||
|
|
||||||
|
|
22
mealie/db/models/recipe/assets.py
Normal file
22
mealie/db/models/recipe/assets.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from mealie.db.models.model_base import SqlAlchemyBase
|
||||||
|
|
||||||
|
|
||||||
|
class RecipeAsset(SqlAlchemyBase):
|
||||||
|
__tablename__ = "recipe_assets"
|
||||||
|
id = sa.Column(sa.Integer, primary_key=True)
|
||||||
|
parent_id = sa.Column(sa.Integer, sa.ForeignKey("recipes.id"))
|
||||||
|
name = sa.Column(sa.String)
|
||||||
|
icon = sa.Column(sa.String)
|
||||||
|
file_name = sa.Column(sa.String)
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
name=None,
|
||||||
|
icon=None,
|
||||||
|
file_name=None,
|
||||||
|
) -> None:
|
||||||
|
print("Asset Saved", name)
|
||||||
|
self.name = name
|
||||||
|
self.file_name = file_name
|
||||||
|
self.icon = icon
|
|
@ -41,7 +41,7 @@ class Category(SqlAlchemyBase):
|
||||||
id = sa.Column(sa.Integer, primary_key=True)
|
id = sa.Column(sa.Integer, primary_key=True)
|
||||||
name = sa.Column(sa.String, index=True, nullable=False)
|
name = sa.Column(sa.String, index=True, nullable=False)
|
||||||
slug = sa.Column(sa.String, index=True, unique=True, nullable=False)
|
slug = sa.Column(sa.String, index=True, unique=True, nullable=False)
|
||||||
recipes = orm.relationship("RecipeModel", secondary=recipes2categories, back_populates="recipeCategory")
|
recipes = orm.relationship("RecipeModel", secondary=recipes2categories, back_populates="recipe_category")
|
||||||
|
|
||||||
@validates("name")
|
@validates("name")
|
||||||
def validate_name(self, key, name):
|
def validate_name(self, key, name):
|
||||||
|
|
|
@ -6,7 +6,7 @@ class RecipeIngredient(SqlAlchemyBase):
|
||||||
__tablename__ = "recipes_ingredients"
|
__tablename__ = "recipes_ingredients"
|
||||||
id = sa.Column(sa.Integer, primary_key=True)
|
id = sa.Column(sa.Integer, primary_key=True)
|
||||||
position = sa.Column(sa.Integer)
|
position = sa.Column(sa.Integer)
|
||||||
parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id"))
|
parent_id = sa.Column(sa.Integer, sa.ForeignKey("recipes.id"))
|
||||||
ingredient = sa.Column(sa.String)
|
ingredient = sa.Column(sa.String)
|
||||||
|
|
||||||
def update(self, ingredient):
|
def update(self, ingredient):
|
||||||
|
|
|
@ -5,7 +5,8 @@ from mealie.db.models.model_base import SqlAlchemyBase
|
||||||
class RecipeInstruction(SqlAlchemyBase):
|
class RecipeInstruction(SqlAlchemyBase):
|
||||||
__tablename__ = "recipe_instructions"
|
__tablename__ = "recipe_instructions"
|
||||||
id = sa.Column(sa.Integer, primary_key=True)
|
id = sa.Column(sa.Integer, primary_key=True)
|
||||||
parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id"))
|
parent_id = sa.Column(sa.Integer, sa.ForeignKey("recipes.id"))
|
||||||
position = sa.Column(sa.Integer)
|
position = sa.Column(sa.Integer)
|
||||||
type = sa.Column(sa.String, default="")
|
type = sa.Column(sa.String, default="")
|
||||||
text = sa.Column(sa.String)
|
text = sa.Column(sa.String)
|
||||||
|
title = sa.Column(sa.String)
|
||||||
|
|
|
@ -5,7 +5,7 @@ from mealie.db.models.model_base import SqlAlchemyBase
|
||||||
class Note(SqlAlchemyBase):
|
class Note(SqlAlchemyBase):
|
||||||
__tablename__ = "notes"
|
__tablename__ = "notes"
|
||||||
id = sa.Column(sa.Integer, primary_key=True)
|
id = sa.Column(sa.Integer, primary_key=True)
|
||||||
parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id"))
|
parent_id = sa.Column(sa.Integer, sa.ForeignKey("recipes.id"))
|
||||||
title = sa.Column(sa.String)
|
title = sa.Column(sa.String)
|
||||||
text = sa.Column(sa.String)
|
text = sa.Column(sa.String)
|
||||||
|
|
||||||
|
|
|
@ -5,26 +5,29 @@ from mealie.db.models.model_base import SqlAlchemyBase
|
||||||
class Nutrition(SqlAlchemyBase):
|
class Nutrition(SqlAlchemyBase):
|
||||||
__tablename__ = "recipe_nutrition"
|
__tablename__ = "recipe_nutrition"
|
||||||
id = sa.Column(sa.Integer, primary_key=True)
|
id = sa.Column(sa.Integer, primary_key=True)
|
||||||
parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id"))
|
parent_id = sa.Column(sa.Integer, sa.ForeignKey("recipes.id"))
|
||||||
calories = sa.Column(sa.String)
|
calories = sa.Column(sa.String)
|
||||||
fatContent = sa.Column(sa.String)
|
fat_content = sa.Column(sa.String)
|
||||||
fiberContent = sa.Column(sa.String)
|
fiber_content = sa.Column(sa.String)
|
||||||
proteinContent = sa.Column(sa.String)
|
protein_content = sa.Column(sa.String)
|
||||||
sodiumContent = sa.Column(sa.String)
|
carbohydrate_content = sa.Column(sa.String)
|
||||||
sugarContent = sa.Column(sa.String)
|
sodium_content = sa.Column(sa.String)
|
||||||
|
sugar_content = sa.Column(sa.String)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
calories=None,
|
calories=None,
|
||||||
fatContent=None,
|
fat_content=None,
|
||||||
fiberContent=None,
|
fiber_content=None,
|
||||||
proteinContent=None,
|
protein_content=None,
|
||||||
sodiumContent=None,
|
sodium_content=None,
|
||||||
sugarContent=None,
|
sugar_content=None,
|
||||||
|
carbohydrate_content=None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.calories = calories
|
self.calories = calories
|
||||||
self.fatContent = fatContent
|
self.fat_content = fat_content
|
||||||
self.fiberContent = fiberContent
|
self.fiber_content = fiber_content
|
||||||
self.proteinContent = proteinContent
|
self.protein_content = protein_content
|
||||||
self.sodiumContent = sodiumContent
|
self.sodium_content = sodium_content
|
||||||
self.sugarContent = sugarContent
|
self.sugar_content = sugar_content
|
||||||
|
self.carbohydrate_content = carbohydrate_content
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
import datetime
|
import datetime
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from typing import List
|
|
||||||
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
import sqlalchemy.orm as orm
|
import sqlalchemy.orm as orm
|
||||||
from mealie.db.models.model_base import BaseMixins, SqlAlchemyBase
|
from mealie.db.models.model_base import BaseMixins, SqlAlchemyBase
|
||||||
from mealie.db.models.recipe.api_extras import ApiExtras
|
from mealie.db.models.recipe.api_extras import ApiExtras
|
||||||
|
from mealie.db.models.recipe.assets import RecipeAsset
|
||||||
from mealie.db.models.recipe.category import Category, recipes2categories
|
from mealie.db.models.recipe.category import Category, recipes2categories
|
||||||
from mealie.db.models.recipe.ingredient import RecipeIngredient
|
from mealie.db.models.recipe.ingredient import RecipeIngredient
|
||||||
from mealie.db.models.recipe.instruction import RecipeInstruction
|
from mealie.db.models.recipe.instruction import RecipeInstruction
|
||||||
from mealie.db.models.recipe.note import Note
|
from mealie.db.models.recipe.note import Note
|
||||||
from mealie.db.models.recipe.nutrition import Nutrition
|
from mealie.db.models.recipe.nutrition import Nutrition
|
||||||
|
from mealie.db.models.recipe.settings import RecipeSettings
|
||||||
from mealie.db.models.recipe.tag import Tag, recipes2tags
|
from mealie.db.models.recipe.tag import Tag, recipes2tags
|
||||||
from mealie.db.models.recipe.tool import Tool
|
from mealie.db.models.recipe.tool import Tool
|
||||||
from sqlalchemy.ext.orderinglist import ordering_list
|
from sqlalchemy.ext.orderinglist import ordering_list
|
||||||
|
@ -26,23 +27,24 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
|
||||||
name = sa.Column(sa.String, nullable=False)
|
name = sa.Column(sa.String, nullable=False)
|
||||||
description = sa.Column(sa.String)
|
description = sa.Column(sa.String)
|
||||||
image = sa.Column(sa.String)
|
image = sa.Column(sa.String)
|
||||||
totalTime = sa.Column(sa.String)
|
total_time = sa.Column(sa.String)
|
||||||
prepTime = sa.Column(sa.String)
|
prep_time = sa.Column(sa.String)
|
||||||
performTime = sa.Column(sa.String)
|
perform_time = sa.Column(sa.String)
|
||||||
cookTime = sa.Column(sa.String)
|
cookTime = sa.Column(sa.String)
|
||||||
recipeYield = sa.Column(sa.String)
|
recipe_yield = sa.Column(sa.String)
|
||||||
recipeCuisine = sa.Column(sa.String)
|
recipeCuisine = sa.Column(sa.String)
|
||||||
tools: List[Tool] = orm.relationship("Tool", cascade="all, delete-orphan")
|
tools: list[Tool] = orm.relationship("Tool", cascade="all, delete-orphan")
|
||||||
|
assets: list[RecipeAsset] = orm.relationship("RecipeAsset", cascade="all, delete-orphan")
|
||||||
nutrition: Nutrition = orm.relationship("Nutrition", uselist=False, cascade="all, delete-orphan")
|
nutrition: Nutrition = orm.relationship("Nutrition", uselist=False, cascade="all, delete-orphan")
|
||||||
recipeCategory: List = orm.relationship("Category", secondary=recipes2categories, back_populates="recipes")
|
recipe_category: list = orm.relationship("Category", secondary=recipes2categories, back_populates="recipes")
|
||||||
|
|
||||||
recipeIngredient: List[RecipeIngredient] = orm.relationship(
|
recipe_ingredient: list[RecipeIngredient] = orm.relationship(
|
||||||
"RecipeIngredient",
|
"RecipeIngredient",
|
||||||
cascade="all, delete-orphan",
|
cascade="all, delete-orphan",
|
||||||
order_by="RecipeIngredient.position",
|
order_by="RecipeIngredient.position",
|
||||||
collection_class=ordering_list("position"),
|
collection_class=ordering_list("position"),
|
||||||
)
|
)
|
||||||
recipeInstructions: List[RecipeInstruction] = orm.relationship(
|
recipe_instructions: list[RecipeInstruction] = orm.relationship(
|
||||||
"RecipeInstruction",
|
"RecipeInstruction",
|
||||||
cascade="all, delete-orphan",
|
cascade="all, delete-orphan",
|
||||||
order_by="RecipeInstruction.position",
|
order_by="RecipeInstruction.position",
|
||||||
|
@ -51,12 +53,13 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
|
||||||
|
|
||||||
# Mealie Specific
|
# Mealie Specific
|
||||||
slug = sa.Column(sa.String, index=True, unique=True)
|
slug = sa.Column(sa.String, index=True, unique=True)
|
||||||
tags: List[Tag] = orm.relationship("Tag", secondary=recipes2tags, back_populates="recipes")
|
settings = orm.relationship("RecipeSettings", uselist=False, cascade="all, delete-orphan")
|
||||||
dateAdded = sa.Column(sa.Date, default=date.today)
|
tags: list[Tag] = orm.relationship("Tag", secondary=recipes2tags, back_populates="recipes")
|
||||||
notes: List[Note] = orm.relationship("Note", cascade="all, delete-orphan")
|
date_added = sa.Column(sa.Date, default=date.today)
|
||||||
|
notes: list[Note] = orm.relationship("Note", cascade="all, delete-orphan")
|
||||||
rating = sa.Column(sa.Integer)
|
rating = sa.Column(sa.Integer)
|
||||||
orgURL = sa.Column(sa.String)
|
org_url = sa.Column(sa.String)
|
||||||
extras: List[ApiExtras] = orm.relationship("ApiExtras", cascade="all, delete-orphan")
|
extras: list[ApiExtras] = orm.relationship("ApiExtras", cascade="all, delete-orphan")
|
||||||
|
|
||||||
@validates("name")
|
@validates("name")
|
||||||
def validate_name(self, key, name):
|
def validate_name(self, key, name):
|
||||||
|
@ -69,23 +72,25 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
|
||||||
name: str = None,
|
name: str = None,
|
||||||
description: str = None,
|
description: str = None,
|
||||||
image: str = None,
|
image: str = None,
|
||||||
recipeYield: str = None,
|
recipe_yield: str = None,
|
||||||
recipeIngredient: List[str] = None,
|
recipe_ingredient: list[str] = None,
|
||||||
recipeInstructions: List[dict] = None,
|
recipe_instructions: list[dict] = None,
|
||||||
recipeCuisine: str = None,
|
recipeCuisine: str = None,
|
||||||
totalTime: str = None,
|
total_time: str = None,
|
||||||
prepTime: str = None,
|
prep_time: str = None,
|
||||||
nutrition: dict = None,
|
nutrition: dict = None,
|
||||||
tools: list[str] = [],
|
tools: list[str] = None,
|
||||||
performTime: str = None,
|
perform_time: str = None,
|
||||||
slug: str = None,
|
slug: str = None,
|
||||||
recipeCategory: List[str] = None,
|
recipe_category: list[str] = None,
|
||||||
tags: List[str] = None,
|
tags: list[str] = None,
|
||||||
dateAdded: datetime.date = None,
|
date_added: datetime.date = None,
|
||||||
notes: List[dict] = None,
|
notes: list[dict] = None,
|
||||||
rating: int = None,
|
rating: int = None,
|
||||||
orgURL: str = None,
|
org_url: str = None,
|
||||||
extras: dict = None,
|
extras: dict = None,
|
||||||
|
assets: list = None,
|
||||||
|
settings: dict = None,
|
||||||
*args,
|
*args,
|
||||||
**kwargs
|
**kwargs
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -95,77 +100,33 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
|
||||||
self.recipeCuisine = recipeCuisine
|
self.recipeCuisine = recipeCuisine
|
||||||
|
|
||||||
self.nutrition = Nutrition(**nutrition) if self.nutrition else Nutrition()
|
self.nutrition = Nutrition(**nutrition) if self.nutrition else Nutrition()
|
||||||
|
|
||||||
self.tools = [Tool(tool=x) for x in tools] if tools else []
|
self.tools = [Tool(tool=x) for x in tools] if tools else []
|
||||||
|
|
||||||
self.recipeYield = recipeYield
|
self.recipe_yield = recipe_yield
|
||||||
self.recipeIngredient = [RecipeIngredient(ingredient=ingr) for ingr in recipeIngredient]
|
self.recipe_ingredient = [RecipeIngredient(ingredient=ingr) for ingr in recipe_ingredient]
|
||||||
self.recipeInstructions = [
|
self.assets = [RecipeAsset(**a) for a in assets]
|
||||||
RecipeInstruction(text=instruc.get("text"), type=instruc.get("@type", None))
|
self.recipe_instructions = [
|
||||||
for instruc in recipeInstructions
|
RecipeInstruction(text=instruc.get("text"), title=instruc.get("title"), type=instruc.get("@type", None))
|
||||||
|
for instruc in recipe_instructions
|
||||||
]
|
]
|
||||||
self.totalTime = totalTime
|
self.total_time = total_time
|
||||||
self.prepTime = prepTime
|
self.prep_time = prep_time
|
||||||
self.performTime = performTime
|
self.perform_time = perform_time
|
||||||
|
|
||||||
self.recipeCategory = [Category.create_if_not_exist(session=session, name=cat) for cat in recipeCategory]
|
self.recipe_category = [Category.create_if_not_exist(session=session, name=cat) for cat in recipe_category]
|
||||||
|
|
||||||
# Mealie Specific
|
# Mealie Specific
|
||||||
|
self.settings = RecipeSettings(**settings) if settings else RecipeSettings()
|
||||||
|
print(self.settings)
|
||||||
self.tags = [Tag.create_if_not_exist(session=session, name=tag) for tag in tags]
|
self.tags = [Tag.create_if_not_exist(session=session, name=tag) for tag in tags]
|
||||||
self.slug = slug
|
self.slug = slug
|
||||||
self.dateAdded = dateAdded
|
self.date_added = date_added
|
||||||
self.notes = [Note(**note) for note in notes]
|
self.notes = [Note(**note) for note in notes]
|
||||||
self.rating = rating
|
self.rating = rating
|
||||||
self.orgURL = orgURL
|
self.org_url = org_url
|
||||||
self.extras = [ApiExtras(key=key, value=value) for key, value in extras.items()]
|
self.extras = [ApiExtras(key=key, value=value) for key, value in extras.items()]
|
||||||
|
|
||||||
def update(
|
def update(self, *args, **kwargs):
|
||||||
self,
|
|
||||||
session,
|
|
||||||
name: str = None,
|
|
||||||
description: str = None,
|
|
||||||
image: str = None,
|
|
||||||
recipeYield: str = None,
|
|
||||||
recipeIngredient: List[str] = None,
|
|
||||||
recipeInstructions: List[dict] = None,
|
|
||||||
recipeCuisine: str = None,
|
|
||||||
totalTime: str = None,
|
|
||||||
tools: list[str] = [],
|
|
||||||
prepTime: str = None,
|
|
||||||
performTime: str = None,
|
|
||||||
nutrition: dict = None,
|
|
||||||
slug: str = None,
|
|
||||||
recipeCategory: List[str] = None,
|
|
||||||
tags: List[str] = None,
|
|
||||||
dateAdded: datetime.date = None,
|
|
||||||
notes: List[dict] = None,
|
|
||||||
rating: int = None,
|
|
||||||
orgURL: str = None,
|
|
||||||
extras: dict = None,
|
|
||||||
*args,
|
|
||||||
**kwargs
|
|
||||||
):
|
|
||||||
"""Updated a database entry by removing nested rows and rebuilds the row through the __init__ functions"""
|
"""Updated a database entry by removing nested rows and rebuilds the row through the __init__ functions"""
|
||||||
|
self.__init__(*args, **kwargs)
|
||||||
self.__init__(
|
|
||||||
session=session,
|
|
||||||
name=name,
|
|
||||||
description=description,
|
|
||||||
image=image,
|
|
||||||
recipeYield=recipeYield,
|
|
||||||
recipeIngredient=recipeIngredient,
|
|
||||||
recipeInstructions=recipeInstructions,
|
|
||||||
totalTime=totalTime,
|
|
||||||
recipeCuisine=recipeCuisine,
|
|
||||||
prepTime=prepTime,
|
|
||||||
performTime=performTime,
|
|
||||||
nutrition=nutrition,
|
|
||||||
tools=tools,
|
|
||||||
slug=slug,
|
|
||||||
recipeCategory=recipeCategory,
|
|
||||||
tags=tags,
|
|
||||||
dateAdded=dateAdded,
|
|
||||||
notes=notes,
|
|
||||||
rating=rating,
|
|
||||||
orgURL=orgURL,
|
|
||||||
extras=extras,
|
|
||||||
)
|
|
||||||
|
|
18
mealie/db/models/recipe/settings.py
Normal file
18
mealie/db/models/recipe/settings.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from mealie.db.models.model_base import SqlAlchemyBase
|
||||||
|
|
||||||
|
|
||||||
|
class RecipeSettings(SqlAlchemyBase):
|
||||||
|
__tablename__ = "recipe_settings"
|
||||||
|
id = sa.Column(sa.Integer, primary_key=True)
|
||||||
|
parent_id = sa.Column(sa.Integer, sa.ForeignKey("recipes.id"))
|
||||||
|
public = sa.Column(sa.Boolean)
|
||||||
|
show_nutrition = sa.Column(sa.Boolean)
|
||||||
|
show_assets = sa.Column(sa.Boolean)
|
||||||
|
landscape_view = sa.Column(sa.Boolean)
|
||||||
|
|
||||||
|
def __init__(self, public=True, show_nutrition=True, show_assets=True, landscape_view=True) -> None:
|
||||||
|
self.public = public
|
||||||
|
self.show_nutrition = show_nutrition
|
||||||
|
self.show_assets = show_assets
|
||||||
|
self.landscape_view = landscape_view
|
|
@ -5,7 +5,7 @@ from mealie.db.models.model_base import SqlAlchemyBase
|
||||||
class Tool(SqlAlchemyBase):
|
class Tool(SqlAlchemyBase):
|
||||||
__tablename__ = "tools"
|
__tablename__ = "tools"
|
||||||
id = sa.Column(sa.Integer, primary_key=True)
|
id = sa.Column(sa.Integer, primary_key=True)
|
||||||
parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id"))
|
parent_id = sa.Column(sa.Integer, sa.ForeignKey("recipes.id"))
|
||||||
tool = sa.Column(sa.String)
|
tool = sa.Column(sa.String)
|
||||||
|
|
||||||
def __init__(self, tool) -> None:
|
def __init__(self, tool) -> None:
|
||||||
|
|
|
@ -21,4 +21,4 @@ def get_shopping_list(
|
||||||
mealplan: MealPlanInDB
|
mealplan: MealPlanInDB
|
||||||
slugs = [x.slug for x in mealplan.meals]
|
slugs = [x.slug for x in mealplan.meals]
|
||||||
recipes: list[Recipe] = [db.recipes.get(session, x) for x in slugs]
|
recipes: list[Recipe] = [db.recipes.get(session, x) for x in slugs]
|
||||||
return [{"name": x.name, "recipeIngredient": x.recipeIngredient} for x in recipes if x]
|
return [{"name": x.name, "recipe_ingredient": x.recipe_ingredient} for x in recipes if x]
|
||||||
|
|
|
@ -50,11 +50,11 @@ def get_all_recipes(
|
||||||
- description
|
- description
|
||||||
- image
|
- image
|
||||||
- recipeYield
|
- recipeYield
|
||||||
- totalTime
|
- total_time
|
||||||
- prepTime
|
- prep_time
|
||||||
- performTime
|
- perform_time
|
||||||
- rating
|
- rating
|
||||||
- orgURL
|
- org_url
|
||||||
|
|
||||||
**Note:** You may experience problems with with query parameters. As an alternative
|
**Note:** You may experience problems with with query parameters. As an alternative
|
||||||
you may also use the post method and provide a body.
|
you may also use the post method and provide a body.
|
||||||
|
@ -78,11 +78,11 @@ def get_all_recipes_post(body: AllRecipeRequest, session: Session = Depends(gene
|
||||||
- description
|
- description
|
||||||
- image
|
- image
|
||||||
- recipeYield
|
- recipeYield
|
||||||
- totalTime
|
- total_time
|
||||||
- prepTime
|
- prep_time
|
||||||
- performTime
|
- perform_time
|
||||||
- rating
|
- rating
|
||||||
- orgURL
|
- org_url
|
||||||
|
|
||||||
Refer to the body example for data formats.
|
Refer to the body example for data formats.
|
||||||
|
|
||||||
|
|
50
mealie/routes/recipe/recipe_assets.py
Normal file
50
mealie/routes/recipe/recipe_assets.py
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Depends, File, Form
|
||||||
|
from fastapi.datastructures import UploadFile
|
||||||
|
from mealie.core.config import app_dirs
|
||||||
|
from mealie.db.database import db
|
||||||
|
from mealie.db.db_setup import generate_session
|
||||||
|
from mealie.routes.deps import get_current_user
|
||||||
|
from mealie.schema.recipe import Recipe, RecipeAsset
|
||||||
|
from mealie.schema.snackbar import SnackResponse
|
||||||
|
from slugify import slugify
|
||||||
|
from sqlalchemy.orm.session import Session
|
||||||
|
from starlette.responses import FileResponse
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/api/recipes", tags=["Recipe Assets"])
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/{recipe_slug}/asset")
|
||||||
|
async def get_recipe_asset(recipe_slug, file_name: str):
|
||||||
|
""" Returns a recipe asset """
|
||||||
|
file = app_dirs.RECIPE_DATA_DIR.joinpath(recipe_slug, file_name)
|
||||||
|
return FileResponse(file)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{recipe_slug}/asset", response_model=RecipeAsset)
|
||||||
|
def upload_recipe_asset(
|
||||||
|
recipe_slug: str,
|
||||||
|
name: str = Form(...),
|
||||||
|
icon: str = Form(...),
|
||||||
|
extension: str = Form(...),
|
||||||
|
file: UploadFile = File(...),
|
||||||
|
session: Session = Depends(generate_session),
|
||||||
|
current_user=Depends(get_current_user),
|
||||||
|
):
|
||||||
|
""" Upload a file to store as a recipe asset """
|
||||||
|
file_name = slugify(name) + "." + extension
|
||||||
|
asset_in = RecipeAsset(name=name, icon=icon, file_name=file_name)
|
||||||
|
dest = app_dirs.RECIPE_DATA_DIR.joinpath(recipe_slug, file_name)
|
||||||
|
dest.parent.mkdir(exist_ok=True, parents=True)
|
||||||
|
|
||||||
|
with dest.open("wb") as buffer:
|
||||||
|
shutil.copyfileobj(file.file, buffer)
|
||||||
|
|
||||||
|
if dest.is_file():
|
||||||
|
recipe: Recipe = db.recipes.get(session, recipe_slug)
|
||||||
|
recipe.assets.append(asset_in)
|
||||||
|
db.recipes.update(session, recipe_slug, recipe.dict())
|
||||||
|
return asset_in
|
||||||
|
else:
|
||||||
|
return SnackResponse.error("Failure uploading file")
|
|
@ -56,6 +56,7 @@ def update_recipe(
|
||||||
""" Updates a recipe by existing slug and data. """
|
""" Updates a recipe by existing slug and data. """
|
||||||
|
|
||||||
recipe: Recipe = db.recipes.update(session, recipe_slug, data.dict())
|
recipe: Recipe = db.recipes.update(session, recipe_slug, data.dict())
|
||||||
|
print(recipe.assets)
|
||||||
|
|
||||||
if recipe_slug != recipe.slug:
|
if recipe_slug != recipe.slug:
|
||||||
rename_image(original_slug=recipe_slug, new_slug=recipe.slug)
|
rename_image(original_slug=recipe_slug, new_slug=recipe.slug)
|
||||||
|
@ -64,7 +65,7 @@ def update_recipe(
|
||||||
|
|
||||||
|
|
||||||
@router.patch("/{recipe_slug}")
|
@router.patch("/{recipe_slug}")
|
||||||
def update_recipe(
|
def patch_recipe(
|
||||||
recipe_slug: str,
|
recipe_slug: str,
|
||||||
data: dict,
|
data: dict,
|
||||||
session: Session = Depends(generate_session),
|
session: Session = Depends(generate_session),
|
||||||
|
|
|
@ -1,12 +1,23 @@
|
||||||
import datetime
|
import datetime
|
||||||
from typing import Any, List, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
from fastapi_camelcase import CamelModel
|
||||||
from mealie.db.models.recipe.recipe import RecipeModel
|
from mealie.db.models.recipe.recipe import RecipeModel
|
||||||
from pydantic import BaseModel, validator
|
from pydantic import BaseModel, Field, validator
|
||||||
from pydantic.utils import GetterDict
|
from pydantic.utils import GetterDict
|
||||||
from slugify import slugify
|
from slugify import slugify
|
||||||
|
|
||||||
|
|
||||||
|
class RecipeSettings(CamelModel):
|
||||||
|
public: bool = True
|
||||||
|
show_nutrition: bool = True
|
||||||
|
show_assets: bool = True
|
||||||
|
landscape_view: bool = True
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
class RecipeNote(BaseModel):
|
class RecipeNote(BaseModel):
|
||||||
title: str
|
title: str
|
||||||
text: str
|
text: str
|
||||||
|
@ -15,34 +26,45 @@ class RecipeNote(BaseModel):
|
||||||
orm_mode = True
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
class RecipeStep(BaseModel):
|
class RecipeStep(CamelModel):
|
||||||
|
title: Optional[str] = ""
|
||||||
text: str
|
text: str
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
orm_mode = True
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
class Nutrition(BaseModel):
|
class RecipeAsset(CamelModel):
|
||||||
calories: Optional[str]
|
name: str
|
||||||
fatContent: Optional[str]
|
icon: str
|
||||||
fiberContent: Optional[str]
|
file_name: Optional[str]
|
||||||
proteinContent: Optional[str]
|
|
||||||
sodiumContent: Optional[str]
|
|
||||||
sugarContent: Optional[str]
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
orm_mode = True
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
class RecipeSummary(BaseModel):
|
class Nutrition(CamelModel):
|
||||||
|
calories: Optional[str]
|
||||||
|
fat_content: Optional[str]
|
||||||
|
protein_content: Optional[str]
|
||||||
|
carbohydrate_content: Optional[str]
|
||||||
|
fiber_content: Optional[str]
|
||||||
|
sodium_content: Optional[str]
|
||||||
|
sugar_content: Optional[str]
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
class RecipeSummary(CamelModel):
|
||||||
id: Optional[int]
|
id: Optional[int]
|
||||||
name: str
|
name: str
|
||||||
slug: Optional[str] = ""
|
slug: Optional[str] = ""
|
||||||
image: Optional[Any]
|
image: Optional[Any]
|
||||||
|
|
||||||
description: Optional[str]
|
description: Optional[str]
|
||||||
recipeCategory: Optional[List[str]] = []
|
recipe_category: Optional[list[str]] = []
|
||||||
tags: Optional[List[str]] = []
|
tags: Optional[list[str]] = []
|
||||||
rating: Optional[int]
|
rating: Optional[int]
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
|
@ -52,26 +74,28 @@ class RecipeSummary(BaseModel):
|
||||||
def getter_dict(_cls, name_orm: RecipeModel):
|
def getter_dict(_cls, name_orm: RecipeModel):
|
||||||
return {
|
return {
|
||||||
**GetterDict(name_orm),
|
**GetterDict(name_orm),
|
||||||
"recipeCategory": [x.name for x in name_orm.recipeCategory],
|
"recipe_category": [x.name for x in name_orm.recipe_category],
|
||||||
"tags": [x.name for x in name_orm.tags],
|
"tags": [x.name for x in name_orm.tags],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Recipe(RecipeSummary):
|
class Recipe(RecipeSummary):
|
||||||
recipeYield: Optional[str]
|
recipe_yield: Optional[str]
|
||||||
recipeIngredient: Optional[list[str]]
|
recipe_ingredient: Optional[list[str]]
|
||||||
recipeInstructions: Optional[list[RecipeStep]]
|
recipe_instructions: Optional[list[RecipeStep]]
|
||||||
nutrition: Optional[Nutrition]
|
nutrition: Optional[Nutrition]
|
||||||
tools: Optional[list[str]] = []
|
tools: Optional[list[str]] = []
|
||||||
|
|
||||||
totalTime: Optional[str] = None
|
total_time: Optional[str] = None
|
||||||
prepTime: Optional[str] = None
|
prep_time: Optional[str] = None
|
||||||
performTime: Optional[str] = None
|
perform_time: Optional[str] = None
|
||||||
|
|
||||||
# Mealie Specific
|
# Mealie Specific
|
||||||
dateAdded: Optional[datetime.date]
|
settings: Optional[RecipeSettings]
|
||||||
notes: Optional[List[RecipeNote]] = []
|
assets: Optional[list[RecipeAsset]] = []
|
||||||
orgURL: Optional[str]
|
date_added: Optional[datetime.date]
|
||||||
|
notes: Optional[list[RecipeNote]] = []
|
||||||
|
org_url: Optional[str] = Field(None, alias="orgURL")
|
||||||
extras: Optional[dict] = {}
|
extras: Optional[dict] = {}
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
|
@ -81,8 +105,8 @@ class Recipe(RecipeSummary):
|
||||||
def getter_dict(_cls, name_orm: RecipeModel):
|
def getter_dict(_cls, name_orm: RecipeModel):
|
||||||
return {
|
return {
|
||||||
**GetterDict(name_orm),
|
**GetterDict(name_orm),
|
||||||
"recipeIngredient": [x.ingredient for x in name_orm.recipeIngredient],
|
"recipe_ingredient": [x.ingredient for x in name_orm.recipe_ingredient],
|
||||||
"recipeCategory": [x.name for x in name_orm.recipeCategory],
|
"recipe_category": [x.name for x in name_orm.recipe_category],
|
||||||
"tags": [x.name for x in name_orm.tags],
|
"tags": [x.name for x in name_orm.tags],
|
||||||
"tools": [x.tool for x in name_orm.tools],
|
"tools": [x.tool for x in name_orm.tools],
|
||||||
"extras": {x.key_name: x.value for x in name_orm.extras},
|
"extras": {x.key_name: x.value for x in name_orm.extras},
|
||||||
|
@ -93,22 +117,22 @@ class Recipe(RecipeSummary):
|
||||||
"name": "Chicken and Rice With Leeks and Salsa Verde",
|
"name": "Chicken and Rice With Leeks and Salsa Verde",
|
||||||
"description": "This one-skillet dinner gets deep oniony flavor from lots of leeks cooked down to jammy tenderness.",
|
"description": "This one-skillet dinner gets deep oniony flavor from lots of leeks cooked down to jammy tenderness.",
|
||||||
"image": "chicken-and-rice-with-leeks-and-salsa-verde.jpg",
|
"image": "chicken-and-rice-with-leeks-and-salsa-verde.jpg",
|
||||||
"recipeYield": "4 Servings",
|
"recipe_yield": "4 Servings",
|
||||||
"recipeIngredient": [
|
"recipe_ingredient": [
|
||||||
"1 1/2 lb. skinless, boneless chicken thighs (4-8 depending on size)",
|
"1 1/2 lb. skinless, boneless chicken thighs (4-8 depending on size)",
|
||||||
"Kosher salt, freshly ground pepper",
|
"Kosher salt, freshly ground pepper",
|
||||||
"3 Tbsp. unsalted butter, divided",
|
"3 Tbsp. unsalted butter, divided",
|
||||||
],
|
],
|
||||||
"recipeInstructions": [
|
"recipe_instructions": [
|
||||||
{
|
{
|
||||||
"text": "Season chicken with salt and pepper.",
|
"text": "Season chicken with salt and pepper.",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"slug": "chicken-and-rice-with-leeks-and-salsa-verde",
|
"slug": "chicken-and-rice-with-leeks-and-salsa-verde",
|
||||||
"tags": ["favorite", "yummy!"],
|
"tags": ["favorite", "yummy!"],
|
||||||
"recipeCategory": ["Dinner", "Pasta"],
|
"recipe_category": ["Dinner", "Pasta"],
|
||||||
"notes": [{"title": "Watch Out!", "text": "Prep the day before!"}],
|
"notes": [{"title": "Watch Out!", "text": "Prep the day before!"}],
|
||||||
"orgURL": "https://www.bonappetit.com/recipe/chicken-and-rice-with-leeks-and-salsa-verde",
|
"org_url": "https://www.bonappetit.com/recipe/chicken-and-rice-with-leeks-and-salsa-verde",
|
||||||
"rating": 3,
|
"rating": 3,
|
||||||
"extras": {"message": "Don't forget to defrost the chicken!"},
|
"extras": {"message": "Don't forget to defrost the chicken!"},
|
||||||
}
|
}
|
||||||
|
@ -126,7 +150,7 @@ class Recipe(RecipeSummary):
|
||||||
|
|
||||||
|
|
||||||
class AllRecipeRequest(BaseModel):
|
class AllRecipeRequest(BaseModel):
|
||||||
properties: List[str]
|
properties: list[str]
|
||||||
limit: Optional[int]
|
limit: Optional[int]
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
|
|
|
@ -83,7 +83,7 @@ class ImportDatabase:
|
||||||
del recipe_dict["categories"]
|
del recipe_dict["categories"]
|
||||||
try:
|
try:
|
||||||
del recipe_dict["_id"]
|
del recipe_dict["_id"]
|
||||||
del recipe_dict["dateAdded"]
|
del recipe_dict["date_added"]
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
# Migration from list to Object Type Data
|
# Migration from list to Object Type Data
|
||||||
|
|
|
@ -144,7 +144,7 @@ class MigrationBase(BaseModel):
|
||||||
"""Calls the rewrite_alias function and the Cleaner.clean function on a
|
"""Calls the rewrite_alias function and the Cleaner.clean function on a
|
||||||
dictionary and returns the result unpacked into a Recipe object"""
|
dictionary and returns the result unpacked into a Recipe object"""
|
||||||
recipe_dict = self.rewrite_alias(recipe_dict)
|
recipe_dict = self.rewrite_alias(recipe_dict)
|
||||||
recipe_dict = Cleaner.clean(recipe_dict, url=recipe_dict.get("orgURL", None))
|
recipe_dict = Cleaner.clean(recipe_dict, url=recipe_dict.get("org_url", None))
|
||||||
|
|
||||||
return Recipe(**recipe_dict)
|
return Recipe(**recipe_dict)
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ class NextcloudDir:
|
||||||
class NextcloudMigration(MigrationBase):
|
class NextcloudMigration(MigrationBase):
|
||||||
key_aliases: Optional[list[MigrationAlias]] = [
|
key_aliases: Optional[list[MigrationAlias]] = [
|
||||||
MigrationAlias(key="tags", alias="keywords", func=helpers.split_by_comma),
|
MigrationAlias(key="tags", alias="keywords", func=helpers.split_by_comma),
|
||||||
MigrationAlias(key="orgURL", alias="url", func=None),
|
MigrationAlias(key="org_url", alias="url", func=None),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,16 @@
|
||||||
|
from mealie.core.config import app_dirs, settings
|
||||||
|
|
||||||
|
#! I don't like it either!
|
||||||
|
SQLITE_FILE = app_dirs.SQLITE_DIR.joinpath("test.db")
|
||||||
|
SQLITE_FILE.unlink(missing_ok=True)
|
||||||
|
|
||||||
|
settings.SQLITE_FILE = SQLITE_FILE
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from mealie.app import app
|
from mealie.app import app
|
||||||
from mealie.core.config import app_dirs, settings
|
|
||||||
from mealie.db.db_setup import generate_session, sql_global_init
|
from mealie.db.db_setup import generate_session, sql_global_init
|
||||||
from mealie.db.init_db import init_db
|
from mealie.db.init_db import init_db
|
||||||
from pytest import fixture
|
from pytest import fixture
|
||||||
|
@ -12,10 +19,6 @@ from tests.app_routes import AppRoutes
|
||||||
from tests.test_config import TEST_DATA
|
from tests.test_config import TEST_DATA
|
||||||
from tests.utils.recipe_data import build_recipe_store, get_raw_no_image, get_raw_recipe
|
from tests.utils.recipe_data import build_recipe_store, get_raw_no_image, get_raw_recipe
|
||||||
|
|
||||||
SQLITE_FILE = app_dirs.SQLITE_DIR.joinpath("test.db")
|
|
||||||
SQLITE_FILE.unlink(missing_ok=True)
|
|
||||||
|
|
||||||
|
|
||||||
TestSessionLocal = sql_global_init(SQLITE_FILE, check_thread=False)
|
TestSessionLocal = sql_global_init(SQLITE_FILE, check_thread=False)
|
||||||
init_db(TestSessionLocal())
|
init_db(TestSessionLocal())
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue