From 530d6b0cb60fc7d5a6c55c8458f6b8d9a3028376 Mon Sep 17 00:00:00 2001 From: AquaticLava Date: Sun, 23 Jul 2023 11:51:07 -0600 Subject: [PATCH 01/19] changed random recipe to be index based. --- cookbook/views/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 74910174..67bb0dd6 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -688,7 +688,7 @@ class AutoPlanViewSet(viewsets.ViewSet): for i in range(0, days): day = start_date + datetime.timedelta(i) - recipe = random.choice(recipes) + recipe = recipes[i % len(recipes)] args = {'recipe': recipe, 'servings': servings, 'title': recipe.name, 'created_by': request.user, 'meal_type': meal_type, From 8f53b399c60d5db5915dc85b5da4df854be95d52 Mon Sep 17 00:00:00 2001 From: Sriyukthika <148747664+Sriyukthika26@users.noreply.github.com> Date: Sat, 9 Dec 2023 23:58:26 +0530 Subject: [PATCH 02/19] Update truenas_portainer.md --- docs/install/truenas_portainer.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/install/truenas_portainer.md b/docs/install/truenas_portainer.md index 03b288fd..9ff0525f 100644 --- a/docs/install/truenas_portainer.md +++ b/docs/install/truenas_portainer.md @@ -76,7 +76,8 @@ Basic guide to setup Docker and Portainer TrueNAS Core. ![Screenshot of Stack List](https://2914113074-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FiZWHJxqQsgWYd9sI88sO%2Fuploads%2FnBx62EIPhmUy1L0S1iKI%2F2.15-docker_add_stack_web_editor.gif?alt=media&token=c45c0151-9c15-4d79-b229-1a90a7a86b84) -Use the below code and input it into the Web Editor: -`version: "3" +```yaml +version: "3" services: db_recipes: restart: always @@ -87,13 +88,13 @@ services: - stack.env web_recipes: -# image: vabene1111/recipes:latest + # image: vabene1111/recipes:latest image: vabene1111/recipes:beta env_file: - stack.env volumes: - staticfiles:/opt/recipes/staticfiles - # Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes-vs-bind-mounts + # Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes-vs-bind-mounts - nginx_config:/opt/recipes/nginx/conf.d - ./mediafiles:/opt/recipes/mediafiles depends_on: @@ -116,7 +117,8 @@ services: volumes: nginx_config: - staticfiles:` + staticfiles: +``` -Download the .env template from [HERE](https://raw.githubusercontent.com/vabene1111/recipes/develop/.env.template) and load this file by pressing the "Load Variables from .env File" button: ![Screenshot of Add Stack screen](https://www.portainer.io/hubfs/image-png-Feb-21-2022-06-21-15-88-PM.png) From 044ed1ec1883addf250af41dc99073e9bbb6e35d Mon Sep 17 00:00:00 2001 From: Sriyukthika <148747664+Sriyukthika26@users.noreply.github.com> Date: Sun, 10 Dec 2023 00:44:15 +0530 Subject: [PATCH 03/19] Update truenas_portainer.md Spelling Error --- docs/install/truenas_portainer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/install/truenas_portainer.md b/docs/install/truenas_portainer.md index 9ff0525f..fde9e41a 100644 --- a/docs/install/truenas_portainer.md +++ b/docs/install/truenas_portainer.md @@ -71,7 +71,7 @@ Basic guide to setup Docker and Portainer TrueNAS Core. -Select "Get Started" to use the Enviroment Portainer is running in ![Screenshot of Enviroment Wizard](https://2914113074-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FiZWHJxqQsgWYd9sI88sO%2Fuploads%2Fsig45vFliINvOKGKVStk%2F2.15-install-server-setup-wizard.png?alt=media&token=cd21d9e8-0632-40db-af9a-581365f98209) -### 3. Install Tandoor Recipies VIA Portainer Web Editor +### 3. Install Tandoor Recipes VIA Portainer Web Editor -From the menu select Stacks, click Add stack, give the stack a descriptive name then select Web editor. ![Screenshot of Stack List](https://2914113074-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FiZWHJxqQsgWYd9sI88sO%2Fuploads%2FnBx62EIPhmUy1L0S1iKI%2F2.15-docker_add_stack_web_editor.gif?alt=media&token=c45c0151-9c15-4d79-b229-1a90a7a86b84) -Use the below code and input it into the Web Editor: From 4058c997deca82b97a45635b757f615135b8aa9d Mon Sep 17 00:00:00 2001 From: smilerz Date: Wed, 20 Dec 2023 15:46:28 -0600 Subject: [PATCH 04/19] updates to admin pages --- cookbook/admin.py | 52 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/cookbook/admin.py b/cookbook/admin.py index d2b5c31a..b9287ce2 100644 --- a/cookbook/admin.py +++ b/cookbook/admin.py @@ -60,7 +60,7 @@ admin.site.register(UserSpace, UserSpaceAdmin) class UserPreferenceAdmin(admin.ModelAdmin): - list_display = ('name', 'theme', 'nav_color', 'default_page',) + list_display = ('name', 'theme', 'nav_color', 'default_page') search_fields = ('user__username',) list_filter = ('theme', 'nav_color', 'default_page',) date_hierarchy = 'created_at' @@ -75,7 +75,7 @@ admin.site.register(UserPreference, UserPreferenceAdmin) class SearchPreferenceAdmin(admin.ModelAdmin): - list_display = ('name', 'search', 'trigram_threshold',) + list_display = ('name', 'search', 'trigram_threshold', ) search_fields = ('user__username',) list_filter = ('search',) @@ -108,11 +108,16 @@ class SupermarketCategoryInline(admin.TabularInline): class SupermarketAdmin(admin.ModelAdmin): + list_display = ('name', 'space',) inlines = (SupermarketCategoryInline,) +class SupermarketCategoryAdmin(admin.ModelAdmin): + list_display = ('name', 'space',) + + admin.site.register(Supermarket, SupermarketAdmin) -admin.site.register(SupermarketCategory) +admin.site.register(SupermarketCategory, SupermarketCategoryAdmin) class SyncLogAdmin(admin.ModelAdmin): @@ -163,10 +168,18 @@ def delete_unattached_steps(modeladmin, request, queryset): class StepAdmin(admin.ModelAdmin): - list_display = ('name', 'order',) - search_fields = ('name',) + list_display = ('recipe_and_name', 'order', 'space') + ordering = ('recipe__name', 'name', 'space', ) + search_fields = ('name', 'recipe__name') actions = [delete_unattached_steps] + @staticmethod + @admin.display(description="Name") + def recipe_and_name(obj): + if not obj.recipe_set.exists(): + return f"Orphaned Step{'':s if not obj.name else f': {obj.name}'}" + return f"{obj.recipe_set.first().name}: {obj.name}" if obj.name else obj.recipe_set.first().name + admin.site.register(Step, StepAdmin) @@ -183,7 +196,7 @@ def rebuild_index(modeladmin, request, queryset): class RecipeAdmin(admin.ModelAdmin): - list_display = ('name', 'internal', 'created_by', 'storage') + list_display = ('name', 'internal', 'created_by', 'storage', 'space') search_fields = ('name', 'created_by__username') list_filter = ('internal',) date_hierarchy = 'created_at' @@ -198,7 +211,14 @@ class RecipeAdmin(admin.ModelAdmin): admin.site.register(Recipe, RecipeAdmin) -admin.site.register(Unit) + +class UnitAdmin(admin.ModelAdmin): + list_display = ('name', 'space') + ordering = ('name', 'space', ) + search_fields = ('name',) + + +admin.site.register(Unit, UnitAdmin) # admin.site.register(FoodInheritField) @@ -229,10 +249,16 @@ def delete_unattached_ingredients(modeladmin, request, queryset): class IngredientAdmin(admin.ModelAdmin): - list_display = ('food', 'amount', 'unit') - search_fields = ('food__name', 'unit__name') + list_display = ('recipe_name', 'amount', 'unit', 'food', 'space') + search_fields = ('food__name', 'unit__name', 'step__recipe__name') actions = [delete_unattached_ingredients] + @staticmethod + @admin.display(description="Recipe") + def recipe_name(obj): + recipes = obj.step_set.first().recipe_set.all() if obj.step_set.exists() else None + return recipes.first().name if recipes else 'Orphaned Ingredient' + admin.site.register(Ingredient, IngredientAdmin) @@ -258,7 +284,7 @@ admin.site.register(RecipeImport, RecipeImportAdmin) class RecipeBookAdmin(admin.ModelAdmin): - list_display = ('name', 'user_name') + list_display = ('name', 'user_name', 'space') search_fields = ('name', 'created_by__username') @staticmethod @@ -334,11 +360,11 @@ class ShoppingListEntryAdmin(admin.ModelAdmin): admin.site.register(ShoppingListEntry, ShoppingListEntryAdmin) -class ShoppingListAdmin(admin.ModelAdmin): - list_display = ('id', 'created_by', 'created_at') +# class ShoppingListAdmin(admin.ModelAdmin): +# list_display = ('id', 'created_by', 'created_at') -admin.site.register(ShoppingList, ShoppingListAdmin) +# admin.site.register(ShoppingList, ShoppingListAdmin) class ShareLinkAdmin(admin.ModelAdmin): From 7a5b744ff00addbac65ea03cbab1a14950e9ba1d Mon Sep 17 00:00:00 2001 From: smilerz Date: Wed, 20 Dec 2023 15:49:54 -0600 Subject: [PATCH 05/19] order recipes in admin --- cookbook/admin.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cookbook/admin.py b/cookbook/admin.py index b9287ce2..bed49ca8 100644 --- a/cookbook/admin.py +++ b/cookbook/admin.py @@ -198,6 +198,7 @@ def rebuild_index(modeladmin, request, queryset): class RecipeAdmin(admin.ModelAdmin): list_display = ('name', 'internal', 'created_by', 'storage', 'space') search_fields = ('name', 'created_by__username') + ordering = ('name', 'created_by__username', ) list_filter = ('internal',) date_hierarchy = 'created_at' From 26f694576a1afd81842688ed68111a540a296bfb Mon Sep 17 00:00:00 2001 From: smilerz Date: Wed, 20 Dec 2023 15:55:02 -0600 Subject: [PATCH 06/19] update __str__() on Step and Ingredient models --- cookbook/models.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cookbook/models.py b/cookbook/models.py index c40bb41f..b09963ed 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -718,6 +718,10 @@ class Ingredient(ExportModelOperationsMixin('ingredient'), models.Model, Permiss space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') + def __str__(self): + recipes = self.step_set.first().recipe_set.all() if self.step_set.exists() else None + return f'{recipes.first().name}: {self.pk}' if recipes else f'Orphaned Ingredient: {self.pk}' + class Meta: ordering = ['order', 'pk'] indexes = ( @@ -745,7 +749,9 @@ class Step(ExportModelOperationsMixin('step'), models.Model, PermissionModelMixi return render_instructions(self) def __str__(self): - return f'{self.pk} {self.name}' + if not self.recipe_set.exists(): + return f"Orphaned Step{'':s if not obj.name else f': {self.pk} {self.name}'}" + return f"{self.recipe_set.first().name}: {self.name}" if self.name else self.recipe_set.first().name class Meta: ordering = ['order', 'pk'] From a7ea7a898713148e8446c60bc8486740266d1af2 Mon Sep 17 00:00:00 2001 From: Lucas Gasenzer Date: Wed, 27 Dec 2023 10:43:56 +0100 Subject: [PATCH 07/19] fix code block and replace tab with spaces --- docs/install/truenas_portainer.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/install/truenas_portainer.md b/docs/install/truenas_portainer.md index 03b288fd..057125d5 100644 --- a/docs/install/truenas_portainer.md +++ b/docs/install/truenas_portainer.md @@ -76,7 +76,8 @@ Basic guide to setup Docker and Portainer TrueNAS Core. ![Screenshot of Stack List](https://2914113074-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FiZWHJxqQsgWYd9sI88sO%2Fuploads%2FnBx62EIPhmUy1L0S1iKI%2F2.15-docker_add_stack_web_editor.gif?alt=media&token=c45c0151-9c15-4d79-b229-1a90a7a86b84) -Use the below code and input it into the Web Editor: -`version: "3" +```yaml +version: "3" services: db_recipes: restart: always @@ -87,13 +88,13 @@ services: - stack.env web_recipes: -# image: vabene1111/recipes:latest + #image: vabene1111/recipes:latest image: vabene1111/recipes:beta env_file: - stack.env volumes: - staticfiles:/opt/recipes/staticfiles - # Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes-vs-bind-mounts + # Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes-vs-bind-mounts - nginx_config:/opt/recipes/nginx/conf.d - ./mediafiles:/opt/recipes/mediafiles depends_on: @@ -116,7 +117,8 @@ services: volumes: nginx_config: - staticfiles:` + staticfiles: +``` -Download the .env template from [HERE](https://raw.githubusercontent.com/vabene1111/recipes/develop/.env.template) and load this file by pressing the "Load Variables from .env File" button: ![Screenshot of Add Stack screen](https://www.portainer.io/hubfs/image-png-Feb-21-2022-06-21-15-88-PM.png) From 7ca5a34b28f4cf50ecd75da6e103581624aa6b41 Mon Sep 17 00:00:00 2001 From: smilerz Date: Thu, 28 Dec 2023 10:00:15 -0600 Subject: [PATCH 08/19] fixed recursion in Step.__str__() --- cookbook/models.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cookbook/models.py b/cookbook/models.py index b09963ed..d4deed1f 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -749,9 +749,7 @@ class Step(ExportModelOperationsMixin('step'), models.Model, PermissionModelMixi return render_instructions(self) def __str__(self): - if not self.recipe_set.exists(): - return f"Orphaned Step{'':s if not obj.name else f': {self.pk} {self.name}'}" - return f"{self.recipe_set.first().name}: {self.name}" if self.name else self.recipe_set.first().name + return f"{self.pk}: {self.name}" if self.name else f"Step: {self.pk}" class Meta: ordering = ['order', 'pk'] From cb63bb26157495f308e25323bb38e3c6218a12d6 Mon Sep 17 00:00:00 2001 From: smilerz Date: Thu, 28 Dec 2023 10:44:51 -0600 Subject: [PATCH 09/19] avoid recursion in ingredient.__str__ --- cookbook/models.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cookbook/models.py b/cookbook/models.py index d4deed1f..b7c3e3c8 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -719,8 +719,7 @@ class Ingredient(ExportModelOperationsMixin('ingredient'), models.Model, Permiss objects = ScopedManager(space='space') def __str__(self): - recipes = self.step_set.first().recipe_set.all() if self.step_set.exists() else None - return f'{recipes.first().name}: {self.pk}' if recipes else f'Orphaned Ingredient: {self.pk}' + return f'{self.pk}: {self.amount} {self.food.name} {self.unit.name}' class Meta: ordering = ['order', 'pk'] @@ -749,6 +748,8 @@ class Step(ExportModelOperationsMixin('step'), models.Model, PermissionModelMixi return render_instructions(self) def __str__(self): + if not self.recipe_set.exists(): + return f"{self.pk}: {_('Orphaned Step')}" return f"{self.pk}: {self.name}" if self.name else f"Step: {self.pk}" class Meta: From 5059abc232e389fab19ffa18831ea3fad9173b6e Mon Sep 17 00:00:00 2001 From: Jaan Date: Fri, 29 Dec 2023 15:17:56 +0000 Subject: [PATCH 10/19] Translated using Weblate (Russian) Currently translated at 63.4% (344 of 542 strings) Translation: Tandoor/Recipes Frontend Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/ru/ --- vue/src/locales/ru.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vue/src/locales/ru.json b/vue/src/locales/ru.json index 7c1d0e3a..b29b3e1c 100644 --- a/vue/src/locales/ru.json +++ b/vue/src/locales/ru.json @@ -345,5 +345,6 @@ "GroupBy": "Сгруппировать по", "food_inherit_info": "Поля для продуктов питания, которые должны наследоваться по умолчанию.", "warning_space_delete": "Вы можете удалить свое пространство, включая все рецепты, списки покупок, планы питания и все остальное, что вы создали. Этого нельзя отменить! Вы уверены, что хотите это сделать?", - "Description_Replace": "Изменить описание" + "Description_Replace": "Изменить описание", + "err_importing_recipe": "Произошла ошибка при импортировании рецепта!" } From bf61b6474e22576f78f6e3ab9f7fac64f0638382 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Mon, 1 Jan 2024 14:51:20 +0100 Subject: [PATCH 11/19] fixed ingredient note field to high --- vue/src/apps/RecipeEditView/RecipeEditView.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/vue/src/apps/RecipeEditView/RecipeEditView.vue b/vue/src/apps/RecipeEditView/RecipeEditView.vue index 2649c037..7fd5dbe7 100644 --- a/vue/src/apps/RecipeEditView/RecipeEditView.vue +++ b/vue/src/apps/RecipeEditView/RecipeEditView.vue @@ -506,7 +506,6 @@ Date: Sun, 31 Dec 2023 08:59:42 +0000 Subject: [PATCH 15/19] Translated using Weblate (Hebrew) Currently translated at 95.3% (517 of 542 strings) Translation: Tandoor/Recipes Frontend Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/he/ --- vue/src/locales/he.json | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/vue/src/locales/he.json b/vue/src/locales/he.json index 572e6952..747746bf 100644 --- a/vue/src/locales/he.json +++ b/vue/src/locales/he.json @@ -263,9 +263,9 @@ "Current_Period": "תקופה נוכחית", "Next_Day": "היום הבא", "Previous_Day": "יום קודם", - "Inherit": "", - "InheritFields": "", - "FoodInherit": "", + "Inherit": "ירושה", + "InheritFields": "ירושת ערכי שדות", + "FoodInherit": "ערכי מזון", "ShowUncategorizedFood": "הצג לא מוגדר", "GroupBy": "אסוף לפי", "Language": "שפה", @@ -317,14 +317,14 @@ "CategoryName": "שם קטגוריה", "SupermarketName": "שם סופרמרקט", "CategoryInstruction": "גרור קטגוריות לשינוי הסדר שבו הן מופיעות ברשימת הקניות.", - "shopping_recent_days_desc": "", - "shopping_recent_days": "", - "download_pdf": "", - "download_csv": "", + "shopping_recent_days_desc": "מספר ימי קניות להציג.", + "shopping_recent_days": "מספר ימים", + "download_pdf": "הורד PDF", + "download_csv": "הורד CSV", "csv_delim_help": "", "csv_delim_label": "", - "SuccessClipboard": "", - "copy_to_clipboard": "", + "SuccessClipboard": "רשימת קניות הועתקה", + "copy_to_clipboard": "העתק", "csv_prefix_help": "תחילית להוספה כאשר מעתיקים את הרשימה ללוח הכתיבה.", "csv_prefix_label": "רשימת תחיליות", "copy_markdown_table": "העתק כטבלת Markdown", @@ -521,5 +521,15 @@ "Alignment": "יישור", "StartDate": "תאריך התחלה", "EndDate": "תאריך סיום", - "OrderInformation": "המוצרים מוצגים מהמספר הקטן לגדול." + "OrderInformation": "המוצרים מוצגים מהמספר הקטן לגדול.", + "FDC_ID_help": "מספר FDC", + "FDC_ID": "מספר FDC", + "show_step_ingredients_setting": "הצג חומרי גלם בתוך שלבי המרשם", + "err_importing_recipe": "שגיאה בעת יבוא המרשם!", + "FDC_Search": "חפש FDC", + "property_type_fdc_hint": "רק תכונות עם מספר FDC ימשכו מבסיס נתוני FDC", + "Property_Editor": "עורך ערכים", + "show_step_ingredients_setting_help": "הצג טבלת חומרי גלם לצדי שלבי המרשם. ניתן לשנות בזמן עריכת המרשם.", + "show_step_ingredients": "הראה חומרי גלם בשלבי המרשם", + "hide_step_ingredients": "הסתר חומרי גלם בשלבי המרשם" } From 3d8b1d6ccb39e8b1645d46b2942690e36ea31dc5 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Mon, 1 Jan 2024 22:14:01 +0100 Subject: [PATCH 16/19] lots of theming related changes - upload a custom logo for your space - space settings can override user settings for theming - spaces can upload custom CSS overrides - allow users to disable showing the tandoor/space logo - allow changing navigation background color to any color desired - allow switching navigation text color between dark/light (different effects depending on theme) --- cookbook/admin.py | 12 +- cookbook/forms.py | 58 - ...vbar_userpreference_nav_sticky_and_more.py | 128 + cookbook/models.py | 58 +- cookbook/serializer.py | 12 +- cookbook/static/themes/tandoor.min.css | 34 +- cookbook/static/themes/tandoor_dark.min.css | 32 +- cookbook/templates/base.html | 13 +- cookbook/templatetags/theming_tags.py | 52 +- cookbook/views/api.py | 2 +- .../apps/SpaceManageView/SpaceManageView.vue | 169 +- .../Settings/CosmeticSettingsComponent.vue | 36 +- vue/src/locales/en.json | 1095 ++--- vue/src/utils/openapi/api.ts | 3935 ++++++++++++++++- 14 files changed, 4811 insertions(+), 825 deletions(-) create mode 100644 cookbook/migrations/0206_rename_sticky_navbar_userpreference_nav_sticky_and_more.py diff --git a/cookbook/admin.py b/cookbook/admin.py index bed49ca8..82324628 100644 --- a/cookbook/admin.py +++ b/cookbook/admin.py @@ -60,9 +60,9 @@ admin.site.register(UserSpace, UserSpaceAdmin) class UserPreferenceAdmin(admin.ModelAdmin): - list_display = ('name', 'theme', 'nav_color', 'default_page') + list_display = ('name', 'theme', 'default_page') search_fields = ('user__username',) - list_filter = ('theme', 'nav_color', 'default_page',) + list_filter = ('theme', 'default_page',) date_hierarchy = 'created_at' filter_horizontal = ('plan_share', 'shopping_share',) @@ -75,7 +75,7 @@ admin.site.register(UserPreference, UserPreferenceAdmin) class SearchPreferenceAdmin(admin.ModelAdmin): - list_display = ('name', 'search', 'trigram_threshold', ) + list_display = ('name', 'search', 'trigram_threshold',) search_fields = ('user__username',) list_filter = ('search',) @@ -169,7 +169,7 @@ def delete_unattached_steps(modeladmin, request, queryset): class StepAdmin(admin.ModelAdmin): list_display = ('recipe_and_name', 'order', 'space') - ordering = ('recipe__name', 'name', 'space', ) + ordering = ('recipe__name', 'name', 'space',) search_fields = ('name', 'recipe__name') actions = [delete_unattached_steps] @@ -198,7 +198,7 @@ def rebuild_index(modeladmin, request, queryset): class RecipeAdmin(admin.ModelAdmin): list_display = ('name', 'internal', 'created_by', 'storage', 'space') search_fields = ('name', 'created_by__username') - ordering = ('name', 'created_by__username', ) + ordering = ('name', 'created_by__username',) list_filter = ('internal',) date_hierarchy = 'created_at' @@ -215,7 +215,7 @@ admin.site.register(Recipe, RecipeAdmin) class UnitAdmin(admin.ModelAdmin): list_display = ('name', 'space') - ordering = ('name', 'space', ) + ordering = ('name', 'space',) search_fields = ('name',) diff --git a/cookbook/forms.py b/cookbook/forms.py index 36b35ed5..dd62aa0b 100644 --- a/cookbook/forms.py +++ b/cookbook/forms.py @@ -33,64 +33,6 @@ class DateWidget(forms.DateInput): super().__init__(**kwargs) -class UserPreferenceForm(forms.ModelForm): - prefix = 'preference' - - def __init__(self, *args, **kwargs): - space = kwargs.pop('space') - super().__init__(*args, **kwargs) - self.fields['plan_share'].queryset = User.objects.filter(userspace__space=space).all() - - class Meta: - model = UserPreference - fields = ( - 'default_unit', 'use_fractions', 'use_kj', 'theme', 'nav_color', - 'sticky_navbar', 'default_page', 'plan_share', 'ingredient_decimals', 'comments', 'left_handed', 'show_step_ingredients', - ) - - labels = { - 'default_unit': _('Default unit'), - 'use_fractions': _('Use fractions'), - 'use_kj': _('Use KJ'), - 'theme': _('Theme'), - 'nav_color': _('Navbar color'), - 'sticky_navbar': _('Sticky navbar'), - 'default_page': _('Default page'), - 'plan_share': _('Plan sharing'), - 'ingredient_decimals': _('Ingredient decimal places'), - 'shopping_auto_sync': _('Shopping list auto sync period'), - 'comments': _('Comments'), - 'left_handed': _('Left-handed mode'), - 'show_step_ingredients': _('Show step ingredients table') - } - - help_texts = { - 'nav_color': _('Color of the top navigation bar. Not all colors work with all themes, just try them out!'), - 'default_unit': _('Default Unit to be used when inserting a new ingredient into a recipe.'), - 'use_fractions': _( - 'Enables support for fractions in ingredient amounts (e.g. convert decimals to fractions automatically)'), - 'use_kj': _('Display nutritional energy amounts in joules instead of calories'), - 'plan_share': _('Users with whom newly created meal plans should be shared by default.'), - 'shopping_share': _('Users with whom to share shopping lists.'), - 'ingredient_decimals': _('Number of decimals to round ingredients.'), - 'comments': _('If you want to be able to create and see comments underneath recipes.'), - 'shopping_auto_sync': _( - 'Setting to 0 will disable auto sync. When viewing a shopping list the list is updated every set seconds to sync changes someone else might have made. Useful when shopping with multiple people but might use a little bit ' - 'of mobile data. If lower than instance limit it is reset when saving.' - ), - 'sticky_navbar': _('Makes the navbar stick to the top of the page.'), - 'mealplan_autoadd_shopping': _('Automatically add meal plan ingredients to shopping list.'), - 'mealplan_autoexclude_onhand': _('Exclude ingredients that are on hand.'), - 'left_handed': _('Will optimize the UI for use with your left hand.'), - 'show_step_ingredients': _('Add ingredients table next to recipe steps. Applies at creation time for manually created and URL imported recipes. Individual steps can be overridden in the edit recipe view.') - } - - widgets = { - 'plan_share': MultiSelectWidget, - 'shopping_share': MultiSelectWidget, - } - - class UserNameForm(forms.ModelForm): prefix = 'name' diff --git a/cookbook/migrations/0206_rename_sticky_navbar_userpreference_nav_sticky_and_more.py b/cookbook/migrations/0206_rename_sticky_navbar_userpreference_nav_sticky_and_more.py new file mode 100644 index 00000000..fb949029 --- /dev/null +++ b/cookbook/migrations/0206_rename_sticky_navbar_userpreference_nav_sticky_and_more.py @@ -0,0 +1,128 @@ +# Generated by Django 4.2.7 on 2024-01-01 18:44 +import django +from django.db import migrations, models +from django_scopes import scopes_disabled + +TANDOOR = 'TANDOOR' +TANDOOR_DARK = 'TANDOOR_DARK' +BOOTSTRAP = 'BOOTSTRAP' +DARKLY = 'DARKLY' +FLATLY = 'FLATLY' +SUPERHERO = 'SUPERHERO' + +PRIMARY = 'PRIMARY' +SECONDARY = 'SECONDARY' +SUCCESS = 'SUCCESS' +INFO = 'INFO' +WARNING = 'WARNING' +DANGER = 'DANGER' +LIGHT = 'LIGHT' +DARK = 'DARK' + + +# ['light', 'warning', 'info', 'success'] --> light (theming_tags L45) +def get_nav_bg_color(theme, nav_color): + if theme == TANDOOR: # primary not actually primary color but override existed before update, same for dark + return {PRIMARY: '#ddbf86', SECONDARY: '#b55e4f', SUCCESS: '#82aa8b', INFO: '#385f84', WARNING: '#eaaa21', DANGER: '#a7240e', LIGHT: '#cfd5cd', DARK: '#221e1e'}[nav_color] + if theme == TANDOOR_DARK: + return {PRIMARY: '#ddbf86', SECONDARY: '#b55e4f', SUCCESS: '#82aa8b', INFO: '#385f84', WARNING: '#eaaa21', DANGER: '#a7240e', LIGHT: '#cfd5cd', DARK: '#221e1e'}[nav_color] + if theme == BOOTSTRAP: + return {PRIMARY: '#007bff', SECONDARY: '#6c757d', SUCCESS: '#28a745', INFO: '#17a2b8', WARNING: '#ffc107', DANGER: '#dc3545', LIGHT: '#f8f9fa', DARK: '#343a40'}[nav_color] + if theme == DARKLY: + return {PRIMARY: '#375a7f', SECONDARY: '#444', SUCCESS: '#00bc8c', INFO: '#3498DB', WARNING: '#F39C12', DANGER: '#E74C3C', LIGHT: '#999', DARK: '#303030'}[nav_color] + if theme == FLATLY: + return {PRIMARY: '#2C3E50', SECONDARY: '#95a5a6', SUCCESS: '#18BC9C', INFO: '#3498DB', WARNING: '#F39C12', DANGER: '#E74C3C', LIGHT: '#ecf0f1', DARK: '#7b8a8b'}[nav_color] + if theme == SUPERHERO: + return {PRIMARY: '#DF691A', SECONDARY: '#4E5D6C', SUCCESS: '#5cb85c', INFO: '#5bc0de', WARNING: '#f0ad4e', DANGER: '#d9534f', LIGHT: '#abb6c2', DARK: '#4E5D6C'}[nav_color] + + +def get_nav_text_color(theme, nav_color): + if theme == TANDOOR: + return {PRIMARY: DARK, SECONDARY: DARK, SUCCESS: DARK, INFO: DARK, WARNING: DARK, DANGER: DARK, LIGHT: DARK, DARK: DARK}[nav_color] + if theme == TANDOOR_DARK: + return {PRIMARY: DARK, SECONDARY: DARK, SUCCESS: DARK, INFO: DARK, WARNING: DARK, DANGER: DARK, LIGHT: DARK, DARK: DARK}[nav_color] + if theme == BOOTSTRAP: + return {PRIMARY: DARK, SECONDARY: DARK, SUCCESS: DARK, INFO: DARK, WARNING: DARK, DANGER: DARK, LIGHT: DARK, DARK: DARK}[nav_color] + if theme == DARKLY: + return {PRIMARY: DARK, SECONDARY: DARK, SUCCESS: DARK, INFO: DARK, WARNING: DARK, DANGER: DARK, LIGHT: DARK, DARK: DARK}[nav_color] + if theme == FLATLY: + return {PRIMARY: DARK, SECONDARY: DARK, SUCCESS: LIGHT, INFO: LIGHT, WARNING: LIGHT, DANGER: DARK, LIGHT: LIGHT, DARK: DARK}[nav_color] + if theme == SUPERHERO: + return {PRIMARY: DARK, SECONDARY: DARK, SUCCESS: LIGHT, INFO: LIGHT, WARNING: LIGHT, DANGER: DARK, LIGHT: LIGHT, DARK: DARK}[nav_color] + + +def get_current_colors(apps, schema_editor): + with scopes_disabled(): + # in case any food had a non digit fdc ID before this migration, remove it + UserPreference = apps.get_model('cookbook', 'UserPreference') + + update_ups = [] + for up in UserPreference.objects.all(): + if up.theme != TANDOOR or up.nav_color != PRIMARY: + up.nav_bg_color = get_nav_bg_color(up.theme, up.nav_color) + up.nav_text_color = get_nav_text_color(up.theme, up.nav_color) + up.nav_show_logo = (up.theme == TANDOOR or up.theme == TANDOOR_DARK) + update_ups.append(up) + + UserPreference.objects.bulk_update(update_ups, ['nav_bg_color', 'nav_text_color', 'nav_show_logo']) + + +class Migration(migrations.Migration): + dependencies = [ + ('cookbook', '0205_alter_food_fdc_id_alter_propertytype_fdc_id'), + ] + + operations = [ + migrations.RenameField( + model_name='userpreference', + old_name='sticky_navbar', + new_name='nav_sticky', + ), + migrations.AddField( + model_name='userpreference', + name='nav_bg_color', + field=models.CharField(default='#ddbf86', max_length=8), + ), + migrations.AddField( + model_name='userpreference', + name='nav_text_color', + field=models.CharField(choices=[('LIGHT', 'Light'), ('DARK', 'Dark')], default='DARK', max_length=16), + ), + migrations.AddField( + model_name='userpreference', + name='nav_show_logo', + field=models.BooleanField(default=True), + ), + migrations.RunPython(get_current_colors), + migrations.RemoveField( + model_name='userpreference', + name='nav_color', + ), + migrations.AddField( + model_name='space', + name='nav_bg_color', + field=models.CharField(blank=True, default='', max_length=8), + ), + migrations.AddField( + model_name='space', + name='nav_logo', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='space_nav_logo', to='cookbook.userfile'), + ), + migrations.AddField( + model_name='space', + name='nav_text_color', + field=models.CharField(choices=[('BLANK', '-------'), ('LIGHT', 'Light'), ('DARK', 'Dark')], default='BLANK', max_length=16), + ), + migrations.AddField( + model_name='space', + name='space_theme', + field=models.CharField(choices=[('BLANK', '-------'), ('TANDOOR', 'Tandoor'), ('BOOTSTRAP', 'Bootstrap'), ('DARKLY', 'Darkly'), ('FLATLY', 'Flatly'), ('SUPERHERO', 'Superhero'), ('TANDOOR_DARK', 'Tandoor Dark (INCOMPLETE)')], + default='BLANK', + max_length=128), + ), + migrations.AddField( + model_name='space', + name='custom_space_theme', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='space_theme', to='cookbook.userfile'), + ), + ] diff --git a/cookbook/models.py b/cookbook/models.py index b7c3e3c8..a1162cff 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -251,8 +251,44 @@ class FoodInheritField(models.Model, PermissionModelMixin): class Space(ExportModelOperationsMixin('space'), models.Model): + # TODO remove redundant theming constants + # Themes + BLANK = 'BLANK' + TANDOOR = 'TANDOOR' + TANDOOR_DARK = 'TANDOOR_DARK' + BOOTSTRAP = 'BOOTSTRAP' + DARKLY = 'DARKLY' + FLATLY = 'FLATLY' + SUPERHERO = 'SUPERHERO' + + THEMES = ( + (BLANK, '-------'), + (TANDOOR, 'Tandoor'), + (BOOTSTRAP, 'Bootstrap'), + (DARKLY, 'Darkly'), + (FLATLY, 'Flatly'), + (SUPERHERO, 'Superhero'), + (TANDOOR_DARK, 'Tandoor Dark (INCOMPLETE)'), + ) + + LIGHT = 'LIGHT' + DARK = 'DARK' + + NAV_TEXT_COLORS = ( + (BLANK, '-------'), + (LIGHT, 'Light'), + (DARK, 'Dark') + ) + name = models.CharField(max_length=128, default='Default') + image = models.ForeignKey("UserFile", on_delete=models.SET_NULL, null=True, blank=True, related_name='space_image') + space_theme = models.CharField(choices=THEMES, max_length=128, default=TANDOOR) + custom_space_theme = models.ForeignKey("UserFile", on_delete=models.SET_NULL, null=True, blank=True, related_name='space_theme') + nav_logo = models.ForeignKey("UserFile", on_delete=models.SET_NULL, null=True, blank=True, related_name='space_nav_logo') + nav_bg_color = models.CharField(max_length=8, default='', blank=True, ) + nav_text_color = models.CharField(max_length=16, choices=NAV_TEXT_COLORS, default=DARK) + created_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True) created_at = models.DateTimeField(auto_now_add=True) message = models.CharField(max_length=512, default='', blank=True) @@ -338,22 +374,10 @@ class UserPreference(models.Model, PermissionModelMixin): ) # Nav colors - PRIMARY = 'PRIMARY' - SECONDARY = 'SECONDARY' - SUCCESS = 'SUCCESS' - INFO = 'INFO' - WARNING = 'WARNING' - DANGER = 'DANGER' LIGHT = 'LIGHT' DARK = 'DARK' - COLORS = ( - (PRIMARY, 'Primary'), - (SECONDARY, 'Secondary'), - (SUCCESS, 'Success'), - (INFO, 'Info'), - (WARNING, 'Warning'), - (DANGER, 'Danger'), + NAV_TEXT_COLORS = ( (LIGHT, 'Light'), (DARK, 'Dark') ) @@ -371,8 +395,13 @@ class UserPreference(models.Model, PermissionModelMixin): user = AutoOneToOneField(User, on_delete=models.CASCADE, primary_key=True) image = models.ForeignKey("UserFile", on_delete=models.SET_NULL, null=True, blank=True, related_name='user_image') + theme = models.CharField(choices=THEMES, max_length=128, default=TANDOOR) - nav_color = models.CharField(choices=COLORS, max_length=128, default=PRIMARY) + nav_bg_color = models.CharField(max_length=8, default='#ddbf86') + nav_text_color = models.CharField(max_length=16, choices=NAV_TEXT_COLORS, default=DARK) + nav_show_logo = models.BooleanField(default=True) + nav_sticky = models.BooleanField(default=STICKY_NAV_PREF_DEFAULT) + default_unit = models.CharField(max_length=32, default='g') use_fractions = models.BooleanField(default=FRACTION_PREF_DEFAULT) use_kj = models.BooleanField(default=KJ_PREF_DEFAULT) @@ -382,7 +411,6 @@ class UserPreference(models.Model, PermissionModelMixin): ingredient_decimals = models.IntegerField(default=2) comments = models.BooleanField(default=COMMENT_PREF_DEFAULT) shopping_auto_sync = models.IntegerField(default=5) - sticky_navbar = models.BooleanField(default=STICKY_NAV_PREF_DEFAULT) mealplan_autoadd_shopping = models.BooleanField(default=False) mealplan_autoexclude_onhand = models.BooleanField(default=True) mealplan_autoinclude_related = models.BooleanField(default=True) diff --git a/cookbook/serializer.py b/cookbook/serializer.py index ff4e2dfc..c1796351 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -212,7 +212,7 @@ class UserFileSerializer(serializers.ModelSerializer): Image.open(obj.file.file.file) return self.context['request'].build_absolute_uri(obj.file.url) except Exception: - traceback.print_exc() + # traceback.print_exc() return "" def check_file_limit(self, validated_data): @@ -260,7 +260,7 @@ class UserFileViewSerializer(serializers.ModelSerializer): Image.open(obj.file.file.file) return self.context['request'].build_absolute_uri(obj.file.url) except Exception: - traceback.print_exc() + # traceback.print_exc() return "" def create(self, validated_data): @@ -281,6 +281,8 @@ class SpaceSerializer(WritableNestedModelSerializer): file_size_mb = serializers.SerializerMethodField('get_file_size_mb') food_inherit = FoodInheritFieldSerializer(many=True) image = UserFileViewSerializer(required=False, many=False, allow_null=True) + nav_logo = UserFileViewSerializer(required=False, many=False, allow_null=True) + custom_space_theme = UserFileViewSerializer(required=False, many=False, allow_null=True) def get_user_count(self, obj): return UserSpace.objects.filter(space=obj).count() @@ -302,7 +304,7 @@ class SpaceSerializer(WritableNestedModelSerializer): fields = ( 'id', 'name', 'created_by', 'created_at', 'message', 'max_recipes', 'max_file_storage_mb', 'max_users', 'allow_sharing', 'demo', 'food_inherit', 'user_count', 'recipe_count', 'file_size_mb', - 'image', 'use_plural',) + 'image', 'nav_logo', 'space_theme', 'custom_space_theme', 'nav_bg_color', 'nav_text_color', 'use_plural',) read_only_fields = ( 'id', 'created_by', 'created_at', 'max_recipes', 'max_file_storage_mb', 'max_users', 'allow_sharing', 'demo',) @@ -372,8 +374,8 @@ class UserPreferenceSerializer(WritableNestedModelSerializer): class Meta: model = UserPreference fields = ( - 'user', 'image', 'theme', 'nav_color', 'default_unit', 'default_page', 'use_fractions', 'use_kj', - 'plan_share', 'sticky_navbar', + 'user', 'image', 'theme', 'nav_bg_color', 'nav_text_color', 'nav_show_logo', 'default_unit', 'default_page', 'use_fractions', 'use_kj', + 'plan_share', 'nav_sticky', 'ingredient_decimals', 'comments', 'shopping_auto_sync', 'mealplan_autoadd_shopping', 'food_inherit_default', 'default_delay', 'mealplan_autoinclude_related', 'mealplan_autoexclude_onhand', 'shopping_share', 'shopping_recent_days', diff --git a/cookbook/static/themes/tandoor.min.css b/cookbook/static/themes/tandoor.min.css index a7740b7f..5744a8d8 100644 --- a/cookbook/static/themes/tandoor.min.css +++ b/cookbook/static/themes/tandoor.min.css @@ -4457,28 +4457,28 @@ input[type=button].btn-block, input[type=reset].btn-block, input[type=submit].bt } .navbar-light .navbar-brand, .navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover { - color: rgba(46, 46, 46, .9) + color: rgba(0, 0, 0, .9) } .navbar-light .navbar-nav .nav-link { - color: rgba(46, 46, 46, .5) + color: rgba(0, 0, 0, .5) } .navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .nav-link:hover { - color: rgba(46, 46, 46, .7) + color: rgba(0, 0, 0, .7) } .navbar-light .navbar-nav .nav-link.disabled { - color: rgba(46, 46, 46, .3) + color: rgba(0, 0, 0, .3) } .navbar-light .navbar-nav .active > .nav-link, .navbar-light .navbar-nav .nav-link.active, .navbar-light .navbar-nav .nav-link.show, .navbar-light .navbar-nav .show > .nav-link { - color: rgba(46, 46, 46, .9) + color: rgba(0, 0, 0, .9) } .navbar-light .navbar-toggler { - color: rgba(46, 46, 46, .5); - border-color: rgba(46, 46, 46, .1) + color: rgba(0, 0, 0, .5); + border-color: rgba(0, 0, 0, .1) } .navbar-light .navbar-toggler-icon { @@ -4486,11 +4486,7 @@ input[type=button].btn-block, input[type=reset].btn-block, input[type=submit].bt } .navbar-light .navbar-text { - color: rgba(46, 46, 46, .5) -} - -.navbar-light .navbar-text a, .navbar-light .navbar-text a:focus, .navbar-light .navbar-text a:hover { - color: rgba(46, 46, 46, .9) + color: rgba(0, 0, 0, .5) } .navbar-dark .navbar-brand, .navbar-dark .navbar-brand:focus, .navbar-dark .navbar-brand:hover { @@ -4498,24 +4494,24 @@ input[type=button].btn-block, input[type=reset].btn-block, input[type=submit].bt } .navbar-dark .navbar-nav .nav-link { - color: hsla(0, 0%, 18%, .5) + color: rgba(255, 255, 255, .5) } .navbar-dark .navbar-nav .nav-link:focus, .navbar-dark .navbar-nav .nav-link:hover { - color: hsla(0, 0%, 18%, .75) + color: rgba(255, 255, 255, .75) } .navbar-dark .navbar-nav .nav-link.disabled { - color: hsla(0, 0%, 18%, .25) + color: rgba(255, 255, 255, .25) } .navbar-dark .navbar-nav .active > .nav-link, .navbar-dark .navbar-nav .nav-link.active, .navbar-dark .navbar-nav .nav-link.show, .navbar-dark .navbar-nav .show > .nav-link { - color: #2e2e2e + color: #FFF } .navbar-dark .navbar-toggler { - color: rgba(46, 46, 46, 0.5); - border-color: rgba(46, 46, 46, 0.5); + color: rgba(255, 255, 255, .5); + border-color: rgba(255, 255, 255, .1) } .navbar-dark .navbar-toggler-icon { @@ -4523,7 +4519,7 @@ input[type=button].btn-block, input[type=reset].btn-block, input[type=submit].bt } .navbar-dark .navbar-text { - color: hsla(0, 0%, 18%, .5) + color: rgba(255, 255, 255, .5) } .navbar-dark .navbar-text a, .navbar-dark .navbar-text a:focus, .navbar-dark .navbar-text a:hover { diff --git a/cookbook/static/themes/tandoor_dark.min.css b/cookbook/static/themes/tandoor_dark.min.css index 97c9cf6c..68a14037 100644 --- a/cookbook/static/themes/tandoor_dark.min.css +++ b/cookbook/static/themes/tandoor_dark.min.css @@ -4460,28 +4460,28 @@ input[type=button].btn-block, input[type=reset].btn-block, input[type=submit].bt } .navbar-light .navbar-brand, .navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover { - color: rgba(46, 46, 46, .9) + color: rgba(0, 0, 0, .9) } .navbar-light .navbar-nav .nav-link { - color: rgba(46, 46, 46, .5) + color: rgba(0, 0, 0, .5) } .navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .nav-link:hover { - color: rgba(46, 46, 46, .7) + color: rgba(0, 0, 0, .7) } .navbar-light .navbar-nav .nav-link.disabled { - color: rgba(46, 46, 46, .3) + color: rgba(0, 0, 0, .3) } .navbar-light .navbar-nav .active > .nav-link, .navbar-light .navbar-nav .nav-link.active, .navbar-light .navbar-nav .nav-link.show, .navbar-light .navbar-nav .show > .nav-link { - color: rgba(46, 46, 46, .9) + color: rgba(0, 0, 0, .9) } .navbar-light .navbar-toggler { - color: rgba(46, 46, 46, .5); - border-color: rgba(46, 46, 46, .1) + color: rgba(0, 0, 0, .5); + border-color: rgba(0, 0, 0, .1) } .navbar-light .navbar-toggler-icon { @@ -4489,11 +4489,11 @@ input[type=button].btn-block, input[type=reset].btn-block, input[type=submit].bt } .navbar-light .navbar-text { - color: rgba(46, 46, 46, .5) + color: rgba(0, 0, 0, .5) } .navbar-light .navbar-text a, .navbar-light .navbar-text a:focus, .navbar-light .navbar-text a:hover { - color: rgba(46, 46, 46, .9) + color: rgba(0, 0, 0, .9) } .navbar-dark .navbar-brand, .navbar-dark .navbar-brand:focus, .navbar-dark .navbar-brand:hover { @@ -4501,24 +4501,24 @@ input[type=button].btn-block, input[type=reset].btn-block, input[type=submit].bt } .navbar-dark .navbar-nav .nav-link { - color: hsla(0, 0%, 5%, .5) + color: rgba(255, 255, 255, .5) } .navbar-dark .navbar-nav .nav-link:focus, .navbar-dark .navbar-nav .nav-link:hover { - color: hsla(0, 0%, 5%, .75) + color: rgba(255, 255, 255, .75) } .navbar-dark .navbar-nav .nav-link.disabled { - color: hsla(0, 0%, 5%, .25) + color: rgba(255, 255, 255, .25) } .navbar-dark .navbar-nav .active > .nav-link, .navbar-dark .navbar-nav .nav-link.active, .navbar-dark .navbar-nav .nav-link.show, .navbar-dark .navbar-nav .show > .nav-link { - color: #1E1E1E + color: #FFF } .navbar-dark .navbar-toggler { - color: rgba(46, 46, 46, 0.5); - border-color: rgba(46, 46, 46, 0.5); + color: rgba(255, 255, 255, .5); + border-color: rgba(255, 255, 255, .1) } .navbar-dark .navbar-toggler-icon { @@ -4526,7 +4526,7 @@ input[type=button].btn-block, input[type=reset].btn-block, input[type=submit].bt } .navbar-dark .navbar-text { - color: hsla(0, 0%, 18%, .5) + color: rgba(255, 255, 255, .5) } .navbar-dark .navbar-text a, .navbar-dark .navbar-text a:focus, .navbar-dark .navbar-text a:hover { diff --git a/cookbook/templates/base.html b/cookbook/templates/base.html index 21049230..db70ed89 100644 --- a/cookbook/templates/base.html +++ b/cookbook/templates/base.html @@ -33,6 +33,11 @@ + {% if request.user.is_authenticated and request.space.custom_space_theme %} + + {% endif %} + + @@ -74,12 +79,12 @@ -