diff --git a/boot.sh b/boot.sh index 1a6cdb521..313fbd42d 100644 --- a/boot.sh +++ b/boot.sh @@ -1,8 +1,30 @@ #!/bin/sh source venv/bin/activate - TANDOOR_PORT="${TANDOOR_PORT:-8080}" +NGINX_CONF_FILE=/opt/recipes/nginx/conf.d/Recipes.conf + +display_warning() { + echo "[WARNING]" + echo -e "$1" +} + +echo "Checking configuration..." + +# Nginx config file must exist if gunicorn is not active +if [ ! -f "$NGINX_CONF_FILE" ] && [ $GUNICORN_MEDIA -eq 0 ]; then + display_warning "Nginx configuration file could not be found at the default location!\nPath: ${NGINX_CONF_FILE}" +fi + +# SECRET_KEY must be set in .env file +if [ -z "${SECRET_KEY}" ]; then + display_warning "The environment variable 'SECRET_KEY' is not set but REQUIRED for running Tandoor!" +fi + +# POSTGRES_PASSWORD must be set in .env file +if [ -z "${POSTGRES_PASSWORD}" ]; then + display_warning "The environment variable 'POSTGRES_PASSWORD' is not set but REQUIRED for running Tandoor!" +fi echo "Waiting for database to be ready..." @@ -36,4 +58,4 @@ echo "Done" chmod -R 755 /opt/recipes/mediafiles -exec gunicorn -b :$TANDOOR_PORT --access-logfile - --error-logfile - --log-level INFO recipes.wsgi +exec gunicorn -b :$TANDOOR_PORT --access-logfile - --error-logfile - --log-level INFO recipes.wsgi \ No newline at end of file diff --git a/docs/install/docker.md b/docs/install/docker.md index 233e05a63..b8ed504eb 100644 --- a/docs/install/docker.md +++ b/docs/install/docker.md @@ -347,4 +347,35 @@ follow these instructions: - Delete local database folder (usually 'postgresql' in the same folder as your 'docker-compose.yml' file) - Start Tandoor containers again (`docker-compose up -d`) - Wait for at least 2-3 minutes and then check if everything is working now (migrations can take quite some time!) -- If not, check logs of the web_recipes container with `docker logs ` and make sure that all migrations are indeed already done \ No newline at end of file +- If not, check logs of the web_recipes container with `docker logs ` and make sure that all migrations are indeed already done + +### Sub Path nginx config + +If hosting under a sub-path you might want to change the default nginx config (which gets mounted through the named volume from the application container into the nginx container) +with the following config. + +``` +location /my_app { # change to subfolder name + include /config/nginx/proxy.conf; + proxy_pass https://mywebapp.com/; # change to your host name:port + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Script-Name /my_app; # change to subfolder name + proxy_cookie_path / /my_app; # change to subfolder name +} + +location /media/ { + include /config/nginx/proxy.conf; + alias /mediafiles/; + client_max_body_size 16M; + +} + + +location /static/ { + include /config/nginx/proxy.conf; + alias /staticfiles/; + client_max_body_size 16M; + +} +``` \ No newline at end of file diff --git a/vue/src/apps/RecipeEditView/RecipeEditView.vue b/vue/src/apps/RecipeEditView/RecipeEditView.vue index 0bd118fa6..14ccd0c3f 100644 --- a/vue/src/apps/RecipeEditView/RecipeEditView.vue +++ b/vue/src/apps/RecipeEditView/RecipeEditView.vue @@ -210,6 +210,18 @@ {{ $t("File") }} + + {{ $t("paste_ingredients") }} + @@ -516,6 +528,17 @@ + + + + + @@ -574,7 +597,8 @@ export default { recipes_loading: false, message: "", options_limit: 25, - + paste_ingredients: undefined, + paste_step: undefined, show_file_create: false, step_for_file_create: undefined, } @@ -942,6 +966,29 @@ export default { energy: function () { return energyHeading() }, + appendIngredients: function () { + let ing_list = this.paste_ingredients.split(/\r?\n/) + let step = this.recipe.steps.findIndex((x) => x.id == this.paste_step) + let order = Math.max(...this.recipe.steps[step].ingredients.map((x) => x.order), -1) + 1 + this.recipe.steps[step].ingredients_visible = true + ing_list.forEach((ing) => { + if (ing.trim() !== "") { + this.genericPostAPI("api_ingredient_from_string", { text: ing }).then((result) => { + let unit = null + if (result.data.unit !== "") { + unit = { name: result.data.unit } + } + this.recipe.steps[step].ingredients.splice(order, 0, { + amount: result.data.amount, + unit: unit, + food: { name: result.data.food }, + note: result.data.note, + }) + }) + order++ + } + }) + }, }, } diff --git a/vue/src/components/MealPlanEditModal.vue b/vue/src/components/MealPlanEditModal.vue index e7c62841d..18f35cc5c 100644 --- a/vue/src/components/MealPlanEditModal.vue +++ b/vue/src/components/MealPlanEditModal.vue @@ -206,7 +206,7 @@ export default { } if (!cancel) { this.$bvModal.hide(`edit-modal`) - this.$emit("save-entry", { ...this.mealplan_settings, ...this.entryEditing }) + this.$emit("save-entry", { ...this.mealplan_settings, ...this.entryEditing, ...{ addshopping: this.entryEditing.addshopping && !this.autoMealPlan } }) } }, deleteEntry() { diff --git a/vue/src/components/RecipeContextMenu.vue b/vue/src/components/RecipeContextMenu.vue index c7abee90a..a1c3d3640 100644 --- a/vue/src/components/RecipeContextMenu.vue +++ b/vue/src/components/RecipeContextMenu.vue @@ -31,6 +31,9 @@ {{ $t("Print") }} + + + {{ $t("Export") }} @@ -202,6 +205,21 @@ export default { addToShopping() { this.$bvModal.show(`shopping_${this.modal_id}`) }, + copyToNew: function () { + let recipename = window.prompt(this.$t("copy_to_new"), this.$t("recipe_name")) + let apiClient = new ApiApiFactory() + apiClient.retrieveRecipe(this.recipe.id).then((results) => { + apiClient + .createRecipe({ ...results.data, ...{ id: undefined, name: recipename } }) + .then((newrecipe) => { + StandardToasts.makeStandardToast(StandardToasts.SUCCESS_CREATE) + window.open(this.resolveDjangoUrl("view_recipe", newrecipe.data.id)) + }) + .catch((error) => { + StandardToasts.makeStandardToast(StandardToasts.FAIL_CREATE) + }) + }) + }, }, } diff --git a/vue/src/locales/en.json b/vue/src/locales/en.json index 4895cd878..2ce13465e 100644 --- a/vue/src/locales/en.json +++ b/vue/src/locales/en.json @@ -326,6 +326,11 @@ "book_filter_help": "Include recipes from recipe filter in addition to manually assigned ones.", "review_shopping": "Review shopping entries before saving", "view_recipe": "View Recipe", + "copy_to_new": "Copy To New Recipe", + "recipe_name": "Recipe Name", + "paste_ingredients_placeholder": "Paste ingredient list here...", + "paste_ingredients": "Paste Ingredients", + "ingredient_list": "Ingredient List", "explain": "Explain", "filter": "Filter", "reset_children": "Reset Child Inheritance", diff --git a/vue/yarn.lock b/vue/yarn.lock index a3ed32e1f..f34632674 100644 --- a/vue/yarn.lock +++ b/vue/yarn.lock @@ -5369,9 +5369,9 @@ flush-write-stream@^1.0.0: readable-stream "^2.3.6" follow-redirects@^1.0.0, follow-redirects@^1.14.4: - version "1.14.7" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685" - integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ== + version "1.14.8" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc" + integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA== for-in@^1.0.2: version "1.0.2"