Commit b311b80a128b045bfa23e5ea5693838d91554c8a

Authored by Adabriand Furtado
1 parent eea5b9a5
Exists in master

Adiciona upload do avatar no cadastro.

pybossa/forms/account_view_forms.py
... ... @@ -24,4 +24,5 @@ from forms import (
24 24 ChangePasswordForm,
25 25 ResetPasswordForm,
26 26 ForgotPasswordForm,
27   - AvatarUploadForm)
  27 + AvatarUploadForm,
  28 + AvatarUploadRegisterForm)
... ...
pybossa/forms/forms.py
... ... @@ -392,3 +392,11 @@ class AvatarUploadForm(Form):
392 392 y1 = IntegerField(label=None, widget=HiddenInput(), default=0)
393 393 x2 = IntegerField(label=None, widget=HiddenInput(), default=0)
394 394 y2 = IntegerField(label=None, widget=HiddenInput(), default=0)
  395 +
  396 +class AvatarUploadRegisterForm(Form):
  397 + id = IntegerField(label=None, widget=HiddenInput())
  398 + avatar = FileField(lazy_gettext('Avatar (optional)'))
  399 + x1 = IntegerField(label=None, widget=HiddenInput(), default=0)
  400 + y1 = IntegerField(label=None, widget=HiddenInput(), default=0)
  401 + x2 = IntegerField(label=None, widget=HiddenInput(), default=0)
  402 + y2 = IntegerField(label=None, widget=HiddenInput(), default=0)
... ...
pybossa/themes/default/static/css/theme.css
... ... @@ -310,10 +310,12 @@ h6 small {
310 310 color: #6F9CA2;
311 311 background-color: #d9edf7;
312 312 border-color: #d9edf7;
  313 +}
313 314 .alert-warning {
314 315 color: #B59D5A;
315 316 background-color: #FFE7AB;
316 317 border-color: #FFE7AB;
  318 +}
317 319 .alert-danger {
318 320 color: #A45E4D;
319 321 background-color: #F8AFAB;
... ... @@ -326,11 +328,9 @@ h6 small {
326 328 background-color: blue;
327 329 border: 1px solid #ddd;
328 330 }
329   -/*
330   -.carousel-indicators li {
331   - border: solid 1px #34495E;
  331 +.upload-container {
  332 + padding-bottom: 30px;
332 333 }
333   -.carousel-indicators .active {
334   - background-color: #34495E;
  334 +.upload-container .form-actions {
  335 + padding-top: 10px;
335 336 }
336   -*/
... ...
pybossa/themes/default/templates/_navbar.html
... ... @@ -12,13 +12,7 @@
12 12  
13 13 <div class="collapse navbar-collapse" id="main-navbar-collapse">
14 14 <ul class="nav navbar-nav">
15   - <!-- Link para a página da Comunidade
16   - <li {% if active_page == 'community' %} class="active" {% endif %}><a href="{{ url_for('account.index')}}">{{ _('Community') }}</a></li>
17   - -->
18 15 <li {% if active_page == 'projects' %} class="active" {% endif %}><a href="{{ url_for('project.index') }}">{{ _('Projects') }}</a></li>
19   - <!--
20   - <li {% if active_page == 'create' %} class="active" {% endif %}><a href="{{ url_for('project.new') }}">{{ _('Create') }}</a></li>
21   - -->
22 16 <li {% if active_page == 'about' %} class="active" {% endif %}><a href="{{ url_for('home.about')}}">{{ _('About') }}</a></li>
23 17 </ul>
24 18 {% include '_gcs_form.html' ignore missing %}
... ... @@ -27,7 +21,9 @@
27 21 <li {% if active_page == 'profile' %} class="active" {% endif %}><a href="#" data-toggle="dropdown" class="dropdown-toggle"><i class="icon icon-user"></i> {{ current_user.name }} <span class="caret"></span></a>
28 22 <ul class="dropdown-menu">
29 23 <li><a href="{{ url_for('account.profile', name=current_user.name) }}"><i class="icon icon-user"></i> {{ _('My Profile') }}</a></li>
  24 + {% if current_user.admin == 1 %}
30 25 <li><a href="{{ url_for('account.projects', name=current_user.name) }}"><i class="icon icon-th-large"></i> {{ _('My Projects') }}</a></li>
  26 + {% endif %}
31 27 <li><a href="{{ url_for('account.update_profile', name=current_user.name) }}"><i class="icon icon-cog"></i> {{ _('My Settings') }}</a></li>
32 28 {% if current_user.admin == 1 %}
33 29 <li class="divider"></li>
... ...
pybossa/themes/default/templates/account/_helpers.html
... ... @@ -3,7 +3,9 @@
3 3 <div class="container">
4 4 <ul class="nav nav-pills nav-justified nav-pills-inverse">
5 5 <li role="presentation" {% if active_link=="profile"%}class="active"{% endif %}><a href="{{url_for('account.profile', name=current_user.name)}}">{{ _('My Profile') }}</a></li>
  6 + {% if current_user.admin %}
6 7 <li role="presentation" {% if active_link=="projects"%}class="active"{% endif %}><a href="{{url_for('account.projects', name=current_user.name)}}">{{ _('My Projects') }}</a></li>
  8 + {% endif %}
7 9 <li role="presentation" {% if active_link=="settings"%}class="active"{% endif %}><a href="{{url_for('account.update_profile', name=current_user.name)}}">{{ _('My Settings') }}</a></li>
8 10 {% if current_user.admin %}
9 11 <li role="presentation" {% if active_link=="admin"%}class="active"{% endif %}><a href="{{url_for('admin.index')}}">{{ _('Admin Site') }}</a></li>
... ... @@ -87,7 +89,7 @@
87 89 {% endmacro %}
88 90  
89 91 {% macro render_user_thumbnail(user, upload_method, id, class, style) %}
90   - {% if user.info.avatar %}
  92 + {% if user.info and user.info.avatar %}
91 93 {% if upload_method == 'rackspace'%}
92 94 <img id="{{id}}" class="{{class}}" style="{{style}}" width="100%" src="{{ url_for('rackspace', filename=user.info.avatar, container=user.info.container)}}" onerror="imgError(this, 'user');">
93 95 {% else %}
... ... @@ -98,6 +100,14 @@
98 100 {% endif %}
99 101 {% endmacro %}
100 102  
  103 +{% macro render_registering_user_thumbnail(user, upload_method, avatar_upload_id) %}
  104 + {% if avatar_upload_id and avatar_upload_id != '' %}
  105 + <img width="100%" src="{{ url_for('uploads.uploaded_file', filename=('tmp/' ~ avatar_upload_id + '_avatar.png'))}}">
  106 + {% else %}
  107 + {{ render_user_thumbnail(user, upload_method) }}
  108 + {% endif %}
  109 +{% endmacro %}
  110 +
101 111 {% macro render_pagination(pagination) %}
102 112 <nav>
103 113 <ul class="pagination pagination-centered">
... ...
pybossa/themes/default/templates/account/register.html
1 1 {% extends "base.html" %}
  2 +{% import "account/_helpers.html" as helper %}
2 3  
3   -{% block content %}<div class="container">
  4 +{% block content %}
  5 +
  6 +<div class="container">
4 7 {% from "_formhelpers.html" import render_field %}
  8 +<script src="{{url_for('static', filename='js/vendor/jquery.Jcrop.min.js')}}"></script>
  9 +<script src="{{url_for('static', filename='js/image_crop.js')}}" type="text/javascript"></script>
  10 +<link rel="stylesheet" href="{{url_for('static', filename='css/jquery.Jcrop.min.css')}}" type="text/css" />
  11 +
5 12 <p style="padding-top:5px;">
6 13 <span class="label label-warning"><i class="glyphicon glyphicon-bullhorn"></i> {{ _('Note') }}</span>
7 14 {{ _('By click the') }}
... ... @@ -12,8 +19,23 @@
12 19 </p>
13 20  
14 21 <legend>{{ _('Create an account') }}</legend>
15   - <form method="post" class="form-horizontal" action="{{ url_for('account.register') }}">
  22 + <form method="post" class="form-horizontal" action="{{ url_for('account.register') }}" enctype="multipart/form-data">
16 23 {{ form.hidden_tag() }}
  24 + <fieldset class="upload-container">
  25 + <div class="col-md-2 img-thumbnail">
  26 + {{ form.hidden_tag() }}
  27 + {{ helper.render_registering_user_thumbnail(current_user, upload_method, avatar_upload_id)}}
  28 + </div>
  29 + {{ render_field(upload_form.avatar, onchange="previewImage()") }}
  30 + {{ upload_form.x1 }}
  31 + {{ upload_form.y1 }}
  32 + {{ upload_form.x2 }}
  33 + {{ upload_form.y2 }}
  34 + <img id="uploadPreview">
  35 + <div class="form-actions">
  36 + <button type="submit" name='btn' value="Upload" class="btn btn-primary btn-lg" />{{ _('Upload') }}</button>
  37 + </div>
  38 + </fieldset>
17 39 <fieldset>
18 40 {{ render_field(form.fullname, placeholder= _('my full name')) }}
19 41 {{ render_field(form.name, placeholder= _('myusername')) }}
... ... @@ -21,6 +43,7 @@
21 43 {{ render_field(form.password, placeholder= _('my secret password')) }}
22 44 {{ render_field(form.confirm, placeholder= _('my secret password')) }}
23 45 {{ render_field(form.profile) }}
  46 + <input id="avatar_upload_id" name="avatar_upload_id" type="hidden" value="{{ avatar_upload_id }}">
24 47 <div class="form-actions">
25 48 <input type="submit" value="{{ _('Create an account') }}" class="btn btn-primary btn-lg" />
26 49 <input type="reset" value="{{ _('Cancel') }}" class="btn btn-default" />
... ... @@ -28,4 +51,5 @@
28 51 </fieldset>
29 52 </form>
30 53 <script src="{{url_for('static', filename='js/forms.js')}}" type="text/javascript"></script>
31   -</div>{% endblock %}
  54 +</div>
  55 +{% endblock %}
... ...
pybossa/themes/default/templates/account/update.html
... ... @@ -19,15 +19,15 @@
19 19 <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
20 20 {{ helper.render_user_thumbnail(current_user, upload_method)}}
21 21 </div>
22   - {{ render_field(upload_form.avatar, onchange="previewImage()") }}
23   - {{ upload_form.x1 }}
24   - {{ upload_form.y1 }}
25   - {{ upload_form.x2 }}
26   - {{ upload_form.y2 }}
27   - <img id="uploadPreview">
28   - <div class="form-actions">
29   - <button type="submit" name='btn' value="Upload" class="btn btn-primary btn-lg" />{{ _('Upload') }}</button>
30   - </div>
  22 + {{ render_field(upload_form.avatar, onchange="previewImage()") }}
  23 + {{ upload_form.x1 }}
  24 + {{ upload_form.y1 }}
  25 + {{ upload_form.x2 }}
  26 + {{ upload_form.y2 }}
  27 + <img id="uploadPreview">
  28 + <div class="form-actions">
  29 + <button type="submit" name='btn' value="Upload" class="btn btn-primary btn-lg" />{{ _('Upload') }}</button>
  30 + </div>
31 31 </fieldset>
32 32 </form>
33 33 <form method="post" class="form-horizontal" action="{{ url_for('account.update_profile', name=current_user.name) }}">
... ...
pybossa/themes/default/templates/projects/presenter.html
... ... @@ -14,19 +14,8 @@
14 14 <div class="col-md-12">
15 15 </div>
16 16 </div>
17   -<!--
18   -{% if invite_new_volunteers %}
19   -<div class="row">
20   - <div class="col-md-12">
21   - <p>
22   - {{ _("Sorry, you've contributed to all the tasks for this project, but this project still needs more volunteers, so please spread the word!") }}
23   - </p>
24   - </div>
25   -</div>
26   -{% endif %}
27   - -->
28   -{{ project.info.task_presenter|safe }}
29 17  
  18 +{{ project.info.task_presenter|safe }}
30 19  
31 20 <div id='PYBOSSA_USER_LOCALE' hidden>
32 21 {% if current_user.is_anonymous() %}
... ...
pybossa/themes/default/templates/projects/update-bak.html
... ... @@ -1,56 +0,0 @@
1   -{% extends "/base.html" %}
2   -{% set active_page = "projects" %}
3   -{% import "projects/_helpers.html" as helper %}
4   -
5   -{% block content %}
6   -
7   -{% from "_formhelpers.html" import render_field %}
8   -{{ helper.render_project_local_nav(project, 'settings', current_user) }}
9   -
10   -<script src="{{url_for('static', filename='js/vendor/jquery.Jcrop.min.js')}}"></script>
11   -<link rel="stylesheet" href="{{url_for('static', filename='css/jquery.Jcrop.min.css')}}" type="text/css" />
12   -<div class="container">
13   - {{helper.render_project_title(project, upload_method, subtitle=_('Update the project')) }}
14   - <!-- Update form for project thumbnail -->
15   - <form method="post" class="form-horizontal" action="{{ url_for('project.update', short_name=project.short_name) }}" enctype="multipart/form-data">
16   - <fieldset>
17   - <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
18   - <p class="text-center">
19   - {{ helper.render_project_thumbnail(project, upload_method, id="uploadPreview") }}
20   - </p>
21   - {{ render_field(upload_form.avatar, onchange="previewImage()") }}
22   - {{ upload_form.x1 }}
23   - {{ upload_form.y1 }}
24   - {{ upload_form.x2 }}
25   - {{ upload_form.y2 }}
26   - <div class="form-actions">
27   - <button type="submit" name='btn' value="Upload" class="btn btn-primary btn-lg">{{ _('Upload') }}</button>
28   - </div>
29   - </fieldset>
30   - </form>
31   -
32   - <!-- Update form for project data-->
33   - <form class="form-horizontal" method="post" action="{{ url_for('project.update', short_name = project.short_name) }}">
34   - <fieldset>
35   - {{ form.hidden_tag() }}
36   - {{ render_field(form.name, class_="input-xlarge", placeholder=_('The name of the project')) }}
37   - {{ render_field(form.short_name, class_="input-xlarge", placeholder=_('Short name or slug for the project'), label_text=_('Project slug:')) }}
38   - {{ render_field(form.description, class_="input-xlarge", placeholder=_('Give some details about the project')) }}
39   - {{ render_field(form.long_description, class_="input-xlarge", placeholder=_('Explain the project (use Markdown!)')) }}
40   - {{ render_field(form.category_id) }}
41   - {{ render_field(form.allow_anonymous_contributors) }}
42   - {{ render_field(form.password) }}
43   - {{ render_field(form.webhook) }}
44   - {{ render_field(form.hidden, tooltip=_('Do you want to hide your project?')) }}
45   - <div class="form-actions">
46   - <button type="submit" name='btn' value="Save the changes" class="btn btn-primary">{{_('Save te changes')}}</button>
47   - <a href="{{url_for('project.settings', short_name=project.short_name)}}" class="btn btn-default">{{_('Cancel')}}</a>
48   - </div>
49   - </fieldset>
50   - </form>
51   -<script>
52   - $("i[rel='tooltip']").tooltip();
53   -</script>
54   -<script src="{{url_for('static', filename='js/image_crop.js')}}" type="text/javascript"></script>
55   -{{ helper.broken_image() }}
56   -</div>{% endblock %}
pybossa/themes/default/translations/pt_BR/LC_MESSAGES/messages.mo
No preview for this file type
pybossa/themes/default/translations/pt_BR/LC_MESSAGES/messages.po
... ... @@ -341,6 +341,9 @@ msgstr &quot;Usuário&quot;
341 341 msgid "Avatar"
342 342 msgstr "Avatar"
343 343  
  344 +msgid "Avatar (optional)"
  345 +msgstr "Avatar (opcional)"
  346 +
344 347 #: forms/validator.py:34
345 348 msgid "This item already exists"
346 349 msgstr "Este item já existe"
... ... @@ -2462,6 +2465,9 @@ msgid &quot;Your avatar has been updated! It may take some minu
2462 2465 msgstr ""
2463 2466 "Seu avatar está sendo atualizado! pode demorar alguns minutos para atualização..."
2464 2467  
  2468 +msgid "Your avatar has been uploaded!"
  2469 +msgstr "Feito o upload do avatar."
  2470 +
2465 2471 #: view/account.py:478
2466 2472 #, python-format
2467 2473 msgid ""
... ...
pybossa/uploader/__init__.py
... ... @@ -122,3 +122,7 @@ class Uploader(object):
122 122 def file_exists(self, name, container): #pragma: no cover
123 123 """Override by the uploader handler."""
124 124 pass
  125 +
  126 + def move_file(self, name, container, dest_name, dest_container): #pragma: no cover
  127 + """Override by the uploader handler."""
  128 + pass
... ...
pybossa/uploader/local.py
... ... @@ -80,3 +80,18 @@ class LocalUploader(Uploader):
80 80 return os.path.isfile(path)
81 81 except Exception:
82 82 return False
  83 +
  84 + def move_file(self, name, container, dest_name, dest_container):
  85 + """Move a file if it exists."""
  86 + try:
  87 + path = os.path.join(self.upload_folder, container, name)
  88 + dest_dir = os.path.join(self.upload_folder, dest_container)
  89 + dest_path = os.path.join(self.upload_folder, dest_container, dest_name)
  90 + if self.file_exists(name, container):
  91 + if not os.path.isdir(dest_dir):
  92 + os.makedirs(dest_dir)
  93 + os.rename(path, dest_path)
  94 + return True
  95 + return False
  96 + except Exception:
  97 + return False
... ...
pybossa/view/account.py
... ... @@ -203,25 +203,34 @@ def register():
203 203 if profiles is None:
204 204 profiles = user_repo.get_profiles_list()
205 205 form.set_profile_choices(profiles)
206   - if request.method == 'POST' and form.validate():
207   - account = dict(fullname=form.fullname.data, name=form.name.data,
208   - email_addr=form.email_addr.data,
209   - password=form.password.data, profile=form.profile.data,
210   - locale=current_app.config.get('DEFAULT_LOCALE'))
211   - confirm_url = get_email_confirmation_url(account)
212   - if current_app.config.get('ACCOUNT_CONFIRMATION_DISABLED'):
213   - return _create_account(account)
214   - msg = dict(subject='Welcome to %s!' % current_app.config.get('BRAND'),
215   - recipients=[account['email_addr']],
216   - body=render_template('/account/email/validate_account.md',
217   - user=account, confirm_url=confirm_url))
218   - msg['html'] = markdown(msg['body'])
219   - mail_queue.enqueue(send_mail, msg)
220   - return render_template('account/account_validation.html')
221   - if request.method == 'POST' and not form.validate():
222   - flash(gettext('Please correct the errors'), 'error')
  206 + avatar_form = AvatarUploadRegisterForm()
  207 + avatar_upload_id = ''
  208 +
  209 + if request.method == 'POST':
  210 + # Update user avatar
  211 + if request.form.get('btn') == 'Upload':
  212 + avatar_upload_id = _handle_avatar_update_on_register(avatar_form, request.form['avatar_upload_id'])
  213 + elif form.validate():
  214 + account = dict(fullname=form.fullname.data, name=form.name.data,
  215 + email_addr=form.email_addr.data,
  216 + password=form.password.data, profile=form.profile.data,
  217 + locale=current_app.config.get('DEFAULT_LOCALE'),
  218 + avatar_upload_id=request.form['avatar_upload_id'])
  219 + confirm_url = get_email_confirmation_url(account)
  220 + if current_app.config.get('ACCOUNT_CONFIRMATION_DISABLED'):
  221 + return _create_account(account)
  222 + msg = dict(subject='Welcome to %s!' % current_app.config.get('BRAND'),
  223 + recipients=[account['email_addr']],
  224 + body=render_template('/account/email/validate_account.md',
  225 + user=account, confirm_url=confirm_url))
  226 + msg['html'] = markdown(msg['body'])
  227 + mail_queue.enqueue(send_mail, msg)
  228 + return render_template('account/account_validation.html')
  229 + else:
  230 + flash(gettext('Please correct the errors'), 'error')
223 231 return render_template('account/register.html',
224   - title=gettext("Register"), form=form)
  232 + title=gettext("Register"),
  233 + form=form, upload_form=avatar_form, avatar_upload_id=avatar_upload_id)
225 234  
226 235  
227 236 @blueprint.route('/newsletter')
... ... @@ -285,10 +294,45 @@ def _create_account(user_data):
285 294 locale=user_data['locale'])
286 295 new_user.set_password(user_data['password'])
287 296 user_repo.save(new_user)
  297 + _update_user_info_on_register(new_user, user_data['avatar_upload_id'])
  298 +
288 299 flash(gettext('Thanks for signing-up'), 'success')
289 300 return _sign_in_user(new_user)
290 301  
291 302  
  303 +def _handle_avatar_update_on_register(avatar_form, avatar_upload_id):
  304 + if avatar_form.validate_on_submit():
  305 + container = "tmp"
  306 + # Delete previous avatar from storage
  307 + if avatar_upload_id != '':
  308 + uploader.delete_file("%s_avatar.png" % avatar_upload_id, container)
  309 +
  310 + _file = request.files['avatar']
  311 + coordinates = (avatar_form.x1.data, avatar_form.y1.data,
  312 + avatar_form.x2.data, avatar_form.y2.data)
  313 + avatar_upload_id = time.time()
  314 + _file.filename = "%s_avatar.png" % avatar_upload_id
  315 + uploader.upload_file(_file,
  316 + container=container,
  317 + coordinates=coordinates)
  318 + flash(gettext('Your avatar has been uploaded!'), 'success')
  319 + return str(avatar_upload_id)
  320 + else:
  321 + flash("You have to provide an image file to update your avatar", "error")
  322 + return ''
  323 +
  324 +def _update_user_info_on_register(new_user, avatar_upload_id):
  325 + if avatar_upload_id == '':
  326 + return
  327 + user = user_repo.get_by_name(new_user.name)
  328 + avatar = "%s_avatar.png" % avatar_upload_id
  329 + container = "user_%s" % user.id
  330 + user.info = {'avatar': avatar,
  331 + 'container': container}
  332 + uploader.move_file(avatar, "tmp", avatar, container)
  333 + user_repo.update(user)
  334 +
  335 +
292 336 def _update_user_with_valid_email(user, email_addr):
293 337 user.valid_email = True
294 338 user.confirmation_email_sent = False
... ...
tmp/.gitempty