implementation of the export for users
Release Inventarsystem / release-docker (push) Successful in 3m8s
Release Inventarsystem / release-docker (push) Successful in 3m8s
This commit is contained in:
+66
@@ -8628,6 +8628,72 @@ def register_csv():
|
|||||||
mimetype='application/pdf'
|
mimetype='application/pdf'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@app.route('/export_users_csv', methods=['POST'])
|
||||||
|
def export_users_csv():
|
||||||
|
"""
|
||||||
|
Exports a filtered list of users to a CSV file.
|
||||||
|
Receives a JSON array of usernames from the frontend.
|
||||||
|
"""
|
||||||
|
if 'username' not in session:
|
||||||
|
flash('Ihnen ist es nicht gestattet, diese Aktion auszuführen.', 'error')
|
||||||
|
return redirect(url_for('login'))
|
||||||
|
|
||||||
|
usernames_json = request.form.get('usernames')
|
||||||
|
if not usernames_json:
|
||||||
|
flash('Keine Benutzer zum Exportieren ausgewählt.', 'error')
|
||||||
|
return redirect(url_for('user_del'))
|
||||||
|
|
||||||
|
try:
|
||||||
|
target_usernames = json.loads(usernames_json)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
flash('Ungültige Daten beim Export übermittelt.', 'error')
|
||||||
|
return redirect(url_for('user_del'))
|
||||||
|
|
||||||
|
# Fetch all users
|
||||||
|
all_users = us.get_all_users()
|
||||||
|
|
||||||
|
# Create CSV in memory
|
||||||
|
si = io.StringIO()
|
||||||
|
# Delimiter set to semicolon (standard for Excel in German locales)
|
||||||
|
cw = csv.writer(si, delimiter=';')
|
||||||
|
|
||||||
|
# Write headers
|
||||||
|
cw.writerow(['Benutzername', 'Vorname', 'Nachname', 'Administrator', 'Rechte-Preset'])
|
||||||
|
|
||||||
|
for user in all_users:
|
||||||
|
encrypted_username = user.get('Username')
|
||||||
|
if not encrypted_username:
|
||||||
|
continue
|
||||||
|
|
||||||
|
uname = decrypt_text(encrypted_username)
|
||||||
|
|
||||||
|
# Only process users that were present in the frontend's filtered view
|
||||||
|
if uname in target_usernames:
|
||||||
|
try:
|
||||||
|
permissions_payload = us.get_effective_permissions(uname)
|
||||||
|
preset = permissions_payload.get('preset', 'standard_user')
|
||||||
|
except Exception:
|
||||||
|
preset = 'standard_user'
|
||||||
|
|
||||||
|
try:
|
||||||
|
name = us.get_name(uname) or ""
|
||||||
|
last_name = us.get_last_name(uname) or ""
|
||||||
|
except Exception:
|
||||||
|
name = ""
|
||||||
|
last_name = ""
|
||||||
|
|
||||||
|
admin_status = "Ja" if user.get('Admin', False) else "Nein"
|
||||||
|
|
||||||
|
cw.writerow([uname, name, last_name, admin_status, preset])
|
||||||
|
|
||||||
|
# Prefix with BOM (Byte Order Mark) to ensure Excel reads UTF-8 (Umlauts) correctly
|
||||||
|
output = '\ufeff' + si.getvalue()
|
||||||
|
|
||||||
|
return Response(
|
||||||
|
output,
|
||||||
|
mimetype="text/csv",
|
||||||
|
headers={"Content-disposition": "attachment; filename=benutzer_export.csv"}
|
||||||
|
)
|
||||||
|
|
||||||
@app.route('/user_del', methods=['GET'])
|
@app.route('/user_del', methods=['GET'])
|
||||||
def user_del():
|
def user_del():
|
||||||
|
|||||||
@@ -53,8 +53,11 @@
|
|||||||
<option value="desc">Absteigend</option>
|
<option value="desc">Absteigend</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2">
|
<div class="col-md-3">
|
||||||
<button class="btn btn-secondary w-100" onclick="resetFilters()">Filter zurücksetzen</button>
|
<div class="d-flex gap-2">
|
||||||
|
<button class="btn btn-secondary flex-grow-1" onclick="resetFilters()">Zurücksetzen</button>
|
||||||
|
<button class="btn btn-success flex-grow-1" onclick="exportFilteredUsers()">Exportieren</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2 text-muted small" id="filter-count"></div>
|
<div class="mt-2 text-muted small" id="filter-count"></div>
|
||||||
@@ -87,14 +90,14 @@
|
|||||||
Löschen
|
Löschen
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<button type="button" class="btn btn-primary btn-sm"
|
<button type="button" class="btn btn-primary btn-sm"
|
||||||
data-username="{{ user.username }}"
|
data-username="{{ user.username }}"
|
||||||
data-firstname="{{ user.name if user.name else '' }}"
|
data-firstname="{{ user.name if user.name else '' }}"
|
||||||
data-lastname="{{ user.last_name if user.last_name else '' }}"
|
data-lastname="{{ user.last_name if user.last_name else '' }}"
|
||||||
onclick="openEditUserModal(this)">
|
onclick="openEditUserModal(this)">
|
||||||
Bearbeiten
|
Bearbeiten
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-warning btn-sm"
|
<button type="button" class="btn btn-warning btn-sm"
|
||||||
onclick="openResetPasswordModal('{{ user.username }}')">
|
onclick="openResetPasswordModal('{{ user.username }}')">
|
||||||
Passwort zurücksetzen
|
Passwort zurücksetzen
|
||||||
</button>
|
</button>
|
||||||
@@ -313,6 +316,48 @@
|
|||||||
applyFilters();
|
applyFilters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function exportFilteredUsers() {
|
||||||
|
var table = document.getElementById('user-table');
|
||||||
|
var tbody = table.querySelector('tbody');
|
||||||
|
var rows = Array.from(tbody.querySelectorAll('tr'));
|
||||||
|
|
||||||
|
var visibleUsernames = [];
|
||||||
|
|
||||||
|
// Sammle alle Benutzernamen, die durch den Filter aktuell NICHT versteckt sind
|
||||||
|
rows.forEach(function(row) {
|
||||||
|
if (row.style.display !== 'none') {
|
||||||
|
var cells = row.querySelectorAll('td');
|
||||||
|
if (cells.length > 0) {
|
||||||
|
// Der Benutzername ist in der ersten Spalte (Index 0)
|
||||||
|
visibleUsernames.push(cells[0].textContent.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (visibleUsernames.length === 0) {
|
||||||
|
alert('Keine Benutzer zum Exportieren vorhanden.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dynamisches Formular erstellen, um die gefilterten Daten per POST ans Backend zu senden
|
||||||
|
var form = document.createElement('form');
|
||||||
|
form.method = 'POST';
|
||||||
|
form.action = "{{ url_for('export_users_csv') }}"; // Passe dies ggf. an deinen Endpunktnamen an
|
||||||
|
|
||||||
|
var input = document.createElement('input');
|
||||||
|
input.type = 'hidden';
|
||||||
|
input.name = 'usernames';
|
||||||
|
input.value = JSON.stringify(visibleUsernames);
|
||||||
|
|
||||||
|
form.appendChild(input);
|
||||||
|
document.body.appendChild(form);
|
||||||
|
|
||||||
|
form.submit();
|
||||||
|
|
||||||
|
// Aufräumen
|
||||||
|
document.body.removeChild(form);
|
||||||
|
}
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
applyFilters();
|
applyFilters();
|
||||||
document.getElementById('filter-search').addEventListener('input', applyFilters);
|
document.getElementById('filter-search').addEventListener('input', applyFilters);
|
||||||
@@ -332,12 +377,12 @@
|
|||||||
var username = button.getAttribute('data-username');
|
var username = button.getAttribute('data-username');
|
||||||
var name = button.getAttribute('data-firstname');
|
var name = button.getAttribute('data-firstname');
|
||||||
var lastName = button.getAttribute('data-lastname');
|
var lastName = button.getAttribute('data-lastname');
|
||||||
|
|
||||||
document.getElementById('edit-username').value = username;
|
document.getElementById('edit-username').value = username;
|
||||||
document.getElementById('edit-username-display').value = username;
|
document.getElementById('edit-username-display').value = username;
|
||||||
document.getElementById('edit-name').value = name;
|
document.getElementById('edit-name').value = name;
|
||||||
document.getElementById('edit-last-name').value = lastName;
|
document.getElementById('edit-last-name').value = lastName;
|
||||||
|
|
||||||
var modal = new bootstrap.Modal(document.getElementById('editUserModal'));
|
var modal = new bootstrap.Modal(document.getElementById('editUserModal'));
|
||||||
modal.show();
|
modal.show();
|
||||||
}
|
}
|
||||||
@@ -345,8 +390,7 @@
|
|||||||
function openResetPasswordModal(username) {
|
function openResetPasswordModal(username) {
|
||||||
document.getElementById('reset-username').value = username;
|
document.getElementById('reset-username').value = username;
|
||||||
document.getElementById('username-display').value = username;
|
document.getElementById('username-display').value = username;
|
||||||
|
|
||||||
// Open modal using Bootstrap
|
|
||||||
var modal = new bootstrap.Modal(document.getElementById('resetPasswordModal'));
|
var modal = new bootstrap.Modal(document.getElementById('resetPasswordModal'));
|
||||||
modal.show();
|
modal.show();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user