1
0
Fork 0
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:
Arnaud Bos 2011-09-11 05:25:42 +02:00
parent f48fc22335
commit 88cd2f8675
5 changed files with 62 additions and 29 deletions

View file

@ -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")

View file

@ -1,5 +1,5 @@
from web import main, db, mail
import api
#import api
from flask import *

View file

@ -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 %}

View file

@ -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 slugify(value):
"""Normalizes string, converts to lowercase, removes non-alpha characters,
and converts spaces to hyphens.
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.
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

View file

@ -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()