Add ability to join a team as a member, migrate team owners to admin members, add Attendee objects
This commit is contained in:
parent
386d757fe9
commit
b29eaf5457
12 changed files with 162 additions and 13 deletions
|
@ -2,9 +2,9 @@ from django.contrib import admin
|
|||
|
||||
# Register your models here.
|
||||
from .models.locale import Language, Continent, Country, SPR, City
|
||||
from .models.profiles import UserProfile, Organization, Team
|
||||
from .models.profiles import UserProfile, Organization, Team, Member
|
||||
from .models.search import Searchable
|
||||
from .models.events import Place, Event
|
||||
from .models.events import Place, Event, Attendee
|
||||
|
||||
admin.site.register(Language)
|
||||
admin.site.register(Continent)
|
||||
|
@ -42,4 +42,6 @@ class EventAdmin(admin.ModelAdmin):
|
|||
raw_id_fields = ('place', 'created_by')
|
||||
admin.site.register(Event, EventAdmin)
|
||||
|
||||
admin.site.register(Member)
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,13 @@ import datetime
|
|||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
ADMIN=2
|
||||
|
||||
def make_owner_admin(apps, schema_editor):
|
||||
Team = apps.get_model('events', 'Team')
|
||||
Member = apps.get_model('events', 'Member')
|
||||
for team in Team.objects.all():
|
||||
Member.objects.get_or_create(team=team, user=team.owner_profile, role=ADMIN, joined_date=team.created_date or datetime.datetime.now())
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
|
@ -27,4 +34,5 @@ class Migration(migrations.Migration):
|
|||
name='members',
|
||||
field=models.ManyToManyField(blank=True, related_name='memberships', through='events.Member', to='events.UserProfile'),
|
||||
),
|
||||
migrations.RunPython(make_owner_admin),
|
||||
]
|
||||
|
|
36
events/migrations/0006_auto_20180124_0303.py
Normal file
36
events/migrations/0006_auto_20180124_0303.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
# Generated by Django 2.0 on 2018-01-24 03:03
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('events', '0005_auto_20180108_2221'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Attendee',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('role', models.SmallIntegerField(choices=[(0, 'Normal'), (1, 'Crew'), (2, 'Host')], db_index=True, default=0, verbose_name='Role')),
|
||||
('status', models.SmallIntegerField(choices=[(-1, 'No'), (0, 'Maybe'), (1, 'Yes')], db_index=True, verbose_name='Attending?')),
|
||||
('joined_date', models.DateTimeField(default=datetime.datetime.now)),
|
||||
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='events.Event')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='events.UserProfile')),
|
||||
],
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='team',
|
||||
name='name',
|
||||
field=models.CharField(max_length=256, verbose_name='Team Name'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='attendees',
|
||||
field=models.ManyToManyField(blank=True, related_name='attending', through='events.Attendee', to='events.UserProfile'),
|
||||
),
|
||||
]
|
|
@ -68,6 +68,8 @@ class Event(models.Model):
|
|||
#image
|
||||
#replies
|
||||
|
||||
attendees = models.ManyToManyField(UserProfile, through='Attendee', related_name="attending", blank=True)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('show-event', kwargs={'event_id': self.id, 'event_slug': self.slug})
|
||||
|
||||
|
@ -105,7 +107,7 @@ def update_event_searchable(event):
|
|||
searchable.longitude = event.place.longitude or None
|
||||
searchable.latitude = event.place.latitude
|
||||
else:
|
||||
searchable.location_name = ""
|
||||
searchable.location_name = team.location_name
|
||||
searchable.longitude = None
|
||||
searchable.latitude = None
|
||||
searchable.save()
|
||||
|
@ -124,3 +126,26 @@ def slugify(s, ok=SLUG_OK, lower=True, spaces=False):
|
|||
if not spaces:
|
||||
new = re.sub('[-\s]+', '-', new)
|
||||
return new.lower() if lower else new
|
||||
|
||||
class Attendee(models.Model):
|
||||
NORMAL=0
|
||||
CREW=1
|
||||
HOST=2
|
||||
ROLES = [
|
||||
(NORMAL, _("Normal")),
|
||||
(CREW, _("Crew")),
|
||||
(HOST, _("Host"))
|
||||
]
|
||||
NO=-1
|
||||
MAYBE=0
|
||||
YES=1
|
||||
STATUSES = [
|
||||
(NO, _("No")),
|
||||
(MAYBE, _("Maybe")),
|
||||
(YES, _("Yes")),
|
||||
]
|
||||
event = models.ForeignKey(Event, on_delete=models.CASCADE)
|
||||
user = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
|
||||
role = models.SmallIntegerField(_("Role"), choices=ROLES, default=NORMAL, db_index=True)
|
||||
status = models.SmallIntegerField(_("Attending?"), choices=STATUSES, db_index=True)
|
||||
joined_date = models.DateTimeField(default=datetime.datetime.now)
|
||||
|
|
|
@ -175,3 +175,11 @@ class Member(models.Model):
|
|||
user = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
|
||||
role = models.SmallIntegerField(_("Member Role"), choices=ROLES, default=NORMAL, db_index=True)
|
||||
joined_date = models.DateTimeField(default=datetime.datetime.now)
|
||||
|
||||
@property
|
||||
def role_name(self):
|
||||
print("Role name: %s=%s" % (self.role, Member.ROLES[self.role]))
|
||||
return Member.ROLES[self.role][1]
|
||||
|
||||
def __str__(self):
|
||||
return '%s in %s' % (self.user, self.team)
|
||||
|
|
15
events/templates/events/member_list.html
Normal file
15
events/templates/events/member_list.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
{% if member_list %}
|
||||
<table border="0" width="960px">
|
||||
{% for member in member_list %}
|
||||
<tr>
|
||||
<td>{{ member.user }}</td>
|
||||
<td>{{ member.joined_date }}</td>
|
||||
<td>{% if member.role > 0 %}{{ member.role_name }}{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<p>No members yet.</p>
|
||||
{% endif %}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
from django.shortcuts import render
|
||||
from django.shortcuts import render, redirect
|
||||
from django.http import HttpResponse, JsonResponse
|
||||
from django.contrib import messages
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from rest_framework.decorators import api_view, throttle_classes
|
||||
from rest_framework.response import Response
|
||||
|
@ -7,6 +9,7 @@ from rest_framework.response import Response
|
|||
from .models.search import Searchable, SearchableSerializer
|
||||
from .models.events import Event, Place, PlaceSerializer
|
||||
from .models.locale import Country ,CountrySerializer, SPR, SPRSerializer, City, CitySerializer
|
||||
from .models.profiles import Team, UserProfile, Member
|
||||
|
||||
import simplejson
|
||||
|
||||
|
@ -71,3 +74,27 @@ def city_list(request, *args, **kwargs):
|
|||
serializer = CitySerializer(cities, many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
def join_team(request, team_id):
|
||||
if request.user.is_anonymous:
|
||||
messages.add_message(request, messages.WARNING, message=_('You must be logged in to join a team.'))
|
||||
return redirect('show-team', team_id=team_id)
|
||||
team = Team.objects.get(id=team_id)
|
||||
if request.user.profile in team.members.all():
|
||||
messages.add_message(request, messages.INFO, message=_('You are already a member of this team.'))
|
||||
return redirect('show-team', team_id=team_id)
|
||||
new_member = Member.objects.create(team=team, user=request.user.profile, role=Member.NORMAL)
|
||||
messages.add_message(request, messages.SUCCESS, message=_('Welcome to the team!'))
|
||||
return redirect('show-team', team_id=team_id)
|
||||
|
||||
def leave_team(request, team_id):
|
||||
if request.user.is_anonymous:
|
||||
messages.add_message(request, messages.WARNING, message=_('You must be logged in to leave a team.'))
|
||||
return redirect('show-team', team_id=team_id)
|
||||
team = Team.objects.get(id=team_id)
|
||||
if request.user.profile not in team.members.all():
|
||||
messages.add_message(request, messages.INFO, message=_('You are not a member of this team.'))
|
||||
return redirect('show-team', team_id=team_id)
|
||||
Member.objects.filter(team=team, user=request.user.profile).delete()
|
||||
messages.add_message(request, messages.SUCCESS, message=_('You are no longer on this team.'))
|
||||
return redirect('show-team', team_id=team_id)
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
{% block content %}
|
||||
<h2>Update {{team.name}}</h2>
|
||||
<form action="{% url "create-team" %}" method="post">
|
||||
<form action="{% url "edit-team" team.id %}" method="post">
|
||||
{% csrf_token %}
|
||||
{% include "events/team_form.html" %}
|
||||
<br />
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
{% block content %}
|
||||
<h2>Welcome to {{ team.name }}</h2>
|
||||
|
||||
<h4>Members</h4>
|
||||
{% include "events/member_list.html" %}
|
||||
<br/>
|
||||
|
||||
<h4>Upcoming Events</h4>
|
||||
{% include "events/event_list.html" %}
|
||||
{% if can_create_event %}
|
||||
|
@ -17,5 +21,15 @@
|
|||
<button type="submit" class="btn btn-secondary">Edit Team</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% if is_member %}
|
||||
<form action="{% url 'leave-team' team.id %}" method="get">
|
||||
<button type="submit" class="btn btn-danger">Leave Team</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<form action="{% url 'join-team' team.id %}" method="get">
|
||||
<button type="submit" class="btn btn-success">Join Team</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
{% extends "get_together/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
{% include "events/team_list.html" %}
|
||||
{% if my_teams %}
|
||||
<h4>My Teams</h4>
|
||||
{% include "events/team_list.html" with teams_list=my_teams %}
|
||||
<br/>
|
||||
{% endif %}
|
||||
|
||||
<h4>All Teams</h4>
|
||||
{% include "events/team_list.html" with teams_list=all_teams%}
|
||||
|
||||
{% if request.user.is_authenticated %}
|
||||
<br/>
|
||||
|
|
|
@ -32,16 +32,18 @@ urlpatterns = [
|
|||
path('api/cities/', event_views.city_list),
|
||||
|
||||
path('events/', views.events_list, name='events'),
|
||||
path('create-team/', views.create_team, name='create-team'),
|
||||
path('+create-team/', views.create_team, name='create-team'),
|
||||
path('teams/', views.teams_list, name='teams'),
|
||||
path('team/<int:team_id>/', views.show_team, name='show-team'),
|
||||
path('team/<int:team_id>/edit/', views.edit_team, name='edit-team'),
|
||||
path('team/<int:team_id>/create-event/', views.create_event, name='create-event'),
|
||||
path('events/<int:event_id>/edit/', views.edit_event, name='edit-event'),
|
||||
path('team/<int:team_id>/+edit/', views.edit_team, name='edit-team'),
|
||||
path('team/<int:team_id>/+join/', event_views.join_team, name='join-team'),
|
||||
path('team/<int:team_id>/+leave/', event_views.leave_team, name='leave-team'),
|
||||
path('team/<int:team_id>/+create-event/', views.create_event, name='create-event'),
|
||||
path('events/<int:event_id>/+edit/', views.edit_event, name='edit-event'),
|
||||
path('events/<int:event_id>/<str:event_slug>/', views.show_event, name='show-event'),
|
||||
|
||||
path('places/', views.places_list, name='places'),
|
||||
path('create-place/', views.create_place, name='create-place'),
|
||||
path('+create-place/', views.create_place, name='create-place'),
|
||||
|
||||
path('oauth/', include('social_django.urls', namespace='social')),
|
||||
]
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.contrib import messages
|
|||
from django.shortcuts import render, redirect
|
||||
from django.http import HttpResponse, JsonResponse
|
||||
|
||||
from events.models.profiles import Team
|
||||
from events.models.profiles import Team, UserProfile, Member
|
||||
from events.forms import TeamForm, NewTeamForm, TeamEventForm, NewTeamEventForm, NewPlaceForm
|
||||
|
||||
from events.models.events import Event, Place
|
||||
|
@ -45,6 +45,7 @@ def create_team(request, *args, **kwargs):
|
|||
new_team = form.save()
|
||||
new_team.owner_profile = request.user.profile
|
||||
new_team.save()
|
||||
Member.objects.create(team=new_team, user=request.user.profile, role=Member.ADMIN)
|
||||
return redirect('show-team', team_id=new_team.pk)
|
||||
else:
|
||||
context = {
|
||||
|
@ -87,8 +88,10 @@ def edit_team(request, team_id):
|
|||
def teams_list(request, *args, **kwargs):
|
||||
teams = Team.objects.all()
|
||||
context = {
|
||||
'teams_list': teams,
|
||||
'all_teams': teams,
|
||||
}
|
||||
if request.user.is_authenticated:
|
||||
context['my_teams'] = request.user.profile.memberships.all()
|
||||
return render(request, 'get_together/teams.html', context)
|
||||
|
||||
|
||||
|
@ -98,6 +101,8 @@ def show_team(request, team_id, *args, **kwargs):
|
|||
context = {
|
||||
'team': team,
|
||||
'events_list': team_events,
|
||||
'is_member': request.user.profile in team.members.all(),
|
||||
'member_list': Member.objects.filter(team=team),
|
||||
'can_create_event': request.user.profile.can_create_event(team),
|
||||
'can_edit_team': request.user.profile.can_edit_team(team),
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue