Initial commit – AufmaßCreater v2.35
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,117 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li><a href="{{ url_for('custom_modules.index') }}">Modul-Builder</a></li>
|
||||
<li class="is-active"><a href="#">{{ module.name if module else 'Neues Modul' }}</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<h2 class="title is-4">{{ '✏️' if module else '➕' }} {{ module.name if module else 'Neues Modul' }}</h2>
|
||||
|
||||
<form method="POST" class="box">
|
||||
<div class="columns is-multiline">
|
||||
<div class="column is-6">
|
||||
<label class="label">Name *</label>
|
||||
<input class="input" name="name" value="{{ module.name if module else '' }}" required>
|
||||
</div>
|
||||
<div class="column is-3">
|
||||
<label class="label">Icon (Emoji)</label>
|
||||
<input class="input" name="icon" value="{{ module.icon if module else '🔧' }}">
|
||||
</div>
|
||||
<div class="column is-3">
|
||||
<label class="label">Kategorie</label>
|
||||
<div class="select is-fullwidth">
|
||||
<select name="kategorie">
|
||||
<option value="allgemein" {% if module and module.kategorie=='allgemein' %}selected{% endif %}>Allgemein</option>
|
||||
<option value="tiefbau" {% if module and module.kategorie=='tiefbau' %}selected{% endif %}>Tiefbau</option>
|
||||
<option value="graben" {% if module and module.kategorie=='graben' %}selected{% endif %}>Graben</option>
|
||||
<option value="montage" {% if module and module.kategorie=='montage' %}selected{% endif %}>Montage</option>
|
||||
<option value="sonder" {% if module and module.kategorie=='sonder' %}selected{% endif %}>Sonder</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-12">
|
||||
<label class="label">Beschreibung</label>
|
||||
<textarea class="textarea" name="description" rows="2">{{ module.description if module else '' }}</textarea>
|
||||
</div>
|
||||
{% if is_superadmin %}
|
||||
<div class="column is-3">
|
||||
<label class="checkbox mt-5">
|
||||
<input type="checkbox" name="is_template" value="1" {% if module and module.is_template %}checked{% endif %}>
|
||||
Globale Vorlage
|
||||
</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="column is-3">
|
||||
<label class="checkbox mt-5">
|
||||
<input type="checkbox" name="is_active" value="1" {% if not module or module.is_active %}checked{% endif %}>
|
||||
Aktiv
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="buttons mt-3">
|
||||
<button class="button is-primary" type="submit">Speichern</button>
|
||||
<a href="{{ url_for('custom_modules.index') }}" class="button is-light">Abbrechen</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% if module %}
|
||||
<div class="buttons mt-4">
|
||||
<a href="{{ url_for('custom_modules.builder', module_id=module.id) }}" class="button is-info is-large">
|
||||
🎨 Zum Builder
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% if module.company_id %}
|
||||
<hr>
|
||||
<h3 class="title is-5">👥 Mitarbeiter-Zugriff</h3>
|
||||
<p class="subtitle is-6">Lege fest, welche Mitarbeiter dieses Modul nutzen dürfen.</p>
|
||||
<div class="table-container">
|
||||
<table class="table is-fullwidth is-hoverable">
|
||||
<thead>
|
||||
<tr><th>Mitarbeiter</th><th>Zugriff</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for u in users %}
|
||||
<tr>
|
||||
<td>{{ u.full_name }}</td>
|
||||
<td>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox"
|
||||
class="js-user-toggle"
|
||||
data-module-id="{{ module.id }}"
|
||||
data-user-id="{{ u.id }}"
|
||||
{% if u.id in assignments %}checked{% endif %}>
|
||||
Freigegeben
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
document.querySelectorAll('.js-user-toggle').forEach(function(cb) {
|
||||
cb.addEventListener('change', function() {
|
||||
var moduleId = this.dataset.moduleId;
|
||||
var userId = this.dataset.userId;
|
||||
fetch('/custom-modules/' + moduleId + '/user/' + userId + '/toggle', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({active: this.checked, can_edit: false})
|
||||
}).then(function(r) { return r.json(); }).then(function(data) {
|
||||
if (data.message) console.log(data.message);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,165 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="level">
|
||||
<div class="level-left">
|
||||
<h2 class="title is-4">🔧 Modul-Builder</h2>
|
||||
</div>
|
||||
<div class="level-right">
|
||||
<a href="{{ url_for('custom_modules.neu') }}" class="button is-primary">+ Neues Modul</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if current_user.is_superadmin() and templates %}
|
||||
<h3 class="title is-5 mt-4">🌐 Globale Vorlagen</h3>
|
||||
<div class="table-container">
|
||||
<table class="table is-fullwidth is-hoverable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:32px"></th>
|
||||
<th>Name</th>
|
||||
<th>Kategorie</th>
|
||||
<th>Erstellt</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="js-sort-templates">
|
||||
{% for m in templates %}
|
||||
<tr data-id="{{ m.id }}">
|
||||
<td class="drag-handle" style="cursor:grab;text-align:center;color:#aaa">⠿</td>
|
||||
<td>{{ m.icon }} {{ m.name }}</td>
|
||||
<td>{{ m.kategorie }}</td>
|
||||
<td>{{ m.created_at.strftime('%d.%m.%Y') if m.created_at else '' }}</td>
|
||||
<td>
|
||||
<a href="{{ url_for('custom_modules.edit', module_id=m.id) }}" class="button is-small">Bearbeiten</a>
|
||||
<a href="{{ url_for('custom_modules.builder', module_id=m.id) }}" class="button is-small is-info">Builder</a>
|
||||
<form method="POST" action="{{ url_for('custom_modules.loeschen', module_id=m.id) }}" style="display:inline">
|
||||
<button class="button is-small is-danger" onclick="return confirm('Wirklich löschen?')">Löschen</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if current_user.is_superadmin() %}
|
||||
<h3 class="title is-5 mt-4">🏢 Alle Firmen-Module</h3>
|
||||
{% else %}
|
||||
<h3 class="title is-5 mt-4">🏢 Meine Module</h3>
|
||||
{% endif %}
|
||||
|
||||
{% if not current_user.is_superadmin() and templates %}
|
||||
<div class="message is-info">
|
||||
<div class="message-body">
|
||||
<strong>Vorlagen verfügbar:</strong>
|
||||
{% for t in templates %}
|
||||
<span class="tag is-medium ml-2">
|
||||
{{ t.icon }} {{ t.name }}
|
||||
<form method="POST" action="{{ url_for('custom_modules.importieren', module_id=t.id) }}" style="display:inline">
|
||||
<button class="button is-small is-ghost ml-1" title="Importieren">📥</button>
|
||||
</form>
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="table-container">
|
||||
<table class="table is-fullwidth is-hoverable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:32px"></th>
|
||||
<th>Name</th>
|
||||
<th>Kategorie</th>
|
||||
<th>Firma</th>
|
||||
{% if current_user.is_superadmin() %}<th>Vorlage</th>{% endif %}
|
||||
<th>Aktiv</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="js-sort-company">
|
||||
{% for m in company_modules %}
|
||||
<tr data-id="{{ m.id }}">
|
||||
<td class="drag-handle" style="cursor:grab;text-align:center;color:#aaa">⠿</td>
|
||||
<td>{{ m.icon }} {{ m.name }}</td>
|
||||
<td>{{ m.kategorie }}</td>
|
||||
<td>{{ m.company.name if m.company else '—' }}</td>
|
||||
{% if current_user.is_superadmin() %}
|
||||
<td>
|
||||
{% if m.original_template_id %}
|
||||
<span class="tag is-light">kopiert</span>
|
||||
{% else %}
|
||||
<span class="tag is-white">eigenes</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
<td>
|
||||
<span class="tag {% if m.is_active %}is-success{% else %}is-light{% endif %}">
|
||||
{{ 'Aktiv' if m.is_active else 'Inaktiv' }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
{% if current_user.is_superadmin() or (current_user.is_firmadmin() and m.company_id == current_user.company_id) %}
|
||||
<a href="{{ url_for('custom_modules.edit', module_id=m.id) }}" class="button is-small">Bearbeiten</a>
|
||||
<a href="{{ url_for('custom_modules.builder', module_id=m.id) }}" class="button is-small is-info">Builder</a>
|
||||
<form method="POST" action="{{ url_for('custom_modules.loeschen', module_id=m.id) }}" style="display:inline">
|
||||
<button class="button is-small is-danger" onclick="return confirm('Wirklich löschen?')">Löschen</button>
|
||||
</form>
|
||||
{% if current_user.is_superadmin() %}
|
||||
<form method="POST" action="{{ url_for('custom_modules.als_vorlage', module_id=m.id) }}" style="display:inline">
|
||||
<button class="button is-small is-warning">Als Vorlage</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="7" class="has-text-centered"><em>Keine Module vorhanden.</em></td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.sortable-ghost{opacity:0.4}
|
||||
.sortable-chosen{background:#d4e3ff}
|
||||
.drag-handle:hover{color:#2F5496!important}
|
||||
#js-sort-templates tr.dragging, #js-sort-company tr.dragging{background:#f0f4ff}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
function commitSort(listId, endpoint) {
|
||||
var el = document.getElementById(listId);
|
||||
if (!el) return;
|
||||
if (el._sortable) el._sortable.destroy();
|
||||
el._sortable = new Sortable(el, {
|
||||
handle: '.drag-handle',
|
||||
animation: 150,
|
||||
ghostClass: 'sortable-ghost',
|
||||
chosenClass: 'sortable-chosen',
|
||||
dragClass: 'dragging',
|
||||
onEnd: function() {
|
||||
var rows = el.querySelectorAll('tr[data-id]');
|
||||
var order = [];
|
||||
rows.forEach(function(r, idx) {
|
||||
order.push({id: parseInt(r.dataset.id), sort_index: idx});
|
||||
});
|
||||
fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(order)
|
||||
}).then(function(r){return r.json()}).then(function(d){
|
||||
if (!d.ok) console.warn('Sort failed', d);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
commitSort('js-sort-templates', '{{ url_for("custom_modules.sort_batch")|safe }}');
|
||||
commitSort('js-sort-company', '{{ url_for("custom_modules.sort_batch")|safe }}');
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user