Allow creating, listing and leaving groups

This commit is contained in:
Gabriel Augendre 2019-03-03 18:45:47 +01:00
parent 81fa2ad19d
commit 9103545a23
11 changed files with 187 additions and 5 deletions

View file

@ -1,7 +1,8 @@
from django.contrib import admin from django.contrib import admin
from django.contrib.admin import register from django.contrib.admin import register
from django.contrib.auth.admin import UserAdmin from django.contrib.auth.admin import UserAdmin
from .models import Friend, FriendLocation
from .models import Friend, FriendLocation, LocationSharingGroup
admin.site.register(Friend, UserAdmin) admin.site.register(Friend, UserAdmin)
@ -13,3 +14,10 @@ class FriendLocationAdmin(admin.ModelAdmin):
('Place', {'fields': ('latitude', 'longitude')}), ('Place', {'fields': ('latitude', 'longitude')}),
('Dates', {'fields': ('start_date', 'end_date')}), ('Dates', {'fields': ('start_date', 'end_date')}),
] ]
@register(LocationSharingGroup)
class LocationSharingGroupAdmin(admin.ModelAdmin):
list_display = [
'name',
]

View file

@ -0,0 +1,22 @@
# Generated by Django 2.1.7 on 2019-03-03 16:57
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('map', '0006_auto_20190303_1308'),
]
operations = [
migrations.CreateModel(
name='LocationSharingGroup',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=250)),
('friends', models.ManyToManyField(related_name='location_sharing_groups', to=settings.AUTH_USER_MODEL)),
],
),
]

View file

@ -0,0 +1,19 @@
# Generated by Django 2.1.7 on 2019-03-03 17:34
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('map', '0007_locationsharinggroup'),
]
operations = [
migrations.AlterField(
model_name='locationsharinggroup',
name='friends',
field=models.ManyToManyField(blank=True, related_name='location_sharing_groups', to=settings.AUTH_USER_MODEL),
),
]

View file

@ -53,3 +53,8 @@ class FriendLocation(BaseModel):
html += f' until {self.end_date}' html += f' until {self.end_date}'
return html return html
class LocationSharingGroup(models.Model):
name = models.CharField(max_length=250)
friends = models.ManyToManyField(Friend, related_name='location_sharing_groups', blank=True)

View file

@ -6,3 +6,7 @@
.messages-container { .messages-container {
margin-top: 1em; margin-top: 1em;
} }
#quick-actions {
margin-bottom: 1em;
}

View file

@ -45,7 +45,7 @@
</div> </div>
{% block quick_actions %} {% block quick_actions %}
{% if quick_actions %} {% if quick_actions %}
<div class="row"> <div class="row" id="quick-actions">
<div class="col-12 d-none d-md-block"> {# Visible only on large screens #} <div class="col-12 d-none d-md-block"> {# Visible only on large screens #}
{% for qa in quick_actions %} {% for qa in quick_actions %}
<a href="{{ qa.url }}" class="btn btn-{{ qa.category }}"> <a href="{{ qa.url }}" class="btn btn-{{ qa.category }}">

View file

@ -0,0 +1,19 @@
{% extends 'map/base.html' %}
{% load crispy_forms_filters %}
{% block title %}Create a group{% endblock %}
{% block h1 %}Create a group{% endblock %}
{% block content %}
<div class="alert alert-info">
<h4 class="alert-heading">Notice</h4>
<div>
All members in this group can see your location.
</div>
</div>
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Create</button>
</form>
{% endblock %}

View file

@ -0,0 +1,20 @@
{% extends 'map/base.html' %}
{% load crispy_forms_filters %}
{% block title %}Leave a group{% endblock %}
{% block h1 %}Leave a group{% endblock %}
{% block content %}
<div class="alert alert-warning">
<h4 class="alert-heading">Are you sure?</h4>
<div>
If you leave this group you will not be able to see the location of people in the group.
If you're the last member of the group, it will be deleted.
</div>
</div>
<form method="post">
{% csrf_token %}
<button type="submit" class="btn btn-warning">Yes, I'm sure</button>
<a href="{% url 'manage-groups' %}" class="btn btn-secondary">No, cancel</a>
</form>
{% endblock %}

View file

@ -0,0 +1,27 @@
{% extends 'map/base.html' %}
{% load crispy_forms_filters %}
{% block title %}Manage your groups{% endblock %}
{% block h1 %}Manage your groups{% endblock %}
{% block content %}
<div class="alert alert-info">
<h4 class="alert-heading">Notice</h4>
<div>
Here you can list and manage groups you belong to. All members in these groups can see your location.
</div>
</div>
<ul class="list-group">
{% for group in groups %}
<li class="list-group-item d-flex justify-content-between align-items-center">
{{ group.name }}
<span>
<span class="badge badge-secondary badge-pill">{{ group.friends.count }}</span>
<a href="{% url 'leave-group' group.pk %}" class="btn btn-sm btn-secondary">Leave</a>
</span>
</li>
{% endfor %}
</ul>
{% endblock %}

View file

@ -7,6 +7,9 @@ urlpatterns = [
path('change-location', views.EditLocationView.as_view(), name='change-location'), path('change-location', views.EditLocationView.as_view(), name='change-location'),
path('add-location', views.AddLocationView.as_view(), name='add-location'), path('add-location', views.AddLocationView.as_view(), name='add-location'),
path('delete-location', views.DeleteLocationView.as_view(), name='delete-location'), path('delete-location', views.DeleteLocationView.as_view(), name='delete-location'),
path('manage-groups', views.ManageGroupsView.as_view(), name='manage-groups'),
path('add-group', views.CreateGroupView.as_view(), name='add-group'),
path('leave-group/<int:pk>', views.LeaveGroupView.as_view(), name='leave-group'),
path('accounts/profile', views.UpdateProfileView.as_view(), name='change-profile'), path('accounts/profile', views.UpdateProfileView.as_view(), name='change-profile'),
path('accounts/profile/delete', views.DeleteProfileView.as_view(), name='delete-profile'), path('accounts/profile/delete', views.DeleteProfileView.as_view(), name='delete-profile'),
] ]

View file

@ -15,7 +15,7 @@ class MapView(LoginRequiredMixin, QuickActionsMixin, generic.ListView):
def get_quick_actions(self): def get_quick_actions(self):
if hasattr(self.request.user, 'location'): if hasattr(self.request.user, 'location'):
return [{ actions = [{
'url': reverse_lazy('change-location'), 'url': reverse_lazy('change-location'),
'category': 'primary', 'category': 'primary',
'display': f'Change your location' 'display': f'Change your location'
@ -25,12 +25,20 @@ class MapView(LoginRequiredMixin, QuickActionsMixin, generic.ListView):
'display': f'Delete your location' 'display': f'Delete your location'
}] }]
else: else:
return [{ actions = [{
'url': reverse_lazy('add-location'), 'url': reverse_lazy('add-location'),
'category': 'primary', 'category': 'primary',
'display': f'Add your location' 'display': f'Add your location'
}] }]
actions.append({
'url': reverse_lazy('manage-groups'),
'category': 'secondary',
'display': f'Manage your groups'
})
return actions
class EditLocationView(LoginRequiredMixin, generic.UpdateView): class EditLocationView(LoginRequiredMixin, generic.UpdateView):
model = models.FriendLocation model = models.FriendLocation
@ -121,3 +129,50 @@ class DeleteProfileView(LoginRequiredMixin, generic.DeleteView):
def get_success_url(self): def get_success_url(self):
messages.success(self.request, 'Your profile has been successfully and permanently deleted') messages.success(self.request, 'Your profile has been successfully and permanently deleted')
return super().get_success_url() return super().get_success_url()
class ManageGroupsView(LoginRequiredMixin, QuickActionsMixin, generic.ListView):
model = models.LocationSharingGroup
context_object_name = 'groups'
template_name = 'map/list_groups.html'
def get_queryset(self):
return self.request.user.location_sharing_groups.all()
def get_quick_actions(self):
return [{
'url': reverse_lazy('add-group'),
'category': 'primary',
'display': 'Create a group'
}]
class CreateGroupView(LoginRequiredMixin, QuickActionsMixin, generic.CreateView):
model = models.LocationSharingGroup
context_object_name = 'group'
template_name = 'map/change_group.html'
success_url = reverse_lazy('manage-groups')
fields = [
'name'
]
def get_success_url(self):
self.object.friends.add(self.request.user)
messages.success(self.request, 'The group has been successfully created')
return super().get_success_url()
class LeaveGroupView(LoginRequiredMixin, generic.UpdateView):
model = models.LocationSharingGroup
context_object_name = 'group'
template_name = 'map/leave_group.html'
fields = []
success_url = reverse_lazy('manage-groups')
def get_success_url(self):
self.object.friends.remove(self.request.user)
if self.object.friends.count() == 0:
self.object.delete()
messages.success(self.request, 'You successfully left the group')
return super().get_success_url()