mirror of
https://github.com/YunoHost-Apps/ihatemoney_ynh.git
synced 2024-09-03 19:26:15 +02:00
Fix #24 on Authentication and New project forms usability.
- Do not display anymore the identifier field in home. - Let the user enter the id if the slug generated from project name already exists as a project id. - Moved get_billform_for from 'utils' to 'forms', to avoid issue (was 'from forms import ...' into utils, and 'from utils import ...' into forms, which causeed an error).
This commit is contained in:
parent
f48fc22335
commit
88cd2f8675
5 changed files with 62 additions and 29 deletions
|
@ -2,6 +2,8 @@ from flaskext.wtf import *
|
|||
from wtforms.widgets import html_params
|
||||
from models import Project, Person, Bill
|
||||
from datetime import datetime
|
||||
from jinja2 import Markup
|
||||
from utils import slugify
|
||||
|
||||
|
||||
def select_multi_checkbox(field, ul_class='', **kwargs):
|
||||
|
@ -18,16 +20,41 @@ def select_multi_checkbox(field, ul_class='', **kwargs):
|
|||
return u''.join(html)
|
||||
|
||||
|
||||
def get_billform_for(request, project, set_default=True):
|
||||
"""Return an instance of BillForm configured for a particular project.
|
||||
|
||||
:set_default: if set to True, on GET methods (usually when we want to
|
||||
display the default form, it will call set_default on it.
|
||||
|
||||
"""
|
||||
form = BillForm()
|
||||
form.payed_for.choices = form.payer.choices = [(str(m.id), m.name) for m in project.active_members]
|
||||
form.payed_for.default = [str(m.id) for m in project.active_members]
|
||||
|
||||
if set_default and request.method == "GET":
|
||||
form.set_default()
|
||||
return form
|
||||
|
||||
|
||||
class ProjectForm(Form):
|
||||
name = TextField("Project name", validators=[Required()])
|
||||
id = TextField("Project identifier", validators=[Required()])
|
||||
password = PasswordField("Password", validators=[Required()])
|
||||
password = PasswordField("Private code", validators=[Required()])
|
||||
contact_email = TextField("Email", validators=[Required(), Email()])
|
||||
submit = SubmitField("Create the project")
|
||||
|
||||
def validate_id(form, field):
|
||||
if Project.query.get(field.data):
|
||||
raise ValidationError("This project id is already used")
|
||||
form.id.data = slugify(field.data)
|
||||
if Project.query.get(form.id.data):
|
||||
raise ValidationError(Markup("""The project identifier is used
|
||||
to log in and for the URL of the project.
|
||||
<br />
|
||||
We tried to generate an identifier for you but
|
||||
a projet with this identifier already exists.
|
||||
<br />
|
||||
Please create a new identifier you will be able
|
||||
to remember.
|
||||
"""))
|
||||
|
||||
def save(self):
|
||||
"""Create a new project with the information given by this form.
|
||||
|
@ -42,7 +69,7 @@ class ProjectForm(Form):
|
|||
|
||||
class AuthenticationForm(Form):
|
||||
id = TextField("Project identifier", validators=[Required()])
|
||||
password = PasswordField("Password", validators=[Required()])
|
||||
password = PasswordField("Private code", validators=[Required()])
|
||||
submit = SubmitField("Get in")
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from web import main, db, mail
|
||||
import api
|
||||
#import api
|
||||
|
||||
from flask import *
|
||||
|
||||
|
|
|
@ -17,8 +17,11 @@
|
|||
</div> <!-- /clearfix -->
|
||||
{% endmacro %}
|
||||
|
||||
{% macro submit(field, cancel=False) -%}
|
||||
{% macro submit(field, cancel=False, home=False) -%}
|
||||
<div class="actions">
|
||||
{% if home %}
|
||||
<a href="{{ url_for(".home") }}" class="btn">Back Home</a>
|
||||
{% endif %}
|
||||
<button type="submit" class="btn primary">{{ field.name }}</button>
|
||||
{% if cancel %}
|
||||
<button id="cancel-form" type="reset" class="btn">Cancel</button>
|
||||
|
@ -42,12 +45,14 @@
|
|||
|
||||
{% include "display_errors.html" %}
|
||||
{{ form.hidden_tag() }}
|
||||
{{ input(form.name) }}
|
||||
{% if not home %}
|
||||
{{ input(form.id) }}
|
||||
{% endif %}
|
||||
{{ input(form.name) }}
|
||||
{{ input(form.password) }}
|
||||
{{ input(form.contact_email) }}
|
||||
{% if not home %}
|
||||
{{ submit(form.submit) }}
|
||||
{{ submit(form.submit, home=True) }}
|
||||
{% endif %}
|
||||
|
||||
{% endmacro %}
|
||||
|
|
|
@ -1,24 +1,19 @@
|
|||
import re
|
||||
from functools import wraps
|
||||
from flask import redirect, url_for, session, request
|
||||
from werkzeug.routing import HTTPException, RoutingException
|
||||
|
||||
from models import Bill, Project
|
||||
from forms import BillForm
|
||||
|
||||
def get_billform_for(project, set_default=True):
|
||||
"""Return an instance of BillForm configured for a particular project.
|
||||
|
||||
:set_default: if set to True, on GET methods (usually when we want to
|
||||
display the default form, it will call set_default on it.
|
||||
def slugify(value):
|
||||
"""Normalizes string, converts to lowercase, removes non-alpha characters,
|
||||
and converts spaces to hyphens.
|
||||
|
||||
Copy/Pasted from ametaireau/pelican/utils itself took from django sources.
|
||||
"""
|
||||
form = BillForm()
|
||||
form.payed_for.choices = form.payer.choices = [(str(m.id), m.name) for m in project.active_members]
|
||||
form.payed_for.default = [str(m.id) for m in project.active_members]
|
||||
|
||||
if set_default and request.method == "GET":
|
||||
form.set_default()
|
||||
return form
|
||||
if type(value) == unicode:
|
||||
import unicodedata
|
||||
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
|
||||
value = unicode(re.sub('[^\w\s-]', '', value).strip().lower())
|
||||
return re.sub('[-\s]+', '-', value)
|
||||
|
||||
class Redirect303(HTTPException, RoutingException):
|
||||
"""Raise if the map requests a redirect. This is for example the case if
|
||||
|
|
|
@ -5,9 +5,9 @@ from flaskext.mail import Mail, Message
|
|||
|
||||
# local modules
|
||||
from models import db, Project, Person, Bill
|
||||
from forms import (ProjectForm, AuthenticationForm, BillForm, MemberForm,
|
||||
InviteForm, CreateArchiveForm)
|
||||
from utils import get_billform_for, Redirect303
|
||||
from forms import (get_billform_for, ProjectForm, AuthenticationForm, BillForm,
|
||||
MemberForm, InviteForm, CreateArchiveForm)
|
||||
from utils import Redirect303
|
||||
|
||||
"""
|
||||
The blueprint for the web interface.
|
||||
|
@ -111,6 +111,12 @@ def create_project():
|
|||
form.name.data = request.values['project_id']
|
||||
|
||||
if request.method == "POST":
|
||||
# At first, we don't want the user to bother with the identifier
|
||||
# so it will automatically be missing because not displayed into the form
|
||||
# Thus we fill it with the same value as the filled name, the validation will
|
||||
# take care of the slug
|
||||
if not form.id.data:
|
||||
form.id.data = form.name.data
|
||||
if form.validate():
|
||||
# save the object in the db
|
||||
project = form.save()
|
||||
|
@ -178,7 +184,7 @@ def list_bills():
|
|||
bills = g.project.get_bills()
|
||||
return render_template("list_bills.html",
|
||||
bills=bills, member_form=MemberForm(g.project),
|
||||
bill_form=get_billform_for(g.project)
|
||||
bill_form=get_billform_for(request, g.project)
|
||||
)
|
||||
|
||||
@main.route("/<project_id>/members/add", methods=["GET", "POST"])
|
||||
|
@ -224,7 +230,7 @@ def remove_member(member_id):
|
|||
|
||||
@main.route("/<project_id>/add", methods=["GET", "POST"])
|
||||
def add_bill():
|
||||
form = get_billform_for(g.project)
|
||||
form = get_billform_for(request, g.project)
|
||||
if request.method == 'POST':
|
||||
if form.validate():
|
||||
bill = Bill()
|
||||
|
@ -250,7 +256,7 @@ def delete_bill(bill_id):
|
|||
@main.route("/<project_id>/edit/<int:bill_id>", methods=["GET", "POST"])
|
||||
def edit_bill(bill_id):
|
||||
bill = Bill.query.get_or_404(bill_id)
|
||||
form = get_billform_for(g.project, set_default=False)
|
||||
form = get_billform_for(request, g.project, set_default=False)
|
||||
if request.method == 'POST' and form.validate():
|
||||
form.save(bill)
|
||||
db.session.commit()
|
||||
|
|
Loading…
Reference in a new issue