ui: restyle login, dedupe navbar with Jinja macros, touch polish

- login: theme variables instead of hardcoded slate colors, decorative
  brand background, show/hide password toggle, dynamic copyright year
- navbar: nav links rendered via shared nav_link/nav_links macros
  (desktop + mobile from one source), active state now also in mobile
  menu, aria-current on active link, fix nonexistent w-4.5 class
- themes.css: btn :active press feedback, btn-lg variant, card hover
  border accent, brand accent-color and ::selection
- fix tmf-input vs pl-10 cascade conflict (themes.css loads after
  tailwind.css) with important utilities — also fixes recipe search icon
- app.py: inject current_year in template globals
- i18n: add Mostra/Nascondi password (IT/EN)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Adriano Dal Pastro
2026-06-11 15:35:53 +00:00
parent 83f8e2d332
commit 821c7c39d5
8 changed files with 209 additions and 275 deletions
+2
View File
@@ -1,6 +1,7 @@
"""TieMeasureFlow Client - Flask Entry Point.""" """TieMeasureFlow Client - Flask Entry Point."""
import json import json
import os import os
from datetime import date
from urllib.parse import urlparse from urllib.parse import urlparse
from flask import Flask, redirect, url_for, session, request from flask import Flask, redirect, url_for, session, request
@@ -101,6 +102,7 @@ def create_app() -> Flask:
"languages": Config.LANGUAGES, "languages": Config.LANGUAGES,
"company_logo": session.get("company_logo"), "company_logo": session.get("company_logo"),
"auto_logout_minutes": session.get("auto_logout_minutes"), "auto_logout_minutes": session.get("auto_logout_minutes"),
"current_year": date.today().year,
} }
return app return app
@@ -69,6 +69,23 @@
} }
/* ============================================================
Brand details
============================================================ */
:root {
accent-color: var(--color-primary);
}
::selection {
background: rgba(37, 99, 235, 0.2);
}
.dark ::selection {
background: rgba(96, 165, 250, 0.3);
}
/* ============================================================ /* ============================================================
Global Transitions Global Transitions
============================================================ */ ============================================================ */
@@ -151,6 +168,7 @@ textarea:focus-visible {
.tmf-card:hover { .tmf-card:hover {
box-shadow: var(--shadow-md); box-shadow: var(--shadow-md);
border-color: var(--scrollbar-thumb);
} }
.tmf-card-header { .tmf-card-header {
@@ -250,11 +268,21 @@ textarea:focus-visible {
border: 1px solid transparent; border: 1px solid transparent;
} }
.btn:active:not(:disabled) {
transform: scale(0.97);
}
.btn:disabled { .btn:disabled {
opacity: 0.5; opacity: 0.5;
cursor: not-allowed; cursor: not-allowed;
} }
.btn-lg {
padding: 0.75rem 1.5rem;
font-size: 1rem;
border-radius: 0.625rem;
}
.btn-primary { .btn-primary {
background: var(--color-primary); background: var(--color-primary);
color: #FFFFFF; color: #FFFFFF;
@@ -2,17 +2,24 @@
{% block title %}Login — TieMeasureFlow{% endblock %} {% block title %}Login — TieMeasureFlow{% endblock %}
{% block content %} {% block content %}
<div class="min-h-screen flex items-center justify-center bg-gradient-to-br from-slate-50 to-slate-100 dark:from-slate-900 dark:to-slate-800 px-4 sm:px-6 lg:px-8"> <div class="relative min-h-screen flex items-center justify-center overflow-hidden bg-[var(--bg-primary)] px-4 sm:px-6 lg:px-8">
<div class="max-w-md w-full space-y-8">
<!-- Decorative brand background -->
<div class="pointer-events-none absolute inset-0" aria-hidden="true">
<div class="absolute -top-32 -left-32 w-96 h-96 rounded-full bg-primary-500/10 dark:bg-primary-400/10 blur-3xl"></div>
<div class="absolute -bottom-40 -right-24 w-[28rem] h-[28rem] rounded-full bg-primary-600/10 dark:bg-primary-500/10 blur-3xl"></div>
</div>
<div class="relative max-w-md w-full space-y-6">
<!-- Card --> <!-- Card -->
<div class="bg-white dark:bg-slate-800 shadow-lg rounded-xl p-8"> <div class="bg-[var(--bg-card)] border border-[var(--border-color)] shadow-lg rounded-2xl p-8">
<!-- Logo --> <!-- Logo -->
<div class="text-center mb-8"> <div class="text-center mb-8">
<div class="mx-auto mb-4 inline-flex justify-center text-slate-900 dark:text-white"> <div class="mx-auto mb-4 inline-flex justify-center text-slate-900 dark:text-white">
{% set logo_class = 'h-16 w-auto' %} {% set logo_class = 'h-16 w-auto' %}
{% include 'components/_app_logo.html' %} {% include 'components/_app_logo.html' %}
</div> </div>
<p class="text-sm text-slate-600 dark:text-slate-400"> <p class="text-sm text-[var(--text-secondary)]">
{{ _('Accedi al sistema') }} {{ _('Accedi al sistema') }}
</p> </p>
</div> </div>
@@ -22,12 +29,12 @@
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<!-- Username --> <!-- Username -->
<div> <div>
<label for="username" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2"> <label for="username" class="tmf-label">
{{ _('Username') }} {{ _('Username') }}
</label> </label>
<div class="relative"> <div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<svg class="h-5 w-5 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg class="h-5 w-5 text-[var(--text-muted)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
</svg> </svg>
</div> </div>
@@ -36,36 +43,52 @@
name="username" name="username"
required required
autofocus autofocus
autocomplete="username"
placeholder="{{ _('Username') }}" placeholder="{{ _('Username') }}"
class="block w-full pl-10 pr-3 py-2.5 border border-slate-300 dark:border-slate-600 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500 dark:focus:ring-primary-400 dark:focus:border-primary-400 bg-white dark:bg-slate-700 text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-500 transition-colors"> class="tmf-input !pl-10 !py-2.5">
</div> </div>
</div> </div>
<!-- Password --> <!-- Password -->
<div> <div x-data="{ show: false }">
<label for="password" class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2"> <label for="password" class="tmf-label">
{{ _('Password') }} {{ _('Password') }}
</label> </label>
<div class="relative"> <div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<svg class="h-5 w-5 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg class="h-5 w-5 text-[var(--text-muted)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
</svg> </svg>
</div> </div>
<input type="password" <input :type="show ? 'text' : 'password'"
type="password"
id="password" id="password"
name="password" name="password"
required required
autocomplete="current-password"
placeholder="{{ _('Password') }}" placeholder="{{ _('Password') }}"
class="block w-full pl-10 pr-3 py-2.5 border border-slate-300 dark:border-slate-600 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500 dark:focus:ring-primary-400 dark:focus:border-primary-400 bg-white dark:bg-slate-700 text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-500 transition-colors"> class="tmf-input !pl-10 !pr-12 !py-2.5">
<button type="button"
@click="show = !show"
:aria-label="show ? {{ _('Nascondi password')|tojson_attr }} : {{ _('Mostra password')|tojson_attr }}"
class="absolute inset-y-0 right-0 px-3 flex items-center text-[var(--text-muted)] hover:text-[var(--text-secondary)] transition-colors">
<!-- Eye (password hidden, click to show) -->
<svg x-show="!show" class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"/>
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
<!-- Eye slash (password visible, click to hide) -->
<svg x-show="show" x-cloak class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 001.934 12c1.292 4.338 5.31 7.5 10.066 7.5.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88"/>
</svg>
</button>
</div> </div>
</div> </div>
<!-- Submit Button --> <!-- Submit Button -->
<div> <div>
<button type="submit" <button type="submit" class="btn btn-primary btn-lg w-full shadow-sm">
class="w-full flex justify-center py-3 px-4 border border-transparent rounded-lg shadow-sm text-sm font-semibold text-white bg-primary-600 hover:bg-primary-700 dark:bg-primary-500 dark:hover:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 transition-all duration-200"> <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="h-5 w-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1" />
</svg> </svg>
{{ _('Accedi') }} {{ _('Accedi') }}
@@ -75,7 +98,7 @@
<!-- Help Text --> <!-- Help Text -->
<div class="mt-6 text-center"> <div class="mt-6 text-center">
<p class="text-xs text-slate-500 dark:text-slate-400"> <p class="text-xs text-[var(--text-muted)]">
{{ _('Hai dimenticato la password?') }} {{ _('Hai dimenticato la password?') }}
<br> <br>
{{ _('Contatta l\'amministratore') }} {{ _('Contatta l\'amministratore') }}
@@ -84,8 +107,8 @@
</div> </div>
<!-- Footer --> <!-- Footer -->
<div class="text-center text-xs text-slate-500 dark:text-slate-400"> <div class="text-center text-xs text-[var(--text-muted)]">
<p>TieMeasureFlow &copy; 2025 - {{ _('Sistema di misurazione industriale') }}</p> <p>TieMeasureFlow &copy; {{ current_year }} - {{ _('Sistema di misurazione industriale') }}</p>
</div> </div>
</div> </div>
</div> </div>
@@ -1,6 +1,45 @@
<!-- TieMeasureFlow Navbar --> <!-- TieMeasureFlow Navbar -->
{# SVG path data for nav icons, shared between desktop and mobile menus #}
{% set icon_measure %}<path stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"/>{% endset %}
{% set icon_recipes %}<path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>{% endset %}
{% set icon_stats %}<path stroke-linecap="round" stroke-linejoin="round" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>{% endset %}
{% set icon_users %}<path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z"/>{% endset %}
{% set icon_stations %}<path stroke-linecap="round" stroke-linejoin="round" d="M9 17.25v1.007a3 3 0 01-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0115 18.257V17.25m6-12V15a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 15V5.25m18 0A2.25 2.25 0 0018.75 3H5.25A2.25 2.25 0 003 5.25m18 0V12a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 12V5.25"/>{% endset %}
{% set icon_settings %}<path stroke-linecap="round" stroke-linejoin="round" d="M10.343 3.94c.09-.542.56-.94 1.11-.94h1.093c.55 0 1.02.398 1.11.94l.149.894c.07.424.384.764.78.93.398.164.855.142 1.205-.108l.737-.527a1.125 1.125 0 011.45.12l.773.774c.39.389.44 1.002.12 1.45l-.527.737c-.25.35-.272.806-.107 1.204.165.397.505.71.93.78l.893.15c.543.09.94.56.94 1.109v1.094c0 .55-.397 1.02-.94 1.11l-.893.149c-.425.07-.765.383-.93.78-.165.398-.143.854.107 1.204l.527.738c.32.447.269 1.06-.12 1.45l-.774.773a1.125 1.125 0 01-1.449.12l-.738-.527c-.35-.25-.806-.272-1.204-.107-.397.165-.71.505-.78.929l-.15.894c-.09.542-.56.94-1.11.94h-1.094c-.55 0-1.019-.398-1.11-.94l-.148-.894c-.071-.424-.384-.764-.781-.93-.398-.164-.854-.142-1.204.108l-.738.527c-.447.32-1.06.269-1.45-.12l-.773-.774a1.125 1.125 0 01-.12-1.45l.527-.737c.25-.35.273-.806.108-1.204-.165-.397-.506-.71-.93-.78l-.894-.15c-.542-.09-.94-.56-.94-1.109v-1.094c0-.55.398-1.02.94-1.11l.894-.149c.424-.07.765-.383.93-.78.165-.398.143-.854-.107-1.204l-.527-.738a1.125 1.125 0 01.12-1.45l.773-.773a1.125 1.125 0 011.45-.12l.737.527c.35.25.807.272 1.204.107.397-.165.71-.505.78-.929l.15-.894z"/><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>{% endset %}
{# Single nav link, desktop or mobile variant. `icon` is SVG path markup. #}
{% macro nav_link(href, label, icon, active=false, mobile=false) -%}
<a href="{{ href }}"
{% if active %}aria-current="page"{% endif %}
class="flex items-center {{ 'gap-3 px-3 py-2.5' if mobile else 'gap-2 px-3 py-2' }} rounded-lg text-sm font-medium transition-colors duration-200
{% if active %}text-primary bg-primary-50 dark:bg-primary-900/20{% else %}text-[var(--text-secondary)] hover:text-primary hover:bg-primary-50 dark:hover:bg-primary-900/20{% endif %}">
<svg class="{{ 'w-5 h-5' if mobile else 'w-[18px] h-[18px]' }} shrink-0" fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24">{{ icon }}</svg>
<span>{{ label }}</span>
</a>
{%- endmacro %}
{# Render all role-gated nav links for the current user #}
{% macro nav_links(mobile=false) -%}
{% set ep = request.endpoint or '' %}
{% if current_user.get('roles') and 'MeasurementTec' in current_user.roles %}
{{ nav_link(url_for('measure.select_recipe'), _('Misure'), icon_measure, ep.startswith('measure.'), mobile) }}
{% endif %}
{% if current_user.get('roles') and 'Maker' in current_user.roles %}
{{ nav_link(url_for('maker.recipe_list'), _('Ricette'), icon_recipes, ep.startswith('maker.'), mobile) }}
{% endif %}
{% if current_user.get('roles') and 'Metrologist' in current_user.roles %}
{{ nav_link(url_for('statistics.dashboard'), _('Statistiche'), icon_stats, ep.startswith('statistics.'), mobile) }}
{% endif %}
{% if current_user.get('is_admin') %}
{{ nav_link(url_for('admin.user_list'), _('Utenti'), icon_users, ep == 'admin.user_list', mobile) }}
{{ nav_link(url_for('admin.station_list'), _('Stazioni'), icon_stations, ep == 'admin.station_list', mobile) }}
{{ nav_link(url_for('admin.settings_page'), _('Impostazioni'), icon_settings, ep == 'admin.settings_page', mobile) }}
{% endif %}
{%- endmacro %}
<nav class="sticky top-0 z-40 bg-[var(--bg-card)] border-b border-[var(--border-color)] shadow-sm transition-colors duration-300" <nav class="sticky top-0 z-40 bg-[var(--bg-card)] border-b border-[var(--border-color)] shadow-sm transition-colors duration-300"
x-data="{ mobileOpen: false, userDropdown: false }"> x-data="{ mobileOpen: false }">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-14"> <div class="flex items-center justify-between h-14">
@@ -21,103 +60,7 @@
<!-- Center: Navigation Links (Desktop) --> <!-- Center: Navigation Links (Desktop) -->
{% if current_user %} {% if current_user %}
<div class="hidden md:flex items-center gap-1"> <div class="hidden md:flex items-center gap-1">
{{ nav_links() }}
{# MeasurementTec: Misure #}
{% if current_user.get('roles') and 'MeasurementTec' in current_user.roles %}
<a href="{{ url_for('measure.select_recipe') }}"
class="nav-link group flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium
text-[var(--text-secondary)] hover:text-primary hover:bg-primary-50 dark:hover:bg-primary-900/20
transition-colors duration-200
{% if request.endpoint and request.endpoint.startswith('measure.') %}
text-primary bg-primary-50 dark:bg-primary-900/20
{% endif %}">
<!-- Clipboard Icon -->
<svg class="w-4.5 h-4.5" fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"/>
</svg>
<span>{{ _('Misure') }}</span>
</a>
{% endif %}
{# Maker: Ricette #}
{% if current_user.get('roles') and 'Maker' in current_user.roles %}
<a href="{{ url_for('maker.recipe_list') }}"
class="nav-link group flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium
text-[var(--text-secondary)] hover:text-primary hover:bg-primary-50 dark:hover:bg-primary-900/20
transition-colors duration-200
{% if request.endpoint and request.endpoint.startswith('maker.') %}
text-primary bg-primary-50 dark:bg-primary-900/20
{% endif %}">
<!-- Edit/Pencil Icon -->
<svg class="w-4.5 h-4.5" fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
</svg>
<span>{{ _('Ricette') }}</span>
</a>
{% endif %}
{# Metrologist: Statistiche #}
{% if current_user.get('roles') and 'Metrologist' in current_user.roles %}
<a href="{{ url_for('statistics.dashboard') }}"
class="nav-link group flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium
text-[var(--text-secondary)] hover:text-primary hover:bg-primary-50 dark:hover:bg-primary-900/20
transition-colors duration-200
{% if request.endpoint and request.endpoint.startswith('statistics.') %}
text-primary bg-primary-50 dark:bg-primary-900/20
{% endif %}">
<!-- Chart Icon -->
<svg class="w-4.5 h-4.5" fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
</svg>
<span>{{ _('Statistiche') }}</span>
</a>
{% endif %}
{# Admin: Utenti #}
{% if current_user.get('is_admin') %}
<a href="{{ url_for('admin.user_list') }}"
class="nav-link group flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium
text-[var(--text-secondary)] hover:text-primary hover:bg-primary-50 dark:hover:bg-primary-900/20
transition-colors duration-200
{% if request.endpoint == 'admin.user_list' %}
text-primary bg-primary-50 dark:bg-primary-900/20
{% endif %}">
<!-- Users Icon -->
<svg class="w-4.5 h-4.5" fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z"/>
</svg>
<span>{{ _('Utenti') }}</span>
</a>
<a href="{{ url_for('admin.station_list') }}"
class="nav-link group flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium
text-[var(--text-secondary)] hover:text-primary hover:bg-primary-50 dark:hover:bg-primary-900/20
transition-colors duration-200
{% if request.endpoint == 'admin.station_list' %}
text-primary bg-primary-50 dark:bg-primary-900/20
{% endif %}">
<!-- Station / Workstation Icon -->
<svg class="w-4.5 h-4.5" fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 17.25v1.007a3 3 0 01-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0115 18.257V17.25m6-12V15a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 15V5.25m18 0A2.25 2.25 0 0018.75 3H5.25A2.25 2.25 0 003 5.25m18 0V12a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 12V5.25"/>
</svg>
<span>{{ _('Stazioni') }}</span>
</a>
<a href="{{ url_for('admin.settings_page') }}"
class="nav-link group flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium
text-[var(--text-secondary)] hover:text-primary hover:bg-primary-50 dark:hover:bg-primary-900/20
transition-colors duration-200
{% if request.endpoint == 'admin.settings_page' %}
text-primary bg-primary-50 dark:bg-primary-900/20
{% endif %}">
<svg class="w-4.5 h-4.5" fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M10.343 3.94c.09-.542.56-.94 1.11-.94h1.093c.55 0 1.02.398 1.11.94l.149.894c.07.424.384.764.78.93.398.164.855.142 1.205-.108l.737-.527a1.125 1.125 0 011.45.12l.773.774c.39.389.44 1.002.12 1.45l-.527.737c-.25.35-.272.806-.107 1.204.165.397.505.71.93.78l.893.15c.543.09.94.56.94 1.109v1.094c0 .55-.397 1.02-.94 1.11l-.893.149c-.425.07-.765.383-.93.78-.165.398-.143.854.107 1.204l.527.738c.32.447.269 1.06-.12 1.45l-.774.773a1.125 1.125 0 01-1.449.12l-.738-.527c-.35-.25-.806-.272-1.204-.107-.397.165-.71.505-.78.929l-.15.894c-.09.542-.56.94-1.11.94h-1.094c-.55 0-1.019-.398-1.11-.94l-.148-.894c-.071-.424-.384-.764-.781-.93-.398-.164-.854-.142-1.204.108l-.738.527c-.447.32-1.06.269-1.45-.12l-.773-.774a1.125 1.125 0 01-.12-1.45l.527-.737c.25-.35.273-.806.108-1.204-.165-.397-.506-.71-.93-.78l-.894-.15c-.542-.09-.94-.56-.94-1.109v-1.094c0-.55.398-1.02.94-1.11l.894-.149c.424-.07.765-.383.93-.78.165-.398.143-.854-.107-1.204l-.527-.738a1.125 1.125 0 01.12-1.45l.773-.773a1.125 1.125 0 011.45-.12l.737.527c.35.25.807.272 1.204.107.397-.165.71-.505.78-.929l.15-.894z"/>
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
<span>{{ _('Impostazioni') }}</span>
</a>
{% endif %}
</div> </div>
{% endif %} {% endif %}
@@ -126,24 +69,17 @@
<!-- Language Toggle --> <!-- Language Toggle -->
<div class="flex items-center border border-[var(--border-color)] rounded-lg overflow-hidden"> <div class="flex items-center border border-[var(--border-color)] rounded-lg overflow-hidden">
<a href="{{ url_for('set_language', lang='it') }}" {% for lang_code in ['it', 'en'] %}
<a href="{{ url_for('set_language', lang=lang_code) }}"
class="px-2 py-1.5 text-xs font-semibold transition-colors duration-200 class="px-2 py-1.5 text-xs font-semibold transition-colors duration-200
{% if current_language == 'it' %} {% if current_language == lang_code %}
bg-primary text-white bg-primary text-white
{% else %} {% else %}
text-[var(--text-secondary)] hover:bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-secondary)]
{% endif %}"> {% endif %}">
IT {{ lang_code|upper }}
</a>
<a href="{{ url_for('set_language', lang='en') }}"
class="px-2 py-1.5 text-xs font-semibold transition-colors duration-200
{% if current_language == 'en' %}
bg-primary text-white
{% else %}
text-[var(--text-secondary)] hover:bg-[var(--bg-secondary)]
{% endif %}">
EN
</a> </a>
{% endfor %}
</div> </div>
<!-- Theme Toggle --> <!-- Theme Toggle -->
@@ -265,77 +201,7 @@
x-cloak x-cloak
class="md:hidden border-t border-[var(--border-color)] bg-[var(--bg-card)]"> class="md:hidden border-t border-[var(--border-color)] bg-[var(--bg-card)]">
<div class="px-4 py-3 space-y-1"> <div class="px-4 py-3 space-y-1">
{{ nav_links(mobile=true) }}
{% if current_user.get('roles') and 'MeasurementTec' in current_user.roles %}
<a href="{{ url_for('measure.select_recipe') }}"
class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium
text-[var(--text-secondary)] hover:text-primary hover:bg-primary-50 dark:hover:bg-primary-900/20
transition-colors">
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"/>
</svg>
{{ _('Misure') }}
</a>
{% endif %}
{% if current_user.get('roles') and 'Maker' in current_user.roles %}
<a href="{{ url_for('maker.recipe_list') }}"
class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium
text-[var(--text-secondary)] hover:text-primary hover:bg-primary-50 dark:hover:bg-primary-900/20
transition-colors">
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
</svg>
{{ _('Ricette') }}
</a>
{% endif %}
{% if current_user.get('roles') and 'Metrologist' in current_user.roles %}
<a href="{{ url_for('statistics.dashboard') }}"
class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium
text-[var(--text-secondary)] hover:text-primary hover:bg-primary-50 dark:hover:bg-primary-900/20
transition-colors">
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
</svg>
{{ _('Statistiche') }}
</a>
{% endif %}
{# Admin: Utenti + Stazioni #}
{% if current_user.get('is_admin') %}
<a href="{{ url_for('admin.user_list') }}"
class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium
text-[var(--text-secondary)] hover:text-primary hover:bg-primary-50 dark:hover:bg-primary-900/20
transition-colors">
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z"/>
</svg>
{{ _('Utenti') }}
</a>
<a href="{{ url_for('admin.station_list') }}"
class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium
text-[var(--text-secondary)] hover:text-primary hover:bg-primary-50 dark:hover:bg-primary-900/20
transition-colors">
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 17.25v1.007a3 3 0 01-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0115 18.257V17.25m6-12V15a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 15V5.25m18 0A2.25 2.25 0 0018.75 3H5.25A2.25 2.25 0 003 5.25m18 0V12a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 12V5.25"/>
</svg>
{{ _('Stazioni') }}
</a>
<a href="{{ url_for('admin.settings_page') }}"
class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium
text-[var(--text-secondary)] hover:text-primary hover:bg-primary-50 dark:hover:bg-primary-900/20
transition-colors">
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M10.343 3.94c.09-.542.56-.94 1.11-.94h1.093c.55 0 1.02.398 1.11.94l.149.894c.07.424.384.764.78.93.398.164.855.142 1.205-.108l.737-.527a1.125 1.125 0 011.45.12l.773.774c.39.389.44 1.002.12 1.45l-.527.737c-.25.35-.272.806-.107 1.204.165.397.505.71.93.78l.893.15c.543.09.94.56.94 1.109v1.094c0 .55-.397 1.02-.94 1.11l-.893.149c-.425.07-.765.383-.93.78-.165.398-.143.854.107 1.204l.527.738c.32.447.269 1.06-.12 1.45l-.774.773a1.125 1.125 0 01-1.449.12l-.738-.527c-.35-.25-.806-.272-1.204-.107-.397.165-.71.505-.78.929l-.15.894c-.09.542-.56.94-1.11.94h-1.094c-.55 0-1.019-.398-1.11-.94l-.148-.894c-.071-.424-.384-.764-.781-.93-.398-.164-.854-.142-1.204.108l-.738.527c-.447.32-1.06.269-1.45-.12l-.773-.774a1.125 1.125 0 01-.12-1.45l.527-.737c.25-.35.273-.806.108-1.204-.165-.397-.506-.71-.93-.78l-.894-.15c-.542-.09-.94-.56-.94-1.109v-1.094c0-.55.398-1.02.94-1.11l.894-.149c.424-.07.765-.383.93-.78.165-.398.143-.854-.107-1.204l-.527-.738a1.125 1.125 0 01.12-1.45l.773-.773a1.125 1.125 0 011.45-.12l.737.527c.35.25.807.272 1.204.107.397-.165.71-.505.78-.929l.15-.894z"/>
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
{{ _('Impostazioni') }}
</a>
{% endif %}
</div> </div>
</div> </div>
{% endif %} {% endif %}
@@ -120,7 +120,7 @@
</div> </div>
<input type="text" <input type="text"
x-model="search" x-model="search"
class="tmf-input pl-10" class="tmf-input !pl-10"
:placeholder="'{{ _('Cerca per nome, codice o descrizione...') }}'"> :placeholder="'{{ _('Cerca per nome, codice o descrizione...') }}'">
</div> </div>
</div> </div>
@@ -3,7 +3,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: TieMeasureFlow 1.0\n" "Project-Id-Version: TieMeasureFlow 1.0\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-11 12:49+0000\n" "POT-Creation-Date: 2026-06-11 15:33+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: en\n" "Language: en\n"
@@ -163,8 +163,7 @@ msgstr "seconds due to inactivity."
msgid "Continua a lavorare" msgid "Continua a lavorare"
msgstr "Keep working" msgstr "Keep working"
#: templates/admin/settings.html:3 templates/components/navbar.html:117 #: templates/admin/settings.html:3 templates/components/navbar.html:37
#: templates/components/navbar.html:335
msgid "Impostazioni" msgid "Impostazioni"
msgstr "Settings" msgstr "Settings"
@@ -456,8 +455,8 @@ msgid "Nuovo Utente"
msgstr "New User" msgstr "New User"
#: templates/admin/users.html:48 templates/admin/users.html:173 #: templates/admin/users.html:48 templates/admin/users.html:173
#: templates/admin/users.html:179 templates/auth/login.html:26 #: templates/admin/users.html:179 templates/auth/login.html:33
#: templates/auth/login.html:39 templates/auth/profile.html:36 #: templates/auth/login.html:47 templates/auth/profile.html:36
#: templates/measure/task_execute.html:649 #: templates/measure/task_execute.html:649
msgid "Username" msgid "Username"
msgstr "Username" msgstr "Username"
@@ -509,7 +508,7 @@ msgid "Il nome utente non può essere modificato"
msgstr "Username cannot be changed" msgstr "Username cannot be changed"
#: templates/admin/users.html:206 templates/admin/users.html:214 #: templates/admin/users.html:206 templates/admin/users.html:214
#: templates/auth/login.html:47 templates/auth/login.html:59 #: templates/auth/login.html:55 templates/auth/login.html:69
#: templates/measure/task_execute.html:654 #: templates/measure/task_execute.html:654
msgid "Password" msgid "Password"
msgstr "Password" msgstr "Password"
@@ -579,28 +578,36 @@ msgid "Username, nome visualizzato e password sono obbligatori"
msgstr "Username, display name and password are required" msgstr "Username, display name and password are required"
# Login Page # Login Page
#: templates/auth/login.html:16 #: templates/auth/login.html:23
msgid "Accedi al sistema" msgid "Accedi al sistema"
msgstr "Sign in to your account" msgstr "Sign in to your account"
#: templates/auth/login.html:71 #: templates/auth/login.html:73
msgid "Nascondi password"
msgstr "Hide password"
#: templates/auth/login.html:73
msgid "Mostra password"
msgstr "Show password"
#: templates/auth/login.html:94
msgid "Accedi" msgid "Accedi"
msgstr "Sign In" msgstr "Sign In"
#: templates/auth/login.html:79 #: templates/auth/login.html:102
msgid "Hai dimenticato la password?" msgid "Hai dimenticato la password?"
msgstr "Forgot password?" msgstr "Forgot password?"
#: templates/auth/login.html:81 #: templates/auth/login.html:104
msgid "Contatta l'amministratore" msgid "Contatta l'amministratore"
msgstr "Contact administrator" msgstr "Contact administrator"
# Additional Login Page # Additional Login Page
#: templates/auth/login.html:88 #: templates/auth/login.html:111
msgid "Sistema di misurazione industriale" msgid "Sistema di misurazione industriale"
msgstr "Industrial measurement system" msgstr "Industrial measurement system"
#: templates/auth/profile.html:2 templates/components/navbar.html:211 #: templates/auth/profile.html:2 templates/components/navbar.html:147
msgid "Profilo" msgid "Profilo"
msgstr "Profile" msgstr "Profile"
@@ -650,8 +657,8 @@ msgstr "Logout from system"
msgid "Termina la sessione corrente e torna alla schermata di login" msgid "Termina la sessione corrente e torna alla schermata di login"
msgstr "End current session and return to login screen" msgstr "End current session and return to login screen"
#: templates/auth/profile.html:197 templates/components/navbar.html:222 #: templates/auth/profile.html:197 templates/components/navbar.html:158
#: templates/components/navbar.html:231 #: templates/components/navbar.html:167
msgid "Logout" msgid "Logout"
msgstr "Logout" msgstr "Logout"
@@ -720,33 +727,31 @@ msgid "NON CONFORME"
msgstr "NON-CONFORMING" msgstr "NON-CONFORMING"
# Navbar # Navbar
#: templates/components/navbar.html:38 templates/components/navbar.html:277 #: templates/components/navbar.html:26 templates/measure/task_complete.html:16
#: templates/measure/task_complete.html:16
#: templates/measure/task_execute.html:2 templates/measure/task_list.html:16 #: templates/measure/task_execute.html:2 templates/measure/task_list.html:16
msgid "Misure" msgid "Misure"
msgstr "Activities" msgstr "Activities"
#: templates/components/navbar.html:55 templates/components/navbar.html:289 #: templates/components/navbar.html:29 templates/maker/recipe_editor.html:51
#: templates/maker/recipe_editor.html:51 templates/maker/recipe_list.html:83 #: templates/maker/recipe_list.html:83 templates/maker/recipe_preview.html:61
#: templates/maker/recipe_preview.html:61 templates/maker/task_drawing.html:84 #: templates/maker/task_drawing.html:84 templates/maker/task_editor.html:110
#: templates/maker/task_editor.html:110 templates/maker/version_history.html:73 #: templates/maker/version_history.html:73
msgid "Ricette" msgid "Ricette"
msgstr "Recipes" msgstr "Recipes"
#: templates/components/navbar.html:72 templates/components/navbar.html:301 #: templates/components/navbar.html:32 templates/measure/task_complete.html:261
#: templates/measure/task_complete.html:261
msgid "Statistiche" msgid "Statistiche"
msgstr "Statistics" msgstr "Statistics"
#: templates/components/navbar.html:89 templates/components/navbar.html:314 #: templates/components/navbar.html:35
msgid "Utenti" msgid "Utenti"
msgstr "Users" msgstr "Users"
#: templates/components/navbar.html:103 templates/components/navbar.html:324 #: templates/components/navbar.html:36
msgid "Stazioni" msgid "Stazioni"
msgstr "Stations" msgstr "Stations"
#: templates/components/navbar.html:218 #: templates/components/navbar.html:154
msgid "Logout bloccato durante le misurazioni" msgid "Logout bloccato durante le misurazioni"
msgstr "Logout blocked during measurements" msgstr "Logout blocked during measurements"
@@ -3,7 +3,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: TieMeasureFlow 1.0\n" "Project-Id-Version: TieMeasureFlow 1.0\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-11 12:49+0000\n" "POT-Creation-Date: 2026-06-11 15:33+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: it\n" "Language: it\n"
@@ -163,8 +163,7 @@ msgstr "secondi per inattività."
msgid "Continua a lavorare" msgid "Continua a lavorare"
msgstr "Continua a lavorare" msgstr "Continua a lavorare"
#: templates/admin/settings.html:3 templates/components/navbar.html:117 #: templates/admin/settings.html:3 templates/components/navbar.html:37
#: templates/components/navbar.html:335
msgid "Impostazioni" msgid "Impostazioni"
msgstr "Impostazioni" msgstr "Impostazioni"
@@ -458,8 +457,8 @@ msgid "Nuovo Utente"
msgstr "Nuovo Utente" msgstr "Nuovo Utente"
#: templates/admin/users.html:48 templates/admin/users.html:173 #: templates/admin/users.html:48 templates/admin/users.html:173
#: templates/admin/users.html:179 templates/auth/login.html:26 #: templates/admin/users.html:179 templates/auth/login.html:33
#: templates/auth/login.html:39 templates/auth/profile.html:36 #: templates/auth/login.html:47 templates/auth/profile.html:36
#: templates/measure/task_execute.html:649 #: templates/measure/task_execute.html:649
msgid "Username" msgid "Username"
msgstr "Username" msgstr "Username"
@@ -511,7 +510,7 @@ msgid "Il nome utente non può essere modificato"
msgstr "Il nome utente non può essere modificato" msgstr "Il nome utente non può essere modificato"
#: templates/admin/users.html:206 templates/admin/users.html:214 #: templates/admin/users.html:206 templates/admin/users.html:214
#: templates/auth/login.html:47 templates/auth/login.html:59 #: templates/auth/login.html:55 templates/auth/login.html:69
#: templates/measure/task_execute.html:654 #: templates/measure/task_execute.html:654
msgid "Password" msgid "Password"
msgstr "Password" msgstr "Password"
@@ -581,28 +580,36 @@ msgid "Username, nome visualizzato e password sono obbligatori"
msgstr "Username, nome visualizzato e password sono obbligatori" msgstr "Username, nome visualizzato e password sono obbligatori"
# Login Page # Login Page
#: templates/auth/login.html:16 #: templates/auth/login.html:23
msgid "Accedi al sistema" msgid "Accedi al sistema"
msgstr "Accedi al sistema" msgstr "Accedi al sistema"
#: templates/auth/login.html:71 #: templates/auth/login.html:73
msgid "Nascondi password"
msgstr "Nascondi password"
#: templates/auth/login.html:73
msgid "Mostra password"
msgstr "Mostra password"
#: templates/auth/login.html:94
msgid "Accedi" msgid "Accedi"
msgstr "Accedi" msgstr "Accedi"
#: templates/auth/login.html:79 #: templates/auth/login.html:102
msgid "Hai dimenticato la password?" msgid "Hai dimenticato la password?"
msgstr "Hai dimenticato la password?" msgstr "Hai dimenticato la password?"
#: templates/auth/login.html:81 #: templates/auth/login.html:104
msgid "Contatta l'amministratore" msgid "Contatta l'amministratore"
msgstr "Contatta l'amministratore" msgstr "Contatta l'amministratore"
# Additional Login Page # Additional Login Page
#: templates/auth/login.html:88 #: templates/auth/login.html:111
msgid "Sistema di misurazione industriale" msgid "Sistema di misurazione industriale"
msgstr "Sistema di misurazione industriale" msgstr "Sistema di misurazione industriale"
#: templates/auth/profile.html:2 templates/components/navbar.html:211 #: templates/auth/profile.html:2 templates/components/navbar.html:147
msgid "Profilo" msgid "Profilo"
msgstr "Profilo" msgstr "Profilo"
@@ -652,8 +659,8 @@ msgstr "Esci dal sistema"
msgid "Termina la sessione corrente e torna alla schermata di login" msgid "Termina la sessione corrente e torna alla schermata di login"
msgstr "Termina la sessione corrente e torna alla schermata di login" msgstr "Termina la sessione corrente e torna alla schermata di login"
#: templates/auth/profile.html:197 templates/components/navbar.html:222 #: templates/auth/profile.html:197 templates/components/navbar.html:158
#: templates/components/navbar.html:231 #: templates/components/navbar.html:167
msgid "Logout" msgid "Logout"
msgstr "Logout" msgstr "Logout"
@@ -722,33 +729,31 @@ msgid "NON CONFORME"
msgstr "NON CONFORME" msgstr "NON CONFORME"
# Navbar # Navbar
#: templates/components/navbar.html:38 templates/components/navbar.html:277 #: templates/components/navbar.html:26 templates/measure/task_complete.html:16
#: templates/measure/task_complete.html:16
#: templates/measure/task_execute.html:2 templates/measure/task_list.html:16 #: templates/measure/task_execute.html:2 templates/measure/task_list.html:16
msgid "Misure" msgid "Misure"
msgstr "Attività" msgstr "Attività"
#: templates/components/navbar.html:55 templates/components/navbar.html:289 #: templates/components/navbar.html:29 templates/maker/recipe_editor.html:51
#: templates/maker/recipe_editor.html:51 templates/maker/recipe_list.html:83 #: templates/maker/recipe_list.html:83 templates/maker/recipe_preview.html:61
#: templates/maker/recipe_preview.html:61 templates/maker/task_drawing.html:84 #: templates/maker/task_drawing.html:84 templates/maker/task_editor.html:110
#: templates/maker/task_editor.html:110 templates/maker/version_history.html:73 #: templates/maker/version_history.html:73
msgid "Ricette" msgid "Ricette"
msgstr "Ricette" msgstr "Ricette"
#: templates/components/navbar.html:72 templates/components/navbar.html:301 #: templates/components/navbar.html:32 templates/measure/task_complete.html:261
#: templates/measure/task_complete.html:261
msgid "Statistiche" msgid "Statistiche"
msgstr "Statistiche" msgstr "Statistiche"
#: templates/components/navbar.html:89 templates/components/navbar.html:314 #: templates/components/navbar.html:35
msgid "Utenti" msgid "Utenti"
msgstr "Utenti" msgstr "Utenti"
#: templates/components/navbar.html:103 templates/components/navbar.html:324 #: templates/components/navbar.html:36
msgid "Stazioni" msgid "Stazioni"
msgstr "Stazioni" msgstr "Stazioni"
#: templates/components/navbar.html:218 #: templates/components/navbar.html:154
msgid "Logout bloccato durante le misurazioni" msgid "Logout bloccato durante le misurazioni"
msgstr "Logout bloccato durante le misurazioni" msgstr "Logout bloccato durante le misurazioni"
@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-11 12:49+0000\n" "POT-Creation-Date: 2026-06-11 15:33+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -160,8 +160,7 @@ msgstr ""
msgid "Continua a lavorare" msgid "Continua a lavorare"
msgstr "" msgstr ""
#: templates/admin/settings.html:3 templates/components/navbar.html:117 #: templates/admin/settings.html:3 templates/components/navbar.html:37
#: templates/components/navbar.html:335
msgid "Impostazioni" msgid "Impostazioni"
msgstr "" msgstr ""
@@ -448,8 +447,8 @@ msgid "Nuovo Utente"
msgstr "" msgstr ""
#: templates/admin/users.html:48 templates/admin/users.html:173 #: templates/admin/users.html:48 templates/admin/users.html:173
#: templates/admin/users.html:179 templates/auth/login.html:26 #: templates/admin/users.html:179 templates/auth/login.html:33
#: templates/auth/login.html:39 templates/auth/profile.html:36 #: templates/auth/login.html:47 templates/auth/profile.html:36
#: templates/measure/task_execute.html:649 #: templates/measure/task_execute.html:649
msgid "Username" msgid "Username"
msgstr "" msgstr ""
@@ -501,7 +500,7 @@ msgid "Il nome utente non può essere modificato"
msgstr "" msgstr ""
#: templates/admin/users.html:206 templates/admin/users.html:214 #: templates/admin/users.html:206 templates/admin/users.html:214
#: templates/auth/login.html:47 templates/auth/login.html:59 #: templates/auth/login.html:55 templates/auth/login.html:69
#: templates/measure/task_execute.html:654 #: templates/measure/task_execute.html:654
msgid "Password" msgid "Password"
msgstr "" msgstr ""
@@ -570,27 +569,35 @@ msgstr ""
msgid "Username, nome visualizzato e password sono obbligatori" msgid "Username, nome visualizzato e password sono obbligatori"
msgstr "" msgstr ""
#: templates/auth/login.html:16 #: templates/auth/login.html:23
msgid "Accedi al sistema" msgid "Accedi al sistema"
msgstr "" msgstr ""
#: templates/auth/login.html:71 #: templates/auth/login.html:73
msgid "Nascondi password"
msgstr ""
#: templates/auth/login.html:73
msgid "Mostra password"
msgstr ""
#: templates/auth/login.html:94
msgid "Accedi" msgid "Accedi"
msgstr "" msgstr ""
#: templates/auth/login.html:79 #: templates/auth/login.html:102
msgid "Hai dimenticato la password?" msgid "Hai dimenticato la password?"
msgstr "" msgstr ""
#: templates/auth/login.html:81 #: templates/auth/login.html:104
msgid "Contatta l'amministratore" msgid "Contatta l'amministratore"
msgstr "" msgstr ""
#: templates/auth/login.html:88 #: templates/auth/login.html:111
msgid "Sistema di misurazione industriale" msgid "Sistema di misurazione industriale"
msgstr "" msgstr ""
#: templates/auth/profile.html:2 templates/components/navbar.html:211 #: templates/auth/profile.html:2 templates/components/navbar.html:147
msgid "Profilo" msgid "Profilo"
msgstr "" msgstr ""
@@ -638,8 +645,8 @@ msgstr ""
msgid "Termina la sessione corrente e torna alla schermata di login" msgid "Termina la sessione corrente e torna alla schermata di login"
msgstr "" msgstr ""
#: templates/auth/profile.html:197 templates/components/navbar.html:222 #: templates/auth/profile.html:197 templates/components/navbar.html:158
#: templates/components/navbar.html:231 #: templates/components/navbar.html:167
msgid "Logout" msgid "Logout"
msgstr "" msgstr ""
@@ -703,33 +710,31 @@ msgstr ""
msgid "NON CONFORME" msgid "NON CONFORME"
msgstr "" msgstr ""
#: templates/components/navbar.html:38 templates/components/navbar.html:277 #: templates/components/navbar.html:26 templates/measure/task_complete.html:16
#: templates/measure/task_complete.html:16
#: templates/measure/task_execute.html:2 templates/measure/task_list.html:16 #: templates/measure/task_execute.html:2 templates/measure/task_list.html:16
msgid "Misure" msgid "Misure"
msgstr "" msgstr ""
#: templates/components/navbar.html:55 templates/components/navbar.html:289 #: templates/components/navbar.html:29 templates/maker/recipe_editor.html:51
#: templates/maker/recipe_editor.html:51 templates/maker/recipe_list.html:83 #: templates/maker/recipe_list.html:83 templates/maker/recipe_preview.html:61
#: templates/maker/recipe_preview.html:61 templates/maker/task_drawing.html:84 #: templates/maker/task_drawing.html:84 templates/maker/task_editor.html:110
#: templates/maker/task_editor.html:110 templates/maker/version_history.html:73 #: templates/maker/version_history.html:73
msgid "Ricette" msgid "Ricette"
msgstr "" msgstr ""
#: templates/components/navbar.html:72 templates/components/navbar.html:301 #: templates/components/navbar.html:32 templates/measure/task_complete.html:261
#: templates/measure/task_complete.html:261
msgid "Statistiche" msgid "Statistiche"
msgstr "" msgstr ""
#: templates/components/navbar.html:89 templates/components/navbar.html:314 #: templates/components/navbar.html:35
msgid "Utenti" msgid "Utenti"
msgstr "" msgstr ""
#: templates/components/navbar.html:103 templates/components/navbar.html:324 #: templates/components/navbar.html:36
msgid "Stazioni" msgid "Stazioni"
msgstr "" msgstr ""
#: templates/components/navbar.html:218 #: templates/components/navbar.html:154
msgid "Logout bloccato durante le misurazioni" msgid "Logout bloccato durante le misurazioni"
msgstr "" msgstr ""