diff --git a/cookbook/migrations/0182_userpreference_image.py b/cookbook/migrations/0182_userpreference_image.py
new file mode 100644
index 00000000..d9405e40
--- /dev/null
+++ b/cookbook/migrations/0182_userpreference_image.py
@@ -0,0 +1,19 @@
+# Generated by Django 4.0.6 on 2022-07-14 13:32
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('cookbook', '0181_space_image'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='userpreference',
+ name='image',
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='user_image', to='cookbook.userfile'),
+ ),
+ ]
diff --git a/cookbook/models.py b/cookbook/models.py
index 359fd29e..bcb7a604 100644
--- a/cookbook/models.py
+++ b/cookbook/models.py
@@ -358,22 +358,15 @@ 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, 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_color = models.CharField(choices=COLORS, max_length=128, default=PRIMARY)
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)
- default_page = models.CharField(
- choices=PAGES, max_length=64, default=SEARCH
- )
- plan_share = models.ManyToManyField(
- User, blank=True, related_name='plan_share_default'
- )
- shopping_share = models.ManyToManyField(
- User, blank=True, related_name='shopping_share'
- )
+ default_page = models.CharField(choices=PAGES, max_length=64, default=SEARCH)
+ plan_share = models.ManyToManyField(User, blank=True, related_name='plan_share_default')
+ shopping_share = models.ManyToManyField(User, blank=True, related_name='shopping_share')
ingredient_decimals = models.IntegerField(default=2)
comments = models.BooleanField(default=COMMENT_PREF_DEFAULT)
shopping_auto_sync = models.IntegerField(default=5)
diff --git a/cookbook/serializer.py b/cookbook/serializer.py
index 0de4d093..a752e79b 100644
--- a/cookbook/serializer.py
+++ b/cookbook/serializer.py
@@ -320,6 +320,7 @@ class UserPreferenceSerializer(WritableNestedModelSerializer):
plan_share = UserNameSerializer(many=True, allow_null=True, required=False)
shopping_share = UserNameSerializer(many=True, allow_null=True, required=False)
food_children_exist = serializers.SerializerMethodField('get_food_children_exist')
+ image = UserFileViewSerializer(required=False, allow_null=True, many=False)
def get_food_inherit_defaults(self, obj):
return FoodInheritFieldSerializer(obj.user.get_active_space().food_inherit.all(), many=True).data
@@ -338,8 +339,8 @@ class UserPreferenceSerializer(WritableNestedModelSerializer):
class Meta:
model = UserPreference
fields = (
- 'user', 'theme', 'nav_color', 'default_unit', 'default_page', 'use_fractions', 'use_kj',
- 'plan_share',
+ 'user', 'image', 'theme', 'nav_color', 'default_unit', 'default_page', 'use_fractions', 'use_kj',
+ 'plan_share', 'sticky_navbar',
'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/templates/user_settings.html b/cookbook/templates/user_settings.html
new file mode 100644
index 00000000..2ffb9b7a
--- /dev/null
+++ b/cookbook/templates/user_settings.html
@@ -0,0 +1,45 @@
+{% extends "base.html" %}
+{% load render_bundle from webpack_loader %}
+{% load static %}
+{% load i18n %}
+{% load l10n %}
+{% load custom_tags %}
+
+{% block title %}{% trans 'Settings' %}{% endblock %}
+
+
+{% block content %}
+
+
+
+
+
+
+
+{% endblock %}
+
+
+{% block script %}
+ {% if debug %}
+
+ {% else %}
+
+ {% endif %}
+
+
+
+ {% render_bundle 'settings_view' %}
+{% endblock %}
\ No newline at end of file
diff --git a/cookbook/urls.py b/cookbook/urls.py
index 3d4633a8..8f7f99d7 100644
--- a/cookbook/urls.py
+++ b/cookbook/urls.py
@@ -68,6 +68,7 @@ urlpatterns = [
path('plan/', views.meal_plan, name='view_plan'),
path('shopping/', lists.shopping_list, name='view_shopping'),
path('settings/', views.user_settings, name='view_settings'),
+ path('user-settings/', views.user_settings_new, name='view_user_settings'),
path('history/', views.history, name='view_history'),
path('supermarket/', views.supermarket, name='view_supermarket'),
path('ingredient-editor/', views.ingredient_editor, name='view_ingredient_editor'),
diff --git a/cookbook/views/views.py b/cookbook/views/views.py
index dad7bd29..4af0829a 100644
--- a/cookbook/views/views.py
+++ b/cookbook/views/views.py
@@ -182,6 +182,11 @@ def view_profile(request, user_id):
return render(request, 'profile.html', {})
+@group_required('guest')
+def user_settings_new(request):
+ return render(request, 'user_settings.html', {})
+
+
@group_required('user')
def ingredient_editor(request):
template_vars = {'food_id': -1, 'unit_id': -1}
diff --git a/vue/src/apps/SettingsView/SettingsView.vue b/vue/src/apps/SettingsView/SettingsView.vue
new file mode 100644
index 00000000..9fac1a2b
--- /dev/null
+++ b/vue/src/apps/SettingsView/SettingsView.vue
@@ -0,0 +1,66 @@
+
+
+
+
+ Cosmetic
+
+ Account
+
+ Search
+
+ Shopping
+
+ Meal Plan
+
+ API
+
+
+
+
+ Overview
+
+
+
+
+
+
+
+
diff --git a/vue/src/apps/SettingsView/main.js b/vue/src/apps/SettingsView/main.js
new file mode 100644
index 00000000..4f2d1dff
--- /dev/null
+++ b/vue/src/apps/SettingsView/main.js
@@ -0,0 +1,17 @@
+import Vue from 'vue'
+import App from './SettingsView.vue'
+import i18n from '@/i18n'
+
+Vue.config.productionTip = false
+
+// TODO move this and other default stuff to centralized JS file (verify nothing breaks)
+let publicPath = localStorage.STATIC_URL + 'vue/'
+if (process.env.NODE_ENV === 'development') {
+ publicPath = 'http://localhost:8080/'
+}
+export default __webpack_public_path__ = publicPath // eslint-disable-line
+
+new Vue({
+ i18n,
+ render: h => h(App),
+}).$mount('#app')
diff --git a/vue/src/components/Settings/CosmeticSettingsComponent.vue b/vue/src/components/Settings/CosmeticSettingsComponent.vue
new file mode 100644
index 00000000..3a23a326
--- /dev/null
+++ b/vue/src/components/Settings/CosmeticSettingsComponent.vue
@@ -0,0 +1,110 @@
+
+
+
+
+
+ {{ user_preferences.ingredient_decimals }}
+
+
+
+
+
+ Language
+
+ {{ l[0] }} ({{
+ l[1]
+ }})
+
+
+
+
+ Tandoor
+ Bootstrap
+ Darkly
+ Flatly
+ Superhero
+
+
+
+
+
+ Primary
+ Secondary
+ Success
+ Info
+ Warning
+ Danger
+ Light
+ Dark
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vue/src/utils/openapi/api.ts b/vue/src/utils/openapi/api.ts
index 62c7b3f8..c2b7f786 100644
--- a/vue/src/utils/openapi/api.ts
+++ b/vue/src/utils/openapi/api.ts
@@ -3110,6 +3110,43 @@ export interface Space {
* @memberof Space
*/
file_size_mb?: string;
+ /**
+ *
+ * @type {SpaceImage}
+ * @memberof Space
+ */
+ image?: SpaceImage;
+}
+/**
+ *
+ * @export
+ * @interface SpaceImage
+ */
+export interface SpaceImage {
+ /**
+ *
+ * @type {number}
+ * @memberof SpaceImage
+ */
+ id?: number;
+ /**
+ *
+ * @type {string}
+ * @memberof SpaceImage
+ */
+ name: string;
+ /**
+ *
+ * @type {string}
+ * @memberof SpaceImage
+ */
+ file_download?: string;
+ /**
+ *
+ * @type {string}
+ * @memberof SpaceImage
+ */
+ preview?: string;
}
/**
*
@@ -3528,6 +3565,12 @@ export interface UserPreference {
* @memberof UserPreference
*/
user: number;
+ /**
+ *
+ * @type {RecipeFile}
+ * @memberof UserPreference
+ */
+ image?: RecipeFile | null;
/**
*
* @type {string}
@@ -3570,6 +3613,12 @@ export interface UserPreference {
* @memberof UserPreference
*/
plan_share?: Array | null;
+ /**
+ *
+ * @type {boolean}
+ * @memberof UserPreference
+ */
+ sticky_navbar?: boolean;
/**
*
* @type {number}
diff --git a/vue/vue.config.js b/vue/vue.config.js
index 1b48c39a..13e06ce6 100644
--- a/vue/vue.config.js
+++ b/vue/vue.config.js
@@ -64,6 +64,10 @@ const pages = {
profile_view: {
entry: "./src/apps/ProfileView/main.js",
chunks: ["chunk-vendors"],
+ },
+ settings_view: {
+ entry: "./src/apps/SettingsView/main.js",
+ chunks: ["chunk-vendors"],
}
}