diff --git a/cutprogress.py b/cutprogress.py index a187fb7136d53ad7ede2cfd2b07dee83b19280a7..3e94a8d7bf8e4080150977a464ec621cf91cd515 100644 --- a/cutprogress.py +++ b/cutprogress.py @@ -1,14 +1,10 @@ from server import * from datetime import time -@register_navbar('Schnittfortschritt User', icon='spinner', iconlib='fa', userendpoint=True) -@app.route('/internal/user/<int:user>/cutprogress') -@mod_required -def cutprogress_user(user): - return cutprogress(user) - +@register_navbar('Schnittfortschritt User', icon='spinner', iconlib='fa', userendpoint=True, endpoint='cutprogress_user') @register_navbar('Schnittfortschritt', icon='spinner', iconlib='fa') @app.route('/internal/cutprogress', endpoint="cutprogress") +@app.route('/internal/user/<int:user>/cutprogress', endpoint='cutprogress_user') @mod_required def cutprogress(user=None): allsemester = query('SELECT DISTINCT semester from courses ORDER BY semester DESC'); diff --git a/edit.py b/edit.py index 0943c475ee72bf22ee055477fb899bab115ba268..33df20b8d7a0fd5e588d3eda375b24f5e57aa674 100644 --- a/edit.py +++ b/edit.py @@ -192,7 +192,7 @@ def create(table): return str(id), 200 @app.route('/internal/changelog') -@register_navbar('Changelog', icon='book') +@register_navbar('Changelog', icon='book', group='weitere') @mod_required def changelog(): if 'page' in request.args: diff --git a/jobs.py b/jobs.py index 1168e3331f49842c3f19a956232b70c0567ec138..a410e4a152d06d0e5d3514c4d32a5f8fd01e8130 100644 --- a/jobs.py +++ b/jobs.py @@ -33,7 +33,7 @@ def restart_job(job_id, canceled=False): modify('UPDATE jobs SET state = "ready" WHERE id = ? AND state = "failed" AND NOT canceled', job_id) @app.route('/internal/jobs/overview') -@register_navbar('Jobs', iconlib='fa', icon='suitcase') +@register_navbar('Jobs', iconlib='fa', icon='suitcase', group='weitere') @mod_required def jobs_overview(): if 'page' in request.args: diff --git a/server.py b/server.py index 282c75ebdb970290d3e68320645d41cd71612808..e484976657a9d9980653c821692dc946f3498202 100644 --- a/server.py +++ b/server.py @@ -75,26 +75,14 @@ def evalperm(perms): return cperms return [{'type': 'public'}] -app.jinja_env.globals['navbar'] = [] -# iconlib can be 'bootstrap' -# ( see: http://getbootstrap.com/components/#glyphicons ) -# or 'fa' -# ( see: http://fontawesome.io/icons/ ) -def register_navbar(name, iconlib='bootstrap', icon=None, userendpoint=False): - def wrapper(func): - endpoint = func.__name__ - app.jinja_env.globals['navbar'].append((endpoint, name, iconlib, icon, not endpoint in mod_endpoints, userendpoint)) - return func - return wrapper from db import query, modify, show, searchquery +from template_helper import * from mail import notify_mods, notify_admins from ldap import ldapauth from legacy import legacy_index from scheduler import sched_func -from template_helper import * - def render_endpoint(endpoint, flashtext=None, **kargs): if flashtext: flash(flashtext) @@ -458,7 +446,7 @@ def sitemap(): return Response(render_template('sitemap.xml', pages=pages), 200, {'Content-Type': 'application/atom+xml'} ) @app.route('/internal/dbstatus') -@register_navbar('DB-Status', icon='ok') +@register_navbar('DB-Status', icon='ok', group='weitere') @mod_required def dbstatus(): hosts = set() diff --git a/sorter.py b/sorter.py index ffac660fe0f6b9c42a434f29bd96ab0d0993df0b..d52016c84f956ed32ddfc9e519f7cd2971d90b8f 100644 --- a/sorter.py +++ b/sorter.py @@ -3,7 +3,7 @@ import traceback import os.path @app.route('/internal/sort/log') -@register_navbar('Sortierlog', icon='sort-by-attributes-alt') +@register_navbar('Sortierlog', icon='sort-by-attributes-alt', group='weitere') @mod_required def sort_log(): return render_template('sortlog.html',sortlog=query(''' diff --git a/template_helper.py b/template_helper.py index cfe252be18a56cf0a1f11b47dbc6825912f6d18e..26be0e7215fc5b849558187d656f4ce4a3fd78e8 100644 --- a/template_helper.py +++ b/template_helper.py @@ -20,8 +20,29 @@ app.jinja_env.globals['gitversion'] = {'hash': output[1], 'longhash': output[0], def ismod(*args): return ('user' in session) -csrf_endpoints = [] +app.jinja_env.globals['navbar'] = [] +# iconlib can be 'bootstrap' +# ( see: http://getbootstrap.com/components/#glyphicons ) +# or 'fa' +# ( see: http://fontawesome.io/icons/ ) +def register_navbar(name, iconlib='bootstrap', icon=None, userendpoint=False, group=None, endpoint=None): + def wrapper(func): + urlendpoint = endpoint + if not endpoint: + urlendpoint = func.__name__ + item = {} + item['iconlib'] = iconlib + item['icon'] = icon + item['userendpoint'] = userendpoint + item['group'] = group + item['endpoint'] = urlendpoint + item['visible'] = not urlendpoint in mod_endpoints + item['name'] = name + app.jinja_env.globals['navbar'].append(item) + return func + return wrapper +csrf_endpoints = [] def csrf_protect(func): csrf_endpoints.append(func.__name__) @wraps(func) diff --git a/templates/base.html b/templates/base.html index 7a72d98ad3d763a1104b327d45093ad8ec9f2dc7..8e2e8c8abe95552175ead90c9ff7fb5c6086c0c6 100644 --- a/templates/base.html +++ b/templates/base.html @@ -8,7 +8,7 @@ <html lang="de"> <head> {% block header %} - <title>Video AG {% block title %}{% for endpoint, caption, iconlib, gly, visible, userendpoint in navbar if ((visible or ismod()) and (endpoint == request.endpoint)) %}- {{ caption }}{% else%}{% endfor %}{% endblock %}</title> + <title>Video AG {% block title %}{% for n in navbar if ((n.visible or ismod()) and (endpoint == request.endpoint)) %}- {{ n.name }}{% endfor %}{% endblock %}</title> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <link rel="icon" type="image/png" href="{{url_for('static', filename='favicon.png')}}"> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> @@ -43,6 +43,20 @@ </head> <body> {% block navbar %} + {% macro navbaricon(data, user=none) -%} + <li{% if data.endpoint == request.endpoint %} class="active"{% endif %}> + <a href="{{ url_for(data.endpoint, user=user) }}" style="padding: 10px 6px;"> + {% if data.gly != '' %} + {% if data.iconlib == 'bootstrap' %} + <span aria-hidden="true" class="glyphicon glyphicon-{{ data.icon }}"></span> + {% elif data.iconlib == 'fa' %} + <span aria-hidden="true" class="fa fa-{{ data.icon }}"></span> + {% endif %} + {{ data.name }} + {% endif %} + </a> + </li> + {%- endmacro %} <nav class="hidden-print navbar navbar-default navbar-static-top" {% if config.DEBUG %} style="background-color: red" {% endif %} > <div class="container-fluid"> <div class="navbar-header"> @@ -56,39 +70,27 @@ <img alt="Brand" src="{{url_for('static', filename='logo.png')}}" style="height: 44px; width: 44px" > </a> <ul class="nav nav-pills" style="margin-top: 5px; padding-left: 40px;"> - {% for endpoint, caption, iconlib, gly, visible, userendpoint in navbar if visible and (not userendpoint) %} - <li{% if endpoint == request.endpoint %} class="active"{% endif %}> - <a href="{{ url_for(endpoint) }}" style="padding: 10px 6px;"> - {% if gly != '' %} - {% if iconlib == 'bootstrap' %} - <span aria-hidden="true" class="glyphicon glyphicon-{{ gly }}"></span> - {% elif iconlib == 'fa' %} - <span aria-hidden="true" class="fa fa-{{ gly }}"></span> - {% endif %} - {{ caption }} - {% endif %} - </a> - </li> + {% for n in navbar if n.visible and (not n.userendpoint) %} + {{ navbaricon(n) }} {% endfor %} </ul> </div> <div class="collapse navbar-collapse" style="overflow-y: inherit"> <ul class="nav nav-pills" style="margin-top: 5px;"> - {% for endpoint, caption, iconlib, gly, visible, userendpoint in navbar if (not visible) and ismod() and (not userendpoint) %} - <li{% if endpoint == request.endpoint %} class="active"{% endif %}> - <a href="{{ url_for(endpoint) }}" style="padding: 10px 6px;"> - {% if gly != '' %} - {% if iconlib == 'bootstrap' %} - <span aria-hidden="true" class="glyphicon glyphicon-{{ gly }}"></span> - {% elif iconlib == 'fa' %} - <span aria-hidden="true" class="fa fa-{{ gly }}"></span> - {% endif %} - {{ caption }} - {% endif %} - </a> - </li> + {% for n in navbar if (not n.visible) and ismod() and (not n.userendpoint) and (not n.group) %} + {{ navbaricon(n) }} {% endfor %} + {% for grouper, list in navbar|rejectattr("group", "none")|groupby("group") %} + <li{% if request.endpoint in list|map(attribute='endpoint') %} class="active dropdown"{% endif %}> + <a data-toggle="dropdown" data-boundary="viewport" class="dropdown-toggle" style="padding: 10px 6px;">{{ grouper }}<span class="caret"></span></a> + <ul class="dropdown-menu"> + {% for n in list %} + {{ navbaricon(n) }} + {% endfor %} + </ul> + </li> + {% endfor %} <li class="col-xs-9 col-sm-4 pull-right"> <form action="{{ url_for('search') }}" role="search"> <div class="input-group" style="margin-top: 3px"> @@ -116,19 +118,8 @@ {% else %} <button data-toggle="dropdown" data-boundary="viewport" class="btn dropdown-toggle" style="padding: 10px 6px;">{{ session.user.givenName }} <span class="caret"></span></button> <ul class="dropdown-menu"> - {% for endpoint, caption, iconlib, gly, visible, userendpoint in navbar if userendpoint %} - <li{% if endpoint == request.endpoint %} class="active"{% endif %}> - <a href="{{ url_for(endpoint, user=session.user.dbid) }}"> - {% if gly != '' %} - {% if iconlib == 'bootstrap' %} - <span aria-hidden="true" class="glyphicon glyphicon-{{ gly }}"></span> - {% elif iconlib == 'fa' %} - <span aria-hidden="true" class="fa fa-{{ gly }}"></span> - {% endif %} - {{ caption }} - {% endif %} - </a> - </li> + {% for n in navbar if n.userendpoint %} + {{ navbaricon(n, user=session.user.dbid) }} {% endfor %} <li class="divider"></li> <li><a href="{{url_for('logout', ref=request.url)}}">Logout</a></li> diff --git a/timetable.py b/timetable.py index 2d93dca541ce5a883ed89738b4965e0ed8567124..73d94bcf435215afb7104125ee6810874c8efeb9 100644 --- a/timetable.py +++ b/timetable.py @@ -1,14 +1,10 @@ from server import * from datetime import time -@app.route('/internal/user/<int:user>/timetable') -@register_navbar('personalisierter Drehplan', icon='calendar', userendpoint=True) -@mod_required -def timetable_user(user): - return timetable(user) - -@app.route('/internal/timetable') +@register_navbar('personalisierter Drehplan', icon='calendar', userendpoint=True, endpoint='timetable_user') @register_navbar('Drehplan', icon='calendar') +@app.route('/internal/timetable') +@app.route('/internal/user/<int:user>/timetable', endpoint='timetable_user') @mod_required def timetable(user=None): if 'kw' not in request.args: