diff --git a/boot.sh b/boot.sh index 97a94f477..ae3dbb51d 100644 --- a/boot.sh +++ b/boot.sh @@ -76,4 +76,11 @@ echo "Done" chmod -R 755 /opt/recipes/mediafiles -exec gunicorn -b "[::]:$TANDOOR_PORT" --workers $GUNICORN_WORKERS --threads $GUNICORN_THREADS --access-logfile - --error-logfile - --log-level $GUNICORN_LOG_LEVEL recipes.wsgi +ipv6_disable=$(cat /sys/module/ipv6/parameters/disable) + +# Check if IPv6 is enabled, only then run gunicorn with ipv6 support +if [ "$ipv6_disable" -eq 0 ]; then + exec gunicorn -b "[::]:$TANDOOR_PORT" --workers $GUNICORN_WORKERS --threads $GUNICORN_THREADS --access-logfile - --error-logfile - --log-level $GUNICORN_LOG_LEVEL recipes.wsgi +else + exec gunicorn -b ":$TANDOOR_PORT" --workers $GUNICORN_WORKERS --threads $GUNICORN_THREADS --access-logfile - --error-logfile - --log-level $GUNICORN_LOG_LEVEL recipes.wsgi +fi \ No newline at end of file diff --git a/cookbook/helper/open_data_importer.py b/cookbook/helper/open_data_importer.py index a6fad9764..28f1e22d2 100644 --- a/cookbook/helper/open_data_importer.py +++ b/cookbook/helper/open_data_importer.py @@ -6,6 +6,8 @@ from cookbook.models import (Food, FoodProperty, Property, PropertyType, Superma SupermarketCategory, SupermarketCategoryRelation, Unit, UnitConversion) import re +from recipes.settings import DEBUG + class OpenDataImportResponse: total_created = 0 @@ -367,12 +369,28 @@ class OpenDataImporter: create_list.append({'data': obj_dict}) if self.update_existing and len(update_list) > 0: - model_type.objects.bulk_update(update_list, field_list) - od_response.total_updated += len(update_list) + try: + model_type.objects.bulk_update(update_list, field_list) + od_response.total_updated += len(update_list) + except Exception: + if DEBUG: + print('========= LOAD FOOD FAILED ============') + print(update_list) + print(existing_data_names) + print(existing_data_slugs) + traceback.print_exc() if len(create_list) > 0: - Food.load_bulk(create_list, None) - od_response.total_created += len(create_list) + try: + Food.load_bulk(create_list, None) + od_response.total_created += len(create_list) + except Exception: + if DEBUG: + print('========= LOAD FOOD FAILED ============') + print(create_list) + print(existing_data_names) + print(existing_data_slugs) + traceback.print_exc() # --------------- PROPERTY STUFF ----------------------- model_type = Property diff --git a/cookbook/locale/ca/LC_MESSAGES/django.po b/cookbook/locale/ca/LC_MESSAGES/django.po index a3ba5fc87..4a37f25e4 100644 --- a/cookbook/locale/ca/LC_MESSAGES/django.po +++ b/cookbook/locale/ca/LC_MESSAGES/django.po @@ -13,8 +13,8 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-05-18 14:28+0200\n" -"PO-Revision-Date: 2023-07-06 21:19+0000\n" -"Last-Translator: Rubens \n" +"PO-Revision-Date: 2024-03-08 23:19+0000\n" +"Last-Translator: Enric Bergadà \n" "Language-Team: Catalan \n" "Language: ca\n" @@ -567,11 +567,11 @@ msgstr "No s'ha pogut analitzar el codi de la plantilla." #: .\cookbook\integration\copymethat.py:44 #: .\cookbook\integration\melarecipes.py:37 msgid "Favorite" -msgstr "" +msgstr "Preferit" #: .\cookbook\integration\copymethat.py:50 msgid "I made this" -msgstr "" +msgstr "Ho he fet jo" #: .\cookbook\integration\integration.py:218 msgid "" diff --git a/cookbook/locale/fr/LC_MESSAGES/django.po b/cookbook/locale/fr/LC_MESSAGES/django.po index 91539a593..055875973 100644 --- a/cookbook/locale/fr/LC_MESSAGES/django.po +++ b/cookbook/locale/fr/LC_MESSAGES/django.po @@ -14,7 +14,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-05-18 14:28+0200\n" -"PO-Revision-Date: 2024-03-03 23:19+0000\n" +"PO-Revision-Date: 2024-03-05 22:19+0000\n" "Last-Translator: Jocelin Lebreton \n" "Language-Team: French \n" @@ -2128,7 +2128,7 @@ msgstr "Se connecter via %(provider)s" #, python-format msgid "You are about to sign in using a third party account from %(provider)s." msgstr "" -"ous êtes sur le point de vous connecter en utilisant un compte tiers depuis " +"Vous êtes sur le point de vous connecter en utilisant un compte tiers depuis " "%(provider)s." #: .\cookbook\templates\socialaccount\login.html:20 diff --git a/cookbook/migrations/0217_alter_userpreference_default_page.py b/cookbook/migrations/0217_alter_userpreference_default_page.py new file mode 100644 index 000000000..ae02a1ab0 --- /dev/null +++ b/cookbook/migrations/0217_alter_userpreference_default_page.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.10 on 2024-03-09 06:41 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('cookbook', '0216_delete_shoppinglist'), + ] + + operations = [ + migrations.AlterField( + model_name='userpreference', + name='default_page', + field=models.CharField(choices=[('SEARCH', 'Search'), ('PLAN', 'Meal-Plan'), ('BOOKS', 'Books'), ('SHOPPING', 'Shopping')], default='SEARCH', max_length=64), + ), + ] diff --git a/cookbook/models.py b/cookbook/models.py index aab4ec554..d2e160b8d 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -449,11 +449,13 @@ class UserPreference(models.Model, PermissionModelMixin): SEARCH = 'SEARCH' PLAN = 'PLAN' BOOKS = 'BOOKS' + SHOPPING = 'SHOPPING' PAGES = ( (SEARCH, _('Search')), (PLAN, _('Meal-Plan')), (BOOKS, _('Books')), + (SHOPPING, _('Shopping')), ) user = AutoOneToOneField(User, on_delete=models.CASCADE, primary_key=True) diff --git a/cookbook/urls.py b/cookbook/urls.py index 10ae2d129..8dca5544b 100644 --- a/cookbook/urls.py +++ b/cookbook/urls.py @@ -16,7 +16,7 @@ from .models import (Automation, Comment, CustomFilter, Food, InviteLink, Keywor from .views import api, data, delete, edit, import_export, lists, new, telegram, views from .views.api import CustomAuthToken, ImportOpenData - +import datetime # extend DRF default router class to allow including additional routers class DefaultRouter(routers.DefaultRouter): @@ -122,9 +122,9 @@ urlpatterns = [ path('api/get_recipe_file//', api.get_recipe_file, name='api_get_recipe_file'), path('api/sync_all/', api.sync_all, name='api_sync'), path('api/log_cooking//', api.log_cooking, name='api_log_cooking'), - path('api/plan-ical/', api.get_plan_ical, name='api_get_plan_ical_future'), - path('api/plan-ical//', api.get_plan_ical, name='api_get_plan_ical_from'), - path('api/plan-ical///', api.get_plan_ical, name='api_get_plan_ical'), + + path('api/plan-ical/', api.get_plan_ical, kwargs={'from_date': datetime.date.today(), 'to_date': None}, name='api_get_plan_ical_future'), + path('api/recipe-from-source/', api.RecipeUrlImportView.as_view(), name='api_recipe_from_source'), path('api/backup/', api.get_backup, name='api_backup'), path('api/ingredient-from-string/', api.ingredient_from_string, name='api_ingredient_from_string'), diff --git a/cookbook/views/views.py b/cookbook/views/views.py index d7af864f1..dd89638d0 100644 --- a/cookbook/views/views.py +++ b/cookbook/views/views.py @@ -38,7 +38,7 @@ def index(request): return HttpResponseRedirect(reverse_lazy('view_search')) try: - page_map = {UserPreference.SEARCH: reverse_lazy('view_search'), UserPreference.PLAN: reverse_lazy('view_plan'), UserPreference.BOOKS: reverse_lazy('view_books'), } + page_map = {UserPreference.SEARCH: reverse_lazy('view_search'), UserPreference.PLAN: reverse_lazy('view_plan'), UserPreference.BOOKS: reverse_lazy('view_books'), UserPreference.SHOPPING: reverse_lazy('view_shopping'),} return HttpResponseRedirect(page_map.get(request.user.userpreference.default_page)) except UserPreference.DoesNotExist: @@ -293,11 +293,10 @@ def system(request): if postgres: postgres_current = 16 # will need to be updated as PostgreSQL releases new major versions - from decimal import Decimal from django.db import connection - postgres_ver = Decimal(str(connection.pg_version).replace('00', '.')) + postgres_ver = divmod(connection.pg_version, 10000) if postgres_ver >= postgres_current: database_status = 'success' database_message = _('Everything is fine!') @@ -446,7 +445,7 @@ def web_manifest(request): theme_values['app_name'], "description": _("Manage recipes, shopping list, meal plans and more."), "icons": icons, "start_url": - "./search", "background_color": + "./", "background_color": theme_values['nav_bg_color'], "display": "standalone", "scope": ".", "theme_color": @@ -454,7 +453,7 @@ def web_manifest(request): [{"name": _("Plan"), "short_name": _("Plan"), "description": _("View your meal Plan"), "url": "./plan"}, {"name": _("Books"), "short_name": _("Books"), "description": _("View your cookbooks"), "url": "./books"}, {"name": _("Shopping"), "short_name": _("Shopping"), "description": _("View your shopping lists"), "url": - "./list/shopping-list/"}], "share_target": {"action": "/data/import/url", "method": "GET", "params": {"title": "title", "url": "url", "text": "text"}} + "./shopping/"}], "share_target": {"action": "/data/import/url", "method": "GET", "params": {"title": "title", "url": "url", "text": "text"}} } return JsonResponse(manifest_info, json_dumps_params={'indent': 4}) diff --git a/vue/src/apps/ShoppingListView/ShoppingListView.vue b/vue/src/apps/ShoppingListView/ShoppingListView.vue index b1c8b20be..f5a22a316 100644 --- a/vue/src/apps/ShoppingListView/ShoppingListView.vue +++ b/vue/src/apps/ShoppingListView/ShoppingListView.vue @@ -75,7 +75,7 @@ + v-if="(c.count_unchecked > 0 || user_preference_store.device_settings.shopping_show_checked_entries) && (c.count_unchecked + c.count_checked) > 0 && (c.count_delayed_unchecked < c.count_unchecked ||user_preference_store.device_settings.shopping_show_delayed_entries )"> @@ -569,6 +569,9 @@ export default { api.retrieveSupermarket(useUserPreferenceStore().device_settings.shopping_selected_supermarket.id).then(r => { useUserPreferenceStore().device_settings.shopping_selected_supermarket = r.data useUserPreferenceStore().updateDeviceSettings() + }).catch(err => { + useUserPreferenceStore().device_settings.shopping_selected_supermarket = null + useUserPreferenceStore().updateDeviceSettings() }) } diff --git a/vue/src/components/Settings/CosmeticSettingsComponent.vue b/vue/src/components/Settings/CosmeticSettingsComponent.vue index b37866545..8ce754336 100644 --- a/vue/src/components/Settings/CosmeticSettingsComponent.vue +++ b/vue/src/components/Settings/CosmeticSettingsComponent.vue @@ -37,6 +37,15 @@ + + + {{$t('Search')}} + {{$t('Shopping')}} + {{$t('Meal_Plan')}} + {{$t('Books')}} + + +
diff --git a/vue/src/locales/ca.json b/vue/src/locales/ca.json new file mode 100644 index 000000000..526cb30da --- /dev/null +++ b/vue/src/locales/ca.json @@ -0,0 +1,570 @@ +{ + "warning_feature_beta": "Aquesta funció està en fase BETA (proves). Podrien aparèixer-hi errades i canvis importants en un futur (i es podria perdre informació relacionada amb la seva funcionalitat) quan la utilitzis .", + "err_fetching_resource": "Hi ha hagut una errada a l'hora d'obtenir el recurs!", + "err_creating_resource": "Hi ha hagut un error quan es creava el recurs!", + "err_updating_resource": "Hi ha hagut un error quan s'actualitzava el recurs!", + "err_deleting_resource": "Hi ha hagut un error mentre s'esborrava el recurs!", + "err_deleting_protected_resource": "L'objecte que esteu intentant eliminar s'està utilitzant i no es pot esborrar.", + "err_moving_resource": "Hi ha hagut un error movent el recurs!", + "err_merging_resource": "Hi ha hagut un error fusionant el recurs!", + "err_importing_recipe": "Hi ha hagut un error mentre s'importava la recepta!", + "success_fetching_resource": "S'ha obtingut el recurs amb èxit!", + "success_creating_resource": "El recurs ha estat creat amb èxit!", + "success_updating_resource": "El recurs s'ha actualitzat adequadament!", + "success_deleting_resource": "El recurs s'ha esborrat adequadament!", + "success_moving_resource": "El recurs s'ha mogut adequadament!", + "success_merging_resource": "El recurs s'ha fusionat adequadament!", + "file_upload_disabled": "La càrrega d'arxius no està habilitada per al vostre espai.", + "recipe_property_info": "També podeu afegir propietats als aliments per calcular-les automàticament en funció de la vostra recepta!", + "warning_space_delete": "Podeu eliminar el vostre espai incloent-hi les receptes, llistes de la compra, plans d'àpats i tot el que hi hàgiu creat. Un cop ho feu, no podreu tornar enrere. Esteu segurs que ho voleu fer?", + "food_inherit_info": "Camps que han de ser heretats per defecte.", + "step_time_minutes": "Temps del pas en minuts", + "confirm_delete": "Esteu segurs que voleu eliminar aquest {object}?", + "import_running": "Importació en curs, espereu!", + "all_fields_optional": "Tots els camps són opcionals i es poden deixar buits.", + "convert_internal": "Convertiu-ho en una recepta interna", + "show_only_internal": "Mostreu només les receptes internes", + "show_split_screen": "Vista dividida", + "Log_Recipe_Cooking": "Registre de receptes", + "External_Recipe_Image": "Imatge externa de la recepta", + "Add_to_Shopping": "Afegiu-ho al cistell", + "Add_to_Plan": "Afegiu-ho al pla", + "Step_start_time": "Hora d'inici", + "Sort_by_new": "Ordenar a partir del més nou", + "Table_of_Contents": "Taula de continguts", + "Recipes_per_page": "Receptes per pàgina", + "Show_as_header": "Mostreu com a títol", + "Hide_as_header": "Amagueu com a títol", + "Add_nutrition_recipe": "Afegir nutrició a la recepta", + "Remove_nutrition_recipe": "Esborreu nutrició de la recepta", + "Copy_template_reference": "Copieu el patró", + "per_serving": "per porció", + "Save_and_View": "Graveu-ho i mostreu-ho", + "Manage_Books": "Gestioneu els llibres", + "Meal_Plan": "Pla d'àpats", + "Select_Book": "Seleccioneu llibre", + "Select_File": "Seleccioneu arxiu", + "Recipe_Image": "Imatge de la recepta", + "Import_finished": "Importació finalitzada", + "View_Recipes": "Mostreu les receptes", + "Log_Cooking": "Registreu el que s'ha cuinat", + "New_Recipe": "Nova recepta", + "Url_Import": "Importeu des d'url", + "Reset_Search": "Reinicieu la cerca", + "Recently_Viewed": "Vistos recentment", + "Load_More": "Carregueu-ne més", + "New_Keyword": "Afegiu-hi una nova paraula clau", + "Delete_Keyword": "Esborreu paraula clau", + "Edit_Keyword": "Editeu paraula clau", + "Edit_Recipe": "Editeu recepta", + "Move_Keyword": "Moveu la paraula clau", + "Merge_Keyword": "Fusioneu paraula clau", + "Hide_Keywords": "Amagueu paraula clau", + "Hide_Recipes": "Amagueu receptes", + "Move_Up": "Moveu amunt", + "Move_Down": "Moveu avall", + "Step_Name": "Nom del pas", + "Step_Type": "Tipus de pas", + "Make_Header": "Establiu capçalera", + "Make_Ingredient": "Establiu ingredient", + "Amount": "Quantitat", + "Enable_Amount": "Habiliteu quantitat", + "Disable_Amount": "Deshabiliteu quantitat", + "Ingredient Editor": "Editor d'ingredients", + "Description_Replace": "Substituïu descripció", + "Instruction_Replace": "Substituïu instrucció", + "Auto_Sort": "Ordeneu automàticament", + "Auto_Sort_Help": "Moveu tots els ingredients al pas més adequat.", + "Private_Recipe": "Recepta privada", + "Private_Recipe_Help": "Només tu i la gent amb qui l'has compartit podran veure aquesta recepta.", + "reusable_help_text": "L'enllaç d'invitació es pot fer servir per més d'un usuari.", + "open_data_help_text": "El projecte de dades obertes de Tandoor proporciona dades per a Tandoor a partir de les contribucions de la comunitat. Aquest camp s'emplena automàticament quan s'importa i permet que es facin actualitzacions en un futur.", + "Open_Data_Slug": "", + "Open_Data_Import": "", + "Properties_Food_Amount": "", + "Properties_Food_Unit": "", + "Calculator": "", + "FDC_ID": "", + "FDC_Search": "", + "FDC_ID_help": "", + "property_type_fdc_hint": "", + "Data_Import_Info": "", + "Update_Existing_Data": "", + "Use_Metric": "", + "Learn_More": "", + "converted_unit": "", + "converted_amount": "", + "base_unit": "", + "base_amount": "", + "Datatype": "", + "Input": "", + "Undo": "", + "NoMoreUndo": "", + "Number of Objects": "", + "Add_Step": "", + "Keywords": "", + "Books": "", + "Proteins": "", + "Fats": "", + "Carbohydrates": "", + "Calories": "", + "Energy": "", + "Nutrition": "", + "Date": "", + "StartDate": "", + "EndDate": "", + "Share": "", + "Automation": "", + "Parameter": "", + "Export": "", + "Copy": "", + "Rating": "", + "Close": "", + "Cancel": "", + "Link": "", + "Add": "", + "New": "", + "Note": "", + "Alignment": "", + "Success": "", + "Failure": "", + "Protected": "", + "Ingredients": "", + "Supermarket": "", + "Categories": "", + "Category": "", + "Selected": "", + "min": "", + "Servings": "", + "Waiting": "", + "Preparation": "", + "External": "", + "Size": "", + "Files": "", + "File": "", + "Edit": "", + "Image": "", + "Delete": "", + "Delete_All": "", + "Open": "", + "Ok": "", + "Save": "", + "Step": "", + "Search": "", + "Import": "", + "Print": "", + "Settings": "", + "or": "", + "and": "", + "Information": "", + "Download": "", + "Create": "", + "Search Settings": "", + "View": "", + "Recipes": "", + "Welcome": "", + "Move": "", + "Merge": "", + "Parent": "", + "Copy Link": "", + "Copy Token": "", + "delete_confirmation": "", + "move_confirmation": "", + "merge_confirmation": "", + "create_rule": "", + "move_selection": "", + "merge_selection": "", + "Root": "", + "Ignore_Shopping": "", + "Shopping_Category": "", + "Shopping_Categories": "", + "Shopping_input_placeholder": "", + "Edit_Food": "", + "Move_Food": "", + "New_Food": "", + "Hide_Food": "", + "Food_Alias": "", + "Unit_Alias": "", + "Keyword_Alias": "", + "Delete_Food": "", + "No_ID": "", + "Meal_Plan_Days": "", + "merge_title": "", + "move_title": "", + "Food": "", + "Property": "", + "Property_Editor": "", + "Conversion": "", + "Original_Text": "", + "Recipe_Book": "", + "del_confirmation_tree": "", + "delete_title": "", + "create_title": "", + "edit_title": "", + "Name": "", + "Properties": "", + "Type": "", + "Description": "", + "Recipe": "", + "tree_root": "", + "Icon": "", + "Unit": "", + "Decimals": "", + "Default_Unit": "", + "No_Results": "", + "New_Unit": "", + "Create_New_Shopping Category": "", + "Create_New_Food": "", + "Create_New_Keyword": "", + "Create_New_Unit": "", + "Create_New_Meal_Type": "", + "Create_New_Shopping_Category": "", + "and_up": "", + "and_down": "", + "Instructions": "", + "Unrated": "", + "Automate": "", + "Empty": "", + "Key_Ctrl": "", + "Key_Shift": "", + "Time": "", + "Text": "", + "Shopping_list": "", + "Added_by": "", + "Added_on": "", + "AddToShopping": "", + "IngredientInShopping": "", + "NotInShopping": "", + "OnHand": "", + "FoodOnHand": "", + "FoodNotOnHand": "", + "Undefined": "", + "Create_Meal_Plan_Entry": "", + "Edit_Meal_Plan_Entry": "", + "Title": "", + "Week": "", + "Month": "", + "Year": "", + "created_by": "", + "Planner": "", + "Planner_Settings": "", + "Period": "", + "Plan_Period_To_Show": "", + "Periods": "", + "Plan_Show_How_Many_Periods": "", + "Starting_Day": "", + "Meal_Types": "", + "Meal_Type": "", + "New_Entry": "", + "Clone": "", + "Drag_Here_To_Delete": "", + "Meal_Type_Required": "", + "Title_or_Recipe_Required": "", + "Color": "", + "New_Meal_Type": "", + "Use_Fractions": "", + "Use_Fractions_Help": "", + "AddFoodToShopping": "", + "RemoveFoodFromShopping": "", + "DeleteShoppingConfirm": "", + "IgnoredFood": "", + "Add_Servings_to_Shopping": "", + "Week_Numbers": "", + "Show_Week_Numbers": "", + "Export_As_ICal": "", + "Export_To_ICal": "", + "Cannot_Add_Notes_To_Shopping": "", + "Added_To_Shopping_List": "", + "Shopping_List_Empty": "", + "Next_Period": "", + "Previous_Period": "", + "Current_Period": "", + "Next_Day": "", + "Previous_Day": "", + "Inherit": "", + "InheritFields": "", + "FoodInherit": "", + "ShowUncategorizedFood": "", + "GroupBy": "", + "Language": "", + "Theme": "", + "CustomTheme": "", + "CustomThemeHelp": "", + "CustomImageHelp": "", + "CustomNavLogoHelp": "", + "CustomLogoHelp": "", + "CustomLogos": "", + "SupermarketCategoriesOnly": "", + "MoveCategory": "", + "CountMore": "", + "IgnoreThis": "", + "DelayFor": "", + "Warning": "", + "NoCategory": "", + "InheritWarning": "", + "ShowDelayed": "", + "ShowRecentlyCompleted": "", + "Completed": "", + "OfflineAlert": "", + "ShoppingBackgroundSyncWarning": "", + "shopping_share": "", + "shopping_auto_sync": "", + "one_url_per_line": "", + "mealplan_autoadd_shopping": "", + "mealplan_autoexclude_onhand": "", + "mealplan_autoinclude_related": "", + "default_delay": "", + "plan_share_desc": "", + "shopping_share_desc": "", + "shopping_auto_sync_desc": "", + "mealplan_autoadd_shopping_desc": "", + "mealplan_autoexclude_onhand_desc": "", + "mealplan_autoinclude_related_desc": "", + "default_delay_desc": "", + "filter_to_supermarket": "", + "Coming_Soon": "", + "Auto_Planner": "", + "New_Cookbook": "", + "Hide_Keyword": "", + "Hour": "", + "Hours": "", + "Day": "", + "Days": "", + "Second": "", + "Seconds": "", + "Clear": "", + "Users": "", + "Invites": "", + "err_move_self": "", + "nothing": "", + "err_merge_self": "", + "show_sql": "", + "filter_to_supermarket_desc": "", + "CategoryName": "", + "SupermarketName": "", + "CategoryInstruction": "", + "OrderInformation": "", + "shopping_recent_days_desc": "", + "shopping_recent_days": "", + "download_pdf": "", + "download_csv": "", + "csv_delim_help": "", + "csv_delim_label": "", + "SuccessClipboard": "", + "copy_to_clipboard": "", + "csv_prefix_help": "", + "csv_prefix_label": "", + "copy_markdown_table": "", + "in_shopping": "", + "DelayUntil": "", + "Pin": "", + "Unpin": "", + "PinnedConfirmation": "", + "UnpinnedConfirmation": "", + "mark_complete": "", + "QuickEntry": "", + "shopping_add_onhand_desc": "", + "shopping_add_onhand": "", + "related_recipes": "", + "today_recipes": "", + "sql_debug": "", + "remember_search": "", + "remember_hours": "", + "tree_select": "", + "OnHand_help": "", + "ignore_shopping_help": "", + "shopping_category_help": "", + "food_recipe_help": "", + "Foods": "", + "Account": "", + "Cosmetic": "", + "API": "", + "enable_expert": "", + "expert_mode": "", + "simple_mode": "", + "advanced": "", + "fields": "", + "show_keywords": "", + "show_foods": "", + "show_books": "", + "show_rating": "", + "show_units": "", + "show_filters": "", + "not": "", + "save_filter": "", + "filter_name": "", + "left_handed": "", + "left_handed_help": "", + "show_step_ingredients_setting": "", + "show_step_ingredients_setting_help": "", + "show_step_ingredients": "", + "hide_step_ingredients": "", + "Custom Filter": "", + "shared_with": "", + "sort_by": "", + "asc": "", + "desc": "", + "date_viewed": "", + "last_cooked": "", + "times_cooked": "", + "date_created": "", + "show_sortby": "", + "search_rank": "", + "make_now": "", + "Created": "", + "Updated": "", + "Unchanged": "", + "Error": "", + "make_now_count": "", + "recipe_filter": "", + "book_filter_help": "", + "review_shopping": "", + "view_recipe": "", + "copy_to_new": "", + "recipe_name": "", + "paste_ingredients_placeholder": "", + "paste_ingredients": "", + "ingredient_list": "", + "explain": "", + "filter": "", + "Website": "", + "App": "", + "Message": "", + "Bookmarklet": "", + "Sticky_Nav": "", + "Sticky_Nav_Help": "", + "Logo": "", + "Show_Logo": "", + "Show_Logo_Help": "", + "Nav_Color": "", + "Nav_Text_Mode": "", + "Nav_Text_Mode_Help": "", + "Nav_Color_Help": "", + "Space_Cosmetic_Settings": "", + "Use_Kj": "", + "Comments_setting": "", + "click_image_import": "", + "no_more_images_found": "", + "import_duplicates": "", + "paste_json": "", + "Click_To_Edit": "", + "search_no_recipes": "", + "search_import_help_text": "", + "search_create_help_text": "", + "warning_duplicate_filter": "", + "reset_children": "", + "reset_children_help": "", + "reset_food_inheritance": "", + "reset_food_inheritance_info": "", + "substitute_help": "", + "substitute_siblings_help": "", + "substitute_children_help": "", + "substitute_siblings": "", + "substitute_children": "", + "SubstituteOnHand": "", + "ChildInheritFields": "", + "ChildInheritFields_help": "", + "InheritFields_help": "", + "show_ingredients_table": "", + "show_ingredient_overview": "", + "Ingredient Overview": "", + "last_viewed": "", + "created_on": "", + "updatedon": "", + "Imported_From": "", + "advanced_search_settings": "", + "nothing_planned_today": "", + "no_pinned_recipes": "", + "Planned": "", + "Pinned": "", + "Imported": "", + "Quick actions": "", + "Ratings": "", + "Internal": "", + "Units": "", + "Manage_Emails": "", + "Change_Password": "", + "Social_Authentication": "", + "Random Recipes": "", + "parameter_count": "", + "select_keyword": "", + "add_keyword": "", + "select_file": "", + "select_recipe": "", + "select_unit": "", + "select_food": "", + "remove_selection": "", + "empty_list": "", + "Select": "", + "Supermarkets": "", + "User": "", + "Username": "", + "First_name": "", + "Last_name": "", + "Keyword": "", + "Advanced": "", + "Page": "", + "Single": "", + "Multiple": "", + "Reset": "", + "Disabled": "", + "Disable": "", + "Enable": "", + "Options": "", + "Create Food": "", + "create_food_desc": "", + "additional_options": "", + "Importer_Help": "", + "Documentation": "", + "Select_App_To_Import": "", + "Import_Supported": "", + "Export_Supported": "", + "Import_Not_Yet_Supported": "", + "Export_Not_Yet_Supported": "", + "Import_Result_Info": "", + "Recipes_In_Import": "", + "Toggle": "", + "total": "", + "Import_Error": "", + "Warning_Delete_Supermarket_Category": "", + "New_Supermarket": "", + "New_Supermarket_Category": "", + "Are_You_Sure": "", + "Valid Until": "", + "Split_All_Steps": "", + "Combine_All_Steps": "", + "Plural": "", + "plural_short": "", + "g": "", + "kg": "", + "ounce": "", + "pound": "", + "ml": "", + "l": "", + "fluid_ounce": "", + "pint": "", + "quart": "", + "gallon": "", + "tbsp": "", + "tsp": "", + "imperial_fluid_ounce": "", + "imperial_pint": "", + "imperial_quart": "", + "imperial_gallon": "", + "imperial_tbsp": "", + "imperial_tsp": "", + "Choose_Category": "", + "Back": "", + "Use_Plural_Unit_Always": "", + "Use_Plural_Unit_Simple": "", + "Use_Plural_Food_Always": "", + "Use_Plural_Food_Simple": "", + "plural_usage_info": "", + "Create Recipe": "", + "Import Recipe": "", + "Never_Unit": "", + "Transpose_Words": "", + "Name_Replace": "", + "Food_Replace": "", + "Unit_Replace": "" +} diff --git a/vue/src/locales/de.json b/vue/src/locales/de.json index f1ad1d6ee..9f95f873c 100644 --- a/vue/src/locales/de.json +++ b/vue/src/locales/de.json @@ -114,7 +114,7 @@ "Create_New_Shopping Category": "Neue Einkaufskategorie erstellen", "Automate": "Automatisieren", "Type": "Typ", - "and_up": "& Hoch", + "and_up": "& mehr", "Unrated": "Unbewertet", "Shopping_list": "Einkaufsliste", "step_time_minutes": "Schritt Dauer in Minuten", diff --git a/vue/src/locales/en.json b/vue/src/locales/en.json index 0cfae7887..be25ef264 100644 --- a/vue/src/locales/en.json +++ b/vue/src/locales/en.json @@ -504,6 +504,7 @@ "Keyword": "Keyword", "Advanced": "Advanced", "Page": "Page", + "DefaultPage": "Default Page", "Single": "Single", "Multiple": "Multiple", "Reset": "Reset", diff --git a/vue/src/locales/nl.json b/vue/src/locales/nl.json index 8387489c8..91a85bac0 100644 --- a/vue/src/locales/nl.json +++ b/vue/src/locales/nl.json @@ -520,5 +520,6 @@ "imperial_gallon": "imperial gal [imp gal] (Verenigd Koninkrijk, volume)", "imperial_tsp": "imperial thelepel [imp tsp] (UK, volume)", "Choose_Category": "Kies Categorie", - "Back": "Terug" + "Back": "Terug", + "err_importing_recipe": "Bij het importeren van het recept is een fout opgetreden!" } diff --git a/vue/src/stores/ShoppingListStore.js b/vue/src/stores/ShoppingListStore.js index 6a4aab1e7..bacaf86ab 100644 --- a/vue/src/stores/ShoppingListStore.js +++ b/vue/src/stores/ShoppingListStore.js @@ -65,6 +65,7 @@ export const useShoppingListStore = defineStore(_STORE_ID, { let count_checked = 0 let count_unchecked_food = 0 let count_checked_food = 0 + let count_delayed_unchecked = 0 for (let fi in structure[i]['foods']) { let food_checked = true @@ -74,6 +75,9 @@ export const useShoppingListStore = defineStore(_STORE_ID, { } else { food_checked = false count_unchecked++ + if (structure[i]['foods'][fi]['entries'][ei].delay_until != null){ + count_delayed_unchecked++ + } } } if (food_checked) { @@ -87,6 +91,7 @@ export const useShoppingListStore = defineStore(_STORE_ID, { Vue.set(structure[i], 'count_checked', count_checked) Vue.set(structure[i], 'count_unchecked_food', count_unchecked_food) Vue.set(structure[i], 'count_checked_food', count_checked_food) + Vue.set(structure[i], 'count_delayed_unchecked', count_delayed_unchecked) total_unchecked += count_unchecked total_checked += count_checked diff --git a/vue/src/utils/models.js b/vue/src/utils/models.js index 42182baf8..5e35ff599 100644 --- a/vue/src/utils/models.js +++ b/vue/src/utils/models.js @@ -427,6 +427,15 @@ export class Models { placeholder: "", optional: true, }, + open_data_slug: { + form_field: true, + type: "text", + field: "open_data_slug", + disabled: true, + label: "Open_Data_Slug", + help_text: "open_data_help_text", + optional: true, + }, }, }, }