Lead Management Usability Upgrade
Dieser Commit ist enthalten in:
@@ -27,82 +27,21 @@ def get_lead_service():
|
|||||||
def lead_management():
|
def lead_management():
|
||||||
"""Lead Management Dashboard"""
|
"""Lead Management Dashboard"""
|
||||||
try:
|
try:
|
||||||
# Get current user
|
# Get institutions with contact counts
|
||||||
current_user = flask_session.get('username', 'System')
|
institutions = get_lead_service().list_institutions()
|
||||||
other_user = 'w@rh@mm3r' if current_user == 'rac00n' else 'rac00n'
|
|
||||||
|
|
||||||
# Initialize defaults
|
# Get all contacts with institution names
|
||||||
total_institutions = 0
|
all_contacts = get_lead_service().list_all_contacts()
|
||||||
total_contacts = 0
|
|
||||||
my_entries = 0
|
|
||||||
other_entries = 0
|
|
||||||
activities = []
|
|
||||||
|
|
||||||
with get_db_connection() as conn:
|
# Calculate totals
|
||||||
cur = conn.cursor()
|
total_institutions = len(institutions)
|
||||||
|
total_contacts = len(all_contacts)
|
||||||
# Get statistics
|
|
||||||
cur.execute("SELECT COUNT(*) FROM lead_institutions")
|
|
||||||
result = cur.fetchone()
|
|
||||||
if result:
|
|
||||||
total_institutions = result[0]
|
|
||||||
|
|
||||||
cur.execute("SELECT COUNT(*) FROM lead_contacts")
|
|
||||||
result = cur.fetchone()
|
|
||||||
if result:
|
|
||||||
total_contacts = result[0]
|
|
||||||
|
|
||||||
# Count entries by current user
|
|
||||||
cur.execute("""
|
|
||||||
SELECT COUNT(*) FROM audit_log
|
|
||||||
WHERE username = %s
|
|
||||||
AND entity_type IN ('lead_institution', 'lead_contact')
|
|
||||||
AND action = 'CREATE'
|
|
||||||
""", (current_user,))
|
|
||||||
result = cur.fetchone()
|
|
||||||
if result:
|
|
||||||
my_entries = result[0]
|
|
||||||
|
|
||||||
# Count entries by other user
|
|
||||||
cur.execute("""
|
|
||||||
SELECT COUNT(*) FROM audit_log
|
|
||||||
WHERE username = %s
|
|
||||||
AND entity_type IN ('lead_institution', 'lead_contact')
|
|
||||||
AND action = 'CREATE'
|
|
||||||
""", (other_user,))
|
|
||||||
result = cur.fetchone()
|
|
||||||
if result:
|
|
||||||
other_entries = result[0]
|
|
||||||
|
|
||||||
# Get recent activities
|
|
||||||
cur.execute("""
|
|
||||||
SELECT timestamp, username, action, entity_type, additional_info
|
|
||||||
FROM audit_log
|
|
||||||
WHERE entity_type IN ('lead_institution', 'lead_contact')
|
|
||||||
ORDER BY timestamp DESC
|
|
||||||
LIMIT 10
|
|
||||||
""")
|
|
||||||
rows = cur.fetchall()
|
|
||||||
if rows:
|
|
||||||
for row in rows:
|
|
||||||
activities.append({
|
|
||||||
'timestamp': row[0],
|
|
||||||
'username': row[1],
|
|
||||||
'action': row[2],
|
|
||||||
'entity_type': row[3].replace('lead_', ''),
|
|
||||||
'additional_info': row[4]
|
|
||||||
})
|
|
||||||
|
|
||||||
cur.close()
|
|
||||||
|
|
||||||
return render_template('leads/lead_management.html',
|
return render_template('leads/lead_management.html',
|
||||||
total_institutions=total_institutions,
|
total_institutions=total_institutions,
|
||||||
total_contacts=total_contacts,
|
total_contacts=total_contacts,
|
||||||
my_entries=my_entries,
|
institutions=institutions,
|
||||||
other_entries=other_entries,
|
all_contacts=all_contacts)
|
||||||
other_user=other_user,
|
|
||||||
current_user=current_user,
|
|
||||||
recent_activities=activities)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
import traceback
|
import traceback
|
||||||
print(f"Error in lead_management: {str(e)}")
|
print(f"Error in lead_management: {str(e)}")
|
||||||
@@ -112,11 +51,8 @@ def lead_management():
|
|||||||
return render_template('leads/lead_management.html',
|
return render_template('leads/lead_management.html',
|
||||||
total_institutions=0,
|
total_institutions=0,
|
||||||
total_contacts=0,
|
total_contacts=0,
|
||||||
my_entries=0,
|
institutions=[],
|
||||||
other_entries=0,
|
all_contacts=[])
|
||||||
other_user='',
|
|
||||||
current_user=current_user,
|
|
||||||
recent_activities=[])
|
|
||||||
|
|
||||||
@leads_bp.route('/')
|
@leads_bp.route('/')
|
||||||
@login_required
|
@login_required
|
||||||
@@ -147,12 +83,50 @@ def add_institution():
|
|||||||
|
|
||||||
return redirect(url_for('leads.lead_management'))
|
return redirect(url_for('leads.lead_management'))
|
||||||
|
|
||||||
|
@leads_bp.route('/contact/add', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def add_contact():
|
||||||
|
"""Add new contact from form"""
|
||||||
|
try:
|
||||||
|
data = {
|
||||||
|
'institution_id': request.form.get('institution_id'),
|
||||||
|
'first_name': request.form.get('first_name'),
|
||||||
|
'last_name': request.form.get('last_name'),
|
||||||
|
'position': request.form.get('position')
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validate required fields
|
||||||
|
if not data['institution_id'] or not data['first_name'] or not data['last_name']:
|
||||||
|
flash('Institution, Vorname und Nachname sind erforderlich', 'error')
|
||||||
|
return redirect(url_for('leads.lead_management'))
|
||||||
|
|
||||||
|
# Create contact
|
||||||
|
contact = get_lead_service().create_contact(data, flask_session.get('username', 'System'))
|
||||||
|
|
||||||
|
# Add email if provided
|
||||||
|
email = request.form.get('email')
|
||||||
|
if email:
|
||||||
|
get_lead_service().add_email(contact['id'], email, 'Primär', flask_session.get('username', 'System'))
|
||||||
|
|
||||||
|
# Add phone if provided
|
||||||
|
phone = request.form.get('phone')
|
||||||
|
if phone:
|
||||||
|
get_lead_service().add_phone(contact['id'], phone, 'Primär', flask_session.get('username', 'System'))
|
||||||
|
|
||||||
|
flash(f'Kontakt "{data["first_name"]} {data["last_name"]}" wurde erfolgreich hinzugefügt', 'success')
|
||||||
|
except Exception as e:
|
||||||
|
flash(f'Fehler beim Hinzufügen des Kontakts: {str(e)}', 'error')
|
||||||
|
|
||||||
|
return redirect(url_for('leads.lead_management'))
|
||||||
|
|
||||||
@leads_bp.route('/institution/<uuid:institution_id>')
|
@leads_bp.route('/institution/<uuid:institution_id>')
|
||||||
@login_required
|
@login_required
|
||||||
def institution_detail(institution_id):
|
def institution_detail(institution_id):
|
||||||
"""Show institution with all contacts"""
|
"""Show institution with all contacts"""
|
||||||
try:
|
try:
|
||||||
institution = lead_repository.get_institution_by_id(institution_id)
|
# Get institution through repository
|
||||||
|
service = get_lead_service()
|
||||||
|
institution = service.repo.get_institution_by_id(institution_id)
|
||||||
if not institution:
|
if not institution:
|
||||||
flash('Institution nicht gefunden', 'error')
|
flash('Institution nicht gefunden', 'error')
|
||||||
return redirect(url_for('leads.institutions'))
|
return redirect(url_for('leads.institutions'))
|
||||||
|
|||||||
@@ -2,6 +2,28 @@
|
|||||||
|
|
||||||
{% block title %}Lead Management{% endblock %}
|
{% block title %}Lead Management{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_css %}
|
||||||
|
<style>
|
||||||
|
.nav-tabs .nav-link {
|
||||||
|
color: #495057;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-top-left-radius: 0.25rem;
|
||||||
|
border-top-right-radius: 0.25rem;
|
||||||
|
}
|
||||||
|
.nav-tabs .nav-link.active {
|
||||||
|
color: #495057;
|
||||||
|
background-color: #fff;
|
||||||
|
border-color: #dee2e6 #dee2e6 #fff;
|
||||||
|
}
|
||||||
|
.tab-content {
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
border-top: none;
|
||||||
|
padding: 1.5rem;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container py-5">
|
<div class="container py-5">
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
@@ -33,11 +55,11 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Schnellaktionen</h5>
|
<h5 class="card-title">Schnellaktionen</h5>
|
||||||
<div class="d-flex gap-2">
|
<div class="d-flex gap-2">
|
||||||
<a href="{{ url_for('leads.institutions') }}" class="btn btn-primary">
|
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addInstitutionModal">
|
||||||
<i class="bi bi-building"></i> Institutionen anzeigen
|
<i class="bi bi-building-add"></i> Institution hinzufügen
|
||||||
</a>
|
</button>
|
||||||
<button class="btn btn-success" data-bs-toggle="modal" data-bs-target="#addInstitutionModal">
|
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addContactModal">
|
||||||
<i class="bi bi-plus"></i> Institution hinzufügen
|
<i class="bi bi-person-plus"></i> Kontakt hinzufügen
|
||||||
</button>
|
</button>
|
||||||
<a href="{{ url_for('leads.export_leads') }}" class="btn btn-outline-secondary">
|
<a href="{{ url_for('leads.export_leads') }}" class="btn btn-outline-secondary">
|
||||||
<i class="bi bi-download"></i> Exportieren
|
<i class="bi bi-download"></i> Exportieren
|
||||||
@@ -46,71 +68,161 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Recent Activity -->
|
<!-- Tabbed View -->
|
||||||
<div class="card mb-4">
|
|
||||||
<div class="card-header">
|
|
||||||
<h5 class="mb-0">Letzte Aktivitäten</h5>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Zeitpunkt</th>
|
|
||||||
<th>Benutzer</th>
|
|
||||||
<th>Aktion</th>
|
|
||||||
<th>Details</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for activity in recent_activities %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ activity.timestamp.strftime('%d.%m.%Y %H:%M') }}</td>
|
|
||||||
<td>
|
|
||||||
<span class="badge bg-{{ 'primary' if activity.username == session.username else 'secondary' }}">
|
|
||||||
{{ activity.username }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{% if activity.action == 'CREATE' %}
|
|
||||||
<span class="text-success">➕ Erstellt</span>
|
|
||||||
{% elif activity.action == 'UPDATE' %}
|
|
||||||
<span class="text-info">✏️ Bearbeitet</span>
|
|
||||||
{% elif activity.action == 'DELETE' %}
|
|
||||||
<span class="text-danger">🗑️ Gelöscht</span>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ activity.entity_type|title }}
|
|
||||||
{% if activity.additional_info %}
|
|
||||||
- {{ activity.additional_info }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
{% if not recent_activities %}
|
|
||||||
<p class="text-muted text-center py-3">Noch keine Aktivitäten vorhanden.</p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Search -->
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-body p-0">
|
||||||
<h5 class="mb-0">Suche</h5>
|
<!-- Tabs -->
|
||||||
</div>
|
<ul class="nav nav-tabs" id="leadTabs" role="tablist">
|
||||||
<div class="card-body">
|
<li class="nav-item" role="presentation">
|
||||||
<form method="get" action="{{ url_for('leads.institutions') }}">
|
<button class="nav-link active" id="institutions-tab" data-bs-toggle="tab" data-bs-target="#institutions" type="button" role="tab">
|
||||||
<div class="input-group">
|
<i class="bi bi-building"></i> Institutionen
|
||||||
<input type="text" class="form-control" name="search" placeholder="Nach Institution oder Kontakt suchen...">
|
|
||||||
<button class="btn btn-primary" type="submit">
|
|
||||||
<i class="bi bi-search"></i> Suchen
|
|
||||||
</button>
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link" id="contacts-tab" data-bs-toggle="tab" data-bs-target="#contacts" type="button" role="tab">
|
||||||
|
<i class="bi bi-people"></i> Kontakte
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<!-- Tab Content -->
|
||||||
|
<div class="tab-content" id="leadTabContent">
|
||||||
|
<!-- Institutions Tab -->
|
||||||
|
<div class="tab-pane fade show active" id="institutions" role="tabpanel">
|
||||||
|
<!-- Filter for Institutions -->
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input type="text" class="form-control" id="institutionSearch" placeholder="Institution suchen...">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<select class="form-select" id="institutionSort">
|
||||||
|
<option value="name">Alphabetisch</option>
|
||||||
|
<option value="date">Datum hinzugefügt</option>
|
||||||
|
<option value="contacts">Anzahl Kontakte</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<button class="btn btn-outline-primary w-100" id="filterNoContacts">
|
||||||
|
<i class="bi bi-funnel"></i> Ohne Kontakte
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Institutions List -->
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Anzahl Kontakte</th>
|
||||||
|
<th>Erstellt am</th>
|
||||||
|
<th>Aktionen</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for institution in institutions %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="{{ url_for('leads.institution_detail', institution_id=institution.id) }}">
|
||||||
|
{{ institution.name }}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>{{ institution.contact_count }}</td>
|
||||||
|
<td>{{ institution.created_at.strftime('%d.%m.%Y') }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ url_for('leads.institution_detail', institution_id=institution.id) }}" class="btn btn-sm btn-outline-primary">
|
||||||
|
<i class="bi bi-eye"></i> Details
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% if not institutions %}
|
||||||
|
<p class="text-muted text-center py-3">Keine Institutionen vorhanden.</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
|
||||||
|
<!-- Contacts Tab -->
|
||||||
|
<div class="tab-pane fade" id="contacts" role="tabpanel">
|
||||||
|
<!-- Filter for Contacts -->
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<input type="text" class="form-control" id="contactSearch" placeholder="Kontakt suchen...">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<select class="form-select" id="institutionFilter">
|
||||||
|
<option value="">Alle Institutionen</option>
|
||||||
|
{% for institution in institutions %}
|
||||||
|
<option value="{{ institution.id }}">{{ institution.name }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2">
|
||||||
|
<button class="btn btn-outline-primary w-100" id="filterNoEmail">
|
||||||
|
<i class="bi bi-envelope-slash"></i> Ohne E-Mail
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<button class="btn btn-outline-primary w-100" id="filterNoPhone">
|
||||||
|
<i class="bi bi-telephone-x"></i> Ohne Telefon
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Contacts List -->
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Position</th>
|
||||||
|
<th>Institution</th>
|
||||||
|
<th>E-Mail</th>
|
||||||
|
<th>Telefon</th>
|
||||||
|
<th>Aktionen</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for contact in all_contacts %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="{{ url_for('leads.contact_detail', contact_id=contact.id) }}">
|
||||||
|
{{ contact.first_name }} {{ contact.last_name }}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>{{ contact.position or '-' }}</td>
|
||||||
|
<td>{{ contact.institution_name }}</td>
|
||||||
|
<td>
|
||||||
|
{% if contact.emails %}
|
||||||
|
<small>{{ contact.emails[0] }}</small>
|
||||||
|
{% else %}
|
||||||
|
<span class="text-muted">-</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if contact.phones %}
|
||||||
|
<small>{{ contact.phones[0] }}</small>
|
||||||
|
{% else %}
|
||||||
|
<span class="text-muted">-</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ url_for('leads.contact_detail', contact_id=contact.id) }}" class="btn btn-sm btn-outline-primary">
|
||||||
|
<i class="bi bi-eye"></i> Details
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% if not all_contacts %}
|
||||||
|
<p class="text-muted text-center py-3">Keine Kontakte vorhanden.</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -138,4 +250,118 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Add Contact Modal -->
|
||||||
|
<div class="modal fade" id="addContactModal" tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<form method="POST" action="{{ url_for('leads.add_contact') }}">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Neuen Kontakt hinzufügen</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="institution_id" class="form-label">Institution</label>
|
||||||
|
<select class="form-select" id="institution_id" name="institution_id" required>
|
||||||
|
<option value="">Bitte wählen...</option>
|
||||||
|
{% for institution in institutions %}
|
||||||
|
<option value="{{ institution.id }}">{{ institution.name }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label for="first_name" class="form-label">Vorname</label>
|
||||||
|
<input type="text" class="form-control" id="first_name" name="first_name" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label for="last_name" class="form-label">Nachname</label>
|
||||||
|
<input type="text" class="form-control" id="last_name" name="last_name" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="position" class="form-label">Position</label>
|
||||||
|
<input type="text" class="form-control" id="position" name="position">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="email" class="form-label">E-Mail</label>
|
||||||
|
<input type="email" class="form-control" id="email" name="email">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="phone" class="form-label">Telefon</label>
|
||||||
|
<input type="tel" class="form-control" id="phone" name="phone">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Abbrechen</button>
|
||||||
|
<button type="submit" class="btn btn-primary">Hinzufügen</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_js %}
|
||||||
|
<script>
|
||||||
|
// Filter functionality
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Institution search
|
||||||
|
const institutionSearch = document.getElementById('institutionSearch');
|
||||||
|
if (institutionSearch) {
|
||||||
|
institutionSearch.addEventListener('input', function() {
|
||||||
|
filterTable('institutions', this.value.toLowerCase(), 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contact search
|
||||||
|
const contactSearch = document.getElementById('contactSearch');
|
||||||
|
if (contactSearch) {
|
||||||
|
contactSearch.addEventListener('input', function() {
|
||||||
|
filterTable('contacts', this.value.toLowerCase(), [0, 1, 2]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter table function
|
||||||
|
function filterTable(tabId, searchTerm, columnIndices) {
|
||||||
|
const table = document.querySelector(`#${tabId} table tbody`);
|
||||||
|
const rows = table.getElementsByTagName('tr');
|
||||||
|
|
||||||
|
Array.from(rows).forEach(row => {
|
||||||
|
let match = false;
|
||||||
|
const indices = Array.isArray(columnIndices) ? columnIndices : [columnIndices];
|
||||||
|
|
||||||
|
indices.forEach(index => {
|
||||||
|
const cell = row.getElementsByTagName('td')[index];
|
||||||
|
if (cell && cell.textContent.toLowerCase().includes(searchTerm)) {
|
||||||
|
match = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
row.style.display = match || searchTerm === '' ? '' : 'none';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Institution filter
|
||||||
|
const institutionFilter = document.getElementById('institutionFilter');
|
||||||
|
if (institutionFilter) {
|
||||||
|
institutionFilter.addEventListener('change', function() {
|
||||||
|
const selectedInstitution = this.value;
|
||||||
|
const table = document.querySelector('#contacts table tbody');
|
||||||
|
const rows = table.getElementsByTagName('tr');
|
||||||
|
|
||||||
|
Array.from(rows).forEach(row => {
|
||||||
|
const institutionCell = row.getElementsByTagName('td')[2];
|
||||||
|
if (selectedInstitution === '' || institutionCell.textContent === this.options[this.selectedIndex].text) {
|
||||||
|
row.style.display = '';
|
||||||
|
} else {
|
||||||
|
row.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
In neuem Issue referenzieren
Einen Benutzer sperren