diff --git a/apps/accounts/admin.py b/apps/accounts/admin.py index 36c365e36c..6432fe4b92 100644 --- a/apps/accounts/admin.py +++ b/apps/accounts/admin.py @@ -1,14 +1,15 @@ from django.contrib import admin -from .models import DetailKey, Profile +from .models import AdditionalField, AdditionalFieldValue -class DetailKeyAdmin(admin.ModelAdmin): +class AdditionalFieldAdmin(admin.ModelAdmin): pass -class ProfileAdmin(admin.ModelAdmin): - readonly_fields = ('user', ) +class AdditionalFieldValueAdmin(admin.ModelAdmin): + pass + -admin.site.register(DetailKey, DetailKeyAdmin) -admin.site.register(Profile, ProfileAdmin) +admin.site.register(AdditionalField, AdditionalFieldAdmin) +admin.site.register(AdditionalFieldValue, AdditionalFieldValueAdmin) diff --git a/apps/accounts/forms.py b/apps/accounts/forms.py index 94e4e56f50..76d8d174b5 100644 --- a/apps/accounts/forms.py +++ b/apps/accounts/forms.py @@ -1,42 +1,63 @@ from django import forms from django.contrib.auth.models import User +from django.utils.translation import ugettext_lazy as _ +from .models import AdditionalField, AdditionalFieldValue + + +class ProfileForm(forms.ModelForm): -class UserForm(forms.ModelForm): class Meta: model = User - fields = ('first_name', 'last_name', 'email') + fields = ('first_name', 'last_name') - -class ProfileForm(forms.Form): def __init__(self, *args, **kwargs): - profile = kwargs.pop('profile') - detail_keys = kwargs.pop('detail_keys') - super(ProfileForm, self).__init__(*args, **kwargs) + self.fields['first_name'].widget = forms.TextInput(attrs={'placeholder': _('First name')}) + self.fields['last_name'].widget = forms.TextInput(attrs={'placeholder': _('Last name')}) + + self.additional_fields = AdditionalField.objects.all() + self.additional_values = self.instance.additional_values.all() + # add fields and init values for the Profile model - for detail_key in detail_keys: - if detail_key.type == 'text': - field = forms.CharField() - elif detail_key.type == 'textarea': - field = forms.CharField(widget=forms.Textarea) - elif detail_key.type == 'select': - field = forms.ChoiceField(choices=detail_key.options) - elif detail_key.type == 'radio': - field = forms.ChoiceField(choices=detail_key.options, widget=forms.RadioSelect) - elif detail_key.type == 'multiselect': - field = forms.MultipleChoiceField(choices=detail_key.options) - elif detail_key.type == 'checkbox': - field = forms.MultipleChoiceField(choices=detail_key.options, widget=forms.CheckboxSelectMultiple) + for additional_field in self.additional_fields: + + if additional_field.type == 'text': + field = forms.CharField(widget=forms.TextInput(attrs={'placeholder': additional_field.text})) + elif additional_field.type == 'textarea': + field = forms.CharField(widget=forms.Textarea(attrs={'placeholder': additional_field.text})) else: - raise Exception('Unknown detail key type.') + raise Exception('Unknown additional_field type.') + + field.label = additional_field.text + field.help = additional_field.help + field.required = additional_field.required + + self.fields[additional_field.key] = field + + for additional_field_value in self.additional_values: + self.fields[additional_field.key].initial = additional_field_value.value + + def save(self, *args, **kwargs): + super(ProfileForm, self).save(*args, **kwargs) + self._save_additional_values() + + def _save_additional_values(self, user=None): + if user is None: + user = self.instance + + for additional_field in self.additional_fields: + try: + additional_value = user.additional_values.get(field=additional_field) + except AdditionalFieldValue.DoesNotExist: + additional_value = AdditionalFieldValue(user=user, field=additional_field) + + additional_value.value = self.cleaned_data[additional_field.key] + additional_value.save() + - field.label = detail_key.label - field.required = detail_key.required - field.help_text = detail_key.help_text - self.fields[detail_key.key] = field +class SignupForm(ProfileForm): - # add an initial value, if one is found in the user details - if profile.details and detail_key.key in profile.details: - self.fields[detail_key.key].initial = profile.details[detail_key.key] + def signup(self, request, user): + self._save_additional_values(user) diff --git a/apps/accounts/migrations/0007_additional_fields.py b/apps/accounts/migrations/0007_additional_fields.py new file mode 100644 index 0000000000..8faf7bf2eb --- /dev/null +++ b/apps/accounts/migrations/0007_additional_fields.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2016-11-14 12:13 +from __future__ import unicode_literals + +import apps.core.models +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('accounts', '0006_permissions_removed'), + ] + + operations = [ + migrations.CreateModel( + name='AdditionalField', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.SlugField()), + ('type', models.CharField(choices=[('text', 'Text'), ('textarea', 'Textarea')], max_length=11)), + ('text_en', models.CharField(max_length=256)), + ('text_de', models.CharField(max_length=256)), + ('help_en', models.TextField(blank=True, help_text='Enter a help text to be displayed next to the input element', null=True)), + ('help_de', models.TextField(blank=True, help_text='Enter a help text to be displayed next to the input element', null=True)), + ('required', models.BooleanField()), + ], + options={ + 'ordering': ('key',), + 'verbose_name': 'Additional field', + 'verbose_name_plural': 'Additional fields', + }, + bases=(models.Model, apps.core.models.TranslationMixin), + ), + migrations.CreateModel( + name='AdditionalFieldValue', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('value', models.CharField(max_length=256)), + ('field', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='accounts.AdditionalField')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='additional_fields', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ('user', 'field'), + 'verbose_name': 'Additional field value', + 'verbose_name_plural': 'Additional field values', + }, + ), + migrations.DeleteModel( + name='DetailKey', + ), + migrations.RemoveField( + model_name='profile', + name='user', + ), + migrations.DeleteModel( + name='Profile', + ), + ] diff --git a/apps/accounts/migrations/0008_related_name.py b/apps/accounts/migrations/0008_related_name.py new file mode 100644 index 0000000000..071f442392 --- /dev/null +++ b/apps/accounts/migrations/0008_related_name.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2016-11-15 14:51 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('accounts', '0007_additional_fields'), + ] + + operations = [ + migrations.AlterField( + model_name='additionalfieldvalue', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='additional_values', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/apps/accounts/models.py b/apps/accounts/models.py index 303852d39d..da6b59f6a4 100644 --- a/apps/accounts/models.py +++ b/apps/accounts/models.py @@ -1,79 +1,62 @@ from __future__ import unicode_literals from django.db import models -from django.db.models.signals import post_save from django.contrib.auth.models import User from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ -from jsonfield import JSONField +from apps.core.models import TranslationMixin @python_2_unicode_compatible -class Profile(models.Model): - user = models.OneToOneField(User) - details = JSONField(null=True, blank=True) - - class Meta: - ordering = ('user',) - - verbose_name = _('Profile') - verbose_name_plural = _('Profiles') - - def __str__(self): - return self.user.username - - @property - def full_name(self): - if self.user.first_name and self.user.last_name: - return '%s %s' % (self.user.first_name, self.user.last_name) - else: - return self.user.username - - def as_dl(self): - html = '
' - html += '
%s
%s
' % ('Name', self.full_name) - for detail_key in DetailKey.objects.all(): - if self.details and detail_key.key in self.details: - html += '
%s
%s
' % (detail_key.key.upper(), self.details[detail_key.key]) - html += '
' - return html - - -@python_2_unicode_compatible -class DetailKey(models.Model): +class AdditionalField(models.Model, TranslationMixin): TYPE_CHOICES = ( ('text', 'Text'), ('textarea', 'Textarea'), - ('checkbox', 'Checkbox'), - ('radio', 'Radio button'), - ('select', 'Select'), - ('multiselect', 'Multiselect'), ) key = models.SlugField() - label = models.CharField(max_length=256) type = models.CharField(max_length=11, choices=TYPE_CHOICES) - help_text = models.TextField(blank=True, help_text=_('Enter a help text to be displayed next to the input element')) - options = JSONField(null=True, blank=True, help_text=_('Enter valid JSON of the form [[key, label], [key, label], ...]')) + + text_en = models.CharField(max_length=256) + text_de = models.CharField(max_length=256) + + help_en = models.TextField(null=True, blank=True, help_text=_('Enter a help text to be displayed next to the input element')) + help_de = models.TextField(null=True, blank=True, help_text=_('Enter a help text to be displayed next to the input element')) + required = models.BooleanField() class Meta: ordering = ('key',) - verbose_name = _('DetailKey') - verbose_name_plural = _('DetailKeys') + verbose_name = _('Additional field') + verbose_name_plural = _('Additional fields') def __str__(self): - return self.key + return self.text + + @property + def text(self): + return self.trans('text') + + @property + def help(self): + return self.trans('help') -def create_profile_for_user(sender, **kwargs): - user = kwargs['instance'] - if kwargs['created'] and not kwargs.get('raw', False): - profile = Profile() - profile.user = user - profile.save() +@python_2_unicode_compatible +class AdditionalFieldValue(models.Model): -post_save.connect(create_profile_for_user, sender=User) + user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='additional_values') + field = models.ForeignKey(AdditionalField, on_delete=models.CASCADE, related_name='+') + value = models.CharField(max_length=256) + + class Meta: + ordering = ('user', 'field') + + verbose_name = _('Additional field value') + verbose_name_plural = _('Additional field values') + + def __str__(self): + return self.user.username + '/' + self.field.key diff --git a/apps/accounts/templates/account/email.html b/apps/accounts/templates/account/email.html new file mode 100644 index 0000000000..6fb9e86652 --- /dev/null +++ b/apps/accounts/templates/account/email.html @@ -0,0 +1,82 @@ +{% extends 'core/page.html' %} +{% load i18n %} + +{% block page %} + +

{% trans "E-mail Addresses" %}

+ +{% if user.emailaddress_set.all %} + +

{% trans 'The following e-mail addresses are associated with your account:' %}

+ +
+ {% csrf_token %} + +
+ + {% for emailaddress in user.emailaddress_set.all %} + + + + {% endfor %} + + + +
+
+ +{% else %} + +

+ {% trans 'Warning:'%} {% trans "You currently do not have any e-mail address set up. You should really add an e-mail address so you can receive notifications, reset your password, etc." %} +

+ +{% endif %} + +

{% trans "Add E-mail Address" %}

+ +
+ {% csrf_token %} + + {% include 'core/bootstrap_form_fields.html' %} + + +
+ +{% endblock %} + +{% block extra_body %} + +{% endblock %} diff --git a/apps/accounts/templates/account/email/password_reset_key_message.txt b/apps/accounts/templates/account/email/password_reset_key_message.txt new file mode 100644 index 0000000000..7f08ad60a1 --- /dev/null +++ b/apps/accounts/templates/account/email/password_reset_key_message.txt @@ -0,0 +1,16 @@ +{% load i18n core_tags accounts_tags %}{% trans "Dear" %} {% full_name user %}, + +{% blocktrans trimmed with site_domain=current_site.domain %} +You are receiving this e-mail because you requested that your password on +{{ site_domain }} will be reset. It can be safely ignored if you did not request +a password reset. Click the link below to reset your password. +{% endblocktrans %} + + {{ password_reset_url }} + +{% blocktrans trimmed %} +In case you forgot, your username is '{{ username }}'. +{% endblocktrans %} + +{% trans "Sincerely" %}, + {{ current_site.name }} Admins diff --git a/apps/accounts/templates/account/email/password_reset_key_subject.txt b/apps/accounts/templates/account/email/password_reset_key_subject.txt new file mode 100644 index 0000000000..45101c2f16 --- /dev/null +++ b/apps/accounts/templates/account/email/password_reset_key_subject.txt @@ -0,0 +1 @@ +{% load i18n %}{% trans 'Password reset' %} \ No newline at end of file diff --git a/apps/accounts/templates/account/email_confirm.html b/apps/accounts/templates/account/email_confirm.html new file mode 100644 index 0000000000..3abc4b0402 --- /dev/null +++ b/apps/accounts/templates/account/email_confirm.html @@ -0,0 +1,36 @@ +{% extends 'core/page.html' %} +{% load i18n %} +{% load account %} + +{% block page %} + +

{% trans "Confirm E-mail Address" %}

+ + {% if confirmation %} + + {% user_display confirmation.email_address.user as user_display %} + +

+ {% blocktrans trimmed with confirmation.email_address.email as email %} + Please confirm that {{ email }} is an e-mail address for user {{ user_display }}. + {% endblocktrans %} +

+ +
+ {% csrf_token %} + +
+ + {% else %} + + {% url 'account_email' as email_url %} + +

+ {% blocktrans trimmed %} + This e-mail confirmation link expired or is invalid. Please issue a new e-mail confirmation request. + {% endblocktrans %} +

+ + {% endif %} + +{% endblock %} \ No newline at end of file diff --git a/apps/accounts/templates/account/login.html b/apps/accounts/templates/account/login.html new file mode 100644 index 0000000000..66d4fcadec --- /dev/null +++ b/apps/accounts/templates/account/login.html @@ -0,0 +1,13 @@ +{% extends 'core/page.html' %} +{% load i18n %} +{% load account %} +{% load socialaccount %} +{% load core_tags %} + +{% block page %} + +

{% trans "Login" %}

+ + {% include 'account/login_form.html'%} + +{% endblock %} diff --git a/apps/accounts/templates/account/login_form.html b/apps/accounts/templates/account/login_form.html new file mode 100644 index 0000000000..4f19776773 --- /dev/null +++ b/apps/accounts/templates/account/login_form.html @@ -0,0 +1,43 @@ +{% load i18n %} +{% load account %} +{% load socialaccount %} + +{% get_providers as socialaccount_providers %} + +
+ {% csrf_token %} + + {% if redirect_field_value %} + + {% endif %} + + {% include 'core/bootstrap_form_fields.html' %} + + +
+ +

+ {% url 'account_reset_password' as reset_url %} + {% blocktrans %}If you have not created an account yet, then please sign up first.{% endblocktrans %} +

+ +

+ {% url 'account_reset_password' as reset_url %} + {% blocktrans %}If you forgot your password and want to reset it, click here.{% endblocktrans %} +

+ +{% if socialaccount_providers %} + +

+ {% blocktrans with site.name as site_name %}Alternatively, you can login using one of the following third party accounts:{% endblocktrans %} +

+ +
+ +
+ +{% include "socialaccount/snippets/login_extra.html" %} + +{% endif %} diff --git a/apps/accounts/templates/account/logout.html b/apps/accounts/templates/account/logout.html new file mode 100644 index 0000000000..eb5e68255f --- /dev/null +++ b/apps/accounts/templates/account/logout.html @@ -0,0 +1,22 @@ +{% extends 'core/page.html' %} +{% load i18n %} + +{% block page %} + +

{% trans "Logout" %}

+ +

+ {% trans 'Are you sure you want to sign out?' %} +

+ +
+ {% csrf_token %} + + {% if redirect_field_value %} + + {% endif %} + + +
+ +{% endblock %} diff --git a/apps/accounts/templates/account/password_change.html b/apps/accounts/templates/account/password_change.html new file mode 100644 index 0000000000..847052f859 --- /dev/null +++ b/apps/accounts/templates/account/password_change.html @@ -0,0 +1,20 @@ +{% extends 'core/page.html' %} +{% load i18n %} + +{% block page %} + +

{% trans "Change password" %}

+ +

+ {% trans "Please enter your old password, and then enter your new password twice so we can verify you typed it in correctly." %} +

+ +
+ {% csrf_token %} + + {% include 'core/bootstrap_form_fields.html' %} + + +
+ +{% endblock %} diff --git a/apps/accounts/templates/account/password_reset.html b/apps/accounts/templates/account/password_reset.html new file mode 100644 index 0000000000..09a76bd93f --- /dev/null +++ b/apps/accounts/templates/account/password_reset.html @@ -0,0 +1,24 @@ +{% extends 'core/page.html' %} +{% load i18n %} + +{% block page %} + +

{% trans "Password reset" %}

+ + {% if user.is_authenticated %} + {% include "account/snippets/already_logged_in.html" %} + {% endif %} + +

+ {% trans "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %} +

+ +
+ {% csrf_token %} + + {% include 'core/bootstrap_form_fields.html' %} + + +
+ +{% endblock %} diff --git a/apps/accounts/templates/account/password_reset_done.html b/apps/accounts/templates/account/password_reset_done.html new file mode 100644 index 0000000000..c0b9a3246e --- /dev/null +++ b/apps/accounts/templates/account/password_reset_done.html @@ -0,0 +1,24 @@ +{% extends 'core/page.html' %} +{% load i18n %} + +{% block page %} + +

{% trans "Password reset sent" %}

+ + {% if user.is_authenticated %} + {% include "account/snippets/already_logged_in.html" %} + {% endif %} + +

+ {% blocktrans trimmed %} + We have sent you an e-mail. Please contact us if you do not receive it within a few minutes. + {% endblocktrans %} +

+ +

+ {% blocktrans trimmed %} + If you don't receive an e-mail, please make sure you've entered the address you registered with, and check your spam folder. + {% endblocktrans %} +

+ +{% endblock %} diff --git a/apps/accounts/templates/account/password_reset_from_key.html b/apps/accounts/templates/account/password_reset_from_key.html new file mode 100644 index 0000000000..8bddbe38d0 --- /dev/null +++ b/apps/accounts/templates/account/password_reset_from_key.html @@ -0,0 +1,40 @@ +{% extends 'core/page.html' %} +{% load i18n %} + +{% block page %} + +{% if token_fail %} + +

{% trans "Bad token" %}

+ +

+ {% url 'account_reset_password' as passwd_reset_url %} + {% blocktrans trimmed %}The password reset link was invalid, possibly because it has already been used. + Please request a new password reset.{% endblocktrans %} +

+ +{% else %} + +

{% trans "Enter new password" %}

+ + {% if form %} + +
+ {% csrf_token %} + + {% include 'core/bootstrap_form_fields.html' %} + + +
+ + {% else %} + +

+ {% trans 'Your password is now changed.' %} +

+ + {% endif %} + +{% endif %} + +{% endblock %} diff --git a/apps/accounts/templates/account/password_reset_from_key_done.html b/apps/accounts/templates/account/password_reset_from_key_done.html new file mode 100644 index 0000000000..1a91b201f3 --- /dev/null +++ b/apps/accounts/templates/account/password_reset_from_key_done.html @@ -0,0 +1,17 @@ +{% extends 'core/page.html' %} +{% load i18n %} +{% load core_tags %} + +{% block page %} + +

{% trans "Password reset complete" %}

+ +

+ {% trans "Your password has been set. You may go ahead and log in now." %} +

+ +

+ {% trans 'Login' %} +

+ +{% endblock %} diff --git a/apps/accounts/templates/account/password_set.html b/apps/accounts/templates/account/password_set.html new file mode 100644 index 0000000000..d5f324c0df --- /dev/null +++ b/apps/accounts/templates/account/password_set.html @@ -0,0 +1,20 @@ +{% extends 'core/page.html' %} +{% load i18n %} + +{% block page %} + +

{% trans "Set new password" %}

+ +

+ {% trans "Please enter your new password twice so we can verify you typed it in correctly." %} +

+ +
+ {% csrf_token %} + + {% include 'core/bootstrap_form_fields.html' %} + + +
+ +{% endblock %} diff --git a/apps/accounts/templates/account/signup.html b/apps/accounts/templates/account/signup.html new file mode 100644 index 0000000000..4b5c191bbc --- /dev/null +++ b/apps/accounts/templates/account/signup.html @@ -0,0 +1,32 @@ +{% extends 'core/page.html' %} +{% load i18n %} + +{% block page %} + +

{% trans "Create a new account" %}

+ +

+ {% blocktrans trimmed %} + Already have an account? Then please sign in. + {% endblocktrans %} +

+ +
+ {% csrf_token %} + + {% if redirect_field_value %} + + {% endif %} + + {% include 'core/bootstrap_form_fields.html' %} + + +
+ + + +{% endblock %} diff --git a/apps/accounts/templates/account/signup_closed.html b/apps/accounts/templates/account/signup_closed.html new file mode 100644 index 0000000000..e26c41d45a --- /dev/null +++ b/apps/accounts/templates/account/signup_closed.html @@ -0,0 +1,12 @@ +{% extends 'core/page.html' %} +{% load i18n %} + +{% block page %} + +

{% trans "Sign up closed" %}

+ +

+ {% trans "We are sorry, but the sign up is currently closed." %} +

+ +{% endblock %} diff --git a/apps/accounts/templates/account/verification_sent.html b/apps/accounts/templates/account/verification_sent.html new file mode 100644 index 0000000000..404aa95516 --- /dev/null +++ b/apps/accounts/templates/account/verification_sent.html @@ -0,0 +1,14 @@ +{% extends 'core/page.html' %} +{% load i18n %} + +{% block page %} + +

+ {% trans "Verify your e-mail address" %} +

+ +

+ {% blocktrans %}We have sent an e-mail to you for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktrans %} +

+ +{% endblock %} diff --git a/apps/accounts/templates/account/verified_email_required.html b/apps/accounts/templates/account/verified_email_required.html new file mode 100644 index 0000000000..c065ec1ab6 --- /dev/null +++ b/apps/accounts/templates/account/verified_email_required.html @@ -0,0 +1,22 @@ +{% extends 'core/page.html' %} +{% load i18n %} + +{% block content %} + +

{% trans "Verify your e-mail address" %}

+ + {% url 'account_email' as email_url %} + +

+ {% blocktrans %}This part of the site requires us to verify that you are who you claim to be. For this purpose, we require that you verify ownership of your e-mail address. {% endblocktrans %} +

+ +

+ {% blocktrans %}We have sent an e-mail to you for verification. Please click on the link inside this e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktrans %} +

+ +

+ {% blocktrans %}Note: you can still change your e-mail address.{% endblocktrans %} +

+ +{% endblock %} diff --git a/apps/accounts/templates/accounts/login.html b/apps/accounts/templates/accounts/login.html deleted file mode 100644 index b16ccb7155..0000000000 --- a/apps/accounts/templates/accounts/login.html +++ /dev/null @@ -1,22 +0,0 @@ -{% extends 'core/page.html' %} -{% load i18n %} -{% load core_tags %} - -{% block page %} - -

{% trans "Login" %}

- - {% bootstrap_form submit=_('Login') %} - - - {% if form.errors %} -

- {% trans "Your login was not successful. Maybe you missed a field or your username and password didn't match. Please try again." %} -

- {% endif %} - -

- {% internal_link _('Help, I forgot my password') 'password_reset' %} -

- -{% endblock %} diff --git a/apps/accounts/templates/accounts/password_change_done.html b/apps/accounts/templates/accounts/password_change_done.html deleted file mode 100644 index d46c4ebf82..0000000000 --- a/apps/accounts/templates/accounts/password_change_done.html +++ /dev/null @@ -1,17 +0,0 @@ -{% extends 'core/page.html' %} -{% load i18n %} -{% load core_tags %} - -{% block page %} - -

{% trans "Password change successful" %}

- -

- {% trans "Your password has been changed. From now on, you can use the new password to login." %} -

- -

- {% internal_link 'Home' 'home' %} -

- -{% endblock %} diff --git a/apps/accounts/templates/accounts/password_change_form.html b/apps/accounts/templates/accounts/password_change_form.html deleted file mode 100644 index 6178a44a1f..0000000000 --- a/apps/accounts/templates/accounts/password_change_form.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'core/page.html' %} -{% load i18n %} -{% load core_tags %} - -{% block page %} - -

{% trans "Password change" %}

- -

- {% trans "Please enter your old password, and then enter your new password twice so we can verify you typed it in correctly." %} -

- - {% bootstrap_form submit=_('Change my password') %} - -{% endblock %} diff --git a/apps/accounts/templates/accounts/password_reset_complete.html b/apps/accounts/templates/accounts/password_reset_complete.html deleted file mode 100644 index d10580fe18..0000000000 --- a/apps/accounts/templates/accounts/password_reset_complete.html +++ /dev/null @@ -1,17 +0,0 @@ -{% extends 'core/page.html' %} -{% load i18n %} -{% load core_tags %} - -{% block page %} - -

{% trans 'Password reset complete' %}

- -

- {% trans 'Your password has been set. You may go ahead and log in now.' %} -

- -

- {% internal_link 'Login' 'login' %} -

- -{% endblock %} diff --git a/apps/accounts/templates/accounts/password_reset_confirm.html b/apps/accounts/templates/accounts/password_reset_confirm.html deleted file mode 100644 index d7bf457a8c..0000000000 --- a/apps/accounts/templates/accounts/password_reset_confirm.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'core/page.html' %} -{% load i18n %} -{% load core_tags %} - -{% block page %} - -

{% trans "Enter new password" %}

- -

- {% trans "Please enter your new password twice so we can verify you typed it in correctly." %} -

- - {% bootstrap_form submit=_('Change my password') %} - -{% endblock %} diff --git a/apps/accounts/templates/accounts/password_reset_done.html b/apps/accounts/templates/accounts/password_reset_done.html deleted file mode 100644 index ba6e3da204..0000000000 --- a/apps/accounts/templates/accounts/password_reset_done.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends 'core/page.html' %} -{% load i18n %} - -{% block page %} - -

{% trans "Password reset sent" %}

- -

- {% trans "We've emailed you instructions for setting your password, if an account exists with the email you entered. You should receive them shortly." %} -

- -

- {% trans "If you don't receive an email, please make sure you've entered the address you registered with, and check your spam folder." %} -

- -{% endblock %} diff --git a/apps/accounts/templates/accounts/password_reset_email.txt b/apps/accounts/templates/accounts/password_reset_email.txt deleted file mode 100644 index e0f4e660d0..0000000000 --- a/apps/accounts/templates/accounts/password_reset_email.txt +++ /dev/null @@ -1,25 +0,0 @@ -{% load i18n core_tags %}{% trans "Dear" %} {{ user.profile.full_name }}, - -{% blocktrans trimmed %} -You are receiving this email because you requested that your password be reset -on {{ domain }}. -{% endblocktrans %} - -{% blocktrans trimmed %} -If you do not wish to reset your password, please ignore -this message. -{% endblocktrans %} - -{% blocktrans trimmed %} -To reset your password, please click the following link, or copy and paste it -into your web browser: -{% endblocktrans %} - - {{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uid token %} - -{% blocktrans trimmed with user.username as username %} -In case you've forgotten, your username is "{{ username }}". -{% endblocktrans %} - -{% trans "Sincerely" %}, - {{ site_name }} Admins diff --git a/apps/accounts/templates/accounts/password_reset_form.html b/apps/accounts/templates/accounts/password_reset_form.html deleted file mode 100644 index 3f39c62555..0000000000 --- a/apps/accounts/templates/accounts/password_reset_form.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'core/page.html' %} -{% load i18n %} -{% load core_tags %} - -{% block page %} - -

{% trans "Password reset" %}

- -

- {% trans "Forgotten your password? Enter your email address below, and we'll email instructions for setting a new one." %} -

- - {% bootstrap_form submit=_('Reset my password') %} - -{% endblock %} diff --git a/apps/accounts/templates/accounts/password_reset_subject.txt b/apps/accounts/templates/accounts/password_reset_subject.txt deleted file mode 100644 index 711709a436..0000000000 --- a/apps/accounts/templates/accounts/password_reset_subject.txt +++ /dev/null @@ -1 +0,0 @@ -{% load i18n %}[{{ site_name }}] {% trans "Password reset" %} \ No newline at end of file diff --git a/apps/accounts/templates/accounts/profile_update_form.html b/apps/accounts/templates/accounts/profile_update_form.html deleted file mode 100644 index 3c02180e98..0000000000 --- a/apps/accounts/templates/accounts/profile_update_form.html +++ /dev/null @@ -1,23 +0,0 @@ -{% extends 'core/page.html' %} -{% load i18n %} - -{% block page %} - -

{% trans "Update profile" %}

- -

- {% trans "Please enter your updated account information." %} -

- -
- {% csrf_token %} - - - {% include 'core/bootstrap_form_fields.html' with form=user_form %} - {% include 'core/bootstrap_form_fields.html' with form=profile_form %} - - - -
- -{% endblock %} diff --git a/apps/accounts/templates/profile/profile_update_form.html b/apps/accounts/templates/profile/profile_update_form.html new file mode 100644 index 0000000000..1b5684eadb --- /dev/null +++ b/apps/accounts/templates/profile/profile_update_form.html @@ -0,0 +1,26 @@ +{% extends 'core/page.html' %} +{% load i18n %} + +{% block page %} + +

{% trans "Update profile" %}

+ +

+ {% url 'account_change_password' as password_url %} + {% url 'account_email' as email_url %} + {% blocktrans trimmed %} + Please enter your updated account information. You can change your password using the password form and update your e-mail using the e-mail form. + {% endblocktrans %} +

+ +
+ {% csrf_token %} + + + {% include 'core/bootstrap_form_fields.html' %} + + + +
+ +{% endblock %} diff --git a/apps/accounts/templates/registration/activate.html b/apps/accounts/templates/registration/activate.html deleted file mode 100644 index 248d1396eb..0000000000 --- a/apps/accounts/templates/registration/activate.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'core/page.html' %} -{% load i18n %} - -{% block page %} - -

{% trans "Account activation failed" %}

- -

- {% trans "Your account could not been validated. The provided url is not valid." %} -

- -{% endblock %} diff --git a/apps/accounts/templates/registration/activation_complete.html b/apps/accounts/templates/registration/activation_complete.html deleted file mode 100644 index f0a8077e4b..0000000000 --- a/apps/accounts/templates/registration/activation_complete.html +++ /dev/null @@ -1,19 +0,0 @@ -{% extends 'core/page.html' %} -{% load i18n core_tags %} - -{% block page %} - -

{% trans "Account activated" %}

- -

- {% trans "Your account is now activated." %} - {% if not user.is_authenticated %} - {% trans "You may go ahead and log in now." %} - {% endif %} -

- -

- {% if not user.is_authenticated %}{% internal_link 'Login' 'login' %}{% endif %} -

- -{% endblock %} diff --git a/apps/accounts/templates/registration/activation_email.txt b/apps/accounts/templates/registration/activation_email.txt deleted file mode 100644 index 17e13bef42..0000000000 --- a/apps/accounts/templates/registration/activation_email.txt +++ /dev/null @@ -1,17 +0,0 @@ -{% load i18n core_tags %}{% trans "Dear" %} {{ user.profile.full_name }}, - -{% blocktrans trimmed with site_name=site.name %} -You are receiving this email because you have asked to register an account at -{{ site_name }}. If this wasn't you, please ignore this email -and your address will be removed from our records. -{% endblocktrans %} - -{% blocktrans trimmed %} -To activate this account, please click the following link within the next -{{ expiration_days }} days: -{% endblocktrans %} - - http://{{ site.domain }}{% url 'registration_activate' activation_key %} - -{% trans "Sincerely" %}, - RDMO Admins diff --git a/apps/accounts/templates/registration/activation_email_subject.txt b/apps/accounts/templates/registration/activation_email_subject.txt deleted file mode 100644 index 8fa3bf38b1..0000000000 --- a/apps/accounts/templates/registration/activation_email_subject.txt +++ /dev/null @@ -1 +0,0 @@ -{% load i18n %}[{{ site.name }}] {% trans "Account activation" %} \ No newline at end of file diff --git a/apps/accounts/templates/registration/registration_closed.html b/apps/accounts/templates/registration/registration_closed.html deleted file mode 100644 index b52d54f84a..0000000000 --- a/apps/accounts/templates/registration/registration_closed.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'core/page.html' %} -{% load i18n %} - -{% block page %} - -

{% trans "Registration is closed" %}

- -

- {% trans "Sorry, but registration is closed at this moment. Come back later." %} -

- -{% endblock %} diff --git a/apps/accounts/templates/registration/registration_complete.html b/apps/accounts/templates/registration/registration_complete.html deleted file mode 100644 index 75b1875554..0000000000 --- a/apps/accounts/templates/registration/registration_complete.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends 'core/page.html' %} -{% load i18n %} - -{% block page %} - -

{% trans "Activation email send" %}

- -

- {% trans "We've emailed the activation link for your new account to the provided address." %} -

- -

- {% trans "Please check your email to complete the registration process." %} -

- -{% endblock %} diff --git a/apps/accounts/templates/registration/registration_form.html b/apps/accounts/templates/registration/registration_form.html deleted file mode 100644 index 0a0c1a8c46..0000000000 --- a/apps/accounts/templates/registration/registration_form.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'core/page.html' %} -{% load i18n %} -{% load core_tags %} - -{% block page %} - -

{% trans "Register for an account" %}

- -

- {% trans "Please enter your desired username, your email address, and your desired password twice so we can verify you typed it in correctly." %} -

- - {% bootstrap_form submit=_('Register as a new user') %} - -{% endblock %} diff --git a/apps/accounts/templates/socialaccount/authentication_error.html b/apps/accounts/templates/socialaccount/authentication_error.html new file mode 100644 index 0000000000..c826248f8e --- /dev/null +++ b/apps/accounts/templates/socialaccount/authentication_error.html @@ -0,0 +1,15 @@ +{% extends 'core/page.html' %} +{% load i18n %} +{% load account %} +{% load socialaccount %} +{% load core_tags %} + +{% block page %} + +

{% trans "Social Network Login Failure" %}

+ +

+ {% trans "An error occurred while attempting to login via your social network account." %} +

+ +{% endblock %} \ No newline at end of file diff --git a/apps/accounts/templates/socialaccount/connections.html b/apps/accounts/templates/socialaccount/connections.html new file mode 100644 index 0000000000..8b51c6c051 --- /dev/null +++ b/apps/accounts/templates/socialaccount/connections.html @@ -0,0 +1,66 @@ +{% extends 'core/page.html' %} +{% load i18n %} + +{% block page %} + +

{% trans "Account connections" %}

+ +

{% trans 'Current connections' %}

+ + {% if form.accounts %} + +

+ {% blocktrans trimmed %} + You can sign in to your account using any of the following third party accounts: + {% endblocktrans %} +

+ +
+ {% csrf_token %} + +
+ {% if form.non_field_errors %} +
{{ form.non_field_errors }}
+ {% endif %} + + {% for base_account in form.accounts %} + {% with base_account.get_provider_account as account %} + + + + {% endwith %} + {% endfor %} + +
+ +
+
+
+ + + + {% else %} + +

+ {% trans 'You currently have no social network accounts connected to this account.' %} +

+ + {% endif %} + +

{% trans 'Add an additional account' %}

+ + + + {% include "socialaccount/snippets/login_extra.html" %} + +{% endblock %} diff --git a/apps/accounts/templates/socialaccount/login_cancelled.html b/apps/accounts/templates/socialaccount/login_cancelled.html new file mode 100644 index 0000000000..768986d2f4 --- /dev/null +++ b/apps/accounts/templates/socialaccount/login_cancelled.html @@ -0,0 +1,17 @@ +{% extends 'core/page.html' %} +{% load i18n %} +{% load account %} +{% load socialaccount %} +{% load core_tags %} + +{% block page %} + +

{% trans "Login Cancelled" %}

+ +{% url 'account_login' as login_url %} + +

+ {% blocktrans %}You decided to cancel logging in to our site using one of your existing accounts. If this was a mistake, please proceed to sign in.{% endblocktrans %} +

+ +{% endblock %} diff --git a/apps/accounts/templates/socialaccount/signup.html b/apps/accounts/templates/socialaccount/signup.html new file mode 100644 index 0000000000..62b6c0c55b --- /dev/null +++ b/apps/accounts/templates/socialaccount/signup.html @@ -0,0 +1,31 @@ +{% extends 'core/page.html' %} +{% load i18n %} + +{% block page %} + +

{% trans "Create a new account" %}

+ +

+ {% blocktrans trimmed with provider_name=account.get_provider.name site_name=site.name %} + You are about to use your {{provider_name}} account to login to {{site_name}}. As a final step, please complete the following form:{% endblocktrans %} +

+ +
+ {% csrf_token %} + + {% if redirect_field_value %} + + {% endif %} + + {% include 'core/bootstrap_form_fields.html' %} + + +
+ + + +{% endblock %} diff --git a/apps/accounts/templates/socialaccount/snippets/provider_list.html b/apps/accounts/templates/socialaccount/snippets/provider_list.html new file mode 100644 index 0000000000..17973e5f74 --- /dev/null +++ b/apps/accounts/templates/socialaccount/snippets/provider_list.html @@ -0,0 +1,31 @@ +{% load socialaccount %} +{% load staticfiles %} + +{% get_providers as socialaccount_providers %} + +{% for provider in socialaccount_providers %} + +{% if provider.id == "openid" %} +{% for brand in provider.get_brands %} +
  • + + {{brand.name}} + +
  • +{% endfor %} +{% endif %} + +
  • + + + {% if provider.id != 'orcid' %} + + {% else %} + {{ provider.name }} + {% endif %} + +
  • +{% endfor %} diff --git a/apps/accounts/templatetags/__init__.py b/apps/accounts/templatetags/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/accounts/templatetags/accounts_tags.py b/apps/accounts/templatetags/accounts_tags.py new file mode 100644 index 0000000000..63826b2495 --- /dev/null +++ b/apps/accounts/templatetags/accounts_tags.py @@ -0,0 +1,28 @@ +from django import template +from django.utils.translation import ugettext_lazy as _ +from django.utils.safestring import mark_safe + +from ..utils import get_full_name + +register = template.Library() + + +@register.simple_tag() +def full_name(user): + return get_full_name(user) + + +@register.simple_tag() +def user_data_as_dl(user): + html = '
    ' + html += '
    %(key)s
    %(value)s
    ' % { + 'key': _('Name'), + 'value': get_full_name(user) + } + for additional_value in user.additional_values.all(): + html += '
    %(key)s
    %(value)s
    ' % { + 'key': additional_value.field.text, + 'value': additional_value.value + } + html += '
    ' + return mark_safe(html) diff --git a/apps/accounts/testing/factories.py b/apps/accounts/testing/factories.py index 5f232815c6..5720db8e61 100644 --- a/apps/accounts/testing/factories.py +++ b/apps/accounts/testing/factories.py @@ -1,5 +1,3 @@ -import factory - from django.contrib.auth.models import User from factory.django import DjangoModelFactory @@ -7,14 +5,6 @@ from ..models import * -class ProfileFactory(factory.django.DjangoModelFactory): - - class Meta: - model = Profile - - user = factory.SubFactory('apps.accounts.testing.factories.UserFactory', profile=None) - - class UserFactory(DjangoModelFactory): class Meta: @@ -28,15 +18,6 @@ class Meta: email = 'user@example.com' - profile = factory.RelatedFactory(ProfileFactory, 'user') - - @classmethod - def _generate(cls, create, attrs): - post_save.disconnect(create_profile_for_user, User) - user = super(UserFactory, cls)._generate(create, attrs) - post_save.connect(create_profile_for_user, User) - return user - @classmethod def _create(cls, model_class, *args, **kwargs): manager = cls._get_manager(model_class) @@ -68,61 +49,29 @@ class AdminFactory(UserFactory): is_superuser = True -class DetailKeyFactory(DjangoModelFactory): +class AdditionalFieldFactory(DjangoModelFactory): class Meta: - model = DetailKey + model = AdditionalField -class TextDetailKeyFactory(DetailKeyFactory): +class AdditionalTextFieldFactory(AdditionalFieldFactory): type = 'text' - help_text = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr' - label = 'text' + help_en = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr' + help_de = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr' + text_en = 'text' + text_de = 'text' key = 'text' required = True -class TextareaDetailKeyFactory(DetailKeyFactory): +class AdditionalTextareaFieldFactory(AdditionalFieldFactory): type = 'textarea' - help_text = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr' - label = 'textarea' + help_en = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr' + help_de = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr' + text_en = 'textarea' + text_de = 'textarea' key = 'textarea' required = True - - -class SelectDetailKeyFactory(DetailKeyFactory): - - type = 'select' - help_text = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr' - label = 'select' - key = 'select' - required = True - - -class RadioDetailKeyFactory(DetailKeyFactory): - - type = 'radio' - help_text = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr' - label = 'radio' - key = 'radio' - required = True - - -class MultiselectDetailKeyFactory(DetailKeyFactory): - - type = 'multiselect' - help_text = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr' - label = 'multiselect' - key = 'multiselect' - required = True - - -class ChecboxDetailKeyFactory(DetailKeyFactory): - - type = 'checkbox' - help_text = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr' - label = 'checkbox' - key = 'checkbox' - required = True diff --git a/apps/accounts/testing/tests.py b/apps/accounts/testing/tests.py index 95c0cf444a..9477353e1d 100644 --- a/apps/accounts/testing/tests.py +++ b/apps/accounts/testing/tests.py @@ -7,7 +7,6 @@ from apps.core.testing.mixins import TestModelStringMixin -from ..models import DetailKey, Profile from .factories import * @@ -15,7 +14,9 @@ class ProfileTests(TestModelStringMixin, TestCase): def setUp(self): translation.activate('en') - self.instance = UserFactory().profile + AdditionalTextFieldFactory() + AdditionalTextareaFieldFactory() + self.instance = UserFactory() def test_get_profile_update(self): """ @@ -34,7 +35,7 @@ def test_get_profile_update_redirect(self): """ url = reverse('profile_update') response = self.client.get(url) - self.assertRedirects(response, reverse('login') + '?next=' + url) + self.assertRedirects(response, reverse('account_login') + '?next=' + url) def test_post_profile_update(self): """ @@ -47,7 +48,9 @@ def test_post_profile_update(self): response = self.client.post(url, { 'email': 'test@example.com', 'first_name': 'Albert', - 'last_name': 'Admin' + 'last_name': 'Admin', + 'text': 'text', + 'textarea': 'textarea', }) self.assertRedirects(response, reverse('home'), target_status_code=302) @@ -80,9 +83,9 @@ def test_post_profile_update_cancel2(self): 'first_name': 'Albert', 'last_name': 'Admin', 'cancel': 'cancel', - 'next': '/account/password/change/' + 'next': reverse('account_change_password') }) - self.assertRedirects(response, reverse('password_change')) + self.assertRedirects(response, reverse('account_change_password')) def test_post_profile_update_next(self): """ @@ -98,13 +101,9 @@ def test_post_profile_update_next(self): 'last_name': 'Admin', 'text': 'text', 'textarea': 'textarea', - 'select': 'a', - 'radio': 'a', - 'multiselect': 'a', - 'checkbox': 'a', - 'next': '/account/password/change/' + 'next': reverse('account_change_password') }) - self.assertRedirects(response, reverse('password_change')) + self.assertRedirects(response, reverse('account_change_password')) def test_post_profile_update_next2(self): """ @@ -120,20 +119,16 @@ def test_post_profile_update_next2(self): 'last_name': 'Admin', 'text': 'text', 'textarea': 'textarea', - 'select': 'a', - 'radio': 'a', - 'multiselect': 'a', - 'checkbox': 'a', - 'next': '/account/' + 'next': reverse('profile_update') }) self.assertRedirects(response, reverse('home'), target_status_code=302) -class DetailKeyTests(TestModelStringMixin, TestCase): +class AdditionalFieldTests(TestModelStringMixin, TestCase): def setUp(self): translation.activate('en') - self.instance = TextDetailKeyFactory() + self.instance = AdditionalTextFieldFactory() class PasswordTests(TestCase): @@ -149,7 +144,7 @@ def test_password_change_get(self): """ self.client.login(username='user', password='user') - url = reverse('password_change') + url = reverse('account_change_password') response = self.client.get(url) self.assertEqual(response.status_code, 200) @@ -160,19 +155,19 @@ def test_password_change_post(self): """ self.client.login(username='user', password='user') - url = reverse('password_change') + url = reverse('account_change_password') response = self.client.post(url, { 'old_password': 'user', 'new_password1': 'resu', 'new_password2': 'resu', }) - self.assertRedirects(response, reverse('password_change_done')) + self.assertEqual(response.status_code, 200) def test_password_reset_get(self): """ A GET request to the password reset form returns the form. """ - url = reverse('password_reset') + url = reverse('account_reset_password') response = self.client.get(url) self.assertEqual(response.status_code, 200) @@ -181,9 +176,9 @@ def test_password_reset_post_invalid(self): A POST request to the password reset form with an invalid mail address sends no mail. """ - url = reverse('password_reset') + url = reverse('account_reset_password') response = self.client.post(url, {'email': 'wrong@example.com'}) - self.assertRedirects(response, reverse('password_reset_done')) + self.assertEqual(response.status_code, 200) self.assertEqual(len(mail.outbox), 0) def test_password_reset_post_valid(self): @@ -191,9 +186,9 @@ def test_password_reset_post_valid(self): A POST request to the password reset form with an invalid mail address sends a mail with a correct link. """ - url = reverse('password_reset') + url = reverse('account_reset_password') response = self.client.post(url, {'email': 'user@example.com'}) - self.assertRedirects(response, reverse('password_reset_done')) + self.assertRedirects(response, reverse('account_reset_password_done')) self.assertEqual(len(mail.outbox), 1) # get the link from the mail diff --git a/apps/accounts/urls.py b/apps/accounts/urls.py index 383fa307c4..a1c2e75a81 100644 --- a/apps/accounts/urls.py +++ b/apps/accounts/urls.py @@ -1,5 +1,4 @@ -from django.conf.urls import url -from django.contrib.auth import views as auth_views +from django.conf.urls import url, include from .views import profile_update @@ -8,28 +7,6 @@ # edit own profile url(r'^$', profile_update, name='profile_update'), - # change password - url(r'^password/change/$', auth_views.password_change, { - 'template_name': 'accounts/password_change_form.html' - }, name='password_change'), - url(r'^password/change/done/$', auth_views.password_change_done, { - 'template_name': 'accounts/password_change_done.html' - }, name='password_change_done'), - - # reset password - url(r'^password/reset/$', auth_views.password_reset, { - 'template_name': 'accounts/password_reset_form.html', - 'email_template_name': 'accounts/password_reset_email.txt', - 'subject_template_name': 'accounts/password_reset_subject.txt', - }, name='password_reset'), - url(r'^password/reset/done/$', auth_views.password_reset_done, { - 'template_name': 'accounts/password_reset_done.html', - }, name='password_reset_done'), - url(r'^password/reset/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', auth_views.password_reset_confirm, { - 'template_name': 'accounts/password_reset_confirm.html', - }, name='password_reset_confirm'), - url(r'^password/reset/complete/$', auth_views.password_reset_complete, { - 'template_name': 'accounts/password_reset_complete.html', - }, name='password_reset_complete'), - + # include django-allauth urls + url(r'^', include('allauth.urls')), ] diff --git a/apps/accounts/utils.py b/apps/accounts/utils.py new file mode 100644 index 0000000000..bd566b8806 --- /dev/null +++ b/apps/accounts/utils.py @@ -0,0 +1,5 @@ +def get_full_name(user): + if user.first_name and user.last_name: + return '%s %s' % (user.first_name, user.last_name) + else: + return user.username diff --git a/apps/accounts/views.py b/apps/accounts/views.py index 4773b0cdcb..0bb1c33c85 100644 --- a/apps/accounts/views.py +++ b/apps/accounts/views.py @@ -1,55 +1,24 @@ -import json - from django.shortcuts import render -from django.http import HttpResponseRedirect -from django.core.urlresolvers import reverse from django.contrib.auth.decorators import login_required +from django.http import HttpResponseRedirect +from apps.core.utils import get_referer_path_info, get_next -from apps.core.utils import get_referer, get_next - -from .models import DetailKey -from .forms import UserForm, ProfileForm +from .forms import ProfileForm @login_required() def profile_update(request): - next = get_referer(request) - detail_keys = DetailKey.objects.all() + form = ProfileForm(request.POST or None, instance=request.user) if request.method == 'POST': if 'cancel' in request.POST: - next = get_next(request) - return HttpResponseRedirect(next) - - user_form = UserForm(request.POST) - profile_form = ProfileForm(request.POST, profile=request.user.profile, detail_keys=detail_keys) - - if user_form.is_valid() and profile_form.is_valid(): - request.user.first_name = user_form.cleaned_data['first_name'] - request.user.last_name = user_form.cleaned_data['last_name'] - request.user.email = user_form.cleaned_data['email'] - request.user.save() - - for detail_key in detail_keys: - if not request.user.profile.details: - request.user.profile.details = {} - request.user.profile.details[detail_key.key] = profile_form.cleaned_data[detail_key.key] - request.user.profile.save() - - next = get_next(request) - return HttpResponseRedirect(next) - else: - user_initial = { - 'first_name': request.user.first_name, - 'last_name': request.user.last_name, - 'email': request.user.email - } + return HttpResponseRedirect(get_next(request)) - user_form = UserForm(initial=user_initial) - profile_form = ProfileForm(profile=request.user.profile, detail_keys=detail_keys) + if form.is_valid(): + form.save() + return HttpResponseRedirect(get_next(request)) - return render(request, 'accounts/profile_update_form.html', { - 'user_form': user_form, - 'profile_form': profile_form, - 'next': next + return render(request, 'profile/profile_update_form.html', { + 'form': form, + 'next': get_referer_path_info(request, default='/') }) diff --git a/apps/core/static/core/css/base.scss b/apps/core/static/core/css/base.scss index 9ba1ae025e..ad8048abfb 100644 --- a/apps/core/static/core/css/base.scss +++ b/apps/core/static/core/css/base.scss @@ -163,3 +163,42 @@ ul.list-arrow li.active a:before { text-align: right; content: '\2192\0000a0'; /* right-arrow followed by a space */ } + +/* misc */ +.form-errors { + margin-bottom: 20px; +} +.email-form label, +.connections-form label { + display: block; + margin: 0; + line-height: 40px; + border-bottom: 1px solid $modal-border-color; +} +.email-form label:first-child, +.connections-form label:first-child { + border-top: 1px solid $modal-border-color; +} +.email-form label input, +.connections-form label input { + margin-left: 5px; + margin-right: 5px; +} +.email-form .email-form-buttons, +.connections-form .connections-form-buttons { + margin-top: 10px; +} +.socialaccount_providers { + margin: 0; + padding: 0; + height: 42px; +} +.socialaccount_providers li { + float: left; + margin-right: 10px; + list-style: none; +} +.socialaccount_provider_name { + line-height: 29px; + font-weight: bold; +} \ No newline at end of file diff --git a/apps/core/templates/core/base.html b/apps/core/templates/core/base.html index 7f11580c14..a4e2e32be9 100644 --- a/apps/core/templates/core/base.html +++ b/apps/core/templates/core/base.html @@ -27,5 +27,8 @@ {% endif %} + +{% block extra_body %}{% endblock %} + diff --git a/apps/core/templates/core/base_navigation.html b/apps/core/templates/core/base_navigation.html index 19cc54e4b6..afaee1a2ee 100644 --- a/apps/core/templates/core/base_navigation.html +++ b/apps/core/templates/core/base_navigation.html @@ -1,4 +1,6 @@ -{% load i18n core_tags %} +{% load i18n %} +{% load core_tags %} +{% load accounts_tags %}