v0.0.4: e-mailtemplates met velden ({voornaam}, {model}, {afzender}…), te kiezen bij nieuwe e-mail, antwoord en contact; inbox met nieuwe e-mail, doorsturen, CC en bijlagen, Verzonden, Archief, zoeken, als ongelezen markeren en alles gelezen; agenda per gebruiker met CalDAV (/dav/, app-wachtwoord in Mijn account); zoeken en Nieuw in de bovenbalk; e-mailinstellingen met voorinstellingen (OVHcloud, Gmail), beveiliging per server, kopie in Verzonden en verbindingstest; offerte in het klantportaal

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Machiel
2026-10-16 17:29:47 +02:00
co-authored by Claude Opus 5.5
parent 81fc27fa86
commit 366a3f9d17
26 changed files with 2095 additions and 271 deletions
+44 -5
View File
@@ -3,6 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
{% block head %}{% endblock %}
<title>{% block title %}CRM{% endblock %} · Van Emous CRM</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@@ -19,6 +20,8 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js" defer></script>
<script src="{{ url_for('static', filename='fx.js') }}" defer></script>
{% if g.user %}<script src="{{ url_for('static', filename='search.js') }}" defer></script>{% endif %}
{% block styles %}{% endblock %}
</head>
<body>
{% block body %}
@@ -40,7 +43,9 @@
<a href="{{ url_for('relations', kind='klant') }}" class="{{ 'active' if ep.startswith('relation') and rkind == 'klant' }}">Klanten</a>
<a href="{{ url_for('relations', kind='partner') }}" class="{{ 'active' if ep.startswith('relation') and rkind == 'partner' }}">Partners</a>
<a href="{{ url_for('contacts') }}" class="{{ 'active' if ep.startswith('contact') and ctype != 'lead' }}">Contactpersonen</a>
<a href="{{ url_for('inbox') }}" class="{{ 'active' if ep.startswith('inbox') }}">Inbox {% if unread %}<span class="count">{{ unread }}</span>{% endif %}</a>
<a href="{{ url_for('calendar_view') }}" class="{{ 'active' if ep.startswith('calendar') }}">Agenda</a>
<a href="{{ url_for('inbox') }}" class="{{ 'active' if ep.startswith('inbox') or ep in ('mail_new', 'mail_send') }}">Inbox {% if unread %}<span class="count">{{ unread }}</span>{% endif %}</a>
<a href="{{ url_for('mail_templates') }}" class="{{ 'active' if ep.startswith('mail_template') }}">E-mailtemplates</a>
<a href="{{ url_for('products') }}" class="{{ 'active' if ep.startswith('product') }}">Producten</a>
<a href="{{ url_for('quotes') }}" class="{{ 'active' if ep.startswith('quote') }}">Offertes</a>
<a href="{{ url_for('import_start') }}" class="{{ 'active' if ep.startswith('import') }}">Importeren</a>
@@ -55,12 +60,45 @@
</div>
</aside>
<div class="app-main">
<header class="topbar d-lg-none">
<button class="menu-btn" type="button" data-bs-toggle="offcanvas" data-bs-target="#sidenav" aria-controls="sidenav">
<header class="topbar">
<button class="menu-btn d-lg-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#sidenav" aria-controls="sidenav">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M4 6h16M4 12h16M4 18h16"/></svg>Menu
</button>
<a href="{{ url_for('dashboard') }}"><img src="{{ url_for('static', filename='logo.svg') }}" alt="Van Emous"></a>
{% if unread %}<a href="{{ url_for('inbox') }}" class="count" aria-label="{{ unread }} ongelezen e-mail">{{ unread }}</a>{% endif %}
<a href="{{ url_for('dashboard') }}" class="topbar-logo d-lg-none"><img src="{{ url_for('static', filename='logo.svg') }}" alt="Van Emous"></a>
<div class="topbar-tools">
{% set sq = request.args.get('q', '') if ep == 'search' else '' %}
{% macro search_form(id, sq) %}
<form class="tsearch" action="{{ url_for('search') }}" method="get" role="search" data-live="{{ url_for('search_live') }}">
<svg class="tsearch-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>
<input class="form-control" id="{{ id }}" type="search" name="q" value="{{ sq }}" placeholder="Zoek lead, klant, offerte…" autocomplete="off" aria-label="Zoeken" aria-controls="{{ id }}-results" aria-autocomplete="list">
<div class="tsearch-results" id="{{ id }}-results" role="listbox" aria-label="Zoekresultaten"></div>
</form>
{% endmacro %}
<div class="d-none d-md-block">{{ search_form('q-top', sq) }}</div>
<div class="dropdown d-md-none">
<button class="icon-btn" type="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false" aria-label="Zoeken">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>
</button>
<div class="dropdown-menu dropdown-menu-end tsearch-pop">{{ search_form('q-pop', sq) }}</div>
</div>
{% if unread %}<a href="{{ url_for('inbox') }}" class="count d-lg-none" aria-label="{{ unread }} ongelezen e-mail">{{ unread }}</a>{% endif %}
<div class="dropdown">
<button class="btn btn-primary btn-sm new-btn" type="button" data-bs-toggle="dropdown" aria-expanded="false" aria-label="Nieuw">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg><span class="d-none d-sm-inline">Nieuw</span>
</button>
<ul class="dropdown-menu dropdown-menu-end new-menu">
<li><a class="dropdown-item" href="{{ url_for('contact_new', type='lead') }}">Lead</a></li>
<li><a class="dropdown-item" href="{{ url_for('contact_new', type='klant') }}">Contactpersoon</a></li>
<li><a class="dropdown-item" href="{{ url_for('relation_edit', kind='klant') }}">Klant</a></li>
<li><a class="dropdown-item" href="{{ url_for('relation_edit', kind='partner') }}">Partner</a></li>
<li><hr class="dropdown-divider"></li>
<li><form method="post" action="{{ url_for('quote_new') }}"><button class="dropdown-item">Offerte</button></form></li>
<li><a class="dropdown-item" href="{{ url_for('product_edit') }}">Product</a></li>
<li><a class="dropdown-item" href="{{ url_for('calendar_edit') }}">Afspraak</a></li>
<li><a class="dropdown-item" href="{{ url_for('mail_new') }}">E-mail</a></li>
</ul>
</div>
</div>
</header>
<main class="content">
{% with msgs = get_flashed_messages(with_categories=true) %}
@@ -71,5 +109,6 @@
</div>
</div>
{% endblock %}
{% block scripts %}{% endblock %}
</body>
</html>