From ceb5690838660f5d69a916c0b9943c485573da1b Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 27 Mar 2020 18:02:22 +0100 Subject: [PATCH] Invite people --- apps/activity/forms.py | 30 ++++++++++++++++++- apps/activity/models.py | 33 +++++++++++++++++--- apps/activity/tables.py | 40 +++++++++++++++++++++++++ apps/activity/urls.py | 1 + apps/activity/views.py | 13 ++++++-- apps/member/forms.py | 1 - apps/note/urls.py | 1 - note_kfet/inputs.py | 6 ---- templates/activity/activity_invite.html | 15 ++++++++++ 9 files changed, 125 insertions(+), 15 deletions(-) create mode 100644 apps/activity/tables.py create mode 100644 templates/activity/activity_invite.html diff --git a/apps/activity/forms.py b/apps/activity/forms.py index 081f611c..6ef8a278 100644 --- a/apps/activity/forms.py +++ b/apps/activity/forms.py @@ -2,10 +2,13 @@ # SPDX-License-Identifier: GPL-3.0-or-later from django import forms -from activity.models import Activity +from django.contrib.contenttypes.models import ContentType from member.models import Club +from note.models import NoteUser from note_kfet.inputs import DateTimePickerInput, AutocompleteModelSelect +from .models import Activity, Guest + class ActivityForm(forms.ModelForm): class Meta: @@ -23,3 +26,28 @@ class ActivityForm(forms.ModelForm): "date_start": DateTimePickerInput(), "date_end": DateTimePickerInput(), } + + +class GuestForm(forms.ModelForm): + def clean(self, **kwargs): + cleaned_data = super().clean() + + self.instance.activity = cleaned_data["activity"] = Activity.objects.get(pk=1) + + return cleaned_data + + class Meta: + model = Guest + fields = ('last_name', 'first_name', 'inviter', ) + widgets = { + "inviter": AutocompleteModelSelect( + NoteUser, + attrs={ + 'api_url': '/api/note/note/', + # We don't evaluate the content type at launch because the DB might be not initialized + 'api_url_suffix': + lambda value: '&polymorphic_ctype=' + str(ContentType.objects.get_for_model(NoteUser).pk), + 'placeholder': 'Note ...', + }, + ), + } diff --git a/apps/activity/models.py b/apps/activity/models.py index 8f23060c..7151a2a0 100644 --- a/apps/activity/models.py +++ b/apps/activity/models.py @@ -1,9 +1,9 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later -from django.conf import settings from django.db import models from django.utils.translation import gettext_lazy as _ +from note.models import NoteUser class ActivityType(models.Model): @@ -77,6 +77,18 @@ class Activity(models.Model): verbose_name_plural = _("activities") +class Entry(models.Model): + time = models.DateTimeField( + verbose_name=_("entry time"), + ) + + note = models.ForeignKey( + NoteUser, + on_delete=models.PROTECT, + verbose_name=_("note"), + ) + + class Guest(models.Model): """ People who are not current members of any clubs, and are invited by someone who is a current member. @@ -86,17 +98,30 @@ class Guest(models.Model): on_delete=models.PROTECT, related_name='+', ) - name = models.CharField( + + last_name = models.CharField( max_length=255, + verbose_name=_("last name"), ) + + first_name = models.CharField( + max_length=255, + verbose_name=_("first name"), + ) + inviter = models.ForeignKey( - settings.AUTH_USER_MODEL, + NoteUser, on_delete=models.PROTECT, related_name='+', + verbose_name=_("inviter"), ) - entry = models.DateTimeField( + + entry = models.OneToOneField( + Entry, + on_delete=models.PROTECT, null=True, ) + entry_transaction = models.ForeignKey( 'note.Transaction', on_delete=models.PROTECT, diff --git a/apps/activity/tables.py b/apps/activity/tables.py new file mode 100644 index 00000000..44939bc4 --- /dev/null +++ b/apps/activity/tables.py @@ -0,0 +1,40 @@ +# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +from django.utils.translation import gettext_lazy as _ +from django_tables2 import tables, A + +from .models import Activity, Guest + + +class ActivityTable(tables.Table): + name = tables.columns.LinkColumn('activity:activity_detail', + args=[A('pk'), ],) + + invite = tables.columns.LinkColumn('activity:activity_invite', + args=[A('pk'), ], + verbose_name=_("Invite"), + text=_("Invite"),) + + class Meta: + attrs = { + 'class': 'table table-condensed table-striped table-hover' + } + model = Activity + template_name = 'django_tables2/bootstrap4.html' + fields = ('name', 'activity_type', 'organizer', 'attendees_club', 'date_start', 'date_end', 'invite', ) + + +class GuestTable(tables.Table): + class Meta: + attrs = { + 'class': 'table table-condensed table-striped table-hover' + } + model = Guest + template_name = 'django_tables2/bootstrap4.html' + fields = ('name', 'inviter', ) + row_attrs = { + 'class': 'table-row', + 'id': lambda record: "row-" + str(record.pk), + 'data-href': lambda record: record.pk + } diff --git a/apps/activity/urls.py b/apps/activity/urls.py index fc0b4850..006dcce3 100644 --- a/apps/activity/urls.py +++ b/apps/activity/urls.py @@ -10,6 +10,7 @@ app_name = 'activity' urlpatterns = [ path('', views.ActivityListView.as_view(), name='activity_list'), path('/', views.ActivityDetailView.as_view(), name='activity_detail'), + path('/invite/', views.ActivityInviteView.as_view(), name='activity_invite'), path('/entry/', views.ActivityEntryView.as_view(), name='activity_entry'), path('/update/', views.ActivityUpdateView.as_view(), name='activity_update'), path('new/', views.ActivityCreateView.as_view(), name='activity_create'), diff --git a/apps/activity/views.py b/apps/activity/views.py index be3db16d..03fa793f 100644 --- a/apps/activity/views.py +++ b/apps/activity/views.py @@ -7,8 +7,9 @@ from django.views.generic import CreateView, DetailView, UpdateView, TemplateVie from django.utils.translation import gettext_lazy as _ from django_tables2.views import SingleTableView -from .forms import ActivityForm -from .models import Activity +from .forms import ActivityForm, GuestForm +from .models import Activity, Guest +from .tables import ActivityTable class ActivityCreateView(LoginRequiredMixin, CreateView): @@ -19,6 +20,7 @@ class ActivityCreateView(LoginRequiredMixin, CreateView): class ActivityListView(LoginRequiredMixin, SingleTableView): model = Activity + table_class = ActivityTable def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) @@ -38,5 +40,12 @@ class ActivityUpdateView(LoginRequiredMixin, UpdateView): success_url = reverse_lazy('activity:activity_list') +class ActivityInviteView(LoginRequiredMixin, CreateView): + model = Guest + form_class = GuestForm + success_url = reverse_lazy('activity:activity_list') + template_name = "activity/activity_invite.html" + + class ActivityEntryView(LoginRequiredMixin, TemplateView): pass diff --git a/apps/member/forms.py b/apps/member/forms.py index 52dde34a..76cd146b 100644 --- a/apps/member/forms.py +++ b/apps/member/forms.py @@ -7,7 +7,6 @@ from crispy_forms.layout import Layout from django import forms from django.contrib.auth.forms import UserCreationForm, AuthenticationForm from django.contrib.auth.models import User - from note_kfet.inputs import AutocompleteModelSelect from permission.models import PermissionMask diff --git a/apps/note/urls.py b/apps/note/urls.py index 1bc12b4d..9d6af317 100644 --- a/apps/note/urls.py +++ b/apps/note/urls.py @@ -4,7 +4,6 @@ from django.urls import path from . import views -from .models import Note app_name = 'note' urlpatterns = [ diff --git a/note_kfet/inputs.py b/note_kfet/inputs.py index 35b8b605..e012c1c2 100644 --- a/note_kfet/inputs.py +++ b/note_kfet/inputs.py @@ -40,12 +40,6 @@ class AutocompleteModelSelect(Select): return str(self.model.objects.get(pk=int(value))) return "" - def value_from_datadict(self, data, files, name): - val = super().value_from_datadict(data, files, name) - print(data) - print(self.attrs) - return val - """ The remaining of this file comes from the project `django-bootstrap-datepicker-plus` available on Github: diff --git a/templates/activity/activity_invite.html b/templates/activity/activity_invite.html new file mode 100644 index 00000000..8bdb1965 --- /dev/null +++ b/templates/activity/activity_invite.html @@ -0,0 +1,15 @@ +{% extends "base.html" %} +{% load render_table from django_tables2 %} +{% load i18n crispy_forms_tags %} +{% block content %} +
+ {% csrf_token %} + {{ form|crispy }} + +
+{% endblock %} + +{% block extrajavascript %} + +{% endblock %}