Tag progetto, @menzioni, appuntamenti da conversazioni

- Modello Tag con nome e colore, M2M su Conversazione
- Modello Appuntamento con luogo, note, partecipanti, link a Conversazione
- @menzioni nei commenti e aggiornamenti: @username → link al profilo
- Autocomplete JS per @menzioni nelle textarea
- Auto-data conversazioni (default=now)
- CRUD completo appuntamenti con permessi autore
- Appuntamenti in agenda, dashboard, dettaglio conversazione
- Crea riunione direttamente da una conversazione (pre-compila titolo e partecipanti)
- Admin: Tag, Appuntamento registrati
This commit is contained in:
automationkriz
2026-04-07 14:28:47 +00:00
parent 006bb24215
commit 09f51b1227
19 changed files with 828 additions and 12 deletions

View File

@@ -12,6 +12,9 @@
<small class="text-muted">Panoramica di scadenze e appuntamenti</small>
</div>
<div class="d-flex gap-2">
<a href="{% url 'appuntamento_nuovo' %}" class="btn btn-sm btn-outline-warning">
<i class="bi bi-plus-lg me-1"></i>Appuntamento
</a>
<a href="{% url 'obiettivo_nuovo' %}" class="btn btn-sm btn-outline-primary">
<i class="bi bi-plus-lg me-1"></i>Obiettivo
</a>
@@ -42,6 +45,10 @@
<div class="agenda-icon agenda-icon-scadenza">
<i class="bi bi-bullseye"></i>
</div>
{% elif ev.tipo == 'appuntamento' %}
<div class="agenda-icon agenda-icon-appuntamento">
<i class="bi bi-calendar-check"></i>
</div>
{% else %}
<div class="agenda-icon agenda-icon-conv">
<i class="bi bi-chat-quote"></i>
@@ -69,6 +76,14 @@
{% endif %}
{% endwith %}
</div>
{% elif ev.tipo == 'appuntamento' %}
<a href="{% url 'appuntamento_dettaglio' ev.obj.pk %}" class="text-decoration-none text-dark fw-semibold d-block">
<i class="bi bi-calendar-check me-1 text-warning"></i>{{ ev.obj.titolo }}
</a>
<div class="d-flex align-items-center gap-2 mt-1">
<small class="text-muted"><i class="bi bi-clock me-1"></i>{{ ev.obj.data_ora|date:"H:i" }}</small>
{% if ev.obj.luogo %}<small class="text-muted"><i class="bi bi-geo-alt me-1"></i>{{ ev.obj.luogo }}</small>{% endif %}
</div>
{% else %}
<a href="{% url 'conversazione_dettaglio' ev.obj.pk %}" class="text-decoration-none text-dark fw-semibold d-block">
{{ ev.obj.titolo }}
@@ -126,6 +141,10 @@
<div class="agenda-icon {% if ev.scaduto %}agenda-icon-danger{% else %}agenda-icon-scadenza{% endif %}">
<i class="bi {% if ev.scaduto %}bi-exclamation-triangle{% else %}bi-bullseye{% endif %}"></i>
</div>
{% elif ev.tipo == 'appuntamento' %}
<div class="agenda-icon agenda-icon-appuntamento" style="opacity:.6;">
<i class="bi bi-calendar-check"></i>
</div>
{% else %}
<div class="agenda-icon agenda-icon-conv" style="opacity:.6;">
<i class="bi bi-chat-quote"></i>
@@ -142,6 +161,11 @@
<div class="d-flex align-items-center gap-2 mt-1">
<span class="badge-stato stato-{{ ev.obj.stato }}">{{ ev.obj.get_stato_display }}</span>
</div>
{% elif ev.tipo == 'appuntamento' %}
<a href="{% url 'appuntamento_dettaglio' ev.obj.pk %}" class="text-decoration-none text-muted fw-semibold d-block">
<i class="bi bi-calendar-check me-1"></i>{{ ev.obj.titolo }}
</a>
<small class="text-muted">{{ ev.obj.data_ora|date:"H:i" }}{% if ev.obj.luogo %} · {{ ev.obj.luogo }}{% endif %}</small>
{% else %}
<a href="{% url 'conversazione_dettaglio' ev.obj.pk %}" class="text-decoration-none text-muted fw-semibold d-block">
{{ ev.obj.titolo }}