Merge branch 'develop' into feature/shopping-ui

# Conflicts:
#	cookbook/serializer.py
This commit is contained in:
vabene1111 2024-01-28 11:05:56 +01:00
commit 3e51bdc7f0
15 changed files with 61 additions and 27 deletions

View File

@ -450,7 +450,7 @@ class SpacePreferenceForm(forms.ModelForm):
class Meta:
model = Space
fields = ('food_inherit', 'reset_food_inherit', 'use_plural')
fields = ('food_inherit', 'reset_food_inherit',)
help_texts = {
'food_inherit': _('Fields on food that should be inherited by default.'),

View File

@ -14,12 +14,14 @@ class IngredientObject(object):
unit = ""
food = ""
note = ""
numeric_amount = 0
def __init__(self, ingredient):
if ingredient.no_amount:
self.amount = ""
else:
self.amount = f"<scalable-number v-bind:number='{bleach.clean(str(ingredient.amount))}' v-bind:factor='ingredient_factor'></scalable-number>"
self.numeric_amount = float(ingredient.amount)
if ingredient.unit:
if ingredient.unit.plural_name in (None, ""):
self.unit = bleach.clean(str(ingredient.unit))
@ -83,9 +85,12 @@ def render_instructions(step): # TODO deduplicate markdown cleanup code
for i in step.ingredients.all():
ingredients.append(IngredientObject(i))
def scale(number):
return f"<scalable-number v-bind:number='{bleach.clean(str(number))}' v-bind:factor='ingredient_factor'></scalable-number>"
try:
template = Template(instructions)
instructions = template.render(ingredients=ingredients)
instructions = template.render(ingredients=ingredients, scale=scale)
except TemplateSyntaxError:
return _('Could not parse template code.') + ' Error: Template Syntax broken'
except UndefinedError:

View File

@ -0,0 +1,17 @@
# Generated by Django 4.2.7 on 2024-01-28 07:42
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('cookbook', '0208_space_app_name_userpreference_max_owned_spaces'),
]
operations = [
migrations.RemoveField(
model_name='space',
name='use_plural',
),
]

View File

@ -303,7 +303,6 @@ class Space(ExportModelOperationsMixin('space'), models.Model):
max_recipes = models.IntegerField(default=0)
max_file_storage_mb = models.IntegerField(default=0, help_text=_('Maximum file storage for space in MB. 0 for unlimited, -1 to disable file upload.'))
max_users = models.IntegerField(default=0)
use_plural = models.BooleanField(default=True)
allow_sharing = models.BooleanField(default=True)
no_sharing_limit = models.BooleanField(default=False)
demo = models.BooleanField(default=False)

View File

@ -315,9 +315,8 @@ 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', 'nav_logo', 'space_theme', 'custom_space_theme', 'nav_bg_color', 'nav_text_color', 'use_plural',
'logo_color_32', 'logo_color_128', 'logo_color_144', 'logo_color_180', 'logo_color_192', 'logo_color_512',
'logo_color_svg',)
'image', 'nav_logo', 'space_theme', 'custom_space_theme', 'nav_bg_color', 'nav_text_color',
'logo_color_32', 'logo_color_128', 'logo_color_144', 'logo_color_180', 'logo_color_192', 'logo_color_512', 'logo_color_svg',)
read_only_fields = (
'id', 'created_by', 'created_at', 'max_recipes', 'max_file_storage_mb', 'max_users', 'allow_sharing',
'demo',)

View File

@ -3,7 +3,7 @@ from django.templatetags.static import static
from django_scopes import scopes_disabled
from cookbook.models import UserPreference, UserFile, Space
from recipes.settings import STICKY_NAV_PREF_DEFAULT, UNAUTHENTICATED_THEME_FROM_SPACE
from recipes.settings import STICKY_NAV_PREF_DEFAULT, UNAUTHENTICATED_THEME_FROM_SPACE, FORCE_THEME_FROM_SPACE
register = template.Library()
@ -15,11 +15,14 @@ def theme_values(request):
def get_theming_values(request):
space = None
if getattr(request,'space',None):
if getattr(request, 'space', None):
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 and FORCE_THEME_FROM_SPACE == 0:
with scopes_disabled():
space = Space.objects.filter(id=UNAUTHENTICATED_THEME_FROM_SPACE).first()
if FORCE_THEME_FROM_SPACE:
with scopes_disabled():
space = Space.objects.filter(id=FORCE_THEME_FROM_SPACE).first()
themes = {
UserPreference.BOOTSTRAP: 'themes/bootstrap.min.css',

View File

@ -204,6 +204,22 @@ server {
}
```
Tandoor does not support directly serving of images, as explained in the [Nginx vs Gunicorn"](#nginx-vs-gunicorn) section. If you are already using nginx to serve as a reverse proxy, you can configure it to serve images as well.
Add the following directly after the `location /` context:
```
location /media/ {
root /media/;
index index.html index.htm;
}
```
Make sure you also update your `docker-compose.yml` file to mount the `mediafiles` directory. If you are using the [Plain](#plain) deployment, you do not need to make any changes. If you are using nginx to act as a reverse proxy for other apps, it may not be optimal to have `mediafiles` mounted to `/media`. In that case, adjust the directory declarations as needed, utilizing nginx's [`alias`](https://nginx.org/en/docs/http/ngx_http_core_module.html#alias) if needed.
!!!note
Use `alias` if your mount point directory is not the same as the URL request path. Tandoor media files are requested from `$http_host/media/recipes/xxx.jpg`. This means if you are mounting to a directory that does **NOT** end in `./media`, you will need to use `alias`.
!!!note
Don't forget to [download and configure](#docker-compose) your ```.env``` file!

View File

@ -560,6 +560,15 @@ With this setting you can specify the ID of a space of which the appearance sett
UNAUTHENTICATED_THEME_FROM_SPACE=
```
#### Force Theme
> default `0` - options `1-X` (space ID)
Similar to the Default theme but forces the theme upon all users (authenticated/unauthenticated) and all spaces
```
FORCE_THEME_FROM_SPACE=
```
### Rate Limiting / Performance
#### Shopping auto sync

View File

@ -59,6 +59,7 @@ KJ_PREF_DEFAULT = bool(int(os.getenv('KJ_PREF_DEFAULT', False)))
STICKY_NAV_PREF_DEFAULT = bool(int(os.getenv('STICKY_NAV_PREF_DEFAULT', True)))
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))
FORCE_THEME_FROM_SPACE = int(os.getenv('FORCE_THEME_FROM_SPACE', 0))
# minimum interval that users can set for automatic sync of shopping lists
SHOPPING_MIN_AUTOSYNC_INTERVAL = int(

View File

@ -20,7 +20,7 @@
<cookbook-toc :recipes="recipes" v-if="current_page === 1" v-on:switchRecipe="switchRecipe($event)"></cookbook-toc>
</transition>
<transition name="flip" mode="out-in">
<recipe-card :recipe="display_recipes[1].recipe_content" v-if="current_page > 1 && display_recipes.length === 2" :key="display_recipes[1].recipe" :use_plural="use_plural"></recipe-card>
<recipe-card :recipe="display_recipes[1].recipe_content" v-if="current_page > 1 && display_recipes.length === 2" :key="display_recipes[1].recipe" ></recipe-card>
</transition>
</div>
<div class="col-md-1" @click="swipeLeft" style="cursor: pointer"></div>
@ -57,10 +57,7 @@ export default {
}
},
mounted(){
let apiClient = new ApiApiFactory()
apiClient.retrieveSpace(window.ACTIVE_SPACE_ID).then(r => {
this.use_plural = r.data.use_plural
})
},
data() {
return {
@ -69,7 +66,6 @@ export default {
bounce_left: false,
bounce_right: false,
cookbook_editing: false,
use_plural: false,
}
},
methods: {

View File

@ -76,8 +76,7 @@
<div class="col-md-10 offset-md-2">
<generic-horizontal-card v-for="child in item[children]"
v-bind:key="child.id"
:item="child" :model="model"
:use_plural="use_plural"
:item="child" :model="model"
@item-action="$emit('item-action', $event)"></generic-horizontal-card>
</div>
</div>
@ -160,7 +159,6 @@ export default {
recipe_count: { type: String, default: "numrecipe" },
recipes: { type: String, default: "recipes" },
show_context_menu: { type: Boolean, default: true },
use_plural: { type: Boolean, default: false},
},
data() {
return {

View File

@ -24,7 +24,6 @@
<ingredient-component
:ingredient="i"
:ingredient_factor="ingredient_factor"
:use_plural="use_plural"
:key="i.id"
:detailed="detailed"
@checked-state-changed="$emit('checked-state-changed', $event)"
@ -64,7 +63,6 @@ export default {
recipe: {type: Number},
ingredient_factor: {type: Number, default: 1},
servings: {type: Number, default: 1},
use_plural: {type: Boolean, default: false},
detailed: {type: Boolean, default: true},
header: {type: Boolean, default: false},
recipe_list: {type: Number, default: undefined},

View File

@ -34,7 +34,6 @@
<div v-for="i in r.steps.flatMap((s) => s.ingredients)" v-bind:key="i.id">
<table class="table table-sm mb-0">
<ingredient-component
:use_plural="true"
:key="i.id"
:detailed="true"
:ingredient="i"

View File

@ -145,7 +145,6 @@ export default {
props: {
recipe: Object,
meal_plan: Object,
use_plural: { type: Boolean, default: false },
footer_text: String,
footer_icon: String,
detailed: { type: Boolean, default: true },

View File

@ -90,7 +90,6 @@
:index="index"
:start_time="start_time"
:force_ingredients="true"
:use_plural="use_plural"
></step-component>
</div>
</div>
@ -147,10 +146,6 @@ export default {
type: Boolean,
default: false,
},
use_plural: {
type: Boolean,
default: false,
},
},
computed: {
step_time: function() {