Merge branch 'master' of https://github.com/spiral-project/ihatemoney into project-history

 Conflicts:
	ihatemoney/static/css/main.css
This commit is contained in:
Andrew Dickinson 2020-04-13 00:27:38 -04:00
commit e9831d97c4
7 changed files with 94 additions and 57 deletions

View file

@ -4,11 +4,11 @@ Contributing
Set up a dev environment Set up a dev environment
======================= =======================
You must develop on top of the git master branch:: You must develop on top of the Git master branch::
git clone https://github.com/spiral-project/ihatemoney.git git clone https://github.com/spiral-project/ihatemoney.git
Then you need to build your dev environments. Choose your way… Then you need to build your dev environment. Choose your way…
The quick way The quick way
------------- -------------
@ -43,7 +43,7 @@ It's as simple as that!
Updating Updating
-------- --------
In case you want to update to newer versions (from git), you can just run the "update" command:: In case you want to update to newer versions (from Git), you can just run the "update" command::
make update make update
@ -57,7 +57,7 @@ database revision file::
make create-database-revision make create-database-revision
If your changes are simple enough, the generated script will be populated with If your changes are simple enough, the generated script will be populated with
the necessary migrations steps. You can edit the generated script. eg: to add the necessary migrations steps. You can edit the generated script. e.g: To add
data migrations. data migrations.
For complex migrations, it is recommended to start from an empty revision file For complex migrations, it is recommended to start from an empty revision file
@ -101,7 +101,7 @@ To do so::
make test make test
We are using the `black <https://black.readthedocs.io/en/stable/>`_ formatter We are using the `black <https://black.readthedocs.io/en/stable/>`_ formatter
for all the python files in this project. Be sure to run it locally on your for all the Python files in this project. Be sure to run it locally on your
files. To do so, just run:: files. To do so, just run::
black ihatemoney black ihatemoney
@ -112,16 +112,16 @@ hook, for instance).
As a designer / Front-end developer As a designer / Front-end developer
----------------------------------- -----------------------------------
Feel free to provide us mockups or to involve yourself into the discussions Feel free to provide mockups, or to involve yourself in the discussions
hapenning on the github issue tracker. All ideas are welcome. Of course, if you happening on the GitHub issue tracker. All ideas are welcome. Of course, if you
know how to implement them, feel free to fork and make a pull request. know how to implement them, feel free to fork and make a pull request.
As a translator As a translator
--------------- ---------------
If you're able to translate Ihatemoney in your own language, If you're able to translate Ihatemoney in your own language,
head over to `the website we use for translations <https://hosted.weblate.org/settings/i-hate-money/i-hate-money/>`_ head over to `the website we use for translations <https://hosted.weblate.org/projects/i-hate-money/i-hate-money/>`_
and start translating! and start translating.
All the heavy lifting will be done automatically, and your strings will All the heavy lifting will be done automatically, and your strings will
eventually be integrated. eventually be integrated.
@ -134,7 +134,7 @@ End-user
You are using the application and found a bug? You have some ideas about how to You are using the application and found a bug? You have some ideas about how to
improve the project? Please tell us `by filling a new issue <https://github.com/spiral-project/ihatemoney/issues>`_. improve the project? Please tell us `by filling a new issue <https://github.com/spiral-project/ihatemoney/issues>`_.
Or, if you prefer, you can send me an email to `alexis@notmyidea.org` and I Or, if you prefer, you can send me an e-mail to `alexis@notmyidea.org` and I
will update the issue tracker with your feedback. will update the issue tracker with your feedback.
Thanks again! Thanks again!
@ -150,7 +150,7 @@ Install doc dependencies (within the virtualenv, if any)::
pip install -r docs/requirements.txt pip install -r docs/requirements.txt
And to produce html doc in `docs/_output` folder:: And to produce a HTML doc in the `docs/_output` folder::
cd docs/ cd docs/
make html make html

View file

@ -127,8 +127,11 @@ class EditProjectForm(FlaskForm):
class UploadForm(FlaskForm): class UploadForm(FlaskForm):
file = FileField( file = FileField(
"JSON", validators=[FileRequired(), FileAllowed(["json", "JSON"], "JSON only!")] "JSON",
validators=[FileRequired(), FileAllowed(["json", "JSON"], "JSON only!")],
description=_("Import previously exported JSON file"),
) )
submit = SubmitField(_("Import"))
class ProjectForm(EditProjectForm): class ProjectForm(EditProjectForm):

View file

@ -150,6 +150,11 @@ body {
margin-bottom: 20px; margin-bottom: 20px;
margin-left: 25px; margin-left: 25px;
} }
@media (max-width: 400px) {
.home .card {
min-width: unset;
}
}
/* Other */ /* Other */
#bills { #bills {
@ -180,7 +185,7 @@ footer {
padding: 45px 50px; padding: 45px 50px;
} }
@media (min-width: 768px) { @media (min-width: 1024px) {
footer { footer {
padding-left: calc(25% + 50px); padding-left: calc(25% + 50px);
} }
@ -320,13 +325,16 @@ footer .footer-left {
background: url("../images/see.png") no-repeat right; background: url("../images/see.png") no-repeat right;
} }
#bill_table, #monthly_stats, #history_table { #bill_table,
#monthly_stats,
#history_table {
margin-top: 30px; margin-top: 30px;
margin-bottom: 30px; margin-bottom: 30px;
} }
@media (min-width: 768px) { @media (min-width: 768px) {
.split_bills, #table_overflow.statistics { .split_bills,
#table_overflow.statistics {
/* The table is shifted to left, so add the spacer width on the right to match */ /* The table is shifted to left, so add the spacer width on the right to match */
width: calc(100% + 15px); width: calc(100% + 15px);
} }
@ -550,3 +558,13 @@ footer .icon svg {
#history_warnings { #history_warnings {
margin-top: 30px; margin-top: 30px;
} }
/* edit settings */
.edit-project form {
margin-top: 1em;
margin-bottom: 3em;
}
.edit-project .custom-file {
margin-bottom: 2em;
}

View file

@ -5,18 +5,43 @@
{ {
$(this).html("<a style='color:red; ' href='{{ url_for('.delete_project') }}' >{{_("you sure?")}}</a>"); $(this).html("<a style='color:red; ' href='{{ url_for('.delete_project') }}' >{{_("you sure?")}}</a>");
}); });
$('.custom-file-input').on('change', function(event) {
var filename = [].slice.call(this.files).map(function (file) { return file.name}).join(',')
var $labelElement = $(this).parents('.custom-file').find('.custom-file-label')
$labelElement.text(filename)
})
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="container edit-project">
<h2>{{ _("Edit project") }}</h2> <h2>{{ _("Edit project") }}</h2>
<p>
<form class="form-horizontal" method="post"> <form class="form-horizontal" method="post">
{{ forms.edit_project(edit_form) }} {{ forms.edit_project(edit_form) }}
</form> </form>
</p>
<h2>{{ _("Import JSON") }}</h2>
<form class="form-horizontal" method="post" enctype="multipart/form-data">
{{ import_form.hidden_tag() }}
<div class="custom-file">
<div class="form-group">
{{ import_form.file(class="custom-file-input") }}
<small class="form-text text-muted">
{{ import_form.file.description }}
</small>
</div>
<label class="custom-file-label" for="customFile">{{ _('Choose file') }}</label>
</div>
<div class="actions">
{{ import_form.submit(class="btn btn-primary") }}
</div>
</form>
<h2>{{ _("Download project's data") }}</h2> <h2>{{ _("Download project's data") }}</h2>
<p>
<div class="list-group download-project"> <div class="list-group download-project">
<div class="list-group-item list-group-item-action"> <div class="list-group-item list-group-item-action">
<h5 class="d-flex w-100 justify-content-between"> <h5 class="d-flex w-100 justify-content-between">
@ -51,5 +76,5 @@
<p class="mb-1 text-muted">{{ _('Download the list of transactions needed to settle the current bills.') }}</p> <p class="mb-1 text-muted">{{ _('Download the list of transactions needed to settle the current bills.') }}</p>
</div> </div>
</div> </div>
</p> </div>
{% endblock %} {% endblock %}

View file

@ -48,7 +48,6 @@
<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 == 'statistics' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.statistics") }}">{{ _("Statistics") }}</a></li>
<li class="nav-item{% if current_view == 'history' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.history") }}">{{ _("History") }}</a></li> <li class="nav-item{% if current_view == 'history' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.history") }}">{{ _("History") }}</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> <li class="nav-item{% if current_view == 'edit_project' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.edit_project") }}">{{ _("Settings") }}</a></li>
<li class="nav-item{% if current_view == 'upload_json' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.upload_json") }}">{{ _("Import") }}</a></li>
{% endblock %} {% endblock %}
{% endif %} {% endif %}
</ul> </ul>

View file

@ -1,10 +0,0 @@
{% extends "layout.html" %}
{% block content %}
<h2>{{ _("Import JSON") }}</h2>
<p>
<form class="form-horizontal" method="post" enctype="multipart/form-data">
{{ forms.upload_json(form) }}
</form>
</p>
{% endblock %}

View file

@ -237,6 +237,8 @@ def authenticate(project_id=None):
# add the project on the top of the list # add the project on the top of the list
session["projects"].insert(0, (project_id, project.name)) session["projects"].insert(0, (project_id, project.name))
session[project_id] = True session[project_id] = True
# Set session to permanent to make language choice persist
session.permanent = True
session.update() session.update()
setattr(g, "project", project) setattr(g, "project", project)
return redirect(url_for(".list_bills")) return redirect(url_for(".list_bills"))
@ -384,37 +386,37 @@ def reset_password():
@main.route("/<project_id>/edit", methods=["GET", "POST"]) @main.route("/<project_id>/edit", methods=["GET", "POST"])
def edit_project(): def edit_project():
edit_form = EditProjectForm() edit_form = EditProjectForm()
if request.method == "POST": import_form = UploadForm()
if edit_form.validate(): # Import form
if import_form.validate_on_submit():
try:
import_project(import_form.file.data.stream, g.project)
flash(_("Project successfully uploaded"))
return redirect(url_for("main.list_bills"))
except ValueError:
flash(_("Invalid JSON"), category="error")
# Edit form
if edit_form.validate_on_submit():
project = edit_form.update(g.project) project = edit_form.update(g.project)
db.session.add(project) db.session.add(project)
db.session.commit() db.session.commit()
return redirect(url_for(".list_bills")) return redirect(url_for("main.list_bills"))
else: else:
edit_form.name.data = g.project.name edit_form.name.data = g.project.name
edit_form.logging_preferences.data = g.project.logging_preference edit_form.logging_preferences.data = g.project.logging_preference
edit_form.contact_email.data = g.project.contact_email edit_form.contact_email.data = g.project.contact_email
return render_template( return render_template(
"edit_project.html", edit_form=edit_form, current_view="edit_project" "edit_project.html",
edit_form=edit_form,
import_form=import_form,
current_view="edit_project",
) )
@main.route("/<project_id>/upload_json", methods=["GET", "POST"])
def upload_json():
form = UploadForm()
if form.validate_on_submit():
try:
import_project(form.file.data.stream, g.project)
flash(_("Project successfully uploaded"))
except ValueError:
flash(_("Invalid JSON"), category="error")
return redirect(url_for("main.list_bills"))
return render_template("upload_json.html", form=form)
def import_project(file, project): def import_project(file, project):
json_file = json.load(file) json_file = json.load(file)