removing old accounts app
This commit is contained in:
parent
39b765bb51
commit
623b94fccd
|
@ -1 +0,0 @@
|
|||
default_app_config = 'accounts.apps.AccountsConfig'
|
|
@ -1,9 +0,0 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from accounts.models import Participation, Profile, Transport, Connector
|
||||
|
||||
|
||||
admin.site.register(Profile) # FIXME extend user admin
|
||||
admin.site.register(Participation)
|
||||
admin.site.register(Transport)
|
||||
admin.site.register(Connector)
|
|
@ -1,10 +0,0 @@
|
|||
from django.apps import AppConfig
|
||||
from django.db.models.signals import post_migrate
|
||||
|
||||
|
||||
class AccountsConfig(AppConfig):
|
||||
name = 'accounts'
|
||||
|
||||
def ready(self):
|
||||
import accounts.signals # noqa
|
||||
post_migrate.connect(accounts.signals.create_default_options, sender=self)
|
|
@ -1,28 +0,0 @@
|
|||
from functools import wraps
|
||||
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
||||
from accounts.utils import is_orga, is_staff
|
||||
|
||||
|
||||
def orga_required(view_func):
|
||||
def _is_orga(request, *args, **kwargs):
|
||||
if not request.user.is_authenticated():
|
||||
return login_required(view_func)(request, *args, **kwargs)
|
||||
elif is_orga(request, request.user):
|
||||
return view_func(request, *args, **kwargs)
|
||||
else:
|
||||
raise PermissionDenied
|
||||
return wraps(view_func)(_is_orga)
|
||||
|
||||
|
||||
def staff_required(view_func):
|
||||
def _is_staff(request, *args, **kwargs):
|
||||
if not request.user.is_authenticated():
|
||||
return login_required(view_func)(request, *args, **kwargs)
|
||||
elif is_staff(request, request.user):
|
||||
return view_func(request, *args, **kwargs)
|
||||
else:
|
||||
raise PermissionDenied
|
||||
return wraps(view_func)(_is_staff)
|
|
@ -1,48 +0,0 @@
|
|||
from django import forms
|
||||
from django.contrib.auth.models import User
|
||||
from django.forms.models import modelform_factory
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from django_select2.forms import Select2Widget
|
||||
|
||||
from .models import Participation, Profile
|
||||
|
||||
UserForm = modelform_factory(User, fields=['first_name', 'last_name', 'email', 'username'])
|
||||
|
||||
ProfileForm = modelform_factory(Profile, fields=['phone_number', 'biography', 'twitter', 'website', 'linkedin', 'facebook', 'mastodon'])
|
||||
|
||||
ParticipationForm = modelform_factory(Participation,
|
||||
fields=['need_transport', 'transport', 'transport_city_outward', 'transport_city_return',
|
||||
'accommodation',
|
||||
'connector', 'sound', 'videotaped',
|
||||
'video_licence', 'constraints'],
|
||||
widgets={'transport': forms.CheckboxSelectMultiple(),
|
||||
'connector': forms.CheckboxSelectMultiple()},
|
||||
help_texts = {
|
||||
'constraints': _('For example, you need to be back on saturday evening, you cannot eat meat.'),
|
||||
})
|
||||
|
||||
ProfileOrgaForm = modelform_factory(Profile, fields=['biography'])
|
||||
|
||||
ParticipationOrgaForm = modelform_factory(Participation,
|
||||
fields=['need_transport', 'transport', 'transport_city_outward', 'transport_city_return', 'transport_booked',
|
||||
'accommodation', 'accommodation_booked',
|
||||
'connector', 'sound', 'videotaped',
|
||||
'video_licence',
|
||||
'constraints', 'notes', 'orga'],
|
||||
widgets={'transport': forms.CheckboxSelectMultiple(),
|
||||
'connector': forms.CheckboxSelectMultiple()})
|
||||
|
||||
|
||||
class ParticipationField(forms.ModelChoiceField):
|
||||
def label_from_instance(self, obj):
|
||||
return obj.profile.__str__()
|
||||
|
||||
|
||||
class NewParticipationForm(forms.Form):
|
||||
def __init__(self, *args, **kwargs):
|
||||
site = kwargs.pop('site')
|
||||
super().__init__(*args, **kwargs)
|
||||
queryset = User.objects.exclude(participation__site=site).all()
|
||||
self.fields['participant'] = ParticipationField(queryset, widget=Select2Widget(),
|
||||
label='Add participant from existing account')
|
|
@ -1,107 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.3 on 2017-01-13 10:49
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import accounts.utils
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('sites', '0002_alter_domain_unique'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='AvailabilityTimeslot',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('start', models.DateTimeField(blank=True)),
|
||||
('end', models.DateTimeField(blank=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Connector',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=64, unique=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Participation',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('updated', models.DateTimeField(auto_now=True)),
|
||||
('need_transport', models.NullBooleanField(default=None, verbose_name='Defray transportation?')),
|
||||
('arrival', models.DateTimeField(blank=True, null=True)),
|
||||
('departure', models.DateTimeField(blank=True, null=True)),
|
||||
('transport_city_outward', models.CharField(blank=True, default='', max_length=256, verbose_name='Departure city')),
|
||||
('transport_city_return', models.CharField(blank=True, default='', help_text='If different from departure city', max_length=256, verbose_name='Return city')),
|
||||
('transport_booked', models.BooleanField(default=False)),
|
||||
('accommodation', models.IntegerField(blank=True, choices=[(0, 'No'), (1, 'Hotel'), (2, 'Homestay')], null=True, verbose_name='Need accommodation?')),
|
||||
('accommodation_booked', models.BooleanField(default=False)),
|
||||
('constraints', models.TextField(blank=True, verbose_name='Constraints')),
|
||||
('sound', models.BooleanField(default=False, verbose_name='I need sound')),
|
||||
('videotaped', models.BooleanField(default=True, verbose_name="I'm ok to be recorded on video")),
|
||||
('video_licence', models.IntegerField(choices=[(1, 'CC-Zero'), (2, 'CC-BY'), (3, 'CC-BY-SA'), (4, 'CC-BY-ND'), (5, 'CC-BY-NC'), (6, 'CC-BY-NC-SA'), (7, 'CC-BY-NC-ND')], default=2, verbose_name='Video licence')),
|
||||
('notes', models.TextField(blank=True, default='', help_text='This field is only visible by organizers.', verbose_name='Notes')),
|
||||
('orga', models.BooleanField(default=False)),
|
||||
('connector', models.ManyToManyField(blank=True, to='accounts.Connector', verbose_name='I can output')),
|
||||
('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sites.Site')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Profile',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('updated', models.DateTimeField(auto_now=True)),
|
||||
('phone_number', models.CharField(blank=True, default='', max_length=16, verbose_name='Phone number')),
|
||||
('biography', models.TextField(blank=True, verbose_name='Biography')),
|
||||
('email_token', models.CharField(default=accounts.utils.generate_user_uid, max_length=12, unique=True)),
|
||||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Transport',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=64, unique=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='participation',
|
||||
name='transport',
|
||||
field=models.ManyToManyField(blank=True, to='accounts.Transport', verbose_name='I want to travel by'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='participation',
|
||||
name='user',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='availabilitytimeslot',
|
||||
name='participation',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='availabilities', to='accounts.Participation'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='participation',
|
||||
unique_together=set([('site', 'user')]),
|
||||
),
|
||||
]
|
|
@ -1,40 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.7 on 2017-04-29 21:34
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='profile',
|
||||
name='facebook',
|
||||
field=models.CharField(blank=True, default='', max_length=100, verbose_name='Facebook'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='profile',
|
||||
name='linkedin',
|
||||
field=models.CharField(blank=True, default='', max_length=100, verbose_name='LinkedIn'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='profile',
|
||||
name='mastodon',
|
||||
field=models.CharField(blank=True, default='', max_length=100, verbose_name='Mastodon'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='profile',
|
||||
name='twitter',
|
||||
field=models.CharField(blank=True, default='', max_length=100, verbose_name='Twitter'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='profile',
|
||||
name='website',
|
||||
field=models.CharField(blank=True, default='', max_length=100, verbose_name='Website'),
|
||||
),
|
||||
]
|
|
@ -1,20 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2017-04-30 11:29
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0002_auto_20170429_2134'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='profile',
|
||||
name='github',
|
||||
field=models.CharField(blank=True, default='', max_length=100, verbose_name='Github'),
|
||||
),
|
||||
]
|
|
@ -1,8 +0,0 @@
|
|||
from django.contrib.auth.mixins import UserPassesTestMixin
|
||||
|
||||
from .utils import is_staff
|
||||
|
||||
|
||||
class StaffRequiredMixin(UserPassesTestMixin):
|
||||
def test_func(self):
|
||||
return is_staff(self.request, self.request.user)
|
|
@ -1,31 +0,0 @@
|
|||
from enum import IntEnum
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ugettext
|
||||
|
||||
from ponyconf.utils import PonyConfModel, enum_to_choices
|
||||
|
||||
#from .utils import generate_user_uid
|
||||
|
||||
|
||||
class Profile(PonyConfModel):
|
||||
|
||||
user = models.OneToOneField(User)
|
||||
phone_number = models.CharField(max_length=16, blank=True, default='', verbose_name=_('Phone number'))
|
||||
|
||||
twitter = models.CharField(max_length=100, blank=True, default='', verbose_name=_('Twitter'))
|
||||
linkedin = models.CharField(max_length=100, blank=True, default='', verbose_name=_('LinkedIn'))
|
||||
github = models.CharField(max_length=100, blank=True, default='', verbose_name=_('Github'))
|
||||
website = models.CharField(max_length=100, blank=True, default='', verbose_name=_('Website'))
|
||||
facebook = models.CharField(max_length=100, blank=True, default='', verbose_name=_('Facebook'))
|
||||
mastodon = models.CharField(max_length=100, blank=True, default='', verbose_name=_('Mastodon'))
|
||||
|
||||
def __str__(self):
|
||||
return self.user.get_full_name() or self.user.username
|
||||
|
||||
#def get_absolute_url(self):
|
||||
# return reverse('profile')
|
|
@ -1,45 +0,0 @@
|
|||
from django.contrib import messages
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.signals import user_logged_in, user_logged_out
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ugettext_noop
|
||||
|
||||
from ponyconf.decorators import disable_for_loaddata
|
||||
|
||||
from .models import Connector, Participation, Profile, Transport
|
||||
|
||||
|
||||
def create_default_options(sender, **kwargs):
|
||||
Transport.objects.get_or_create(name=ugettext_noop('Train'))
|
||||
Transport.objects.get_or_create(name=ugettext_noop('Plane'))
|
||||
Transport.objects.get_or_create(name=ugettext_noop('Carpooling'))
|
||||
Connector.objects.get_or_create(name=ugettext_noop('VGA'))
|
||||
Connector.objects.get_or_create(name=ugettext_noop('HDMI'))
|
||||
Connector.objects.get_or_create(name=ugettext_noop('miniDP'))
|
||||
Connector.objects.get_or_create(name=ugettext_noop('I need a computer'))
|
||||
|
||||
|
||||
@receiver(user_logged_in)
|
||||
def on_user_logged_in(sender, request, user, **kwargs):
|
||||
participation, created = Participation.objects.get_or_create(user=user, site=get_current_site(request))
|
||||
if user.is_superuser:
|
||||
participation.orga = True
|
||||
participation.save()
|
||||
if created:
|
||||
messages.info(request, "Please check your profile!\n", fail_silently=True) # FIXME
|
||||
messages.success(request, _('Welcome!'), fail_silently=True) # FIXME
|
||||
|
||||
|
||||
@receiver(user_logged_out)
|
||||
def on_user_logged_out(sender, request, **kwargs):
|
||||
messages.success(request, _('Goodbye!'), fail_silently=True) # FIXME
|
||||
|
||||
|
||||
@receiver(post_save, sender=User, weak=False, dispatch_uid='create_profile')
|
||||
@disable_for_loaddata
|
||||
def create_profile(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
Profile.objects.create(user=instance)
|
|
@ -1,76 +0,0 @@
|
|||
{% extends 'staff.html' %}
|
||||
|
||||
{% load accounts_tags i18n avatar_tags %}
|
||||
|
||||
{% block participantstab %} class="active"{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{{ profile }}</h1>
|
||||
|
||||
{% if request|staff %}
|
||||
<a href="{% url 'user-conversation' profile.user.username %}" class="btn btn-primary ">{% trans "Contact" %}</a>
|
||||
{% endif %}
|
||||
{% if request|edit_profile:profile %}
|
||||
<a href="{% url 'edit-participant' profile.user.username %}" class="btn btn-success">{% trans "Edit" %}</a>
|
||||
{% endif %}
|
||||
|
||||
<img class="pull-right" src="{% avatar_url profile.user 160 %}" />
|
||||
|
||||
<h2>{% trans "Biography" %}</h2>
|
||||
<p>{{ profile.biography }}</p>
|
||||
|
||||
{% if request|staff %}
|
||||
<p><a href="mailto:{{ profile.user.email }}?subject=[Capitole du Libre]">{{ profile.user.email }}</a></p>
|
||||
{% endif %}
|
||||
|
||||
<h2>{% trans "Talks" %}</h2>
|
||||
{% include "proposals/_talk_list.html" %}
|
||||
|
||||
{% if request|edit_profile:profile %}
|
||||
|
||||
<h2>{% trans "Information" %}</h2>
|
||||
|
||||
<h3>{% trans "Travels and hosting" %}</h3>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<b>{% trans "Need transport:" %}</b> {{ participation.need_transport|yesno:"Yes,No,Not specified" }}
|
||||
{% if participation.need_transport %}
|
||||
<ul>
|
||||
{% comment %}
|
||||
<li><b>{% trans "Arrival:" %}</b> {{ participation.arrival }}</li>
|
||||
<li><b>{% trans "Departure:" %}</b> {{ participation.departure }}</li>
|
||||
{% endcomment %}
|
||||
<li><b>{% trans "Accepted transport means:" %}</b> {% for transport in participation.transport.all %}{% if not forloop.first %}, {% endif %}{{ transport }}{% endfor %}</li>
|
||||
<li><b>{% trans "Departure city:" %}</b> {{ participation.transport_city_outward|default:'Not specified' }}</li>
|
||||
{% if participation.transport_city_return %}
|
||||
<li><b>{% trans "Return city:" %}</b> {{ participation.transport_city_return }}</li>
|
||||
{% endif %}
|
||||
<li><b>{% trans "Transport booked:" %}</b> {{ participation.transport_booked|yesno }}</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
<li><b>{% trans "Need accommodation:" %}</b> {% if participation.accommodation is None %}Not specified{% else %}{{ participation.get_accommodation_display }}{% endif %}</li>
|
||||
<li><b>{% trans "Accommodation booked:" %}</b> {{ participation.accommodation_booked|yesno }}</li>
|
||||
</ul>
|
||||
|
||||
<h3>{% trans "Talk needs" %}</h3>
|
||||
|
||||
<ul>
|
||||
<li><b>{% trans "Video output:" %}</b> {% for conn in participation.connector.all %}{% if not forloop.first %}, {% endif %}{{ conn }}{% endfor %}</li>
|
||||
<li><b>{% trans "Need sound:" %}</b> {{ participation.sound|yesno }}</li>
|
||||
<li><b>{% trans "Ok to be recorded on video:" %}</b> {{ participation.videotaped|yesno }}</li>
|
||||
<li><b>{% trans "Video licence:" %}</b> {{ participation.get_video_licence_display }}</li>
|
||||
</ul>
|
||||
|
||||
<h3>{% trans "Constraints" %}</h3>
|
||||
<p>{{ participation.constraints|linebreaksbr }}</p>
|
||||
|
||||
<h3>{% trans "Notes" %}</h3>
|
||||
<p>{{ participation.notes|linebreaksbr }}</p>
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% endblock %}
|
|
@ -1,18 +0,0 @@
|
|||
{% extends 'staff.html' %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block participantstab %} class="active"{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3>{% blocktrans %}{{ profile }}'s profile{% endblocktrans %}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% include "_form.html" %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -1,62 +0,0 @@
|
|||
{% extends 'staff.html' %}
|
||||
|
||||
{% load bootstrap3 accounts_tags i18n %}
|
||||
|
||||
{% block participantstab %} class="active"{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{% trans "Participants" %}</h1>
|
||||
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<th>Username</th>
|
||||
<th>Full name</th>
|
||||
<th>Orga</th>
|
||||
<th>Reviews</th>
|
||||
<th>Conversations</th>
|
||||
</tr>
|
||||
{% for participation in participation_list %}
|
||||
<tr>
|
||||
<td><a href="{{ participation.get_absolute_url }}">{{ participation.user.username }}</a></td>
|
||||
<td>{{ participation.user.get_full_name }}</td>
|
||||
<td>{{ participation.is_orga|yesno:"✔,✘" }}</td>
|
||||
<td>{% for topic in participation.topic_set.all %}{{ topic.get_link }}{% if not forloop.last %},
|
||||
{% endif %}{% endfor %}</td>
|
||||
<td>
|
||||
<a href="{% url 'user-conversation' participation.user.username %}" data-toggle="tooltip" data-placement="bottom"
|
||||
title="{% trans "View conversation" %}"><span class="glyphicon glyphicon-envelope"></span></a>
|
||||
{% if request.user in participation.conversation.subscribers.all %}
|
||||
<a href="{% url 'unsubscribe-conversation' participation.user.username %}?next={% url 'list-participants' %}"
|
||||
data-toggle="tooltip" data-placement="bottom" title="{% trans "Unsubscribe from the conversation" %}">
|
||||
<span class="glyphicon glyphicon-star"></span></a>
|
||||
{% else %}
|
||||
<a href="{% url 'subscribe-conversation' participation.user.username %}?next={% url 'list-participants' %}"
|
||||
data-toggle="tooltip" data-placement="bottom" title="{% trans "Subscribe to the conversation" %}">
|
||||
<span class="glyphicon glyphicon-star-empty"></span></a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% if request|orga %}
|
||||
{% include "_form.html" %}
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ block.css }}
|
||||
{{ form.media.css }}
|
||||
{% endblock %}
|
||||
|
||||
{% block js_end %}
|
||||
{{ block.super }}
|
||||
{{ form.media.js }}
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -1,65 +0,0 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% load bootstrap3 i18n avatar_tags %}
|
||||
|
||||
{% block profiletab %} class="active"{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3>{% trans "Profile" %}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label" for="id_first_name">Avatar</label>
|
||||
{% avatar request.user %}
|
||||
<a href="{% url 'avatar_change' %}" class="btn btn-default">{% trans "Change avatar" %}</a>
|
||||
</div>
|
||||
{% bootstrap_form user_form layout="horizontal" %}
|
||||
{% bootstrap_form profile_form layout="horizontal" %}
|
||||
{% bootstrap_field participation_form.need_transport layout="horizontal" %}
|
||||
<div id="transport_fields">
|
||||
{% bootstrap_field participation_form.transport layout="horizontal" %}
|
||||
{% bootstrap_field participation_form.transport_city_outward layout="horizontal" %}
|
||||
{% bootstrap_field participation_form.transport_city_return layout="horizontal" %}
|
||||
</div>
|
||||
{% bootstrap_form participation_form exclude="need_transport,transport,transport_city_outward,transport_city_return" layout="horizontal" %}
|
||||
{% buttons layout="horizontal" %}
|
||||
<button type="submit" class="btn btn-primary">{% trans "Submit" %}</button>
|
||||
{% for url, class, text in buttons %}
|
||||
<a href="{% url url %}" class="btn btn-{{ class }}">{{ text }}</a>
|
||||
{% endfor %}
|
||||
<a href="{% if request.META.HTTP_REFERER %}{{ request.META.HTTP_REFERER }}{% else %}{% url 'home' %}{% endif %}" class="btn btn-default">{% trans "Cancel" %}</a>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ block.super }}
|
||||
{{ form.media.css }}
|
||||
{% endblock %}
|
||||
|
||||
{% block js_end %}
|
||||
{{ block.super }}
|
||||
{{ form.media.js }}
|
||||
<script type="text/javascript">
|
||||
var update_transport = function() {
|
||||
if ($('#id_need_transport').val() == 2) { // 2 == 'Yes'
|
||||
$("#transport_fields").show();
|
||||
} else {
|
||||
$("#transport_fields").hide();
|
||||
}
|
||||
}
|
||||
$(function(){
|
||||
update_transport();
|
||||
$('#id_need_transport').change(update_transport);
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -1,14 +0,0 @@
|
|||
{% extends "avatar/base.html" %}
|
||||
{% load i18n avatar_tags %}
|
||||
|
||||
{% block avatarcontent %}
|
||||
<p>{% trans "Your current avatar: " %}</p>
|
||||
{% avatar user %}
|
||||
{% if not avatars %}
|
||||
<p>{% trans "You haven't uploaded an avatar yet. Please upload one now." %}</p>
|
||||
{% endif %}
|
||||
<form enctype="multipart/form-data" method="POST" action="{% url 'avatar_add' %}">
|
||||
{{ upload_avatar_form.as_p }}
|
||||
<p>{% csrf_token %}<input type="submit" value="{% trans "Upload New Image" %}" /></p>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -1 +0,0 @@
|
|||
<img src="{{ url }}" alt="{{ alt }}" width="{{ size }}" height="{{ size }}" />
|
|
@ -1,20 +0,0 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block profiletab %} class="active"{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3>{% trans "Avatar" %}
|
||||
<a href="{% url 'profile' %}" class="btn btn-primary pull-right"><span class="glyphicon glyphicon-arrow-left"> {% trans "Back to profile" %}</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% block avatarcontent %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -1,21 +0,0 @@
|
|||
{% extends "avatar/base.html" %}
|
||||
{% load i18n avatar_tags %}
|
||||
|
||||
{% block avatarcontent %}
|
||||
<p>{% trans "Your current avatar: " %}</p>
|
||||
{% avatar user %}
|
||||
{% if not avatars %}
|
||||
<p>{% trans "You haven't uploaded an avatar yet. Please upload one now." %}</p>
|
||||
{% else %}
|
||||
<form method="POST" action="{% url 'avatar_change' %}">
|
||||
<ul>
|
||||
{{ primary_avatar_form.as_ul }}
|
||||
</ul>
|
||||
<p>{% csrf_token %}<input type="submit" value="{% trans "Choose new Default" %}" /></p>
|
||||
</form>
|
||||
{% endif %}
|
||||
<form enctype="multipart/form-data" method="POST" action="{% url 'avatar_add' %}">
|
||||
{{ upload_avatar_form.as_p }}
|
||||
<p>{% csrf_token %}<input type="submit" value="{% trans "Upload New Image" %}" /></p>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -1,17 +0,0 @@
|
|||
{% extends "avatar/base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block avatarcontent %}
|
||||
<p>{% trans "Please select the avatars that you would like to delete." %}</p>
|
||||
{% if not avatars %}
|
||||
{% url 'avatar_change' as avatar_change_url %}
|
||||
<p>{% blocktrans %}You have no avatars to delete. Please <a href="{{ avatar_change_url }}">upload one</a> now.{% endblocktrans %}</p>
|
||||
{% else %}
|
||||
<form method="POST" action="{% url 'avatar_delete' %}">
|
||||
<ul>
|
||||
{{ delete_avatar_form.as_ul }}
|
||||
</ul>
|
||||
<p>{% csrf_token %}<input type="submit" value="{% trans "Delete These" %}" /></p>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -1,20 +0,0 @@
|
|||
from django import template
|
||||
|
||||
from accounts.utils import can_edit_profile, is_orga, is_staff
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def orga(request):
|
||||
return is_orga(request, request.user)
|
||||
|
||||
|
||||
@register.filter
|
||||
def staff(request):
|
||||
return is_staff(request, request.user)
|
||||
|
||||
|
||||
@register.filter
|
||||
def edit_profile(request, profile):
|
||||
return can_edit_profile(request, profile)
|
|
@ -1,108 +0,0 @@
|
|||
from django.contrib.auth.models import User
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.test import TestCase
|
||||
|
||||
from .models import Participation, Profile
|
||||
|
||||
ROOT_URL = 'accounts'
|
||||
|
||||
|
||||
class AccountTests(TestCase):
|
||||
def setUp(self):
|
||||
a, b, c = (User.objects.create_user(guy, email='%s@example.org' % guy, password=guy) for guy in 'abc')
|
||||
Participation.objects.create(user=a, site=Site.objects.first())
|
||||
Participation.objects.create(user=b, site=Site.objects.first())
|
||||
Participation.objects.create(user=c, site=Site.objects.first(), orga=True)
|
||||
|
||||
def test_models(self):
|
||||
self.assertEqual(Profile.objects.count(), 3)
|
||||
self.client.login(username='c', password='c')
|
||||
for model in [Profile, Participation]:
|
||||
item = model.objects.first()
|
||||
self.assertEqual(self.client.get(item.full_link()).status_code, 200)
|
||||
self.assertTrue(str(item))
|
||||
|
||||
def test_views(self):
|
||||
# User b wants to update its username, email and biography
|
||||
user = User.objects.get(username='b')
|
||||
self.assertEqual(user.email, 'b@example.org')
|
||||
self.assertEqual(user.profile.biography, '')
|
||||
|
||||
self.client.login(username='b', password='b')
|
||||
|
||||
# He tries with an invalid address
|
||||
self.client.post(reverse('profile'), {'email': 'bnewdomain.com', 'username': 'z', 'biography': 'tester',
|
||||
'video_licence': 1})
|
||||
self.assertEqual(User.objects.filter(username='z').count(), 0)
|
||||
|
||||
self.client.post(reverse('profile'), {'email': 'b@newdomain.com', 'username': 'z', 'biography': 'tester',
|
||||
'video_licence': 1})
|
||||
|
||||
user = User.objects.get(username='z')
|
||||
self.assertEqual(user.email, 'b@newdomain.com')
|
||||
self.assertEqual(user.profile.biography, 'tester')
|
||||
self.client.logout()
|
||||
|
||||
def test_participant_views(self):
|
||||
self.assertEqual(self.client.get(reverse('registration_register')).status_code, 200)
|
||||
self.client.login(username='b', password='b')
|
||||
self.assertEqual(self.client.get(reverse('list-participants')).status_code, 403)
|
||||
self.assertEqual(self.client.post(reverse('edit-participant', kwargs={'username': 'a'}),
|
||||
{'biography': 'foo'}).status_code, 403)
|
||||
b = User.objects.get(username='b')
|
||||
b.is_superuser = True
|
||||
b.save()
|
||||
p = Participation.objects.get(user=b)
|
||||
self.assertFalse(p.orga)
|
||||
self.assertEqual(self.client.get(reverse('list-participants')).status_code, 403)
|
||||
# login signal should set orga to True due to superuser status
|
||||
self.client.login(username='b', password='b')
|
||||
p = Participation.objects.get(user=b)
|
||||
self.assertTrue(p.orga)
|
||||
self.assertEqual(self.client.get(reverse('list-participants')).status_code, 200)
|
||||
self.assertEqual(self.client.post(reverse('edit-participant', kwargs={'username': 'a'}),
|
||||
{'biography': 'foo', 'nootes': 'bar'}).status_code, 200)
|
||||
self.assertEqual(User.objects.get(username='a').profile.biography, '')
|
||||
self.assertEqual(self.client.post(reverse('edit-participant', kwargs={'username': 'a'}),
|
||||
{'biography': 'foo', 'notes': 'bar', 'first_name': 'Jules', 'username': 'a',
|
||||
'last_name': 'César', 'email': 'a@example.org', 'transport': 1,
|
||||
'connector': 1, 'video_licence': 2, 'constraints': 'nope', 'orga': 0,
|
||||
}).status_code, 200)
|
||||
self.assertEqual(User.objects.get(username='a').profile.biography, 'foo')
|
||||
self.assertEqual(Participation.objects.get(user=User.objects.get(username='a')).video_licence, 2)
|
||||
|
||||
|
||||
from datetime import datetime
|
||||
from .models import AvailabilityTimeslot
|
||||
class DisponibilitiesTests(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.user = User.objects.create_user('a', email='a@example.org', password='a')
|
||||
self.participation = Participation.objects.create(user=self.user, site=Site.objects.first())
|
||||
|
||||
def test_is_available(self):
|
||||
from django.utils.timezone import is_naive, get_default_timezone
|
||||
tz = get_default_timezone()
|
||||
d = {}
|
||||
for i in range(8, 18, 1):
|
||||
d[i] = datetime(2016, 10, 10, i, 0, 0, tzinfo=tz)
|
||||
self.assertEquals(self.participation.is_available(d[10]), None)
|
||||
AvailabilityTimeslot.objects.create(participation=self.participation, start=d[10], end=d[12])
|
||||
self.assertEquals(self.participation.is_available(d[9]), False)
|
||||
self.assertEquals(self.participation.is_available(d[11]), True)
|
||||
self.assertEquals(self.participation.is_available(d[13]), False)
|
||||
self.assertEquals(self.participation.is_available(d[8], d[9]), False)
|
||||
self.assertEquals(self.participation.is_available(d[9], d[11]), False)
|
||||
self.assertEquals(self.participation.is_available(d[10], d[11]), True)
|
||||
self.assertEquals(self.participation.is_available(d[11], d[12]), True)
|
||||
self.assertEquals(self.participation.is_available(d[10], d[12]), True)
|
||||
self.assertEquals(self.participation.is_available(d[11], d[13]), False)
|
||||
self.assertEquals(self.participation.is_available(d[13], d[14]), False)
|
||||
AvailabilityTimeslot.objects.create(participation=self.participation, start=d[14], end=d[16])
|
||||
self.assertEquals(self.participation.is_available(d[10], d[12]), True)
|
||||
self.assertEquals(self.participation.is_available(d[14], d[16]), True)
|
||||
self.assertEquals(self.participation.is_available(d[11], d[15]), False)
|
||||
self.assertEquals(self.participation.is_available(d[11], d[17]), False)
|
||||
self.assertEquals(self.participation.is_available(d[13], d[17]), False)
|
||||
self.assertEquals(self.participation.is_available(d[9], d[15]), False)
|
|
@ -1,18 +0,0 @@
|
|||
from django.conf import settings
|
||||
from django.conf.urls import include, url
|
||||
from django.contrib.auth import views as auth_views
|
||||
|
||||
#from . import views
|
||||
|
||||
urlpatterns = [
|
||||
#url(r'^profile/$', views.profile, name='profile'),
|
||||
#url(r'^login/$', auth_views.login, {'extra_context': {'buttons': [views.RESET_PASSWORD_BUTTON]}}, name='login'),
|
||||
url(r'^login/$', auth_views.login, name='login'),
|
||||
url(r'^logout/$', auth_views.logout, {'next_page': settings.LOGOUT_REDIRECT_URL}, name='logout'),
|
||||
#url(r'^participant/$', views.participation_list, name='list-participants'),
|
||||
#url(r'^participant/(?P<username>[\w.@+-]+)$', views.participant_details, name='show-participant'),
|
||||
#url(r'^participant/(?P<username>[\w.@+-]+)/edit/$', views.participant_edit, name='edit-participant'),
|
||||
#url(r'^avatar/', include('avatar.urls')),
|
||||
url(r'', include('django.contrib.auth.urls')),
|
||||
#url(r'', include('registration.backends.default.urls')),
|
||||
]
|
|
@ -1,102 +0,0 @@
|
|||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .decorators import staff_required
|
||||
from .forms import (NewParticipationForm, ParticipationForm,
|
||||
ParticipationOrgaForm, ProfileForm, ProfileOrgaForm, UserForm)
|
||||
from .models import Participation, Profile, User
|
||||
from .utils import can_edit_profile, is_orga
|
||||
|
||||
from proposals.models import Talk
|
||||
from proposals.utils import allowed_talks
|
||||
|
||||
RESET_PASSWORD_BUTTON = ('password_reset', 'warning', _('Reset your password'))
|
||||
CHANGE_PASSWORD_BUTTON = ('password_change', 'warning', _('Change password'))
|
||||
CHANGE_AVATAR_BUTTON = ('avatar_change', 'default', _('Change avatar'))
|
||||
|
||||
|
||||
@login_required
|
||||
def profile(request):
|
||||
|
||||
user_form = UserForm(request.POST or None, instance=request.user)
|
||||
profile_form = ProfileForm(request.POST or None, instance=request.user.profile)
|
||||
participation_form = ParticipationForm(request.POST or None, instance=Participation.objects.get(site=get_current_site(request),
|
||||
user=request.user))
|
||||
forms = [user_form, profile_form, participation_form]
|
||||
|
||||
if request.method == 'POST':
|
||||
if all(form.is_valid() for form in forms):
|
||||
for form in forms:
|
||||
form.save()
|
||||
messages.success(request, _('Profile updated successfully.'))
|
||||
else:
|
||||
messages.error(request, _('Please correct those errors.'))
|
||||
|
||||
return render(request, 'accounts/profile.html', {
|
||||
'user_form': user_form,
|
||||
'profile_form': profile_form,
|
||||
'participation_form': participation_form,
|
||||
'buttons': [CHANGE_PASSWORD_BUTTON]
|
||||
})
|
||||
|
||||
|
||||
@login_required
|
||||
def participant_edit(request, username):
|
||||
|
||||
profile = get_object_or_404(Profile, user__username=username)
|
||||
if not can_edit_profile(request, profile):
|
||||
raise PermissionDenied()
|
||||
|
||||
participation_form = ParticipationOrgaForm if is_orga(request, request.user) else ParticipationForm
|
||||
forms = [UserForm(request.POST or None, instance=profile.user),
|
||||
ProfileOrgaForm(request.POST or None, instance=profile),
|
||||
participation_form(request.POST or None,
|
||||
instance=Participation.objects.get(site=get_current_site(request), user=profile.user))]
|
||||
|
||||
if request.method == 'POST':
|
||||
if all(form.is_valid() for form in forms):
|
||||
for form in forms:
|
||||
form.save()
|
||||
messages.success(request, _('Profile updated successfully.'))
|
||||
else:
|
||||
messages.error(request, _('Please correct those errors.'))
|
||||
|
||||
return render(request, 'accounts/participant_edit.html', {'forms': forms, 'profile': profile})
|
||||
|
||||
|
||||
@staff_required
|
||||
def participation_list(request):
|
||||
participation_list = Participation.objects.filter(site=get_current_site(request)).all()
|
||||
form = NewParticipationForm(request.POST or None, site=get_current_site(request))
|
||||
|
||||
if request.method == 'POST' and form.is_valid():
|
||||
if not Participation.objects.get(user=request.user, site=get_current_site(request)).is_orga():
|
||||
raise PermissionDenied()
|
||||
user = User.objects.get(username=form.cleaned_data['participant'])
|
||||
participation, created = Participation.objects.get_or_create(user=user, site=get_current_site(request))
|
||||
if created:
|
||||
messages.success(request, _("%(name)s added to participants") % {'name': user.profile})
|
||||
else:
|
||||
messages.info(request, _("%(name)s is already a participant") % {'name': user.profile})
|
||||
return redirect(reverse('list-participants'))
|
||||
|
||||
return render(request, 'accounts/participant_list.html', {
|
||||
'participation_list': participation_list,
|
||||
'form': form,
|
||||
})
|
||||
|
||||
|
||||
@login_required
|
||||
def participant_details(request, username):
|
||||
user = get_object_or_404(User, username=username)
|
||||
participation = get_object_or_404(Participation, user=user, site=get_current_site(request))
|
||||
return render(request, 'accounts/participant_details.html', {
|
||||
'profile': user.profile,
|
||||
'participation': participation,
|
||||
'talk_list': allowed_talks(Talk.objects.filter(site=get_current_site(request), speakers=user), request),
|
||||
})
|
Loading…
Reference in New Issue