Release Nouri 1.3.4 with quieter meal cards
This commit is contained in:
@@ -4,8 +4,8 @@
|
|||||||
"author": "Florian Heinz",
|
"author": "Florian Heinz",
|
||||||
"description": "Private Flask app for meals, shopping and gentle food planning",
|
"description": "Private Flask app for meals, shopping and gentle food planning",
|
||||||
"tagline": "einfach essen planen",
|
"tagline": "einfach essen planen",
|
||||||
"version": "1.3.3",
|
"version": "1.3.4",
|
||||||
"upstreamVersion": "1.3.3",
|
"upstreamVersion": "1.3.4",
|
||||||
"healthCheckPath": "/",
|
"healthCheckPath": "/",
|
||||||
"httpPort": 8000,
|
"httpPort": 8000,
|
||||||
"manifestVersion": 2,
|
"manifestVersion": 2,
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Nouri 1.3.4
|
||||||
|
|
||||||
|
Nouri 1.3.4 räumt die Mahlzeiten-Übersicht auf und bringt sie optisch näher an die ruhigeren Lebensmittel-Karten. Der Fokus liegt auf weniger sichtbaren Details, klarerem Scannen und dem Namen direkt unter dem Bild.
|
||||||
|
|
||||||
|
## Neu in 1.3.4
|
||||||
|
|
||||||
|
- Mahlzeitenkarten zeigen auf der Übersichtsseite jetzt zuerst Bild oder Platzhalter und darunter den Namen.
|
||||||
|
- Details wie Sichtbarkeit, Zielperson, Mahlzeitentyp, Energie und Tags liegen in einer Hover-Ansicht.
|
||||||
|
- Komponenten und Notizen werden ebenfalls erst beim Hover bzw. Fokus eingeblendet.
|
||||||
|
- Die sichtbaren Text-Buttons auf Mahlzeitenkarten wurden durch kompakte Icon-Aktionen ersetzt.
|
||||||
|
- Archivieren bleibt als kleiner Kreis oben rechts erreichbar.
|
||||||
|
- Tagesplan und Einkaufsliste sind als schnelle Icon-Aktionen oben links erreichbar.
|
||||||
|
|
||||||
|
## Bedienung
|
||||||
|
|
||||||
|
- Auf Desktop erscheinen Zusatzinfos beim Mouseover.
|
||||||
|
- Per Tastatur erscheinen Zusatzinfos, sobald eine Aktion auf der Karte fokussiert ist.
|
||||||
|
- Auf kleinen Bildschirmen bleibt die Übersicht bewusst reduziert, wie bei den Lebensmittelkarten.
|
||||||
|
|
||||||
|
## Betrieb
|
||||||
|
|
||||||
|
- Cloudron-Version und Upstream-Version stehen jetzt auf `1.3.4`.
|
||||||
|
- Die interne Schema-Version und der App-Version-Fallback wurden auf `1.3.4` angehoben.
|
||||||
|
- Der Service Worker nutzt einen neuen Cache-Namen für `1.3.4`.
|
||||||
+1
-1
@@ -93,7 +93,7 @@ def load_app_version(root_dir: Path) -> str:
|
|||||||
).strip()
|
).strip()
|
||||||
if manifest_version:
|
if manifest_version:
|
||||||
return manifest_version
|
return manifest_version
|
||||||
return "1.3.3"
|
return "1.3.4"
|
||||||
|
|
||||||
|
|
||||||
def load_release_url() -> str:
|
def load_release_url() -> str:
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ from .constants import (
|
|||||||
DEFAULT_CATEGORY_BUILDERS,
|
DEFAULT_CATEGORY_BUILDERS,
|
||||||
)
|
)
|
||||||
|
|
||||||
CURRENT_SCHEMA_VERSION = "1.3.3"
|
CURRENT_SCHEMA_VERSION = "1.3.4"
|
||||||
|
|
||||||
ANIMAL_HINTS = (
|
ANIMAL_HINTS = (
|
||||||
"huhn",
|
"huhn",
|
||||||
|
|||||||
@@ -1236,7 +1236,8 @@ h3 {
|
|||||||
border-color: color-mix(in srgb, var(--line) 58%, rgba(243, 177, 125, 0.16) 42%);
|
border-color: color-mix(in srgb, var(--line) 58%, rgba(243, 177, 125, 0.16) 42%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-card-food {
|
.item-card-food,
|
||||||
|
.item-card-meal {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
gap: 0.9rem;
|
gap: 0.9rem;
|
||||||
align-content: start;
|
align-content: start;
|
||||||
@@ -1248,20 +1249,23 @@ h3 {
|
|||||||
opacity: 0.72;
|
opacity: 0.72;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-card-food .item-media-food {
|
.item-card-food .item-media-food,
|
||||||
|
.item-card-meal .item-media-meal {
|
||||||
width: min(100%, 170px);
|
width: min(100%, 170px);
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
border-radius: 24px;
|
border-radius: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-card-food .item-body-food {
|
.item-card-food .item-body-food,
|
||||||
|
.item-card-meal .item-body-meal {
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-card-food .item-body-food h2 {
|
.item-card-food .item-body-food h2,
|
||||||
|
.item-card-meal .item-body-meal h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 1.9rem;
|
font-size: 1.9rem;
|
||||||
line-height: 1.08;
|
line-height: 1.08;
|
||||||
@@ -1330,6 +1334,10 @@ h3 {
|
|||||||
box-shadow: 0 10px 22px rgba(70, 48, 34, 0.12);
|
box-shadow: 0 10px 22px rgba(70, 48, 34, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item-card-icon-link {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
.item-card-icon-button:hover {
|
.item-card-icon-button:hover {
|
||||||
background: color-mix(in srgb, var(--accent) 78%, #fff 22%);
|
background: color-mix(in srgb, var(--accent) 78%, #fff 22%);
|
||||||
color: #201a17;
|
color: #201a17;
|
||||||
@@ -1397,7 +1405,9 @@ h3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.item-card-food:hover .item-card-hover-meta,
|
.item-card-food:hover .item-card-hover-meta,
|
||||||
.item-card-food:focus-within .item-card-hover-meta {
|
.item-card-food:focus-within .item-card-hover-meta,
|
||||||
|
.item-card-meal:hover .item-card-hover-meta,
|
||||||
|
.item-card-meal:focus-within .item-card-hover-meta {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
@@ -3613,11 +3623,13 @@ legend {
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-card-food {
|
.item-card-food,
|
||||||
|
.item-card-meal {
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-card-food .item-media-food {
|
.item-card-food .item-media-food,
|
||||||
|
.item-card-meal .item-media-meal {
|
||||||
width: min(100%, 156px);
|
width: min(100%, 156px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const CACHE_NAME = "nouri-v1-3-3";
|
const CACHE_NAME = "nouri-v1-3-4";
|
||||||
const OFFLINE_URL = "/static/pwa/offline.html";
|
const OFFLINE_URL = "/static/pwa/offline.html";
|
||||||
const STATIC_ASSETS = [
|
const STATIC_ASSETS = [
|
||||||
"/static/css/styles.css",
|
"/static/css/styles.css",
|
||||||
|
|||||||
@@ -162,8 +162,44 @@
|
|||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
{% else %}
|
{% else %}
|
||||||
<article class="item-card">
|
<article class="item-card item-card-meal">
|
||||||
<div class="item-media">
|
{% if item.can_edit %}
|
||||||
|
<a class="item-card-cover-link" href="{{ url_for('main.item_edit', item_id=item.id) }}">
|
||||||
|
<span class="sr-only">{{ item.name }} bearbeiten</span>
|
||||||
|
</a>
|
||||||
|
<form
|
||||||
|
class="item-card-archive-form"
|
||||||
|
method="post"
|
||||||
|
action="{{ url_for('main.item_archive', item_id=item.id) }}"
|
||||||
|
onsubmit="return confirm('Willst du diese Mahlzeitenidee wirklich archivieren?');"
|
||||||
|
>
|
||||||
|
{{ csrf_input() }}
|
||||||
|
<button class="item-card-archive-button" type="submit" aria-label="{{ item.name }} archivieren">×</button>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
<div class="item-card-quick-actions">
|
||||||
|
<a
|
||||||
|
class="item-card-icon-button item-card-icon-link"
|
||||||
|
href="{{ url_for('main.planner_day', date=today.isoformat(), item_id=item.id, daypart_id=item.primary_daypart_id) }}"
|
||||||
|
aria-label="{{ item.name }} im Tagesplan öffnen"
|
||||||
|
title="Im Tagesplan öffnen"
|
||||||
|
>
|
||||||
|
<span class="ui-icon icon-calendar"></span>
|
||||||
|
</a>
|
||||||
|
<form method="post" action="{{ url_for('main.item_remove_from_shopping' if item.is_on_shopping_list else 'main.item_add_to_shopping', item_id=item.id) }}">
|
||||||
|
{{ csrf_input() }}
|
||||||
|
<button
|
||||||
|
class="item-card-icon-button {% if item.is_on_shopping_list %}is-active{% else %}is-inactive{% endif %}"
|
||||||
|
type="submit"
|
||||||
|
aria-label="{% if item.is_on_shopping_list %}{{ item.name }} von der Einkaufsliste entfernen{% else %}{{ item.name }} auf die Einkaufsliste setzen{% endif %}"
|
||||||
|
title="{% if item.is_on_shopping_list %}Auf Einkaufsliste{% else %}Nicht auf Einkaufsliste{% endif %}"
|
||||||
|
>
|
||||||
|
<span class="ui-icon icon-cart-shopping"></span>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item-media item-media-meal">
|
||||||
{% if item.photo_filename %}
|
{% if item.photo_filename %}
|
||||||
<img
|
<img
|
||||||
src="{{ image_url(item.photo_filename, 'md') }}"
|
src="{{ image_url(item.photo_filename, 'md') }}"
|
||||||
@@ -175,7 +211,12 @@
|
|||||||
<div class="placeholder-tile">{{ item.name[:1] }}</div>
|
<div class="placeholder-tile">{{ item.name[:1] }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="item-body">
|
|
||||||
|
<div class="item-body item-body-meal">
|
||||||
|
<h2>{{ item.name }}</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item-card-hover-meta" aria-hidden="true">
|
||||||
<div class="chip-row">
|
<div class="chip-row">
|
||||||
<span class="chip">{{ item.visibility_label }}</span>
|
<span class="chip">{{ item.visibility_label }}</span>
|
||||||
<span class="chip status-soft">{{ item.owner_label }}</span>
|
<span class="chip status-soft">{{ item.owner_label }}</span>
|
||||||
@@ -202,22 +243,6 @@
|
|||||||
<p>{{ item.note }}</p>
|
<p>{{ item.note }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="item-actions">
|
|
||||||
{% if item.can_edit %}
|
|
||||||
<a class="ghost-button" href="{{ url_for('main.item_edit', item_id=item.id) }}">Bearbeiten</a>
|
|
||||||
{% endif %}
|
|
||||||
<a class="ghost-button" href="{{ url_for('main.planner_day', date=today.isoformat(), item_id=item.id, daypart_id=item.primary_daypart_id) }}">Im Tagesplan öffnen</a>
|
|
||||||
<form class="primary-action" method="post" action="{{ url_for('main.item_add_to_shopping', item_id=item.id) }}">
|
|
||||||
{{ csrf_input() }}
|
|
||||||
<button type="submit">Auf Einkaufsliste</button>
|
|
||||||
</form>
|
|
||||||
{% if item.can_edit %}
|
|
||||||
<form method="post" action="{{ url_for('main.item_archive', item_id=item.id) }}">
|
|
||||||
{{ csrf_input() }}
|
|
||||||
<button class="ghost-button" type="submit">Archivieren</button>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</article>
|
</article>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
Reference in New Issue
Block a user