Merge branch 'develop' into HomeAssistantConnector
This commit is contained in:
commit
5f9d59317b
@ -11,8 +11,8 @@ msgstr ""
|
|||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
|
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
|
||||||
"PO-Revision-Date: 2023-07-31 14:19+0000\n"
|
"PO-Revision-Date: 2024-01-09 12:07+0000\n"
|
||||||
"Last-Translator: Mára Štěpánek <stepanekm7@gmail.com>\n"
|
"Last-Translator: Jan Kubošek <kuboja@outlook.cz>\n"
|
||||||
"Language-Team: Czech <http://translate.tandoor.dev/projects/tandoor/"
|
"Language-Team: Czech <http://translate.tandoor.dev/projects/tandoor/"
|
||||||
"recipes-backend/cs/>\n"
|
"recipes-backend/cs/>\n"
|
||||||
"Language: cs\n"
|
"Language: cs\n"
|
||||||
@ -190,7 +190,7 @@ msgid ""
|
|||||||
"Leave empty for dropbox and enter only base url for nextcloud "
|
"Leave empty for dropbox and enter only base url for nextcloud "
|
||||||
"(<code>/remote.php/webdav/</code> is added automatically)"
|
"(<code>/remote.php/webdav/</code> is added automatically)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Pro dropbox ponechejte nevyplňené pole. Pro nextcloud použijte pouze "
|
"Pro dropbox ponechejte nevyplněné pole. Pro nextcloud použijte pouze "
|
||||||
"základní url (<code>/remote.php/webdav/</code> bude přidán automaticky)."
|
"základní url (<code>/remote.php/webdav/</code> bude přidán automaticky)."
|
||||||
|
|
||||||
#: .\cookbook\forms.py:263
|
#: .\cookbook\forms.py:263
|
||||||
@ -529,7 +529,7 @@ msgstr "Dávková úprava receptu"
|
|||||||
|
|
||||||
#: .\cookbook\templates\batch\edit.html:20
|
#: .\cookbook\templates\batch\edit.html:20
|
||||||
msgid "Add the specified keywords to all recipes containing a word"
|
msgid "Add the specified keywords to all recipes containing a word"
|
||||||
msgstr "Přidat štítek ke všem receptům, které obsahují specifické slovo."
|
msgstr "Přidat štítek ke všem receptům, které obsahují specifické slovo"
|
||||||
|
|
||||||
#: .\cookbook\templates\batch\monitor.html:6 .\cookbook\views\edit.py:66
|
#: .\cookbook\templates\batch\monitor.html:6 .\cookbook\views\edit.py:66
|
||||||
msgid "Sync"
|
msgid "Sync"
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 4.2.7 on 2024-01-14 23:06
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('cookbook', '0207_space_logo_color_128_space_logo_color_144_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='space',
|
||||||
|
name='app_name',
|
||||||
|
field=models.CharField(blank=True, max_length=40, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='userpreference',
|
||||||
|
name='max_owned_spaces',
|
||||||
|
field=models.IntegerField(default=100),
|
||||||
|
),
|
||||||
|
]
|
@ -1,4 +1,4 @@
|
|||||||
# Generated by Django 4.2.7 on 2024-01-17 21:12
|
# Generated by Django 4.2.7 on 2024-01-17 21:49
|
||||||
|
|
||||||
import cookbook.models
|
import cookbook.models
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -11,7 +11,7 @@ class Migration(migrations.Migration):
|
|||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
('cookbook', '0207_space_logo_color_128_space_logo_color_144_and_more'),
|
('cookbook', '0208_space_app_name_userpreference_max_owned_spaces'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
@ -24,7 +24,7 @@ from PIL import Image
|
|||||||
from treebeard.mp_tree import MP_Node, MP_NodeManager
|
from treebeard.mp_tree import MP_Node, MP_NodeManager
|
||||||
|
|
||||||
from recipes.settings import (COMMENT_PREF_DEFAULT, FRACTION_PREF_DEFAULT, KJ_PREF_DEFAULT,
|
from recipes.settings import (COMMENT_PREF_DEFAULT, FRACTION_PREF_DEFAULT, KJ_PREF_DEFAULT,
|
||||||
SORT_TREE_BY_NAME, STICKY_NAV_PREF_DEFAULT)
|
SORT_TREE_BY_NAME, STICKY_NAV_PREF_DEFAULT, MAX_OWNED_SPACES_PREF_DEFAULT)
|
||||||
|
|
||||||
|
|
||||||
def get_user_display_name(self):
|
def get_user_display_name(self):
|
||||||
@ -288,7 +288,7 @@ class Space(ExportModelOperationsMixin('space'), models.Model):
|
|||||||
nav_logo = models.ForeignKey("UserFile", on_delete=models.SET_NULL, null=True, blank=True, related_name='space_nav_logo')
|
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_bg_color = models.CharField(max_length=8, default='', blank=True, )
|
||||||
nav_text_color = models.CharField(max_length=16, choices=NAV_TEXT_COLORS, default=BLANK)
|
nav_text_color = models.CharField(max_length=16, choices=NAV_TEXT_COLORS, default=BLANK)
|
||||||
|
app_name = models.CharField(max_length=40, null=True, blank=True, )
|
||||||
logo_color_32 = models.ForeignKey("UserFile", on_delete=models.SET_NULL, null=True, blank=True, related_name='space_logo_color_32')
|
logo_color_32 = models.ForeignKey("UserFile", on_delete=models.SET_NULL, null=True, blank=True, related_name='space_logo_color_32')
|
||||||
logo_color_128 = models.ForeignKey("UserFile", on_delete=models.SET_NULL, null=True, blank=True, related_name='space_logo_color_128')
|
logo_color_128 = models.ForeignKey("UserFile", on_delete=models.SET_NULL, null=True, blank=True, related_name='space_logo_color_128')
|
||||||
logo_color_144 = models.ForeignKey("UserFile", on_delete=models.SET_NULL, null=True, blank=True, related_name='space_logo_color_144')
|
logo_color_144 = models.ForeignKey("UserFile", on_delete=models.SET_NULL, null=True, blank=True, related_name='space_logo_color_144')
|
||||||
@ -435,7 +435,7 @@ class UserPreference(models.Model, PermissionModelMixin):
|
|||||||
nav_text_color = models.CharField(max_length=16, choices=NAV_TEXT_COLORS, default=DARK)
|
nav_text_color = models.CharField(max_length=16, choices=NAV_TEXT_COLORS, default=DARK)
|
||||||
nav_show_logo = models.BooleanField(default=True)
|
nav_show_logo = models.BooleanField(default=True)
|
||||||
nav_sticky = models.BooleanField(default=STICKY_NAV_PREF_DEFAULT)
|
nav_sticky = models.BooleanField(default=STICKY_NAV_PREF_DEFAULT)
|
||||||
|
max_owned_spaces = models.IntegerField(default=MAX_OWNED_SPACES_PREF_DEFAULT)
|
||||||
default_unit = models.CharField(max_length=32, default='g')
|
default_unit = models.CharField(max_length=32, default='g')
|
||||||
use_fractions = models.BooleanField(default=FRACTION_PREF_DEFAULT)
|
use_fractions = models.BooleanField(default=FRACTION_PREF_DEFAULT)
|
||||||
use_kj = models.BooleanField(default=KJ_PREF_DEFAULT)
|
use_kj = models.BooleanField(default=KJ_PREF_DEFAULT)
|
||||||
@ -460,6 +460,15 @@ class UserPreference(models.Model, PermissionModelMixin):
|
|||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
objects = ScopedManager(space='space')
|
objects = ScopedManager(space='space')
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if not self.pk:
|
||||||
|
self.max_owned_spaces = MAX_OWNED_SPACES_PREF_DEFAULT
|
||||||
|
self.comments = COMMENT_PREF_DEFAULT
|
||||||
|
self.nav_sticky = STICKY_NAV_PREF_DEFAULT
|
||||||
|
self.use_kj = KJ_PREF_DEFAULT
|
||||||
|
self.use_fractions = FRACTION_PREF_DEFAULT
|
||||||
|
|
||||||
|
return super().save(*args, **kwargs)
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.user)
|
return str(self.user)
|
||||||
|
|
||||||
|
@ -686,9 +686,8 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
|
|||||||
|
|
||||||
properties = validated_data.pop('properties', None)
|
properties = validated_data.pop('properties', None)
|
||||||
|
|
||||||
obj, created = Food.objects.get_or_create(
|
obj, created = Food.objects.get_or_create(name=name, plural_name=plural_name, space=space, properties_food_unit=properties_food_unit,
|
||||||
name=name, plural_name=plural_name, space=space, properties_food_unit=properties_food_unit,
|
defaults=validated_data)
|
||||||
defaults=validated_data)
|
|
||||||
|
|
||||||
if properties and len(properties) > 0:
|
if properties and len(properties) > 0:
|
||||||
for p in properties:
|
for p in properties:
|
||||||
@ -1276,9 +1275,8 @@ class InviteLinkSerializer(WritableNestedModelSerializer):
|
|||||||
|
|
||||||
if obj.email:
|
if obj.email:
|
||||||
try:
|
try:
|
||||||
if InviteLink.objects.filter(
|
if InviteLink.objects.filter(space=self.context['request'].space,
|
||||||
space=self.context['request'].space,
|
created_at__gte=datetime.now() - timedelta(hours=4)).count() < 20:
|
||||||
created_at__gte=datetime.now() - timedelta(hours=4)).count() < 20:
|
|
||||||
message = _('Hello') + '!\n\n' + _('You have been invited by ') + escape(
|
message = _('Hello') + '!\n\n' + _('You have been invited by ') + escape(
|
||||||
self.context['request'].user.get_user_display_name())
|
self.context['request'].user.get_user_display_name())
|
||||||
message += _(' to join their Tandoor Recipes space ') + escape(
|
message += _(' to join their Tandoor Recipes space ') + escape(
|
||||||
@ -1433,15 +1431,12 @@ class RecipeExportSerializer(WritableNestedModelSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class RecipeShoppingUpdateSerializer(serializers.ModelSerializer):
|
class RecipeShoppingUpdateSerializer(serializers.ModelSerializer):
|
||||||
list_recipe = serializers.IntegerField(
|
list_recipe = serializers.IntegerField(write_only=True, allow_null=True, required=False,
|
||||||
write_only=True, allow_null=True, required=False,
|
help_text=_("Existing shopping list to update"))
|
||||||
help_text=_("Existing shopping list to update"))
|
ingredients = serializers.IntegerField(write_only=True, allow_null=True, required=False, help_text=_(
|
||||||
ingredients = serializers.IntegerField(
|
"List of ingredient IDs from the recipe to add, if not provided all ingredients will be added."))
|
||||||
write_only=True, allow_null=True, required=False, help_text=_(
|
servings = serializers.IntegerField(default=1, write_only=True, allow_null=True, required=False, help_text=_(
|
||||||
"List of ingredient IDs from the recipe to add, if not provided all ingredients will be added."))
|
"Providing a list_recipe ID and servings of 0 will delete that shopping list."))
|
||||||
servings = serializers.IntegerField(
|
|
||||||
default=1, write_only=True, allow_null=True, required=False, help_text=_(
|
|
||||||
"Providing a list_recipe ID and servings of 0 will delete that shopping list."))
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Recipe
|
model = Recipe
|
||||||
@ -1449,15 +1444,12 @@ class RecipeShoppingUpdateSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class FoodShoppingUpdateSerializer(serializers.ModelSerializer):
|
class FoodShoppingUpdateSerializer(serializers.ModelSerializer):
|
||||||
amount = serializers.IntegerField(
|
amount = serializers.IntegerField(write_only=True, allow_null=True, required=False,
|
||||||
write_only=True, allow_null=True, required=False,
|
help_text=_("Amount of food to add to the shopping list"))
|
||||||
help_text=_("Amount of food to add to the shopping list"))
|
unit = serializers.IntegerField(write_only=True, allow_null=True, required=False,
|
||||||
unit = serializers.IntegerField(
|
help_text=_("ID of unit to use for the shopping list"))
|
||||||
write_only=True, allow_null=True, required=False,
|
delete = serializers.ChoiceField(choices=['true'], write_only=True, allow_null=True, allow_blank=True,
|
||||||
help_text=_("ID of unit to use for the shopping list"))
|
help_text=_("When set to true will delete all food from active shopping lists."))
|
||||||
delete = serializers.ChoiceField(
|
|
||||||
choices=['true'], write_only=True, allow_null=True, allow_blank=True,
|
|
||||||
help_text=_("When set to true will delete all food from active shopping lists."))
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Recipe
|
model = Recipe
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% load crispy_forms_tags %}
|
|
||||||
{% load i18n %}
|
|
||||||
{% load django_tables2 %}
|
|
||||||
|
|
||||||
{% block title %}{% trans 'List' %}{% endblock %}
|
|
||||||
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
{% if request.resolver_match.url_name in 'list_storage,list_recipe_import,list_sync_log' %}
|
|
||||||
<nav aria-label="breadcrumb">
|
|
||||||
<ol class="breadcrumb">
|
|
||||||
<li class="breadcrumb-item"><a href="{% url 'data_sync' %}">{% trans 'External Recipes' %}</a></li>
|
|
||||||
<li class="breadcrumb-item active" aria-current="page">{{ title }}</li>
|
|
||||||
</ol>
|
|
||||||
</nav>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="table-container">
|
|
||||||
<span class="col col-md-9">
|
|
||||||
<h3 style="margin-bottom: 2vh">{{ title }} {% trans 'List' %}</h3>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
{% if filter %}
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
<form action="." method="get">
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ filter.form|crispy }}
|
|
||||||
<button type="submit" class="btn btn-success">{% trans 'Filter' %}</button>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if import_btn %}
|
|
||||||
<a href="{% url 'data_batch_import' %}" class="btn btn-warning">{% trans 'Import all' %}</a>
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% for table in tables %}
|
|
||||||
<span class="col col-md-9">
|
|
||||||
<h3 style="margin-bottom: 2vh">{{ table.attrs.table_name }} {% trans 'List' %}
|
|
||||||
{% if table.attrs.create_url %}
|
|
||||||
<a href="{% url table.attrs.create_url %}"> <i class="fas fa-plus-circle"></i> </a>
|
|
||||||
{% endif %}
|
|
||||||
</h3>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
{% render_table table %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock content %}
|
|
@ -10,17 +10,17 @@ register = template.Library()
|
|||||||
|
|
||||||
@register.simple_tag
|
@register.simple_tag
|
||||||
def theme_values(request):
|
def theme_values(request):
|
||||||
|
return get_theming_values(request)
|
||||||
|
|
||||||
|
|
||||||
|
def get_theming_values(request):
|
||||||
space = None
|
space = None
|
||||||
if space in request and request.space:
|
if getattr(request,'space',None):
|
||||||
space = request.space
|
space = request.space
|
||||||
if not request.user.is_authenticated and UNAUTHENTICATED_THEME_FROM_SPACE > 0:
|
if not request.user.is_authenticated and UNAUTHENTICATED_THEME_FROM_SPACE > 0:
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
space = Space.objects.filter(id=UNAUTHENTICATED_THEME_FROM_SPACE).first()
|
space = Space.objects.filter(id=UNAUTHENTICATED_THEME_FROM_SPACE).first()
|
||||||
|
|
||||||
return get_theming_values(space, request.user)
|
|
||||||
|
|
||||||
|
|
||||||
def get_theming_values(space, user):
|
|
||||||
themes = {
|
themes = {
|
||||||
UserPreference.BOOTSTRAP: 'themes/bootstrap.min.css',
|
UserPreference.BOOTSTRAP: 'themes/bootstrap.min.css',
|
||||||
UserPreference.FLATLY: 'themes/flatly.min.css',
|
UserPreference.FLATLY: 'themes/flatly.min.css',
|
||||||
@ -46,31 +46,34 @@ def get_theming_values(space, user):
|
|||||||
'nav_bg_color': '#ddbf86',
|
'nav_bg_color': '#ddbf86',
|
||||||
'nav_text_class': 'navbar-light',
|
'nav_text_class': 'navbar-light',
|
||||||
'sticky_nav': 'position: sticky; top: 0; left: 0; z-index: 1000;',
|
'sticky_nav': 'position: sticky; top: 0; left: 0; z-index: 1000;',
|
||||||
|
'app_name': 'Tandoor Recipes',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if request.user.is_authenticated:
|
||||||
if user.is_authenticated:
|
if request.user.userpreference.theme in themes:
|
||||||
if user.userpreference.theme in themes:
|
tv['theme'] = static(themes[request.user.userpreference.theme])
|
||||||
tv['theme'] = static(themes[user.userpreference.theme])
|
if request.user.userpreference.nav_bg_color:
|
||||||
if user.userpreference.nav_bg_color:
|
tv['nav_bg_color'] = request.user.userpreference.nav_bg_color
|
||||||
tv['nav_bg_color'] = user.userpreference.nav_bg_color
|
if request.user.userpreference.nav_text_color and request.user.userpreference.nav_text_color in nav_text_type_mapping:
|
||||||
if user.userpreference.nav_text_color and user.userpreference.nav_text_color in nav_text_type_mapping:
|
tv['nav_text_class'] = nav_text_type_mapping[request.user.userpreference.nav_text_color]
|
||||||
tv['nav_text_class'] = nav_text_type_mapping[user.userpreference.nav_text_color]
|
if not request.user.userpreference.nav_sticky:
|
||||||
if not user.userpreference.nav_sticky:
|
|
||||||
tv['sticky_nav'] = ''
|
tv['sticky_nav'] = ''
|
||||||
|
|
||||||
if space:
|
if space:
|
||||||
for logo in list(tv.keys()):
|
for logo in list(tv.keys()):
|
||||||
if logo.startswith('logo_color_') and getattr(space, logo, None):
|
if logo.startswith('logo_color_') and getattr(space, logo, None):
|
||||||
tv[logo] = getattr(space, logo).file.url
|
tv[logo] = getattr(space, logo).file.url
|
||||||
if space.custom_space_theme:
|
|
||||||
tv['custom_theme'] = space.custom_space_theme.file.url
|
if space.custom_space_theme:
|
||||||
if space.space_theme in themes:
|
tv['custom_theme'] = space.custom_space_theme.file.url
|
||||||
tv['theme'] = static(themes[space.space_theme])
|
if space.space_theme in themes:
|
||||||
if space.nav_logo:
|
tv['theme'] = static(themes[space.space_theme])
|
||||||
tv['nav_logo'] = space.nav_logo.file.url
|
if space.nav_logo:
|
||||||
if space.nav_bg_color:
|
tv['nav_logo'] = space.nav_logo.file.url
|
||||||
tv['nav_bg_color'] = space.nav_bg_color
|
if space.nav_bg_color:
|
||||||
if space.nav_text_color and space.nav_text_color in nav_text_type_mapping:
|
tv['nav_bg_color'] = space.nav_bg_color
|
||||||
tv['nav_text_class'] = nav_text_type_mapping[space.nav_text_color]
|
if space.nav_text_color and space.nav_text_color in nav_text_type_mapping:
|
||||||
|
tv['nav_text_class'] = nav_text_type_mapping[space.nav_text_color]
|
||||||
|
if space.app_name:
|
||||||
|
tv['app_name'] = space.app_name
|
||||||
return tv
|
return tv
|
||||||
|
@ -1,36 +1,68 @@
|
|||||||
from django.contrib import auth
|
from django.contrib import auth
|
||||||
from django.templatetags.static import static
|
from django.templatetags.static import static
|
||||||
|
from django.test import RequestFactory
|
||||||
|
from django_scopes import scopes_disabled
|
||||||
|
|
||||||
from cookbook.models import Space, UserPreference, UserFile
|
from cookbook.models import Space, UserPreference, UserFile
|
||||||
from cookbook.templatetags.theming_tags import theme_values, get_theming_values
|
from cookbook.templatetags.theming_tags import theme_values, get_theming_values
|
||||||
|
|
||||||
|
|
||||||
def test_theming_function(space_1, u1_s1):
|
def test_theming_function(space_1, u1_s1):
|
||||||
user = auth.get_user(u1_s1)
|
|
||||||
# uf = UserFile.objects.create(name='test', space=space_1, created_by=user) #TODO add file tests
|
# uf = UserFile.objects.create(name='test', space=space_1, created_by=user) #TODO add file tests
|
||||||
|
user = auth.get_user(u1_s1)
|
||||||
|
request = RequestFactory()
|
||||||
|
request.user = auth.get_user(u1_s1)
|
||||||
|
request.space = space_1
|
||||||
|
|
||||||
assert get_theming_values(space_1, user)['theme'] == static('themes/tandoor.min.css')
|
# defaults apply without setting anything (user preference is automatically created with these defaults)
|
||||||
assert get_theming_values(space_1, user)['nav_bg_color'] == '#ddbf86'
|
assert get_theming_values(request)['theme'] == static('themes/tandoor.min.css')
|
||||||
assert get_theming_values(space_1, user)['nav_text_class'] == 'navbar-light'
|
assert get_theming_values(request)['nav_bg_color'] == '#ddbf86'
|
||||||
assert get_theming_values(space_1, user)['nav_logo'] == static('assets/brand_logo.png')
|
assert get_theming_values(request)['nav_text_class'] == 'navbar-light'
|
||||||
assert get_theming_values(space_1, user)['sticky_nav'] == 'position: sticky; top: 0; left: 0; z-index: 1000;'
|
assert get_theming_values(request)['nav_logo'] == static('assets/brand_logo.png')
|
||||||
|
assert get_theming_values(request)['sticky_nav'] == 'position: sticky; top: 0; left: 0; z-index: 1000;'
|
||||||
|
assert get_theming_values(request)['app_name'] == 'Tandoor Recipes'
|
||||||
|
|
||||||
user.userpreference.theme = UserPreference.TANDOOR_DARK
|
with scopes_disabled():
|
||||||
user.userpreference.nav_bg_color = '#ffffff'
|
up = UserPreference.objects.filter(user=request.user).first()
|
||||||
user.userpreference.nav_text_color = UserPreference.LIGHT
|
up.theme = UserPreference.TANDOOR_DARK
|
||||||
user.userpreference.nav_sticky = False
|
up.nav_bg_color = '#ffffff'
|
||||||
user.userpreference.save()
|
up.nav_text_color = UserPreference.LIGHT
|
||||||
|
up.nav_sticky = False
|
||||||
|
up.save()
|
||||||
|
|
||||||
assert get_theming_values(space_1, user)['theme'] == static('themes/tandoor_dark.min.css')
|
request = RequestFactory()
|
||||||
assert get_theming_values(space_1, user)['nav_bg_color'] == '#ffffff'
|
request.user = auth.get_user(u1_s1)
|
||||||
assert get_theming_values(space_1, user)['nav_text_class'] == 'navbar-dark'
|
request.space = space_1
|
||||||
assert get_theming_values(space_1, user)['sticky_nav'] == ''
|
|
||||||
|
# user values apply if only those are present
|
||||||
|
assert get_theming_values(request)['theme'] == static('themes/tandoor_dark.min.css')
|
||||||
|
assert get_theming_values(request)['nav_bg_color'] == '#ffffff'
|
||||||
|
assert get_theming_values(request)['nav_text_class'] == 'navbar-dark'
|
||||||
|
assert get_theming_values(request)['sticky_nav'] == ''
|
||||||
|
assert get_theming_values(request)['app_name'] == 'Tandoor Recipes'
|
||||||
|
|
||||||
space_1.space_theme = Space.BOOTSTRAP
|
space_1.space_theme = Space.BOOTSTRAP
|
||||||
space_1.nav_bg_color = '#000000'
|
space_1.nav_bg_color = '#000000'
|
||||||
space_1.nav_text_color = UserPreference.DARK
|
space_1.nav_text_color = UserPreference.DARK
|
||||||
|
space_1.app_name = 'test_app_name'
|
||||||
space_1.save()
|
space_1.save()
|
||||||
|
|
||||||
assert get_theming_values(space_1, user)['theme'] == static('themes/bootstrap.min.css')
|
request = RequestFactory()
|
||||||
assert get_theming_values(space_1, user)['nav_bg_color'] == '#000000'
|
request.user = auth.get_user(u1_s1)
|
||||||
assert get_theming_values(space_1, user)['nav_text_class'] == 'navbar-light'
|
request.space = space_1
|
||||||
|
|
||||||
|
# space settings apply when set
|
||||||
|
assert get_theming_values(request)['theme'] == static('themes/bootstrap.min.css')
|
||||||
|
assert get_theming_values(request)['nav_bg_color'] == '#000000'
|
||||||
|
assert get_theming_values(request)['nav_text_class'] == 'navbar-light'
|
||||||
|
assert get_theming_values(request)['app_name'] == 'test_app_name'
|
||||||
|
|
||||||
|
user.userspace_set.all().delete()
|
||||||
|
request = RequestFactory()
|
||||||
|
request.user = auth.get_user(u1_s1)
|
||||||
|
|
||||||
|
# default user settings should apply when user has no space
|
||||||
|
assert get_theming_values(request)['nav_bg_color'] == '#ffffff'
|
||||||
|
assert get_theming_values(request)['nav_text_class'] == 'navbar-dark'
|
||||||
|
assert get_theming_values(request)['nav_logo'] == static('assets/brand_logo.png')
|
||||||
|
@ -51,7 +51,7 @@ router.register(r'shopping-list-recipe', api.ShoppingListRecipeViewSet)
|
|||||||
router.register(r'space', api.SpaceViewSet)
|
router.register(r'space', api.SpaceViewSet)
|
||||||
router.register(r'step', api.StepViewSet)
|
router.register(r'step', api.StepViewSet)
|
||||||
router.register(r'storage', api.StorageViewSet)
|
router.register(r'storage', api.StorageViewSet)
|
||||||
router.register(r'home-assistant-config', api.ConnectorConfigConfigViewSet)
|
router.register(r'connector-config', api.ConnectorConfigConfigViewSet)
|
||||||
router.register(r'supermarket', api.SupermarketViewSet)
|
router.register(r'supermarket', api.SupermarketViewSet)
|
||||||
router.register(r'supermarket-category', api.SupermarketCategoryViewSet)
|
router.register(r'supermarket-category', api.SupermarketCategoryViewSet)
|
||||||
router.register(r'supermarket-category-relation', api.SupermarketCategoryRelationViewSet)
|
router.register(r'supermarket-category-relation', api.SupermarketCategoryRelationViewSet)
|
||||||
|
@ -87,12 +87,11 @@ def invite_link(request):
|
|||||||
InviteLink.objects.filter(valid_until__gte=datetime.today(), used_by=None, space=request.space).all())
|
InviteLink.objects.filter(valid_until__gte=datetime.today(), used_by=None, space=request.space).all())
|
||||||
RequestConfig(request, paginate={'per_page': 25}).configure(table)
|
RequestConfig(request, paginate={'per_page': 25}).configure(table)
|
||||||
|
|
||||||
return render(
|
return render(request, 'generic/list_template.html', {
|
||||||
request, 'generic/list_template.html', {
|
'title': _("Invite Links"),
|
||||||
'title': _("Invite Links"),
|
'table': table,
|
||||||
'table': table,
|
'create_url': 'new_invite_link'
|
||||||
'create_url': 'new_invite_link'
|
})
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
@group_required('user')
|
@group_required('user')
|
||||||
@ -212,7 +211,7 @@ def custom_filter(request):
|
|||||||
def user_file(request):
|
def user_file(request):
|
||||||
try:
|
try:
|
||||||
current_file_size_mb = UserFile.objects.filter(space=request.space).aggregate(Sum('file_size_kb'))[
|
current_file_size_mb = UserFile.objects.filter(space=request.space).aggregate(Sum('file_size_kb'))[
|
||||||
'file_size_kb__sum'] / 1000
|
'file_size_kb__sum'] / 1000
|
||||||
except TypeError:
|
except TypeError:
|
||||||
current_file_size_mb = 0
|
current_file_size_mb = 0
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ from cookbook.helper.permission_helper import (group_required, has_group_permiss
|
|||||||
from cookbook.models import (Comment, CookLog, InviteLink, SearchFields, SearchPreference,
|
from cookbook.models import (Comment, CookLog, InviteLink, SearchFields, SearchPreference,
|
||||||
ShareLink, Space, UserSpace, ViewLog)
|
ShareLink, Space, UserSpace, ViewLog)
|
||||||
from cookbook.tables import CookLogTable, ViewLogTable
|
from cookbook.tables import CookLogTable, ViewLogTable
|
||||||
|
from cookbook.templatetags.theming_tags import get_theming_values
|
||||||
from cookbook.version_info import VERSION_INFO
|
from cookbook.version_info import VERSION_INFO
|
||||||
from recipes.settings import PLUGINS, BASE_DIR
|
from recipes.settings import PLUGINS, BASE_DIR
|
||||||
|
|
||||||
@ -78,6 +79,11 @@ def space_overview(request):
|
|||||||
messages.add_message(request, messages.WARNING, _('This feature is not available in the demo version!'))
|
messages.add_message(request, messages.WARNING, _('This feature is not available in the demo version!'))
|
||||||
else:
|
else:
|
||||||
if create_form.is_valid():
|
if create_form.is_valid():
|
||||||
|
if Space.objects.filter(created_by=request.user).count() >= request.user.userpreference.max_owned_spaces:
|
||||||
|
messages.add_message(request, messages.ERROR,
|
||||||
|
_('You have the reached the maximum amount of spaces that can be owned by you.') + f' ({request.user.userpreference.max_owned_spaces})')
|
||||||
|
return HttpResponseRedirect(reverse('view_space_overview'))
|
||||||
|
|
||||||
created_space = Space.objects.create(
|
created_space = Space.objects.create(
|
||||||
name=create_form.cleaned_data['name'],
|
name=create_form.cleaned_data['name'],
|
||||||
created_by=request.user,
|
created_by=request.user,
|
||||||
@ -481,29 +487,24 @@ def report_share_abuse(request, token):
|
|||||||
|
|
||||||
|
|
||||||
def web_manifest(request):
|
def web_manifest(request):
|
||||||
|
theme_values = get_theming_values(request)
|
||||||
|
|
||||||
icons = [
|
icons = [
|
||||||
{"src": static("/assets/logo_color.svg"), "sizes": "any"},
|
{"src": theme_values['logo_color_svg'], "sizes": "any"},
|
||||||
{"src": static("/assets/logo_color144.png"), "type": "image/png", "sizes": "144x144"},
|
{"src": theme_values['logo_color_144'], "type": "image/png", "sizes": "144x144"},
|
||||||
{"src": static("/assets/logo_color512.png"), "type": "image/png", "sizes": "512x512"}
|
{"src": theme_values['logo_color_512'], "type": "image/png", "sizes": "512x512"}
|
||||||
]
|
]
|
||||||
|
|
||||||
if request.user.is_authenticated and getattr(request.space, 'logo_color_svg') and getattr(request.space, 'logo_color_144') and getattr(request.space, 'logo_color_512'):
|
|
||||||
icons = [
|
|
||||||
{"src": request.space.logo_color_svg.file.url, "sizes": "any"},
|
|
||||||
{"src": request.space.logo_color_144.file.url, "type": "image/png", "sizes": "144x144"},
|
|
||||||
{"src": request.space.logo_color_512.file.url, "type": "image/png", "sizes": "512x512"}
|
|
||||||
]
|
|
||||||
|
|
||||||
manifest_info = {
|
manifest_info = {
|
||||||
"name": "Tandoor Recipes",
|
"name": theme_values['app_name'],
|
||||||
"short_name": "Tandoor",
|
"short_name": theme_values['app_name'],
|
||||||
"description": _("Manage recipes, shopping list, meal plans and more."),
|
"description": _("Manage recipes, shopping list, meal plans and more."),
|
||||||
"icons": icons,
|
"icons": icons,
|
||||||
"start_url": "./search",
|
"start_url": "./search",
|
||||||
"background_color": "#ffcb76",
|
"background_color": theme_values['nav_bg_color'],
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"scope": ".",
|
"scope": ".",
|
||||||
"theme_color": "#ffcb76",
|
"theme_color": theme_values['nav_bg_color'],
|
||||||
"shortcuts": [
|
"shortcuts": [
|
||||||
{
|
{
|
||||||
"name": _("Plan"),
|
"name": _("Plan"),
|
||||||
|
@ -524,6 +524,18 @@ The default value for the user preference 'sticky navigation' (always show navba
|
|||||||
STICKY_NAV_PREF_DEFAULT=1
|
STICKY_NAV_PREF_DEFAULT=1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Max owned spaces
|
||||||
|
|
||||||
|
> default `100` - options: `0-X`
|
||||||
|
|
||||||
|
The default for the number of spaces a user can own. By setting to 0 space creation for users will be disabled.
|
||||||
|
Superusers can always bypass this limit.
|
||||||
|
|
||||||
|
```
|
||||||
|
MAX_OWNED_SPACES_PREF_DEFAULT=100
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### Cosmetic / Preferences
|
### Cosmetic / Preferences
|
||||||
|
|
||||||
#### Timezone
|
#### Timezone
|
||||||
|
@ -57,7 +57,8 @@ COMMENT_PREF_DEFAULT = bool(int(os.getenv('COMMENT_PREF_DEFAULT', True)))
|
|||||||
FRACTION_PREF_DEFAULT = bool(int(os.getenv('FRACTION_PREF_DEFAULT', False)))
|
FRACTION_PREF_DEFAULT = bool(int(os.getenv('FRACTION_PREF_DEFAULT', False)))
|
||||||
KJ_PREF_DEFAULT = bool(int(os.getenv('KJ_PREF_DEFAULT', False)))
|
KJ_PREF_DEFAULT = bool(int(os.getenv('KJ_PREF_DEFAULT', False)))
|
||||||
STICKY_NAV_PREF_DEFAULT = bool(int(os.getenv('STICKY_NAV_PREF_DEFAULT', True)))
|
STICKY_NAV_PREF_DEFAULT = bool(int(os.getenv('STICKY_NAV_PREF_DEFAULT', True)))
|
||||||
UNAUTHENTICATED_THEME_FROM_SPACE = 2 #int(os.getenv('UNAUTHENTICATED_THEME_FROM_SPACE', 0))
|
MAX_OWNED_SPACES_PREF_DEFAULT = int(os.getenv('MAX_OWNED_SPACES_PREF_DEFAULT', 100))
|
||||||
|
UNAUTHENTICATED_THEME_FROM_SPACE = int(os.getenv('UNAUTHENTICATED_THEME_FROM_SPACE', 0))
|
||||||
|
|
||||||
# minimum interval that users can set for automatic sync of shopping lists
|
# minimum interval that users can set for automatic sync of shopping lists
|
||||||
SHOPPING_MIN_AUTOSYNC_INTERVAL = int(
|
SHOPPING_MIN_AUTOSYNC_INTERVAL = int(
|
||||||
|
@ -16,14 +16,14 @@
|
|||||||
"file_upload_disabled": "Nahrávání souborů není povoleno pro Váš prostor.",
|
"file_upload_disabled": "Nahrávání souborů není povoleno pro Váš prostor.",
|
||||||
"warning_space_delete": "Můžete smazat váš prostor včetně všech receptů, nákupních seznamů, jídelníčků a všeho ostatního, co jste vytvořili. Tuto akci nemůžete vzít zpět! Jste si jisti, že chcete pokračovat?",
|
"warning_space_delete": "Můžete smazat váš prostor včetně všech receptů, nákupních seznamů, jídelníčků a všeho ostatního, co jste vytvořili. Tuto akci nemůžete vzít zpět! Jste si jisti, že chcete pokračovat?",
|
||||||
"food_inherit_info": "Pole potravin, která budou standardně zděděna.",
|
"food_inherit_info": "Pole potravin, která budou standardně zděděna.",
|
||||||
"step_time_minutes": "Nastavte čas v minutách",
|
"step_time_minutes": "Délka kroku v minutách",
|
||||||
"confirm_delete": "Jste si jisti že chcete odstranit tento {objekt}?",
|
"confirm_delete": "Jste si jisti že chcete odstranit tento {objekt}?",
|
||||||
"import_running": "Probíhá import, čekejte prosím!",
|
"import_running": "Probíhá import, čekejte prosím!",
|
||||||
"all_fields_optional": "Všechna pole jsou nepviná a mohou být ponechána prázdná.",
|
"all_fields_optional": "Všechna pole jsou nepviná a mohou být ponechána prázdná.",
|
||||||
"convert_internal": "Převést na interní recept",
|
"convert_internal": "Převést na interní recept",
|
||||||
"show_only_internal": "Zobrazit pouze interní recepty",
|
"show_only_internal": "Zobrazit pouze interní recepty",
|
||||||
"show_split_screen": "Rozdělené zobrazení",
|
"show_split_screen": "Rozdělené zobrazení",
|
||||||
"Log_Recipe_Cooking": "",
|
"Log_Recipe_Cooking": "Záznam vaření receptu",
|
||||||
"External_Recipe_Image": "Externí obrázek receptu",
|
"External_Recipe_Image": "Externí obrázek receptu",
|
||||||
"Add_to_Shopping": "Přidat k nákupu",
|
"Add_to_Shopping": "Přidat k nákupu",
|
||||||
"Add_to_Plan": "Přidat do jídelníčku",
|
"Add_to_Plan": "Přidat do jídelníčku",
|
||||||
@ -35,8 +35,8 @@
|
|||||||
"Hide_as_header": "Skryj jako nadpis",
|
"Hide_as_header": "Skryj jako nadpis",
|
||||||
"Add_nutrition_recipe": "Přidat nutriční hodnoty",
|
"Add_nutrition_recipe": "Přidat nutriční hodnoty",
|
||||||
"Remove_nutrition_recipe": "Smazat nutriční hodnoty",
|
"Remove_nutrition_recipe": "Smazat nutriční hodnoty",
|
||||||
"Copy_template_reference": "",
|
"Copy_template_reference": "Zkopírovat šablonu odkazu",
|
||||||
"Save_and_View": "Uložit & Zobrazit",
|
"Save_and_View": "Uložit a zobrazit",
|
||||||
"Manage_Books": "Spravovat kuchařky",
|
"Manage_Books": "Spravovat kuchařky",
|
||||||
"Meal_Plan": "Jídelníček",
|
"Meal_Plan": "Jídelníček",
|
||||||
"Select_Book": "Vyber kuchařku",
|
"Select_Book": "Vyber kuchařku",
|
||||||
@ -44,19 +44,19 @@
|
|||||||
"Recipe_Image": "Obrázek k receptu",
|
"Recipe_Image": "Obrázek k receptu",
|
||||||
"Import_finished": "Import dokončen",
|
"Import_finished": "Import dokončen",
|
||||||
"View_Recipes": "Zobrazit recepty",
|
"View_Recipes": "Zobrazit recepty",
|
||||||
"Log_Cooking": "",
|
"Log_Cooking": "Zaznamenat vaření",
|
||||||
"New_Recipe": "Nový recept",
|
"New_Recipe": "Nový recept",
|
||||||
"Url_Import": "Import pomocí URL odkazu",
|
"Url_Import": "Import pomocí URL odkazu",
|
||||||
"Reset_Search": "Zrušit filtry vyhledávání",
|
"Reset_Search": "Zrušit filtry vyhledávání",
|
||||||
"Recently_Viewed": "Naposledy prohlížené",
|
"Recently_Viewed": "Naposledy prohlížené",
|
||||||
"Load_More": "Načíst další",
|
"Load_More": "Načíst další",
|
||||||
"New_Keyword": "Nové klíčové slovo",
|
"New_Keyword": "Nový štítek",
|
||||||
"Delete_Keyword": "Smazat klíčové slovo",
|
"Delete_Keyword": "Smazat štítek",
|
||||||
"Edit_Keyword": "Upravit klíčové slovo",
|
"Edit_Keyword": "Upravit štítek",
|
||||||
"Edit_Recipe": "Upravit recept",
|
"Edit_Recipe": "Upravit recept",
|
||||||
"Move_Keyword": "Přesunout klíčové slovo",
|
"Move_Keyword": "Přesunout štítek",
|
||||||
"Merge_Keyword": "Sloučit klíčové slovo",
|
"Merge_Keyword": "Sloučit štítek",
|
||||||
"Hide_Keywords": "Skrýt klíčové slovo",
|
"Hide_Keywords": "Skrýt štítek",
|
||||||
"Hide_Recipes": "Skrýt recept",
|
"Hide_Recipes": "Skrýt recept",
|
||||||
"Move_Up": "Nahoru",
|
"Move_Up": "Nahoru",
|
||||||
"Move_Down": "Dolů",
|
"Move_Down": "Dolů",
|
||||||
@ -76,14 +76,14 @@
|
|||||||
"Private_Recipe_Help": "Recept můžete zobrazit pouze vy a lidé, se kterými jej sdílíte.",
|
"Private_Recipe_Help": "Recept můžete zobrazit pouze vy a lidé, se kterými jej sdílíte.",
|
||||||
"reusable_help_text": "Má-li pozvánka platit pro více než jednoho uživatele.",
|
"reusable_help_text": "Má-li pozvánka platit pro více než jednoho uživatele.",
|
||||||
"Add_Step": "Přidat krok",
|
"Add_Step": "Přidat krok",
|
||||||
"Keywords": "Klíčová slova",
|
"Keywords": "Štítky",
|
||||||
"Books": "Kuchařky",
|
"Books": "Kuchařky",
|
||||||
"Proteins": "Proteiny",
|
"Proteins": "Proteiny",
|
||||||
"Fats": "Tuky",
|
"Fats": "Tuky",
|
||||||
"Carbohydrates": "Sacharidy",
|
"Carbohydrates": "Sacharidy",
|
||||||
"Calories": "Kalorie",
|
"Calories": "Kalorie",
|
||||||
"Energy": "Energie",
|
"Energy": "Energie",
|
||||||
"Nutrition": "",
|
"Nutrition": "Výživové hodnoty",
|
||||||
"Date": "Datum",
|
"Date": "Datum",
|
||||||
"Share": "Sdílet",
|
"Share": "Sdílet",
|
||||||
"Automation": "Automatizace",
|
"Automation": "Automatizace",
|
||||||
@ -153,7 +153,7 @@
|
|||||||
"Hide_Food": "Skrýt potravinu",
|
"Hide_Food": "Skrýt potravinu",
|
||||||
"Food_Alias": "Přezdívka potraviny",
|
"Food_Alias": "Přezdívka potraviny",
|
||||||
"Unit_Alias": "Přezdívka jednotky",
|
"Unit_Alias": "Přezdívka jednotky",
|
||||||
"Keyword_Alias": "Přezdívka klíčového slova",
|
"Keyword_Alias": "Přezdívka štítku",
|
||||||
"Delete_Food": "Smazat potravinu",
|
"Delete_Food": "Smazat potravinu",
|
||||||
"No_ID": "ID nenalezeno, odstranění není možné.",
|
"No_ID": "ID nenalezeno, odstranění není možné.",
|
||||||
"Meal_Plan_Days": "Budoucí jídelníčky",
|
"Meal_Plan_Days": "Budoucí jídelníčky",
|
||||||
@ -162,7 +162,7 @@
|
|||||||
"Food": "Potravina",
|
"Food": "Potravina",
|
||||||
"Original_Text": "Původní text",
|
"Original_Text": "Původní text",
|
||||||
"Recipe_Book": "Kuchařka",
|
"Recipe_Book": "Kuchařka",
|
||||||
"del_confirmation_tree": "Jste si jistí, že chcete odstranit {source} se všemi pořazenými ?",
|
"del_confirmation_tree": "Jste si jistí, že chcete odstranit {source} i se všemi potomky?",
|
||||||
"delete_title": "Smazat {type}",
|
"delete_title": "Smazat {type}",
|
||||||
"create_title": "Nový {type}",
|
"create_title": "Nový {type}",
|
||||||
"edit_title": "Upravit {type}",
|
"edit_title": "Upravit {type}",
|
||||||
@ -170,7 +170,7 @@
|
|||||||
"Type": "Typ",
|
"Type": "Typ",
|
||||||
"Description": "Popis",
|
"Description": "Popis",
|
||||||
"Recipe": "Recept",
|
"Recipe": "Recept",
|
||||||
"tree_root": "",
|
"tree_root": "Kořen stromu",
|
||||||
"Icon": "Ikona",
|
"Icon": "Ikona",
|
||||||
"Unit": "Jednotka",
|
"Unit": "Jednotka",
|
||||||
"Decimals": "Desetinná místa",
|
"Decimals": "Desetinná místa",
|
||||||
@ -179,7 +179,7 @@
|
|||||||
"New_Unit": "Nová jednotka",
|
"New_Unit": "Nová jednotka",
|
||||||
"Create_New_Shopping Category": "Vytvořit novou nákupní kategorii",
|
"Create_New_Shopping Category": "Vytvořit novou nákupní kategorii",
|
||||||
"Create_New_Food": "Přidat novou potravinu",
|
"Create_New_Food": "Přidat novou potravinu",
|
||||||
"Create_New_Keyword": "Přidat nové klíčové slovo",
|
"Create_New_Keyword": "Přidat nový štítek",
|
||||||
"Create_New_Unit": "Přidat novou jednotku",
|
"Create_New_Unit": "Přidat novou jednotku",
|
||||||
"Create_New_Meal_Type": "Přidat nový druh jídla",
|
"Create_New_Meal_Type": "Přidat nový druh jídla",
|
||||||
"Create_New_Shopping_Category": "Přidat novou nákupní kategorii",
|
"Create_New_Shopping_Category": "Přidat novou nákupní kategorii",
|
||||||
@ -254,7 +254,7 @@
|
|||||||
"SupermarketCategoriesOnly": "Pouze kategorie obchodu",
|
"SupermarketCategoriesOnly": "Pouze kategorie obchodu",
|
||||||
"MoveCategory": "Přesunout do: ",
|
"MoveCategory": "Přesunout do: ",
|
||||||
"CountMore": "...+{count} víc",
|
"CountMore": "...+{count} víc",
|
||||||
"IgnoreThis": "Nikdy automaticky nepřídávat {food} na nákupní seznam",
|
"IgnoreThis": "Nikdy nepřidávat automaticky {food} na nákupní seznam",
|
||||||
"DelayFor": "Odložit na {hours} hodin",
|
"DelayFor": "Odložit na {hours} hodin",
|
||||||
"Warning": "Varování",
|
"Warning": "Varování",
|
||||||
"NoCategory": "Není vybrána žádná kategorie.",
|
"NoCategory": "Není vybrána žádná kategorie.",
|
||||||
@ -271,7 +271,7 @@
|
|||||||
"default_delay": "Výchozí doba odložení v hodinách",
|
"default_delay": "Výchozí doba odložení v hodinách",
|
||||||
"plan_share_desc": "Nové položky v jídelníčku budou automaticky sdíleny s vybranými uživateli.",
|
"plan_share_desc": "Nové položky v jídelníčku budou automaticky sdíleny s vybranými uživateli.",
|
||||||
"shopping_share_desc": "Uživatelé uvidí všechny položky na vašem nákupním seznamu. Abyste viděli položky na jejich seznamu, musí si přidat vás.",
|
"shopping_share_desc": "Uživatelé uvidí všechny položky na vašem nákupním seznamu. Abyste viděli položky na jejich seznamu, musí si přidat vás.",
|
||||||
"shopping_auto_sync_desc": "Nastavením 0 dojde k vypnutí automatické synchronizace. Při prohlížení nákupního seznamu je vždy po uplynutí nastaveného počtu vteřin aktualizován o změny, které mohli provést jiní uživatelé. To je užitečné, pokud nakupujete ve více lidech, ale může používat více dat.",
|
"shopping_auto_sync_desc": "Zadáním hodnoty 0 se automatická synchronizace vypne. Při prohlížení nákupního seznamu se seznam aktualizuje po stanovených sekundách, aby se synchronizovaly změny, které mohl provést někdo jiný. To je užitečné při nakupování s více lidmi, ale spotřebovávají se při tom mobilní data.",
|
||||||
"mealplan_autoadd_shopping_desc": "Automaticky podle jídelníčku přidat ingredience na nákupní seznam.",
|
"mealplan_autoadd_shopping_desc": "Automaticky podle jídelníčku přidat ingredience na nákupní seznam.",
|
||||||
"mealplan_autoexclude_onhand_desc": "Nepřidávat ingredience, které jsou k dispozici, na nákupní seznam, když je vytvořen podle jídelníčku (manuálně nebo automaticky).",
|
"mealplan_autoexclude_onhand_desc": "Nepřidávat ingredience, které jsou k dispozici, na nákupní seznam, když je vytvořen podle jídelníčku (manuálně nebo automaticky).",
|
||||||
"mealplan_autoinclude_related_desc": "Když je nákupní seznam vytvořen podle jídelníčku, přidat i položky z přidružených receptů.",
|
"mealplan_autoinclude_related_desc": "Když je nákupní seznam vytvořen podle jídelníčku, přidat i položky z přidružených receptů.",
|
||||||
@ -280,7 +280,7 @@
|
|||||||
"Coming_Soon": "Již brzy",
|
"Coming_Soon": "Již brzy",
|
||||||
"Auto_Planner": "Automatický plánovač",
|
"Auto_Planner": "Automatický plánovač",
|
||||||
"New_Cookbook": "Nová kuchařka",
|
"New_Cookbook": "Nová kuchařka",
|
||||||
"Hide_Keyword": "Skrýt klíčová slova",
|
"Hide_Keyword": "Skrýt štítky",
|
||||||
"Hour": "Hodina",
|
"Hour": "Hodina",
|
||||||
"Hours": "Hodiny",
|
"Hours": "Hodiny",
|
||||||
"Day": "Den",
|
"Day": "Den",
|
||||||
@ -328,7 +328,7 @@
|
|||||||
"OnHand_help": "Potravina je v inventáři a nebude automaticky přidána na nákupní seznam. Status \"k dipozici\" je sdílen s nakupujícími uživateli.",
|
"OnHand_help": "Potravina je v inventáři a nebude automaticky přidána na nákupní seznam. Status \"k dipozici\" je sdílen s nakupujícími uživateli.",
|
||||||
"ignore_shopping_help": "Nikdy nepřidávat potravinu na nákupní seznam (např. voda)",
|
"ignore_shopping_help": "Nikdy nepřidávat potravinu na nákupní seznam (např. voda)",
|
||||||
"shopping_category_help": "Obchody mohou být seřazeny a třízeny pomocí nákupních kategorií podle rozvržení uliček a regálů.",
|
"shopping_category_help": "Obchody mohou být seřazeny a třízeny pomocí nákupních kategorií podle rozvržení uliček a regálů.",
|
||||||
"food_recipe_help": "",
|
"food_recipe_help": "Zde uvedený recept bude připojen k jakémukoli jinému receptu, který používá tuto potravinu",
|
||||||
"Foods": "Potraviny",
|
"Foods": "Potraviny",
|
||||||
"Account": "Účet",
|
"Account": "Účet",
|
||||||
"Cosmetic": "Zobrazení",
|
"Cosmetic": "Zobrazení",
|
||||||
@ -338,7 +338,7 @@
|
|||||||
"simple_mode": "Jednoduchý režim",
|
"simple_mode": "Jednoduchý režim",
|
||||||
"advanced": "Pokročilé",
|
"advanced": "Pokročilé",
|
||||||
"fields": "Pole",
|
"fields": "Pole",
|
||||||
"show_keywords": "Zobrazit klíčová slova",
|
"show_keywords": "Zobrazit štítky",
|
||||||
"show_foods": "Zobrazit potraviny",
|
"show_foods": "Zobrazit potraviny",
|
||||||
"show_books": "Zobrazit kuchařky",
|
"show_books": "Zobrazit kuchařky",
|
||||||
"show_rating": "Zobrazit hodnocení",
|
"show_rating": "Zobrazit hodnocení",
|
||||||
@ -359,8 +359,8 @@
|
|||||||
"times_cooked": "Kolkrát vařeno",
|
"times_cooked": "Kolkrát vařeno",
|
||||||
"date_created": "Datum vytvoření",
|
"date_created": "Datum vytvoření",
|
||||||
"show_sortby": "Zobrazit Seřazeno podle",
|
"show_sortby": "Zobrazit Seřazeno podle",
|
||||||
"search_rank": "",
|
"search_rank": "Skóre shody",
|
||||||
"make_now": "",
|
"make_now": "Udělat hned",
|
||||||
"recipe_filter": "Filtrovat recepty",
|
"recipe_filter": "Filtrovat recepty",
|
||||||
"book_filter_help": "Zahrnout i recepty z filtru stejně jako manuálně přidané.",
|
"book_filter_help": "Zahrnout i recepty z filtru stejně jako manuálně přidané.",
|
||||||
"review_shopping": "Zkontrolovat nákupní položky před uložením",
|
"review_shopping": "Zkontrolovat nákupní položky před uložením",
|
||||||
@ -392,9 +392,9 @@
|
|||||||
"search_create_help_text": "Vytvořit nový recept přímo v Tandoor.",
|
"search_create_help_text": "Vytvořit nový recept přímo v Tandoor.",
|
||||||
"warning_duplicate_filter": "Varování: Kvůli technickým omezení může použití několika filtrů se stejnou kombinací (a/nebo/ne) přinést neočekávaný výsledek.",
|
"warning_duplicate_filter": "Varování: Kvůli technickým omezení může použití několika filtrů se stejnou kombinací (a/nebo/ne) přinést neočekávaný výsledek.",
|
||||||
"reset_children": "Resetovat propsání podřízených",
|
"reset_children": "Resetovat propsání podřízených",
|
||||||
"reset_children_help": "",
|
"reset_children_help": "Přepíše všechny potomky hodnotami dle nastavení propisovaných polí. Pokud není nastaveno pole Propisovaná pole podřízených, tak bude nastaveno pole Propsat hodnoty polí na aktuální hodnotu.",
|
||||||
"reset_food_inheritance": "Resetovat propisování",
|
"reset_food_inheritance": "Resetovat propisování",
|
||||||
"reset_food_inheritance_info": "",
|
"reset_food_inheritance_info": "Obnoví u všech potravin propisovaná pole na výchozí hodnotu a nastavit daná pole dle nadřazené položky.",
|
||||||
"substitute_help": "Při hledání podle ingrediencí, které jsou k dispozici, jsou zvažovány náhrady.",
|
"substitute_help": "Při hledání podle ingrediencí, které jsou k dispozici, jsou zvažovány náhrady.",
|
||||||
"substitute_siblings_help": "Všechny potraviny, které sdílejí nadřazenou položku jsou považovány za náhrady.",
|
"substitute_siblings_help": "Všechny potraviny, které sdílejí nadřazenou položku jsou považovány za náhrady.",
|
||||||
"substitute_children_help": "Všechny potraviny, které jsou podřízeny této, jsou považovány za náhražky.",
|
"substitute_children_help": "Všechny potraviny, které jsou podřízeny této, jsou považovány za náhražky.",
|
||||||
@ -425,8 +425,8 @@
|
|||||||
"Social_Authentication": "Přihlašování pomocí účtů sociálních sítí",
|
"Social_Authentication": "Přihlašování pomocí účtů sociálních sítí",
|
||||||
"Random Recipes": "Náhodné recepty",
|
"Random Recipes": "Náhodné recepty",
|
||||||
"parameter_count": "Parametr {count}",
|
"parameter_count": "Parametr {count}",
|
||||||
"select_keyword": "Vybrat klíčové slovo",
|
"select_keyword": "Vybrat štítek",
|
||||||
"add_keyword": "Přidat klíčové slovo",
|
"add_keyword": "Přidat štítek",
|
||||||
"select_file": "Vybrat soubor",
|
"select_file": "Vybrat soubor",
|
||||||
"select_recipe": "Vybrat recept",
|
"select_recipe": "Vybrat recept",
|
||||||
"select_unit": "Vybrat jednotku",
|
"select_unit": "Vybrat jednotku",
|
||||||
@ -439,7 +439,7 @@
|
|||||||
"Username": "Uživatelské jméno",
|
"Username": "Uživatelské jméno",
|
||||||
"First_name": "Jméno",
|
"First_name": "Jméno",
|
||||||
"Last_name": "Příjmení",
|
"Last_name": "Příjmení",
|
||||||
"Keyword": "Klíčové slovo",
|
"Keyword": "Štítek",
|
||||||
"Advanced": "Rozšířené",
|
"Advanced": "Rozšířené",
|
||||||
"Page": "Stránka",
|
"Page": "Stránka",
|
||||||
"Single": "Jednoduchý",
|
"Single": "Jednoduchý",
|
||||||
@ -479,10 +479,10 @@
|
|||||||
"Create Recipe": "Vytvořit recept",
|
"Create Recipe": "Vytvořit recept",
|
||||||
"Import Recipe": "Importovat recept",
|
"Import Recipe": "Importovat recept",
|
||||||
"per_serving": "na porci",
|
"per_serving": "na porci",
|
||||||
"open_data_help_text": "Projekt Tandoor Open Data nabízí komunitou poskytnutá data pro Tandoor. Toto pole je automaticky vyplněno při importu a může být později upraveno.",
|
"open_data_help_text": "Projekt Tandoor Open Data nabízí komunitou poskytnutá otevřená data pro Tandoor. Toto pole se vyplní automaticky při importu a umožňuje budoucí aktualizace.",
|
||||||
"Data_Import_Info": "Rozšiřte svůj prostor o seznamy potravin, jednotek a další spravované komunitou, a vylepšete tak svoji sbírku receptů.",
|
"Data_Import_Info": "Rozšiřte svůj prostor o seznamy potravin, jednotek a dalších položek spravovaných komunitou, a vylepšete tak svoji sbírku receptů.",
|
||||||
"Update_Existing_Data": "Aktualizovat existující data",
|
"Update_Existing_Data": "Aktualizovat existující data",
|
||||||
"Use_Metric": "Používat metrické jednotky",
|
"Use_Metric": "Použít metrické jednotky",
|
||||||
"Learn_More": "Zjistit víc",
|
"Learn_More": "Zjistit víc",
|
||||||
"converted_unit": "Převedená jendotka",
|
"converted_unit": "Převedená jendotka",
|
||||||
"converted_amount": "Převedené množství",
|
"converted_amount": "Převedené množství",
|
||||||
@ -490,9 +490,67 @@
|
|||||||
"base_amount": "Základní množství",
|
"base_amount": "Základní množství",
|
||||||
"Datatype": "Datový typ",
|
"Datatype": "Datový typ",
|
||||||
"Number of Objects": "Počet Objektů",
|
"Number of Objects": "Počet Objektů",
|
||||||
"Property": "Vlastnost",
|
"Property": "Nutriční vlastnost",
|
||||||
"Conversion": "Převod",
|
"Conversion": "Převod",
|
||||||
"Properties": "Vlastnosti",
|
"Properties": "Nutriční vlastnosti",
|
||||||
"recipe_property_info": "Můžete také přidávat vlastnosti k Vašim potravinám. Hodnoty budou automaticky přepočteny na základě Vašeho receptu!",
|
"recipe_property_info": "Nutriční hodnoty se automaticky dopočtou podle receptu, pokud zadáte nutriční hodnoty přímo potravinám!",
|
||||||
"total": "celkem"
|
"total": "celkem",
|
||||||
|
"CustomTheme": "Vlastní téma",
|
||||||
|
"CustomThemeHelp": "Přepsat styly vybraného motivu nahráním vlastního souboru CSS.",
|
||||||
|
"CustomLogoHelp": "Nahrajte čtvercové obrázky různých velikostí pro úpravu loga v záložce prohlížeče a v nainstalované webové aplikaci.",
|
||||||
|
"err_importing_recipe": "Během importu receptu došlo k chybě!",
|
||||||
|
"Open_Data_Slug": "Identifikátor pro otevřená data",
|
||||||
|
"Open_Data_Import": "Import otevřených dat",
|
||||||
|
"FDC_Search": "Vyhledávání v FDC",
|
||||||
|
"property_type_fdc_hint": "Data z databáze FDC mohou automaticky čerpat pouze typy vlastností se zadaným FDC ID",
|
||||||
|
"StartDate": "Počáteční datum",
|
||||||
|
"EndDate": "Konečné datum",
|
||||||
|
"Welcome": "Vítejte",
|
||||||
|
"Property_Editor": "Editovat nutriční vlastnosti",
|
||||||
|
"FDC_ID": "FDC ID",
|
||||||
|
"FDC_ID_help": "ID v databázi FDC",
|
||||||
|
"CustomImageHelp": "Nahrajte obrázek, který se zobrazí v přehledu prostoru.",
|
||||||
|
"CustomNavLogoHelp": "Nahrajte obrázek, který se má zobrazit jako logo v navigačním panelu.",
|
||||||
|
"CustomLogos": "Vlastní loga",
|
||||||
|
"OrderInformation": "Položky jsou seřazeny podle čísel od malých po velké.",
|
||||||
|
"kg": "kilogram [kg] (metrický systém, hmotnost)",
|
||||||
|
"g": "gram [g] (metrický systém, hmotnost)",
|
||||||
|
"ounce": "unce [oz] (imperiální systém, hmotnost)",
|
||||||
|
"pound": "libra (hmotnost)",
|
||||||
|
"Properties_Food_Unit": "Jednotka nutriční vlastnosti",
|
||||||
|
"Properties_Food_Amount": "Množství nutriční vlastnosti",
|
||||||
|
"tsp": "lžička [tsp] (US, objem)",
|
||||||
|
"imperial_tsp": "lžička imperiální [imp tbsp] (UK, objem)",
|
||||||
|
"Transpose_Words": "Transponovat slova",
|
||||||
|
"show_step_ingredients_setting": "Zobrazit ingredience u jednotlivých kroků receptu",
|
||||||
|
"Logo": "Logo",
|
||||||
|
"Show_Logo": "Zobrazit logo",
|
||||||
|
"show_step_ingredients_setting_help": "Zobrazí tabulku ingrediencí vedle kroků receptu. Nastavení se aplikuje při vytváření receptu a následně je možné volbu změnit při úpravě receptu.",
|
||||||
|
"show_step_ingredients": "Zobrazit ingredience u kroku",
|
||||||
|
"hide_step_ingredients": "Skrýt ingredience u kroku",
|
||||||
|
"Show_Logo_Help": "Zobrazit logo Tandoor nebo logo prostoru na navigačním panelu.",
|
||||||
|
"Nav_Text_Mode_Help": "Pro každé téma se chová jinak.",
|
||||||
|
"Space_Cosmetic_Settings": "Některá kosmetická nastavení mohou měnit správci prostoru a budou mít přednost před nastavením klienta pro daný prostor.",
|
||||||
|
"Nav_Text_Mode": "Textový režim navigace",
|
||||||
|
"show_ingredients_table": "Zobrazit tabulku složek vedle textu kroku",
|
||||||
|
"pint": "pinta [pt] (US, objem)",
|
||||||
|
"quart": "quart [qt] (US, objem)",
|
||||||
|
"imperial_fluid_ounce": "tekutá unce imperiální [imp fl oz] (UK, objem)",
|
||||||
|
"imperial_pint": "pinta imperiální [imp pt] (UK, objem)",
|
||||||
|
"imperial_quart": "quart imperiální [imp qt] (UK, objem)",
|
||||||
|
"gallon": "galon [gal] (US, objem)",
|
||||||
|
"tbsp": "lžíce [tbsp] (US, objem)",
|
||||||
|
"imperial_gallon": "galon imperiální [imp gal] (UK, objem)",
|
||||||
|
"imperial_tbsp": "lžíce imperiální [imp tbsp] (UK, objem)",
|
||||||
|
"Choose_Category": "Vyberte kategorii",
|
||||||
|
"Back": "Zpět",
|
||||||
|
"Food_Replace": "Nahrazení v potravině",
|
||||||
|
"Unit_Replace": "Nahrazení v jednotce",
|
||||||
|
"Name_Replace": "Nahrazení v názvu",
|
||||||
|
"ml": "mililitr [ml] (metrický systém, objem)",
|
||||||
|
"l": "litr [l] (metrický systém, objem)",
|
||||||
|
"fluid_ounce": "tekutá unce [fl oz] (US, objem)",
|
||||||
|
"make_now_count": "Nejvyšší počet chybějících ingrediencí",
|
||||||
|
"Alignment": "Zarovnání",
|
||||||
|
"Never_Unit": "Není jednotkou"
|
||||||
}
|
}
|
||||||
|
@ -536,5 +536,24 @@
|
|||||||
"Unit_Replace": "Einheit Ersetzen",
|
"Unit_Replace": "Einheit Ersetzen",
|
||||||
"quart": "\"Quart\" [qt] (US, Volumen)",
|
"quart": "\"Quart\" [qt] (US, Volumen)",
|
||||||
"imperial_quart": "Engl. \"Quart\" [imp qt] (UK, Volumen)",
|
"imperial_quart": "Engl. \"Quart\" [imp qt] (UK, Volumen)",
|
||||||
"err_importing_recipe": "Beim Importieren des Rezeptes ist ein Fehler aufgetreten!"
|
"err_importing_recipe": "Beim Importieren des Rezeptes ist ein Fehler aufgetreten!",
|
||||||
|
"property_type_fdc_hint": "Nur Nährwerte mit einer FDC ID können automatisch Daten aus der FDC Datenbank beziehen",
|
||||||
|
"Property_Editor": "Nährwerte bearbeiten",
|
||||||
|
"CustomTheme": "Benutzerdefiniertes Theme",
|
||||||
|
"CustomThemeHelp": "Überschreiben Sie die Stile des ausgewählten Themes, indem Sie eine eigene CSS-Datei hochladen.",
|
||||||
|
"CustomLogoHelp": "Laden Sie quadratische Bilder in verschiedenen Größen hoch, um das Logo im Browsertab und der installierten Webanwendung zu ändern.",
|
||||||
|
"Show_Logo_Help": "Zeigen Sie das Tandoor- oder Space-Logo in der Navigationsleiste an.",
|
||||||
|
"Space_Cosmetic_Settings": "Einige optische Einstellungen können von Administratoren des Bereichs geändert werden und setzen die Client-Einstellungen für diesen Bereich außer Kraft.",
|
||||||
|
"Properties_Food_Amount": "Nährwertangaben",
|
||||||
|
"Properties_Food_Unit": "Nährwert Einheit",
|
||||||
|
"FDC_Search": "FDC Suche",
|
||||||
|
"Logo": "Logo",
|
||||||
|
"Show_Logo": "Logo anzeigen",
|
||||||
|
"Nav_Text_Mode": "Navigation Textmodus",
|
||||||
|
"Nav_Text_Mode_Help": "Verhält sich bei jedem Theme anders.",
|
||||||
|
"FDC_ID": "FDC ID",
|
||||||
|
"FDC_ID_help": "FDC Datenbank ID",
|
||||||
|
"CustomImageHelp": "Laden Sie ein Bild hoch, das in der Space-Übersicht angezeigt werden soll.",
|
||||||
|
"CustomNavLogoHelp": "Laden Sie ein Bild hoch, das als Logo für die Navigationsleiste verwendet werden soll.",
|
||||||
|
"CustomLogos": "Individuelle Logos"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user