mirror of
https://github.com/spiral-project/ihatemoney.git
synced 2025-05-01 02:32:23 +02:00
Arrange navbar items by functions
This commit is contained in:
parent
b5cc1592d6
commit
fd49599cc7
9 changed files with 95 additions and 41 deletions
|
@ -8,3 +8,4 @@ ACTIVATE_DEMO_PROJECT = True
|
|||
ADMIN_PASSWORD = ""
|
||||
ALLOW_PUBLIC_PROJECT_CREATION = True
|
||||
ACTIVATE_ADMIN_DASHBOARD = False
|
||||
SUPPORTED_LANGUAGES = ['en', 'fr', 'nl']
|
||||
|
|
|
@ -10,7 +10,8 @@ from werkzeug.contrib.fixers import ProxyFix
|
|||
|
||||
from ihatemoney.api import api
|
||||
from ihatemoney.models import db
|
||||
from ihatemoney.utils import PrefixedWSGI, minimal_round, IhmJSONEncoder
|
||||
from ihatemoney.utils import (IhmJSONEncoder, PrefixedWSGI, locale_from_iso,
|
||||
minimal_round, static_include)
|
||||
from ihatemoney.web import main as web_interface
|
||||
|
||||
from ihatemoney import default_settings
|
||||
|
@ -135,6 +136,8 @@ def create_app(configuration=None, instance_path='/etc/ihatemoney',
|
|||
app.mail = mail
|
||||
|
||||
# Jinja filters
|
||||
app.jinja_env.globals['static_include'] = static_include
|
||||
app.jinja_env.globals['locale_from_iso'] = locale_from_iso
|
||||
app.jinja_env.filters['minimal_round'] = minimal_round
|
||||
|
||||
# Translations
|
||||
|
@ -144,7 +147,10 @@ def create_app(configuration=None, instance_path='/etc/ihatemoney',
|
|||
def get_locale():
|
||||
# get the lang from the session if defined, fallback on the browser "accept
|
||||
# languages" header.
|
||||
lang = session.get('lang', request.accept_languages.best_match(['fr', 'en']))
|
||||
lang = session.get(
|
||||
'lang',
|
||||
request.accept_languages.best_match(app.config['SUPPORTED_LANGUAGES'])
|
||||
)
|
||||
setattr(g, 'lang', lang)
|
||||
return lang
|
||||
|
||||
|
|
|
@ -328,3 +328,16 @@ tr:hover .extra-info {
|
|||
.row-fluid > .offset1 {
|
||||
margin-left: 8.5%;
|
||||
}
|
||||
|
||||
.globe-europe svg {
|
||||
display: inline-block;
|
||||
border-bottom: 0.2em solid transparent;
|
||||
height: 1.2em;
|
||||
fill: rgba(255,255,255,.5)
|
||||
}
|
||||
.navbar-nav .dropdown-toggle:hover .globe-europe svg {
|
||||
fill: rgba(255,255,255,.75);
|
||||
}
|
||||
.navbar-dark .navbar-nav .show > .nav-link svg {
|
||||
fill: white;
|
||||
}
|
1
ihatemoney/static/images/globe.svg
Normal file
1
ihatemoney/static/images/globe.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm200 248c0 22.5-3.9 44.2-10.8 64.4h-20.3c-4.3 0-8.4-1.7-11.4-4.8l-32-32.6c-4.5-4.6-4.5-12.1.1-16.7l12.5-12.5v-8.7c0-3-1.2-5.9-3.3-8l-9.4-9.4c-2.1-2.1-5-3.3-8-3.3h-16c-6.2 0-11.3-5.1-11.3-11.3 0-3 1.2-5.9 3.3-8l9.4-9.4c2.1-2.1 5-3.3 8-3.3h32c6.2 0 11.3-5.1 11.3-11.3v-9.4c0-6.2-5.1-11.3-11.3-11.3h-36.7c-8.8 0-16 7.2-16 16v4.5c0 6.9-4.4 13-10.9 15.2l-31.6 10.5c-3.3 1.1-5.5 4.1-5.5 7.6v2.2c0 4.4-3.6 8-8 8h-16c-4.4 0-8-3.6-8-8s-3.6-8-8-8H247c-3 0-5.8 1.7-7.2 4.4l-9.4 18.7c-2.7 5.4-8.2 8.8-14.3 8.8H194c-8.8 0-16-7.2-16-16V199c0-4.2 1.7-8.3 4.7-11.3l20.1-20.1c4.6-4.6 7.2-10.9 7.2-17.5 0-3.4 2.2-6.5 5.5-7.6l40-13.3c1.7-.6 3.2-1.5 4.4-2.7l26.8-26.8c2.1-2.1 3.3-5 3.3-8 0-6.2-5.1-11.3-11.3-11.3H258l-16 16v8c0 4.4-3.6 8-8 8h-16c-4.4 0-8-3.6-8-8v-20c0-2.5 1.2-4.9 3.2-6.4l28.9-21.7c1.9-.1 3.8-.3 5.7-.3C358.3 56 448 145.7 448 256zM130.1 149.1c0-3 1.2-5.9 3.3-8l25.4-25.4c2.1-2.1 5-3.3 8-3.3 6.2 0 11.3 5.1 11.3 11.3v16c0 3-1.2 5.9-3.3 8l-9.4 9.4c-2.1 2.1-5 3.3-8 3.3h-16c-6.2 0-11.3-5.1-11.3-11.3zm128 306.4v-7.1c0-8.8-7.2-16-16-16h-20.2c-10.8 0-26.7-5.3-35.4-11.8l-22.2-16.7c-11.5-8.6-18.2-22.1-18.2-36.4v-23.9c0-16 8.4-30.8 22.1-39l42.9-25.7c7.1-4.2 15.2-6.5 23.4-6.5h31.2c10.9 0 21.4 3.9 29.6 10.9l43.2 37.1h18.3c8.5 0 16.6 3.4 22.6 9.4l17.3 17.3c3.4 3.4 8.1 5.3 12.9 5.3H423c-32.4 58.9-93.8 99.5-164.9 103.1z"/></svg>
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.3 KiB |
|
@ -28,55 +28,71 @@
|
|||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-expand-sm fixed-top navbar-dark bg-dark">
|
||||
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-dark">
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggler" aria-controls="navbarToggler" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<h1><a class="navbar-brand" href="{{ url_for("main.home") }}">#! money?</a></h1>
|
||||
{% if g.project %}<strong class="d-block d-sm-none text-white">{{ g.project.name }}</strong>{% endif %}
|
||||
{% if g.project %}
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item dropdown">
|
||||
<a href="#" class="nav-link dropdown-toggle" id="navbarProjectsLinks" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<strong class="text-white">{{ g.project.name }}</strong>
|
||||
<b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="navbarProjectsLinks">
|
||||
<li><a class="dropdown-item" href="{{ url_for("main.create_project") }}">{{ _("Start a new project") }}</a></li>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarToggler">
|
||||
<ul class="navbar-nav ml-auto mr-auto">
|
||||
{% if g.project %}
|
||||
<li class="nav-item">
|
||||
</li>
|
||||
|
||||
{% block navbar %}
|
||||
<li class="nav-item{% if current_view == 'list_bills' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.list_bills") }}">{{ _("Bills") }}</a></li>
|
||||
<li class="nav-item{% if current_view == 'settle_bill' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.settle_bill") }}">{{ _("Settle") }}</a></li>
|
||||
<li class="nav-item{% if current_view == 'statistics' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.statistics") }}">{{ _("Statistics") }}</a></li>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
{% if g.project %}
|
||||
<li class="nav-item dropdown">
|
||||
<a href="#" class="nav-link dropdown-toggle" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<strong class="d-none d-sm-inline">{{ g.project.name }}</strong> {{ _("options") }}
|
||||
<b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
|
||||
<li><a class="dropdown-item" href="{{ url_for("main.edit_project") }}">{{ _("Project settings") }}</a></li>
|
||||
<li class="dropdown-divider"></li>
|
||||
{% if (session['projects'] | length) > 1 %}
|
||||
<li class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">{{ _('Other projects :') }}</li>
|
||||
{% for id, name in session['projects'] %}
|
||||
{% if id != g.project.id %}
|
||||
<li><a class="dropdown-item" href="{{ url_for("main.list_bills", project_id=id) }}">{{ _("switch to") }} {{ name }}</a></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<li><a class="dropdown-item" href="{{ url_for("main.create_project") }}">{{ _("Start a new project") }}</a></li>
|
||||
{% if g.show_admin_dashboard_link %}
|
||||
<li class="dropdown-divider"></li>
|
||||
<li class="nav-item{% if request.url_rule.endpoint == "main.dashboard" %} active{% endif %}">
|
||||
<a class="dropdown-item" href="{{ url_for("main.dashboard") }}">{{ _("Dashboard") }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for("main.exit") }}">{{ _("Logout") }}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarToggler">
|
||||
<ul class="navbar-nav ml-auto mr-auto">
|
||||
{% if g.project %}
|
||||
{% block navbar %}
|
||||
<li class="nav-item{% if current_view == 'list_bills' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.list_bills") }}">{{ _("Bills") }}</a></li>
|
||||
<li class="nav-item{% if current_view == 'settle_bill' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.settle_bill") }}">{{ _("Settle") }}</a></li>
|
||||
<li class="nav-item{% if current_view == 'statistics' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.statistics") }}">{{ _("Statistics") }}</a></li>
|
||||
<li class="nav-item{% if current_view == 'edit_project' %} active{% endif %}""><a class="nav-link" href="{{ url_for("main.edit_project") }}">{{ _("Settings") }}</a></li>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
<ul class="navbar-nav secondary-nav">
|
||||
<li class="nav-item{% if g.lang == "fr" %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.change_lang", lang="fr") }}">fr</a></li>
|
||||
<li class="nav-item{% if g.lang == "en" %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.change_lang", lang="en") }}">en</a></li>
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="langMenuButton">
|
||||
<i class="globe-europe">{{ static_include("images/globe.svg") | safe }}</i>
|
||||
{% if g.lang %}
|
||||
{{ locale_from_iso(g.lang).display_name | capitalize }}
|
||||
{% else %}
|
||||
{{ _('Languages') }}
|
||||
{% endif %}
|
||||
<b class="caret"></b>
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="langMenuButton">
|
||||
<h6 class="dropdown-header">{{ _('Languages') }}</h6>
|
||||
{% for lang in config['SUPPORTED_LANGUAGES'] %}
|
||||
{% if g.lang != lang %}
|
||||
<a class="dropdown-item" href="{{ url_for("main.change_lang", lang=lang)}}">{{ locale_from_iso(lang).display_name | capitalize }}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</li>
|
||||
{% if (session['projects'] | length) > 0 or session['is_admin'] %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for("main.exit") }}">{{ _("Logout") }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
from __future__ import division
|
||||
import base64
|
||||
import re
|
||||
import os
|
||||
import ast
|
||||
import operator
|
||||
|
||||
from io import BytesIO, StringIO
|
||||
import jinja2
|
||||
from json import dumps, JSONEncoder
|
||||
from flask import redirect
|
||||
from flask import redirect, current_app
|
||||
from babel import Locale
|
||||
from werkzeug.routing import HTTPException, RoutingException
|
||||
import six
|
||||
from datetime import datetime, timedelta
|
||||
|
@ -93,6 +95,16 @@ def minimal_round(*args, **kw):
|
|||
return (res if res != ires else ires)
|
||||
|
||||
|
||||
def static_include(filename):
|
||||
fullpath = os.path.join(current_app.static_folder, filename)
|
||||
with open(fullpath, 'r') as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
def locale_from_iso(iso_code):
|
||||
return Locale(iso_code)
|
||||
|
||||
|
||||
def list_of_dicts2json(dict_to_convert):
|
||||
"""Take a list of dictionnaries and turns it into
|
||||
a json in-memory file
|
||||
|
|
|
@ -343,7 +343,12 @@ def edit_project():
|
|||
edit_form.name.data = g.project.name
|
||||
edit_form.contact_email.data = g.project.contact_email
|
||||
|
||||
return render_template("edit_project.html", edit_form=edit_form, export_form=export_form)
|
||||
return render_template(
|
||||
"edit_project.html",
|
||||
edit_form=edit_form,
|
||||
export_form=export_form,
|
||||
current_view="edit_project"
|
||||
)
|
||||
|
||||
|
||||
@main.route("/<project_id>/delete")
|
||||
|
|
Loading…
Reference in a new issue