Allow creating, listing and leaving groups
This commit is contained in:
parent
81fa2ad19d
commit
9103545a23
11 changed files with 187 additions and 5 deletions
10
map/admin.py
10
map/admin.py
|
@ -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',
|
||||||
|
]
|
||||||
|
|
22
map/migrations/0007_locationsharinggroup.py
Normal file
22
map/migrations/0007_locationsharinggroup.py
Normal 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)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
19
map/migrations/0008_auto_20190303_1834.py
Normal file
19
map/migrations/0008_auto_20190303_1834.py
Normal 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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -5,4 +5,8 @@
|
||||||
|
|
||||||
.messages-container {
|
.messages-container {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#quick-actions {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
|
@ -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 }}">
|
||||||
|
|
19
map/templates/map/change_group.html
Normal file
19
map/templates/map/change_group.html
Normal 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 %}
|
20
map/templates/map/leave_group.html
Normal file
20
map/templates/map/leave_group.html
Normal 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 %}
|
27
map/templates/map/list_groups.html
Normal file
27
map/templates/map/list_groups.html
Normal 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 %}
|
|
@ -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'),
|
||||||
]
|
]
|
||||||
|
|
59
map/views.py
59
map/views.py
|
@ -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()
|
||||||
|
|
Loading…
Reference in a new issue