new implementation of the mail module relevant fuktions, in addition added thje funktion to add a title to the Terminplan
This commit is contained in:
+10
-2
@@ -1268,7 +1268,8 @@ def inject_version():
|
|||||||
'inventory_module_enabled': cfg.MODULES.is_enabled('inventory'),
|
'inventory_module_enabled': cfg.MODULES.is_enabled('inventory'),
|
||||||
'terminplan_module_enabled': cfg.MODULES.is_enabled('terminplan'),
|
'terminplan_module_enabled': cfg.MODULES.is_enabled('terminplan'),
|
||||||
'library_module_enabled': cfg.MODULES.is_enabled('library'),
|
'library_module_enabled': cfg.MODULES.is_enabled('library'),
|
||||||
'student_cards_module_enabled': cfg.MODULES.is_enabled('student_cards'),
|
'student_cards_module_enabled': cfg.MODULES.is_enabled('student_cards'),#
|
||||||
|
'mail_module_enabled': cfg.MODULES.is_enabled('mail'),
|
||||||
'is_admin': is_admin,
|
'is_admin': is_admin,
|
||||||
'unread_notification_count': unread_notification_count,
|
'unread_notification_count': unread_notification_count,
|
||||||
'current_permissions': current_permissions,
|
'current_permissions': current_permissions,
|
||||||
@@ -2885,6 +2886,7 @@ def home():
|
|||||||
username=session['username'],
|
username=session['username'],
|
||||||
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
||||||
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
|
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
|
||||||
|
mail_module_enabled=cfg.MODULES.is_enabled('mail'),
|
||||||
student_default_borrow_days=cfg.STUDENT_DEFAULT_BORROW_DAYS,
|
student_default_borrow_days=cfg.STUDENT_DEFAULT_BORROW_DAYS,
|
||||||
student_max_borrow_days=cfg.STUDENT_MAX_BORROW_DAYS,
|
student_max_borrow_days=cfg.STUDENT_MAX_BORROW_DAYS,
|
||||||
open_item=request.args.get('open_item')
|
open_item=request.args.get('open_item')
|
||||||
@@ -2927,6 +2929,7 @@ def home_admin():
|
|||||||
username=session['username'],
|
username=session['username'],
|
||||||
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
||||||
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
|
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
|
||||||
|
mail_module_enabled=cfg.MODULES.is_enabled('mail'),
|
||||||
student_default_borrow_days=cfg.STUDENT_DEFAULT_BORROW_DAYS,
|
student_default_borrow_days=cfg.STUDENT_DEFAULT_BORROW_DAYS,
|
||||||
student_max_borrow_days=cfg.STUDENT_MAX_BORROW_DAYS,
|
student_max_borrow_days=cfg.STUDENT_MAX_BORROW_DAYS,
|
||||||
school_info=_get_school_info_for_export(),
|
school_info=_get_school_info_for_export(),
|
||||||
@@ -2947,6 +2950,7 @@ def tutorial_page():
|
|||||||
is_admin=us.check_admin(session['username']),
|
is_admin=us.check_admin(session['username']),
|
||||||
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
||||||
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
|
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
|
||||||
|
mail_module_enabled=cfg.MODULES.is_enabled('mail'),
|
||||||
student_default_borrow_days=cfg.STUDENT_DEFAULT_BORROW_DAYS,
|
student_default_borrow_days=cfg.STUDENT_DEFAULT_BORROW_DAYS,
|
||||||
student_max_borrow_days=cfg.STUDENT_MAX_BORROW_DAYS
|
student_max_borrow_days=cfg.STUDENT_MAX_BORROW_DAYS
|
||||||
)
|
)
|
||||||
@@ -7980,7 +7984,8 @@ def admin_borrowings():
|
|||||||
'admin_borrowings.html',
|
'admin_borrowings.html',
|
||||||
entries=entries,
|
entries=entries,
|
||||||
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
||||||
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards')
|
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
|
||||||
|
mail_module_enabled=cfg.MODULES.is_enabled('mail')
|
||||||
)
|
)
|
||||||
|
|
||||||
"""-----------------------------------------------------------Audit Routes-------------------------------------------------------"""
|
"""-----------------------------------------------------------Audit Routes-------------------------------------------------------"""
|
||||||
@@ -8043,6 +8048,7 @@ def admin_audit_dashboard():
|
|||||||
audit_rows=audit_rows,
|
audit_rows=audit_rows,
|
||||||
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
||||||
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
|
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
|
||||||
|
mail_module_enabled=cfg.MODULES.is_enabled('mail'),
|
||||||
)
|
)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
app.logger.error(f"Error loading audit dashboard: {exc}")
|
app.logger.error(f"Error loading audit dashboard: {exc}")
|
||||||
@@ -8858,6 +8864,7 @@ def library_item_invoices(item_id):
|
|||||||
invoices=entries,
|
invoices=entries,
|
||||||
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
||||||
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
|
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
|
||||||
|
mail_module_enabled=cfg.MODULES.is_enabled('mail')
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
app.logger.error(f"Error loading invoice history for item {item_id}: {e}")
|
app.logger.error(f"Error loading invoice history for item {item_id}: {e}")
|
||||||
@@ -10192,6 +10199,7 @@ def admin_damaged_items():
|
|||||||
damaged_items=damaged_rows,
|
damaged_items=damaged_rows,
|
||||||
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
||||||
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
|
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
|
||||||
|
mail_module_enabled=cfg.MODULES.is_enabled('mail')
|
||||||
)
|
)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
app.logger.error(f"Error loading damaged-items admin view: {exc}")
|
app.logger.error(f"Error loading damaged-items admin view: {exc}")
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from modules.module_registry import ModuleRegistry as mr
|
||||||
import smtplib
|
import smtplib
|
||||||
|
|
||||||
import Web.modules.database.settings as cfg
|
import Web.modules.database.settings as cfg
|
||||||
@@ -27,21 +28,24 @@ def send(email: list, subject: str, note: str, sender: str) -> bool:
|
|||||||
Output:
|
Output:
|
||||||
- bool: true if the sending worked and false if it didnt
|
- bool: true if the sending worked and false if it didnt
|
||||||
"""
|
"""
|
||||||
msg = MIMEMultipart()
|
if not mr.registry.is_enabled('mail'):
|
||||||
msg['Subject'] = subject
|
|
||||||
msg['From'] = sender or cfg.EMAIL_FROM_ADDRESS or cfg.EMAIL_USERNAME
|
|
||||||
msg['To'] = ', '.join(email) if isinstance(email, (list, tuple)) else str(email)
|
|
||||||
msg.attach(MIMEText(note))
|
|
||||||
smtp = None
|
|
||||||
try:
|
|
||||||
smtp = _build_smtp_client()
|
|
||||||
smtp.sendmail(from_addr=msg['From'], to_addrs=email, msg=msg.as_string())
|
|
||||||
return True
|
|
||||||
except Exception:
|
|
||||||
return False
|
return False
|
||||||
finally:
|
else:
|
||||||
|
msg = MIMEMultipart()
|
||||||
|
msg['Subject'] = subject
|
||||||
|
msg['From'] = sender or cfg.EMAIL_FROM_ADDRESS or cfg.EMAIL_USERNAME
|
||||||
|
msg['To'] = ', '.join(email) if isinstance(email, (list, tuple)) else str(email)
|
||||||
|
msg.attach(MIMEText(note))
|
||||||
|
smtp = None
|
||||||
try:
|
try:
|
||||||
if smtp:
|
smtp = _build_smtp_client()
|
||||||
smtp.quit()
|
smtp.sendmail(from_addr=msg['From'], to_addrs=email, msg=msg.as_string())
|
||||||
|
return True
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
return False
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
if smtp:
|
||||||
|
smtp.quit()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
@@ -82,6 +82,7 @@ def build_calendar_ics(appointment_id: str) -> str | None:
|
|||||||
time_span = item.get('time_span', []) or []
|
time_span = item.get('time_span', []) or []
|
||||||
creator = item.get('user', 'Terminplaner')
|
creator = item.get('user', 'Terminplaner')
|
||||||
note = item.get('note', '') or ''
|
note = item.get('note', '') or ''
|
||||||
|
titel = item.get('title', '') or ''
|
||||||
tenant_id = _current_tenant_id()
|
tenant_id = _current_tenant_id()
|
||||||
try:
|
try:
|
||||||
link = url_for('terminplaner.client', appointment_id=str(appointment_id), tenant=tenant_id or None, _external=True)
|
link = url_for('terminplaner.client', appointment_id=str(appointment_id), tenant=tenant_id or None, _external=True)
|
||||||
@@ -108,6 +109,8 @@ def build_calendar_ics(appointment_id: str) -> str | None:
|
|||||||
description_lines.append('Zeitfenster: ' + '; '.join(str(entry) for entry in time_span))
|
description_lines.append('Zeitfenster: ' + '; '.join(str(entry) for entry in time_span))
|
||||||
if note:
|
if note:
|
||||||
description_lines.append('Notiz: ' + str(note))
|
description_lines.append('Notiz: ' + str(note))
|
||||||
|
if titel:
|
||||||
|
description_lines.append('Titel: ' + str(titel))
|
||||||
|
|
||||||
ics_lines = [
|
ics_lines = [
|
||||||
'BEGIN:VCALENDAR',
|
'BEGIN:VCALENDAR',
|
||||||
@@ -123,6 +126,7 @@ def build_calendar_ics(appointment_id: str) -> str | None:
|
|||||||
f'URL:{_escape_ics_text(link)}',
|
f'URL:{_escape_ics_text(link)}',
|
||||||
f'DTSTART;VALUE=DATE:{_format_ics_date(start_date)}',
|
f'DTSTART;VALUE=DATE:{_format_ics_date(start_date)}',
|
||||||
f'DTEND;VALUE=DATE:{_format_ics_date(end_date + timedelta(days=1))}',
|
f'DTEND;VALUE=DATE:{_format_ics_date(end_date + timedelta(days=1))}',
|
||||||
|
f'Titel:{_escape_ics_text(titel)}',
|
||||||
'END:VEVENT',
|
'END:VEVENT',
|
||||||
'END:VCALENDAR',
|
'END:VCALENDAR',
|
||||||
'',
|
'',
|
||||||
@@ -159,7 +163,7 @@ def build_client_slot_ics(appointment_id: str, slot_start: str, client_name: str
|
|||||||
if tenant_id:
|
if tenant_id:
|
||||||
link += f'?tenant={tenant_id}'
|
link += f'?tenant={tenant_id}'
|
||||||
|
|
||||||
title_name = str(client_name or '').strip() or 'Termin'
|
title_name = item.get('title') or f"Terminbuchung mit {client_name}" if client_name else "Terminbuchung"
|
||||||
summary = f"{title_name} - Terminbuchung"
|
summary = f"{title_name} - Terminbuchung"
|
||||||
description_lines = [
|
description_lines = [
|
||||||
f"Buchungslink: {link}",
|
f"Buchungslink: {link}",
|
||||||
@@ -185,6 +189,7 @@ def build_client_slot_ics(appointment_id: str, slot_start: str, client_name: str
|
|||||||
f'URL:{_escape_ics_text(link)}',
|
f'URL:{_escape_ics_text(link)}',
|
||||||
f'DTSTART:{dt_start}',
|
f'DTSTART:{dt_start}',
|
||||||
f'DTEND:{dt_end}',
|
f'DTEND:{dt_end}',
|
||||||
|
f'Titel:{_escape_ics_text(summary)}',
|
||||||
'END:VEVENT',
|
'END:VEVENT',
|
||||||
'END:VCALENDAR',
|
'END:VCALENDAR',
|
||||||
'',
|
'',
|
||||||
@@ -192,7 +197,7 @@ def build_client_slot_ics(appointment_id: str, slot_start: str, client_name: str
|
|||||||
return '\r\n'.join(ics_lines)
|
return '\r\n'.join(ics_lines)
|
||||||
|
|
||||||
|
|
||||||
def new(date_start: str, date_end: str, time_span: list, slots: int, slot_lenght: int, user: str, mail: list=[], note:str="", calendar_enabled: bool=False) -> dict:
|
def new(date_start: str, date_end: str, time_span: list, slots: int, slot_lenght: int, user: str, mail: list=[], note:str="", calendar_enabled: bool=False, title: str="") -> dict:
|
||||||
"""
|
"""
|
||||||
Generates a link for the executive to send to his clients to book a time Slot
|
Generates a link for the executive to send to his clients to book a time Slot
|
||||||
|
|
||||||
@@ -208,7 +213,7 @@ def new(date_start: str, date_end: str, time_span: list, slots: int, slot_lenght
|
|||||||
"""
|
"""
|
||||||
normalized_time_span = _normalize_time_span(time_span)
|
normalized_time_span = _normalize_time_span(time_span)
|
||||||
normalized_mail = _normalize_mail_list(mail)
|
normalized_mail = _normalize_mail_list(mail)
|
||||||
id = termin.add(date_start, date_end, normalized_time_span, slots, slot_lenght, user, normalized_mail, note, calendar_enabled=calendar_enabled)
|
id = termin.add(date_start, date_end, normalized_time_span, slots, slot_lenght, user, normalized_mail, note, calendar_enabled=calendar_enabled, title=title)
|
||||||
id_str = str(id)
|
id_str = str(id)
|
||||||
tenant_id = _current_tenant_id()
|
tenant_id = _current_tenant_id()
|
||||||
|
|
||||||
@@ -219,7 +224,7 @@ def new(date_start: str, date_end: str, time_span: list, slots: int, slot_lenght
|
|||||||
link = host + "/terminplaner/client/" + id_str
|
link = host + "/terminplaner/client/" + id_str
|
||||||
if tenant_id:
|
if tenant_id:
|
||||||
link += f"?tenant={tenant_id}"
|
link += f"?tenant={tenant_id}"
|
||||||
subject = f"Terminanfrage von {user}"
|
subject = f"{title} - Bitte Termin vereinbaren" if title else f"Terminanfrage von {user} - Bitte Termin vereinbaren"
|
||||||
note_link = note + f"Bitte klicken sie auf den folgenden Link um einen Termin zu vereinbaren: {link}"
|
note_link = note + f"Bitte klicken sie auf den folgenden Link um einen Termin zu vereinbaren: {link}"
|
||||||
calendar_link = None
|
calendar_link = None
|
||||||
if calendar_enabled:
|
if calendar_enabled:
|
||||||
@@ -459,6 +464,7 @@ def get_user_upcoming_events(user: str, limit: int = 25) -> list[dict]:
|
|||||||
'note': str(item.get('note') or ''),
|
'note': str(item.get('note') or ''),
|
||||||
'link': link,
|
'link': link,
|
||||||
'calendar_link': calendar_link if item.get('calendar_enabled') else None,
|
'calendar_link': calendar_link if item.get('calendar_enabled') else None,
|
||||||
|
'title': str(item.get('title') or ''),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -173,8 +173,9 @@ def configure():
|
|||||||
mail = request.form.get('mail', '')
|
mail = request.form.get('mail', '')
|
||||||
note = request.form.get('note', '')
|
note = request.form.get('note', '')
|
||||||
add_to_calendar = request.form.get('add_to_calendar') == 'on'
|
add_to_calendar = request.form.get('add_to_calendar') == 'on'
|
||||||
|
titel = request.form.get('titel', '').strip()
|
||||||
|
|
||||||
if not start or not end or not time or not slots_amount or not slot_lenght:
|
if not start or not end or not time or not slots_amount or not slot_lenght or not titel:
|
||||||
flash('Bitte alle Pflichtfelder ausfüllen.', 'error')
|
flash('Bitte alle Pflichtfelder ausfüllen.', 'error')
|
||||||
return render_template(
|
return render_template(
|
||||||
'termin_configure.html',
|
'termin_configure.html',
|
||||||
@@ -183,7 +184,7 @@ def configure():
|
|||||||
email_service_enabled=cfg.EMAIL_ENABLED,
|
email_service_enabled=cfg.EMAIL_ENABLED,
|
||||||
)
|
)
|
||||||
|
|
||||||
result = appointment_service.new(start, end, time, slots_amount, slot_lenght, session["username"], mail, note, calendar_enabled=add_to_calendar)
|
result = appointment_service.new(start, end, time, slots_amount, slot_lenght, session["username"], mail, note, calendar_enabled=add_to_calendar, title=titel)
|
||||||
flash('Der Terminplan wurde angelegt.', 'success')
|
flash('Der Terminplan wurde angelegt.', 'success')
|
||||||
return render_template(
|
return render_template(
|
||||||
'termin_configure.html',
|
'termin_configure.html',
|
||||||
@@ -192,6 +193,7 @@ def configure():
|
|||||||
calendar_link=result.get('calendar_link'),
|
calendar_link=result.get('calendar_link'),
|
||||||
add_to_calendar=add_to_calendar,
|
add_to_calendar=add_to_calendar,
|
||||||
email_service_enabled=cfg.EMAIL_ENABLED,
|
email_service_enabled=cfg.EMAIL_ENABLED,
|
||||||
|
title=titel,
|
||||||
)
|
)
|
||||||
elif request.method == "GET":
|
elif request.method == "GET":
|
||||||
return render_template(
|
return render_template(
|
||||||
@@ -201,6 +203,7 @@ def configure():
|
|||||||
calendar_link=None,
|
calendar_link=None,
|
||||||
add_to_calendar=False,
|
add_to_calendar=False,
|
||||||
email_service_enabled=cfg.EMAIL_ENABLED,
|
email_service_enabled=cfg.EMAIL_ENABLED,
|
||||||
|
title=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -214,8 +217,10 @@ def calendar_export(appointment_id):
|
|||||||
if not ics_content:
|
if not ics_content:
|
||||||
return _appointment_not_found_response()
|
return _appointment_not_found_response()
|
||||||
|
|
||||||
|
title = str(request.args.get('title', '') or '').strip() or appointment_id
|
||||||
|
|
||||||
response = Response(ics_content, mimetype='text/calendar; charset=utf-8')
|
response = Response(ics_content, mimetype='text/calendar; charset=utf-8')
|
||||||
response.headers['Content-Disposition'] = f'attachment; filename=terminplan-{appointment_id}.ics'
|
response.headers['Content-Disposition'] = f'attachment; filename=terminplan-{title}-{appointment_id}.ics'
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@@ -231,8 +236,10 @@ def client_slot_calendar_export(appointment_id):
|
|||||||
if not ics_content:
|
if not ics_content:
|
||||||
return _appointment_not_found_response()
|
return _appointment_not_found_response()
|
||||||
|
|
||||||
|
title = str(request.args.get('title', '') or '').strip() or appointment_id
|
||||||
|
|
||||||
response = Response(ics_content, mimetype='text/calendar; charset=utf-8')
|
response = Response(ics_content, mimetype='text/calendar; charset=utf-8')
|
||||||
response.headers['Content-Disposition'] = f'attachment; filename=termin-{appointment_id}-{slot_start.replace(" ", "_").replace(":", "")}.ics'
|
response.headers['Content-Disposition'] = f'attachment; filename=termin-{title}-{appointment_id}-{slot_start.replace(" ", "_").replace(":", "")}.ics'
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@appoint_bp.route('/')
|
@appoint_bp.route('/')
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
<div class="card-body p-4 p-md-5 bg-white">
|
<div class="card-body p-4 p-md-5 bg-white">
|
||||||
<form method="post" action="{{ url_for('terminplaner.configure') }}" class="vstack gap-3">
|
<form method="post" action="{{ url_for('terminplaner.configure') }}" class="vstack gap-3">
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
|
<labal for="title" class="form-label fw-semibold">Titel des Terminplans</label>
|
||||||
|
<input type="text" id="title" name="title" class="form-control form-control-lg" placeholder="z.B. Elternsprechtag Klasse 10a" value="{{ title or '' }} required>">
|
||||||
<div class="col-12 col-md-6">
|
<div class="col-12 col-md-6">
|
||||||
<label for="start_date" class="form-label fw-semibold">Startdatum</label>
|
<label for="start_date" class="form-label fw-semibold">Startdatum</label>
|
||||||
<input type="date" id="start_date" name="start_date" class="form-control form-control-lg" required>
|
<input type="date" id="start_date" name="start_date" class="form-control form-control-lg" required>
|
||||||
@@ -64,16 +66,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
{% if mail_service_enabled %}
|
||||||
<label for="mail" class="form-label fw-semibold">Empfänger-Mails</label>
|
<div>
|
||||||
<input type="text" id="mail" name="mail" class="form-control" placeholder="adresse1@schule.de, adresse2@schule.de">
|
<label for="mail" class="form-label fw-semibold">Empfänger-Mails</label>
|
||||||
</div>
|
<input type="text" id="mail" name="mail" class="form-control" placeholder="adresse1@schule.de, adresse2@schule.de">
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="note" class="form-label fw-semibold">Notiz</label>
|
<label for="note" class="form-label fw-semibold">Notiz</label>
|
||||||
<textarea id="note" name="note" class="form-control" rows="4" placeholder="Optionaler Einführungstext für die Mail"></textarea>
|
<textarea id="note" name="note" class="form-control" rows="4" placeholder="Optionaler Einführungstext für die Mail"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="checkbox" id="add_to_calendar" name="add_to_calendar" {% if add_to_calendar %}checked{% endif %}>
|
<input class="form-check-input" type="checkbox" id="add_to_calendar" name="add_to_calendar" {% if add_to_calendar %}checked{% endif %}>
|
||||||
<label class="form-check-label fw-semibold" for="add_to_calendar">Kalendereintrag für den Nutzer erzeugen</label>
|
<label class="form-check-label fw-semibold" for="add_to_calendar">Kalendereintrag für den Nutzer erzeugen</label>
|
||||||
|
|||||||
@@ -26,12 +26,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<button id="new-booking" class="primary-button">Zur Termin-Konfiguration</button>
|
<button id="new-booking" class="primary-button">Zur Termin-Konfiguration</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="calendar-legend">
|
|
||||||
<span class="legend-item"><span class="legend-color current"></span> Aktuelle Termine</span>
|
|
||||||
<span class="legend-item"><span class="legend-color planned"></span> Geplante Termine</span>
|
|
||||||
<span class="legend-item"><span class="legend-color completed"></span> Abgeschlossene Termine</span>
|
|
||||||
<span class="legend-item"><span class="legend-color your-bookings"></span> Ihre Termine</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="calendar-options">
|
<div class="calendar-options">
|
||||||
|
|||||||
@@ -71,6 +71,7 @@
|
|||||||
<div class="border rounded-3 p-3">
|
<div class="border rounded-3 p-3">
|
||||||
<div class="d-flex flex-column flex-lg-row justify-content-between gap-3">
|
<div class="d-flex flex-column flex-lg-row justify-content-between gap-3">
|
||||||
<div>
|
<div>
|
||||||
|
<h3 class="h6 fw-bold mb-1">{{ event.title or "Terminplan" }}</h3>
|
||||||
<div class="fw-semibold">{{ event.date_start }} bis {{ event.date_end }}</div>
|
<div class="fw-semibold">{{ event.date_start }} bis {{ event.date_end }}</div>
|
||||||
<div class="text-muted small">ID: {{ event.appointment_id }}</div>
|
<div class="text-muted small">ID: {{ event.appointment_id }}</div>
|
||||||
{% if event.time_span %}
|
{% if event.time_span %}
|
||||||
|
|||||||
@@ -213,6 +213,7 @@ existing['modules'] = {
|
|||||||
'library': {'enabled': True},
|
'library': {'enabled': True},
|
||||||
'student_cards': {'enabled': True, 'default_borrow_days': 14, 'max_borrow_days': 365},
|
'student_cards': {'enabled': True, 'default_borrow_days': 14, 'max_borrow_days': 365},
|
||||||
'terminplan': {'enabled': True},
|
'terminplan': {'enabled': True},
|
||||||
|
'mail': {'enabled': True},
|
||||||
}
|
}
|
||||||
existing['trial'] = trial_config
|
existing['trial'] = trial_config
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user