diff --git a/.env.template b/.env.template index cbe0ed64..d3038270 100644 --- a/.env.template +++ b/.env.template @@ -19,6 +19,14 @@ POSTGRES_USER=djangodb POSTGRES_PASSWORD= POSTGRES_DB=djangodb +# the default value for the user preference 'fractions' (enable/disable fraction support) +# when unset: 0 (disabled) +FRACTION_PREF_DEFAULT=0 + +# the default value for the user preference 'comments' (enable/disable commenting system) +# when unset: 1 (true) +COMMENT_PREF_DEFAULT=1 + # Users can set a amount of time after which the shopping list is refreshed when they are in viewing mode # This is the minimum interval users can set. Setting this to low will allow users to refresh very frequently which # might cause high load on the server. (Technically they can obviously refresh as often as they want with their own scripts) @@ -36,14 +44,9 @@ SHOPPING_MIN_AUTOSYNC_INTERVAL=5 # when unset: 1 (true) - this is temporary until an appropriate amount of time has passed for everyone to migrate GUNICORN_MEDIA=0 - # allow authentication via reverse proxy (e.g. authelia), leave of if you dont know what you are doing # docs: https://github.com/vabene1111/recipes/tree/develop/docs/docker/nginx-proxy%20with%20proxy%20authentication # when unset: 0 (false) REVERSE_PROXY_AUTH=0 -# the default value for the user preference 'comments' (enable/disable commenting system) -# when unset: 1 (true) -COMMENT_PREF_DEFAULT=1 - diff --git a/cookbook/forms.py b/cookbook/forms.py index a53b5a5d..fd2b9d0d 100644 --- a/cookbook/forms.py +++ b/cookbook/forms.py @@ -31,11 +31,12 @@ class UserPreferenceForm(forms.ModelForm): class Meta: model = UserPreference - fields = ('default_unit', 'theme', 'nav_color', 'default_page', 'show_recent', 'search_style', 'plan_share', 'ingredient_decimals', 'shopping_auto_sync', 'comments') + fields = ('default_unit', 'use_fractions', 'theme', 'nav_color', 'default_page', 'show_recent', 'search_style', 'plan_share', 'ingredient_decimals', 'shopping_auto_sync', 'comments') 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)'), 'plan_share': _('Default user to share newly created meal plan entries with.'), 'show_recent': _('Show recently viewed recipes on search page.'), 'ingredient_decimals': _('Number of decimals to round ingredients.'), diff --git a/cookbook/migrations/0090_auto_20201214_1359.py b/cookbook/migrations/0090_auto_20201214_1359.py new file mode 100644 index 00000000..8ed1f1cf --- /dev/null +++ b/cookbook/migrations/0090_auto_20201214_1359.py @@ -0,0 +1,24 @@ +# Generated by Django 3.1.3 on 2020-12-14 12:59 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('cookbook', '0089_auto_20201117_2222'), + ] + + operations = [ + migrations.AddField( + model_name='userpreference', + name='use_fractions', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='invitelink', + name='valid_until', + field=models.DateField(default=datetime.date(2020, 12, 28)), + ), + ] diff --git a/cookbook/models.py b/cookbook/models.py index 2dc4689d..52e9a3e8 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -9,7 +9,7 @@ from django.utils.translation import gettext as _ from django.db import models from django_random_queryset import RandomManager -from recipes.settings import COMMENT_PREF_DEFAULT +from recipes.settings import COMMENT_PREF_DEFAULT, FRACTION_PREF_DEFAULT def get_user_name(self): @@ -69,6 +69,7 @@ class UserPreference(models.Model): theme = models.CharField(choices=THEMES, max_length=128, default=FLATLY) 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) default_page = models.CharField(choices=PAGES, max_length=64, default=SEARCH) search_style = models.CharField(choices=SEARCH_STYLE, max_length=64, default=LARGE) show_recent = models.BooleanField(default=True) diff --git a/cookbook/static/js/frac.js b/cookbook/static/js/frac.js new file mode 100644 index 00000000..40f21767 --- /dev/null +++ b/cookbook/static/js/frac.js @@ -0,0 +1,43 @@ +/* frac.js (C) 2012-present SheetJS -- http://sheetjs.com */ +/*https://developer.aliyun.com/mirror/npm/package/frac/v/0.3.0 Apache license*/ +var frac = function frac(x, D, mixed) { + var n1 = Math.floor(x), d1 = 1; + var n2 = n1+1, d2 = 1; + if(x !== n1) while(d1 <= D && d2 <= D) { + var m = (n1 + n2) / (d1 + d2); + if(x === m) { + if(d1 + d2 <= D) { d1+=d2; n1+=n2; d2=D+1; } + else if(d1 > d2) d2=D+1; + else d1=D+1; + break; + } + else if(x < m) { n2 = n1+n2; d2 = d1+d2; } + else { n1 = n1+n2; d1 = d1+d2; } + } + if(d1 > D) { d1 = d2; n1 = n2; } + if(!mixed) return [0, n1, d1]; + var q = Math.floor(n1/d1); + return [q, n1 - q*d1, d1]; +}; +frac.cont = function cont(x, D, mixed) { + var sgn = x < 0 ? -1 : 1; + var B = x * sgn; + var P_2 = 0, P_1 = 1, P = 0; + var Q_2 = 1, Q_1 = 0, Q = 0; + var A = Math.floor(B); + while(Q_1 < D) { + A = Math.floor(B); + P = A * P_1 + P_2; + Q = A * Q_1 + Q_2; + if((B - A) < 0.00000005) break; + B = 1 / (B - A); + P_2 = P_1; P_1 = P; + Q_2 = Q_1; Q_1 = Q; + } + if(Q > D) { if(Q_1 > D) { Q = Q_2; P = P_2; } else { Q = Q_1; P = P_1; } } + if(!mixed) return [0, sgn * P, Q]; + var q = Math.floor(sgn * P/Q); + return [q, sgn*P - q*Q, Q]; +}; +// eslint-disable-next-line no-undef +if(typeof module !== 'undefined' && typeof DO_NOT_EXPORT_FRAC === 'undefined') module.exports = frac; diff --git a/cookbook/templates/recipe_view.html b/cookbook/templates/recipe_view.html index 09a89694..27b3bfb7 100644 --- a/cookbook/templates/recipe_view.html +++ b/cookbook/templates/recipe_view.html @@ -12,6 +12,8 @@ {% include 'include/vue_base.html' %} + + @@ -150,7 +152,7 @@