Changeset 722ae18 in OpenWorkouts-current


Ignore:
Timestamp:
Dec 17, 2018, 5:13:45 PM (5 years ago)
Author:
borja <borja@…>
Branches:
current, feature/docs, master
Children:
c90d245
Parents:
affc3f7
Message:

(#32) Improvements on the edit profile form:

  • Added field for nickname, set as not required
  • Applied classes to add some styling based on the new code in forms.css
  • Ensure the error messages are displayed clearly by the field that caused the errors.
  • Loaded pickadate js date picker for the birth date field
Location:
ow
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • ow/schemas/user.py

    raffc3f7 r722ae18  
    6666    lastname = validators.UnicodeString(not_empty=True)
    6767    email = validators.Email(not_empty=True)
     68    nickname = UniqueNickname(if_missing='')
    6869    bio = validators.UnicodeString(if_missing='')
    6970    birth_date = validators.DateConverter(month_style='dd/mm/yyyy')
     
    9293    allow_extra_fields = True
    9394    filter_extra_fields = True
    94     nickname = UniqueNickname()
     95    nickname = UniqueNickname(if_missing='')
    9596    firstname = validators.UnicodeString(not_empty=True)
    9697    lastname = validators.UnicodeString(not_empty=True)
     
    108109    allow_extra_fields = True
    109110    filter_extra_fields = True
    110     nickname = UniqueNickname()
     111    nickname = UniqueNickname(if_missing='')
    111112    email = UniqueEmail(not_empty=True)
  • ow/templates/edit_profile.pt

    raffc3f7 r722ae18  
    1313
    1414  <metal:title metal:fill-slot="title">
    15     <tal:t i18n:translate="">Edit profile</tal:t>
     15      <tal:t i18n:translate="">Edit profile</tal:t>
    1616  </metal:title>
    1717
     18  <metal:css metal:fill-slot="css">
     19      <link rel="stylesheet" href="${request.static_url('ow:static/components/pickadate/themes/default.css')}" />
     20      <link rel="stylesheet" href="${request.static_url('ow:static/components/pickadate/themes/default.date.css')}" />
     21  </metal:css>
     22
    1823  <metal:content metal:fill-slot="content">
    19     <div id="add_workout">
     24      <h2 i18n:translate="">Edit profile</h2>
     25    <div class="edit-profile">
    2026      ${form.begin(multipart=True)}
    2127      ${form.csrf_token()}
    2228
    23       <fieldset>
    24         ${form.errorlist('email')}
    25         <label for="email" i18n:translate="">Email address:</label>
    26         ${form.text('email')}
    27       </fieldset>
     29        <fieldset>
     30            <p>
     31                <label for="email" i18n:translate="">Email address:</label>
     32                ${form.errorlist('email')}
     33                ${form.text('email')}
     34            </p>
     35            <p>
     36                <label for="nickname" i18n:translate="">Nickname:</label>
     37                ${form.errorlist('nickname')}
     38                ${form.text('nickname')}
     39            </p>
     40        </fieldset>
    2841
    29       <fieldset>
    30         <tal:c tal:condition="getattr(context, 'picture', None)">
    31           <tal:t i18n:translate="">Current picture:</tal:t>
    32           <img tal:attributes="src request.resource_path(context, 'picture')"
    33                width="150" />
    34         </tal:c>
    35         ${form.errorlist('picture')}
    36         <label for="picture" i18n:translate="">
    37           Picture (jpg, jpeg, png or gif):</label>
    38         ${form.file('picture')}
    39       </fieldset>
     42        <fieldset>
     43            <p>
     44                <tal:c tal:condition="getattr(context, 'picture', None)">
    4045
    41       <fieldset>
    42         ${form.errorlist('firstname')}
    43         <label for="firstname" i18n:translate="">First name:</label>
    44         ${form.text('firstname')}
    45         ${form.errorlist('lastname')}
    46         <label for="lastname" i18n:translate="">Last name:</label>
    47         ${form.text('lastname')}
    48       </fieldset>
     46                    <label for="current_picture" i18n:translate="">
     47                        Current picture:</label>
     48                    <img id="current_picture" tal:attributes="src request.resource_path(context, 'picture')" width="150">
     49                </tal:c>
     50                <label for="picture" i18n:translate="">
     51                    Picture (jpg, jpeg, png or gif):</label>
     52                ${form.errorlist('picture')}
     53                ${form.file('picture')}
     54            </p>
     55        </fieldset>
    4956
    50       <fieldset>
    51         ${form.errorlist('gender')}
    52         <label for="gender" i18n:translate="">Gender:</label>
    53         ${form.select('gender', ['male', 'female'])}
     57        <fieldset>
     58            <p>
     59                <label for="firstname" i18n:translate="">First name:</label>
     60                ${form.errorlist('firstname')}
     61                ${form.text('firstname')}
     62            </p>
     63            <p>
     64                <label for="lastname" i18n:translate="">Last name:</label>
     65                ${form.errorlist('lastname')}
     66                ${form.text('lastname')}
     67            </p>
     68        </fieldset>
    5469
    55         ${form.errorlist('birth_date')}
    56         <label for="birth_date" i18n:translate="">Birth date:</label>
    57         ${form.date('birth_date', date_format='%d/%m/%Y')}
     70        <fieldset>
     71            <p>
     72                <label for="gender" i18n:translate="">Gender:</label>
     73                ${form.errorlist('gender')}
     74                ${form.select('gender', ['male', 'female'])}
     75            </p>
     76            <p>
     77                <label for="birth_date" i18n:translate="">Birth date:</label>
     78                ${form.errorlist('birth_date')}
     79                ${form.date('birth_date', date_format='%d/%m/%Y')}
     80            </p>
     81            <p>
     82                <label for="height" i18n:translate="">Height (meters):</label>
     83                ${form.errorlist('height')}
     84                ${form.text('height')}
     85            </p>
     86            <p>
     87                <label for="weight" i18n:translate="">Weight (kg):</label>
     88                ${form.errorlist('weight')}
     89                ${form.text('weight')}
     90            </p>
     91        </fieldset>
    5892
    59         ${form.errorlist('height')}
    60         <label for="height" i18n:translate="">Height (meters):</label>
    61         ${form.text('height')}
     93        <fieldset>
     94            <p>
     95                <label for="bio" i18n:translate="">Bio/About you:</label>
     96                ${form.errorlist('bio')}
     97                ${form.textarea('bio', rows=10, cols=50)}
     98            </p>
     99        </fieldset>
    62100
    63         ${form.errorlist('weight')}
    64         <label for="weight" i18n:translate="">Weight (kg):</label>
    65         ${form.text('weight')}
    66       </fieldset>
    67 
    68       <fieldset>
    69         ${form.errorlist('bio')}
    70         <label for="bio" i18n:translate="">Bio/About you:</label>
    71         ${form.textarea('bio', rows=10, cols=50)}
    72       </fieldset>
    73 
    74       ${form.submit("submit", "Save")}
    75       <a href="" tal:attributes="href request.resource_url(context, 'profile')"
    76          i18n:translate="">Cancel</a>
    77 
    78       ${form.end()}
     101        <p>
     102            ${form.submit("submit", "Save",  **{'class':"button button-normal"})}
     103            <a href="" class="button button-important"
     104               tal:attributes="href request.resource_url(context, 'profile')"
     105               i18n:translate="">Cancel</a>
     106        </p>
     107        ${form.end()}
    79108    </div>
    80109
    81110  </metal:content>
    82111
     112  <metal:body-js metal:fill-slot="body-js">
     113      <script src="${request.static_url('ow:static/components/pickadate/picker.js')}"></script>
     114      <script src="${request.static_url('ow:static/components/pickadate/picker.date.js')}"></script>
     115      <script type="text/javascript">
     116       $(document).ready(function() {
     117           var today = new Date();
     118           var first_year = new Date();
     119           // start 100 years ago, should be enough for birth date
     120           first_year.setMonth(first_year.getMonth() - 1200);
     121           $('#birth_date').pickadate({
     122               format: 'dd/mm/yyyy',
     123               formatSubmit: 'dd/mm/yyyy',
     124               selectMonths: true,
     125               selectYears: 100,
     126               min: first_year,
     127               max: today
     128           });
     129       });
     130      </script>
     131  </metal:body-js>
     132
    83133</html>
  • ow/tests/views/test_user.py

    raffc3f7 r722ae18  
    258258        # the form carries along the proper data keys, taken from the
    259259        # loaded user profile
    260         data = ['firstname', 'lastname', 'email', 'bio', 'birth_date',
    261                 'height', 'weight', 'gender']
     260        data = ['firstname', 'lastname', 'email', 'nickname', 'bio',
     261                'birth_date', 'height', 'weight', 'gender']
    262262        assert list(response['form'].data.keys()) == data
    263263        # and check the email to see data is properly loaded
  • ow/views/user.py

    raffc3f7 r722ae18  
    150150        request.POST['picture'] = ''
    151151
    152     form = Form(request, schema=UserProfileSchema(), obj=context)
     152    nicknames = request.root.lowercase_nicknames
     153    if context.nickname:
     154        # remove the current user nickname from the list, preventing form
     155        # validation error
     156        nicknames.remove(context.nickname.lower())
     157    state = State(emails=request.root.lowercase_emails, names=nicknames)
     158    form = Form(request, schema=UserProfileSchema(), state=state, obj=context)
    153159
    154160    if 'submit' in request.POST and form.validate():
Note: See TracChangeset for help on using the changeset viewer.