Initial commit – AufmaßCreater v2.35
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="level">
|
||||
<div class="level-left">
|
||||
<h1 class="title is-3">Dashboard</h1>
|
||||
</div>
|
||||
<div class="level-right">
|
||||
<div class="field has-addons">
|
||||
<div class="control">
|
||||
<div class="select is-small">
|
||||
<select id="profile-select" onchange="loadProfile(this.value)">
|
||||
{% for p in profile_list or [] %}
|
||||
<option value="{{ p.id }}" {{ 'selected' if active_profile and active_profile.id == p.id }}>{{ p.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button is-small is-info" onclick="saveProfile()">Speichern</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button is-small is-light" onclick="newProfile()">+ Neu</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="dashboard-cards" class="columns is-multiline mt-3">
|
||||
<div class="column is-one-third" data-card="projekte">
|
||||
<div class="box has-text-centered">
|
||||
<p class="heading">Projekte (aktiv)</p>
|
||||
<p class="title">{{ projekte_anzahl or 0 }}</p>
|
||||
<a href="{{ url_for('aufmass.index') }}" class="button is-small is-link is-outlined mt-2">Alle Projekte</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-one-third" data-card="module">
|
||||
<div class="box has-text-centered">
|
||||
<p class="heading">Module verfügbar</p>
|
||||
<p class="title">{{ modules|length }}</p>
|
||||
<a href="{{ url_for('admin.firma') }}" class="button is-small is-link is-outlined mt-2">Module verwalten</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-one-third" data-card="mitarbeiter">
|
||||
<div class="box has-text-centered">
|
||||
<p class="heading">Mitarbeiter</p>
|
||||
<p class="title">{{ mitarbeiter_anzahl }}</p>
|
||||
<a href="{{ url_for('admin.firma') }}" class="button is-small is-link is-outlined mt-2">Mitarbeiter verwalten</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-one-third" data-card="projektwerte">
|
||||
<div class="box">
|
||||
<p class="heading">Projektwerte (€)</p>
|
||||
{% if gesamt_summe > 0 %}
|
||||
<p class="is-size-4 has-text-weight-bold has-text-primary">Gesamt: {{ gesamt_summe|german_number }} €</p>
|
||||
<table class="table is-fullwidth is-hoverable mt-2" style="font-size:0.85rem">
|
||||
<thead><tr><th>Bezeichnung</th><th style="text-align:right">Wert (€)</th></tr></thead>
|
||||
<tbody>
|
||||
{% for p, summe in projekte_mit_summe %}
|
||||
<tr>
|
||||
<td><a href="{{ url_for('aufmass.aufmass_list', project_id=p.id) }}">{{ p.bezeichnung or p.sm_nr }}</a></td>
|
||||
<td style="text-align:right">{{ summe|german_number }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p class="has-text-grey is-size-7">Keine Projekte mit Werten.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box" data-card="lizenzen">
|
||||
<h2 class="title is-5">Lizenzen</h2>
|
||||
<div class="columns is-multiline">
|
||||
<div class="column is-one-third">
|
||||
<div class="notification is-light has-text-centered" style="margin-bottom:0">
|
||||
<p class="heading">Mitarbeiter</p>
|
||||
<p class="title is-4">{{ mitarbeiter_anzahl }}/{{ license_max_ma }}</p>
|
||||
<p class="is-size-7 has-text-grey">belegt/verfügbar</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-one-third">
|
||||
<div class="notification is-light has-text-centered" style="margin-bottom:0">
|
||||
<p class="heading">Module</p>
|
||||
<p class="title is-4">{{ license_module_used }}/{{ license_module_count }}</p>
|
||||
<p class="is-size-7 has-text-grey">belegt/verfügbar</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-one-third">
|
||||
<div class="notification is-light has-text-centered" style="margin-bottom:0">
|
||||
<p class="heading">Lizenzen</p>
|
||||
<p class="title is-4">{{ license_count }}</p>
|
||||
<p class="is-size-7 has-text-grey">vorhanden</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.6/Sortable.min.js"></script>
|
||||
<script>
|
||||
var cardContainer = document.getElementById('dashboard-cards');
|
||||
|
||||
new Sortable(cardContainer, {
|
||||
animation: 150,
|
||||
handle: '.box',
|
||||
onEnd: function() {
|
||||
var order = [];
|
||||
cardContainer.querySelectorAll('.column[data-card]').forEach(function(col) {
|
||||
order.push(col.dataset.card);
|
||||
});
|
||||
localStorage.setItem('dash_order_' + {{ current_user.id }}, JSON.stringify(order));
|
||||
}
|
||||
});
|
||||
|
||||
function loadOrder() {
|
||||
var saved = localStorage.getItem('dash_order_' + {{ current_user.id }});
|
||||
if (!saved) return;
|
||||
var order = JSON.parse(saved);
|
||||
var cards = {};
|
||||
cardContainer.querySelectorAll('.column[data-card]').forEach(function(col) {
|
||||
cards[col.dataset.card] = col;
|
||||
});
|
||||
order.forEach(function(key) {
|
||||
if (cards[key]) cardContainer.appendChild(cards[key]);
|
||||
});
|
||||
}
|
||||
loadOrder();
|
||||
|
||||
function saveProfile() {
|
||||
var order = [];
|
||||
cardContainer.querySelectorAll('.column[data-card]').forEach(function(col) {
|
||||
order.push(col.dataset.card);
|
||||
});
|
||||
var lizOrder = document.querySelector('[data-card="lizenzen"]');
|
||||
var sel = document.getElementById('profile-select');
|
||||
var profileId = sel.value;
|
||||
fetch('/api/profiles/' + (profileId || ''), {
|
||||
method: profileId ? 'PUT' : 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
name: 'Dashboard',
|
||||
view_type: 'dashboard',
|
||||
config_json: {card_order: order}
|
||||
})
|
||||
}).then(function(r){return r.json()}).then(function(data){
|
||||
if (data.id) {
|
||||
var opt = sel.querySelector('option[value="'+profileId+'"]');
|
||||
if (!opt) {
|
||||
opt = document.createElement('option');
|
||||
opt.value = data.id;
|
||||
opt.textContent = data.name || 'Dashboard';
|
||||
sel.appendChild(opt);
|
||||
}
|
||||
sel.value = data.id;
|
||||
}
|
||||
alert('Gespeichert');
|
||||
});
|
||||
}
|
||||
|
||||
function loadProfile(profileId) {
|
||||
if (!profileId) return;
|
||||
fetch('/api/profiles/' + profileId)
|
||||
.then(function(r){return r.json()})
|
||||
.then(function(data){
|
||||
var cfg = data.config_json || {};
|
||||
if (cfg.card_order) {
|
||||
var cards = {};
|
||||
cardContainer.querySelectorAll('.column[data-card]').forEach(function(col) {
|
||||
cards[col.dataset.card] = col;
|
||||
});
|
||||
cfg.card_order.forEach(function(key) {
|
||||
if (cards[key]) cardContainer.appendChild(cards[key]);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function newProfile() {
|
||||
var name = prompt('Profil-Name:');
|
||||
if (!name) return;
|
||||
fetch('/api/profiles', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
name: name,
|
||||
view_type: 'dashboard',
|
||||
config_json: {card_order: []}
|
||||
})
|
||||
}).then(function(r){return r.json()}).then(function(data){
|
||||
if (data.id) {
|
||||
var sel = document.getElementById('profile-select');
|
||||
var opt = document.createElement('option');
|
||||
opt.value = data.id;
|
||||
opt.textContent = data.name;
|
||||
opt.selected = true;
|
||||
sel.appendChild(opt);
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,203 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="level">
|
||||
<div class="level-left"><h1 class="title is-3">{{ company.name }}</h1></div>
|
||||
<div class="level-right">
|
||||
<a class="button is-light" href="{{ url_for('admin.dashboard') }}">← Zurück</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h2 class="title is-5">Mitarbeiter</h2>
|
||||
<table class="table is-fullwidth is-hoverable">
|
||||
<thead>
|
||||
<tr><th>Name</th><th>E-Mail</th><th>Rolle</th><th>Status</th><th>Rechte</th><th>Aktion</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for u in users %}
|
||||
<tr>
|
||||
<td>{{ u.full_name }}</td>
|
||||
<td>{{ u.email }}</td>
|
||||
<td>
|
||||
<span class="tag {{ 'is-warning' if u.is_firmadmin() else 'is-light' }}">
|
||||
{{ u.rolle }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tag {{ 'is-success' if u.aktiv else 'is-danger' }}">
|
||||
{{ 'Aktiv' if u.aktiv else 'Deaktiviert' }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
{% if u.rolle == 'mitarbeiter' %}
|
||||
<a class="button is-small is-link is-outlined" href="{{ url_for('admin.mitarbeiter_rechte', user_id=u.id) }}">Rechte</a>
|
||||
{% else %}
|
||||
<span class="has-text-grey is-size-7">–</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if current_user.is_firmadmin() and u.id != current_user.id %}
|
||||
<a class="button is-small is-info is-outlined" href="{{ url_for('admin.mitarbeiter_bearbeiten', user_id=u.id) }}">Bearbeiten</a>
|
||||
<a class="button is-small {{ 'is-warning' if u.aktiv else 'is-success' }}"
|
||||
href="{{ url_for('admin.mitarbeiter_toggle', user_id=u.id) }}">
|
||||
{{ 'Deaktivieren' if u.aktiv else 'Aktivieren' }}
|
||||
</a>
|
||||
<form method="POST" action="{{ url_for('admin.mitarbeiter_loeschen', user_id=u.id) }}"
|
||||
style="display:inline" onsubmit="return confirm('Benutzer {{ u.email }} wirklich löschen?')">
|
||||
<button class="button is-small is-danger">Löschen</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% if current_user.is_firmadmin() %}
|
||||
<details class="mt-3">
|
||||
<summary class="has-text-link">+ Mitarbeiter hinzufügen</summary>
|
||||
<form method="POST" action="{{ url_for('admin.mitarbeiter_neu') }}" class="mt-2 box">
|
||||
<div class="columns is-multiline">
|
||||
<div class="column is-4">
|
||||
<input class="input" type="email" name="email" placeholder="E-Mail *" required>
|
||||
</div>
|
||||
<div class="column is-3">
|
||||
<input class="input" type="text" name="vorname" placeholder="Vorname">
|
||||
</div>
|
||||
<div class="column is-3">
|
||||
<input class="input" type="text" name="nachname" placeholder="Nachname">
|
||||
</div>
|
||||
<div class="column is-2">
|
||||
<div class="select is-fullwidth">
|
||||
<select name="rolle">
|
||||
<option value="mitarbeiter">Mitarbeiter</option>
|
||||
<option value="firmadmin">Firmadmin</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<input class="input" type="password" name="password" placeholder="Start-Passwort" minlength="6" required>
|
||||
</div>
|
||||
<div class="column is-8">
|
||||
<label class="checkbox is-size-7 mr-3"><input type="checkbox" name="darf_projekte_anlegen" value="1"> Projekte anlegen</label>
|
||||
<label class="checkbox is-size-7 mr-3"><input type="checkbox" name="darf_lv_verwalten" value="1"> LV verwalten</label>
|
||||
<label class="checkbox is-size-7 mr-3"><input type="checkbox" name="darf_preise_sehen" value="1"> Preise sehen</label>
|
||||
<label class="checkbox is-size-7"><input type="checkbox" name="darf_aufmass_verwalten" value="1"> Aufmaße verwalten</label>
|
||||
{% if company.evergabe_aktiviert %}
|
||||
<br>
|
||||
<label class="checkbox is-size-7 mr-3"><input type="checkbox" name="darf_evergabe_nutzen" value="1"> E-Vergabe Addon nutzen</label>
|
||||
<label class="checkbox is-size-7 mr-3"><input type="checkbox" name="darf_kopfdaten_holen" value="1"> Kopfdaten holen</label>
|
||||
<label class="checkbox is-size-7"><input type="checkbox" name="darf_aufmass_uebertragen" value="1"> Aufmaße übertragen</label>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="column is-2">
|
||||
<button class="button is-primary" type="submit">Anlegen</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</details>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h2 class="title is-5">Firmenlogo</h2>
|
||||
{% if company.logo %}
|
||||
<div style="margin-bottom:12px">
|
||||
<img src="{{ url_for('admin.firma_logo') }}" alt="Logo" style="max-width:200px;max-height:80px;border:1px solid #ddd;border-radius:6px;padding:8px">
|
||||
<p class="is-size-7 has-text-grey mt-1">Aktuelles Logo</p>
|
||||
<form method="POST" action="{{ url_for('admin.firma_logo_upload') }}" style="display:inline">
|
||||
<input type="hidden" name="delete" value="1">
|
||||
<button class="button is-small is-danger is-outlined" type="submit">Entfernen</button>
|
||||
</form>
|
||||
</div>
|
||||
{% else %}
|
||||
<div style="margin-bottom:12px;display:flex;align-items:center;gap:12px;border:2px dashed #ccc;border-radius:8px;padding:16px;background:#fafafa">
|
||||
<div style="width:60px;height:60px;background:#e0e0e0;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:24px;color:#999">🏢</div>
|
||||
<div>
|
||||
<p style="font-weight:600;font-size:1rem;color:#555">{{ company.name }}</p>
|
||||
<p class="is-size-7 has-text-grey">Kein Logo hochgeladen</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<form method="POST" action="{{ url_for('admin.firma_logo_upload') }}" enctype="multipart/form-data">
|
||||
<div class="field has-addons">
|
||||
<div class="control">
|
||||
<input class="input is-small" type="file" name="logo" accept="image/png,image/jpeg,image/gif,image/webp" required>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button is-small is-primary" type="submit">Hochladen</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="is-size-7 has-text-grey">Erlaubte Formate: PNG, JPG, GIF, WebP</p>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h2 class="title is-5">Verfügbare Module ({{ modules|length }})</h2>
|
||||
<p class="is-size-7 has-text-grey mb-2">Diese Module stehen Ihrer Firma zur Verfügung.</p>
|
||||
<table class="table is-fullwidth is-hoverable">
|
||||
<thead><tr><th>Modul</th><th>Kategorie</th></tr></thead>
|
||||
<tbody>
|
||||
{% for m in modules %}
|
||||
<tr>
|
||||
<td>{{ m.icon }} {{ m.titel }}</td>
|
||||
<td>{{ m.kategorie or '–' }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h2 class="title is-5">Lizenz</h2>
|
||||
{% if licenses %}
|
||||
<table class="table is-fullwidth">
|
||||
<thead><tr><th>UID</th><th>Mitarbeiter-Plätze</th><th>Modul-Plätze</th><th>Status</th></tr></thead>
|
||||
<tbody>
|
||||
{% for lic in licenses %}
|
||||
<tr>
|
||||
<td><code>{{ lic.uid }}</code></td>
|
||||
<td>{{ lic.user_slots_display() }}</td>
|
||||
<td>{{ lic.module_slots_display() }}</td>
|
||||
<td><span class="tag {{ 'is-success' if lic.aktiv else 'is-danger' }}">{{ 'Aktiv' if lic.aktiv else 'Inaktiv' }}</span></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p class="has-text-grey">Keine Lizenz hinterlegt. Standard-Module sind aktiv.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if company.evergabe_aktiviert %}
|
||||
<div class="box">
|
||||
<h2 class="title is-5">E-Vergabe</h2>
|
||||
<p class="is-size-7 has-text-grey mb-2">Logindaten für die E-Vergabe-Plattform.</p>
|
||||
<form method="POST" action="{{ url_for('admin.firma_evergabe_save') }}">
|
||||
<div class="columns is-multiline">
|
||||
<div class="column is-3">
|
||||
<div class="field">
|
||||
<label class="label is-small">Benutzer</label>
|
||||
<div class="control"><input class="input is-small" name="evergabe_benutzer" value="{{ company.evergabe_benutzer or '' }}"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3">
|
||||
<div class="field">
|
||||
<label class="label is-small">Passwort</label>
|
||||
<div class="control"><input class="input is-small" name="evergabe_passwort" type="password" value="{{ company.evergabe_passwort or '' }}"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3">
|
||||
<div class="field">
|
||||
<label class="label is-small">Name</label>
|
||||
<div class="control"><input class="input is-small" name="evergabe_name" value="{{ company.evergabe_name or '' }}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field mt-3">
|
||||
<button class="button is-small is-primary" type="submit">Speichern</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,90 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="level">
|
||||
<div class="level-left"><h1 class="title is-3">Benutzer bearbeiten: {{ user.full_name }}</h1></div>
|
||||
<div class="level-right">
|
||||
{% if current_user.is_superadmin() %}
|
||||
<a class="button is-small" href="{{ url_for('superadmin.firma_detail', company_id=user.company_id) }}">← Firma</a>
|
||||
{% else %}
|
||||
<a class="button is-small" href="{{ url_for('admin.firma') }}">← Firma</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<form method="POST">
|
||||
<div class="columns is-multiline">
|
||||
<div class="column is-4">
|
||||
<div class="field">
|
||||
<label class="label">E-Mail</label>
|
||||
<div class="control">
|
||||
<input class="input" type="email" name="email" value="{{ user.email }}" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3">
|
||||
<div class="field">
|
||||
<label class="label">Vorname</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" name="vorname" value="{{ user.vorname or '' }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3">
|
||||
<div class="field">
|
||||
<label class="label">Nachname</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" name="nachname" value="{{ user.nachname or '' }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-2">
|
||||
<div class="field">
|
||||
<label class="label">Rolle</label>
|
||||
<div class="control">
|
||||
<div class="select is-fullwidth">
|
||||
<select name="rolle">
|
||||
<option value="mitarbeiter" {{ 'selected' if user.rolle == 'mitarbeiter' }}>Mitarbeiter</option>
|
||||
<option value="firmadmin" {{ 'selected' if user.rolle == 'firmadmin' }}>Firmadmin</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<div class="field">
|
||||
<label class="label">Neues Passwort (leer lassen für keine Änderung)</label>
|
||||
<div class="control">
|
||||
<input class="input" type="password" name="password" minlength="6" placeholder="mind. 6 Zeichen">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-8">
|
||||
<div class="field">
|
||||
<label class="label">Berechtigungen</label>
|
||||
<div class="control">
|
||||
<label class="checkbox is-size-7 mr-3"><input type="checkbox" name="darf_projekte_anlegen" value="1" {{ 'checked' if user.darf_projekte_anlegen }}> Projekte anlegen</label>
|
||||
<label class="checkbox is-size-7 mr-3"><input type="checkbox" name="darf_lv_verwalten" value="1" {{ 'checked' if user.darf_lv_verwalten }}> LV verwalten</label>
|
||||
<label class="checkbox is-size-7 mr-3"><input type="checkbox" name="darf_preise_sehen" value="1" {{ 'checked' if user.darf_preise_sehen }}> Preise sehen</label>
|
||||
<label class="checkbox is-size-7"><input type="checkbox" name="darf_aufmass_verwalten" value="1" {{ 'checked' if user.darf_aufmass_verwalten }}> Aufmaße verwalten</label>
|
||||
{% if company and company.evergabe_aktiviert %}
|
||||
<br>
|
||||
<label class="checkbox is-size-7 mr-3"><input type="checkbox" name="darf_evergabe_nutzen" value="1" {{ 'checked' if user.darf_evergabe_nutzen }}> E-Vergabe Addon nutzen</label>
|
||||
<label class="checkbox is-size-7 mr-3"><input type="checkbox" name="darf_kopfdaten_holen" value="1" {{ 'checked' if user.darf_kopfdaten_holen }}> Kopfdaten holen</label>
|
||||
<label class="checkbox is-size-7"><input type="checkbox" name="darf_aufmass_uebertragen" value="1" {{ 'checked' if user.darf_aufmass_uebertragen }}> Aufmaße übertragen</label>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-12">
|
||||
<button class="button is-primary" type="submit">Speichern</button>
|
||||
{% if current_user.is_superadmin() %}
|
||||
<a class="button is-light" href="{{ url_for('superadmin.firma_detail', company_id=user.company_id) }}">Abbrechen</a>
|
||||
{% else %}
|
||||
<a class="button is-light" href="{{ url_for('admin.firma') }}">Abbrechen</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,101 @@
|
||||
{% extends "base.html" %}
|
||||
{% block head %}
|
||||
<style>.buttons .button.is-outlined { color:#000 !important; }</style>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="columns is-centered">
|
||||
<div class="column is-half">
|
||||
<div class="box">
|
||||
<div class="level">
|
||||
<div class="level-left">
|
||||
<h1 class="title is-4 has-text-dark">Profil</h1>
|
||||
</div>
|
||||
<div class="level-right">
|
||||
<a class="button is-light is-small" href="{{ url_for('admin.dashboard') }}">← Dashboard</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Avatar -->
|
||||
<div class="has-text-centered mb-4">
|
||||
{% if current_user.profile_image %}
|
||||
<figure class="image is-96x96" style="margin:0 auto;border-radius:50%;overflow:hidden">
|
||||
<img src="{{ url_for('static', filename='avatars/'+current_user.profile_image) }}" alt="Avatar">
|
||||
</figure>
|
||||
{% else %}
|
||||
<div style="width:96px;height:96px;border-radius:50%;background:#2F5496;display:inline-flex;align-items:center;justify-content:center;font-size:2.5rem;font-weight:bold;color:#fff">
|
||||
{{ (current_user.vorname[0] if current_user.vorname else '') + (current_user.nachname[0] if current_user.nachname else '') or '?' }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<form method="POST" action="{{ url_for('admin.avatar_upload') }}" enctype="multipart/form-data" class="mt-2">
|
||||
<div class="field has-addons" style="justify-content:center">
|
||||
<div class="control"><input class="input is-small" type="file" name="avatar" accept="image/*"></div>
|
||||
<div class="control"><button class="button is-small is-primary">Hochladen</button></div>
|
||||
</div>
|
||||
</form>
|
||||
{% if current_user.profile_image %}
|
||||
<form method="POST" action="{{ url_for('admin.avatar_entfernen') }}" class="mt-1">
|
||||
<button class="button is-small is-danger is-outlined">Bild entfernen</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<form method="POST">
|
||||
<div class="field">
|
||||
<label class="label has-text-dark">E-Mail</label>
|
||||
<div class="control">
|
||||
<input class="input" type="email" value="{{ current_user.email }}" disabled>
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<div class="field">
|
||||
<label class="label has-text-dark">Vorname</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" name="vorname" value="{{ current_user.vorname or '' }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="field">
|
||||
<label class="label has-text-dark">Nachname</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" name="nachname" value="{{ current_user.nachname or '' }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label has-text-dark">Neues Passwort (leer lassen für keine Änderung)</label>
|
||||
<div class="control">
|
||||
<input class="input" type="password" name="password" minlength="6">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<h2 class="title is-5 has-text-dark">Einstellungen – Schriftgröße</h2>
|
||||
<div class="field">
|
||||
<label class="label has-text-dark">Schriftgröße für die gesamte Anwendung</label>
|
||||
<div class="control">
|
||||
<div class="buttons">
|
||||
<a class="button {{ 'is-info' if session.get('font_size','1') == '0.8' else 'is-outlined' }}"
|
||||
href="{{ url_for('set_font_size', size='0.8') }}">A− Klein</a>
|
||||
<a class="button {{ 'is-info' if session.get('font_size','1') == '1' else 'is-outlined' }}"
|
||||
href="{{ url_for('set_font_size', size='1') }}">A Normal</a>
|
||||
<a class="button {{ 'is-info' if session.get('font_size','1') == '1.1' else 'is-outlined' }}"
|
||||
href="{{ url_for('set_font_size', size='1.1') }}">A+ Größer</a>
|
||||
<a class="button {{ 'is-info' if session.get('font_size','1') == '1.25' else 'is-outlined' }}"
|
||||
href="{{ url_for('set_font_size', size='1.25') }}">A++ Groß</a>
|
||||
<a class="button {{ 'is-info' if session.get('font_size','1') == '1.5' else 'is-outlined' }}"
|
||||
href="{{ url_for('set_font_size', size='1.5') }}">A+++ Sehr groß</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field mt-4">
|
||||
<button class="button is-primary" type="submit">Speichern</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,116 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="level">
|
||||
<div class="level-left"><h1 class="title is-3">Rechte: {{ user.full_name }}</h1></div>
|
||||
<div class="level-right">
|
||||
<a class="button is-small" href="{{ url_for('admin.firma') }}">← Firma</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h2 class="title is-5">Firmenweite Berechtigungen</h2>
|
||||
<form method="POST">
|
||||
<table class="table is-fullwidth">
|
||||
<tr>
|
||||
<td>Projekte anlegen</td>
|
||||
<td><input type="checkbox" name="darf_projekte_anlegen" value="1" {{ 'checked' if user.darf_projekte_anlegen }}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LV verwalten</td>
|
||||
<td><input type="checkbox" name="darf_lv_verwalten" value="1" {{ 'checked' if user.darf_lv_verwalten }}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Preise sehen</td>
|
||||
<td><input type="checkbox" name="darf_preise_sehen" value="1" {{ 'checked' if user.darf_preise_sehen }}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Aufmaße verwalten</td>
|
||||
<td><input type="checkbox" name="darf_aufmass_verwalten" value="1" {{ 'checked' if user.darf_aufmass_verwalten }}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>E-Vergabe Addon nutzen</td>
|
||||
<td><input type="checkbox" name="darf_evergabe_nutzen" value="1" {{ 'checked' if user.darf_evergabe_nutzen }}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Kopfdaten holen erlauben</td>
|
||||
<td><input type="checkbox" name="darf_kopfdaten_holen" value="1" {{ 'checked' if user.darf_kopfdaten_holen }}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Aufmaße in E-Vergabe übertragen</td>
|
||||
<td><input type="checkbox" name="darf_aufmass_uebertragen" value="1" {{ 'checked' if user.darf_aufmass_uebertragen }}></td>
|
||||
</tr>
|
||||
</table>
|
||||
<button class="button is-primary">Speichern</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% if modules %}
|
||||
<div class="box">
|
||||
<h2 class="title is-5">Modul-Freigaben</h2>
|
||||
<p class="is-size-7 has-text-grey mb-2">Legen Sie fest, welche Module dieser Mitarbeiter nutzen darf.</p>
|
||||
<table class="table is-fullwidth is-hoverable">
|
||||
<thead><tr><th>Modul</th><th>Kategorie</th><th>Status</th><th>Aktion</th></tr></thead>
|
||||
<tbody>
|
||||
{% for m in modules %}
|
||||
<tr>
|
||||
<td>{{ m.icon }} {{ m.titel }}</td>
|
||||
<td>{{ m.kategorie or '–' }}</td>
|
||||
<td>
|
||||
{% if user.rolle == 'firmadmin' %}
|
||||
<span class="tag is-success">Immer aktiv</span>
|
||||
{% elif m.id in user_modules %}
|
||||
<span class="tag is-success">Aktiv</span>
|
||||
{% else %}
|
||||
<span class="tag is-light">Inaktiv</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if user.rolle == 'mitarbeiter' %}
|
||||
<a class="button is-small {{ 'is-warning' if m.id in user_modules else 'is-success' }}"
|
||||
href="{{ url_for('admin.mitarbeiter_module_toggle', user_id=user.id, module_id=m.id) }}">
|
||||
{{ 'Deaktivieren' if m.id in user_modules else 'Aktivieren' }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="box">
|
||||
<h2 class="title is-5">Projekt-Zugriffe</h2>
|
||||
<table class="table is-fullwidth is-hoverable">
|
||||
<thead><tr><th>Projekt</th><th>Zugriff</th><th>Aktion</th></tr></thead>
|
||||
<tbody>
|
||||
{% for p in projekte %}
|
||||
<tr>
|
||||
<td>{{ p.sm_nr }} – {{ p.bezeichnung or '' }}</td>
|
||||
<td>
|
||||
{% set pa = zugriffe.get(p.id) %}
|
||||
<span class="tag {{ 'is-success' if pa and pa.zugriff == 'schreiben' else ('is-link' if pa else 'is-light') }}">
|
||||
{{ pa.zugriff if pa else 'kein Zugriff' }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<form method="POST" action="{{ url_for('admin.mitarbeiter_projekt_zugriff', user_id=user.id) }}" class="field has-addons">
|
||||
<input type="hidden" name="project_id" value="{{ p.id }}">
|
||||
<div class="control">
|
||||
<div class="select is-small">
|
||||
<select name="zugriff">
|
||||
<option value="">–</option>
|
||||
<option value="lesen" {{ 'selected' if zugriffe.get(p.id) and zugriffe[p.id].zugriff == 'lesen' }}>Lesen</option>
|
||||
<option value="schreiben" {{ 'selected' if zugriffe.get(p.id) and zugriffe[p.id].zugriff == 'schreiben' }}>Schreiben</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control"><button class="button is-small is-info">Setzen</button></div>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user