From 62d16b4da8c3e94254e6dec5034efb70f99fa239 Mon Sep 17 00:00:00 2001 From: Tore Brede <Tore.Brede@uib.no> Date: Mon, 1 Nov 2021 15:50:35 +0100 Subject: [PATCH] GREG-94: Working on functionality for resending invitations --- .../routes/sponsor/guest/guestInfo/index.tsx | 30 +++++++++++++++++++ frontend/src/routes/sponsor/guest/index.tsx | 2 ++ gregui/api/urls.py | 1 + gregui/api/views/invitation.py | 28 ++++++++--------- gregui/api/views/person.py | 2 -- 5 files changed, 47 insertions(+), 16 deletions(-) diff --git a/frontend/src/routes/sponsor/guest/guestInfo/index.tsx b/frontend/src/routes/sponsor/guest/guestInfo/index.tsx index 139e1284..841c7bbf 100644 --- a/frontend/src/routes/sponsor/guest/guestInfo/index.tsx +++ b/frontend/src/routes/sponsor/guest/guestInfo/index.tsx @@ -15,14 +15,17 @@ import { import { Guest, Role } from 'interfaces' import SponsorInfoButtons from 'routes/components/sponsorInfoButtons' import { format } from 'date-fns' +import { submitJsonOpts } from '../../../../utils' type GuestInfoParams = { pid: string } + interface RoleLineProps { role: Role pid: string } + type GuestInfoProps = { guest: Guest roles: Role[] @@ -59,6 +62,25 @@ export default function GuestInfo({ guest, roles }: GuestInfoProps) { const { pid } = useParams<GuestInfoParams>() const [t] = useTranslation(['common']) + // Resending the invitation does not cause a change in the state, so nothing needs to be updated after the call + const resend = () => { + fetch(`/api/ui/v1/invite/${guest.pid}/resend`, submitJsonOpts('PATCH', {})) + .then((res) => { + if (!res.ok) { + return null + } + return res.text() + }) + .then((result) => { + if (result !== null) { + console.log('result', result) + } + }) + .catch((error) => { + console.log('error', error) + }) + } + return ( <Page> <SponsorInfoButtons to="/sponsor" name={`${guest.first} ${guest.last}`} /> @@ -93,6 +115,14 @@ export default function GuestInfo({ guest, roles }: GuestInfoProps) { </TableBody> </Table> </TableContainer> + + {/* If the guest has not completed the registration process, he should have an invitation he has not responded to */} + {!guest.registered && ( + <Button sx={{ marginTop: '0.5rem' }} onClick={resend}> + {t('button.resendInvitation')} + </Button> + )} + <h4>{t('guestInfo.roleInfoHead')}</h4> <h5> {t('guestInfo.roleInfoBody')} diff --git a/frontend/src/routes/sponsor/guest/index.tsx b/frontend/src/routes/sponsor/guest/index.tsx index 81152184..62efcc74 100644 --- a/frontend/src/routes/sponsor/guest/index.tsx +++ b/frontend/src/routes/sponsor/guest/index.tsx @@ -32,6 +32,8 @@ function GuestRoutes() { const response = await fetch(`/api/ui/v1/person/${id}`) const rjson = await response.json() if (response.ok) { + console.log('Test30: ' + JSON.stringify(rjson)) + setGuest({ pid: rjson.pid, first: rjson.first, diff --git a/gregui/api/urls.py b/gregui/api/urls.py index a3c5e452..26029489 100644 --- a/gregui/api/urls.py +++ b/gregui/api/urls.py @@ -23,6 +23,7 @@ urlpatterns += [ re_path(r"units/$", UnitsViewSet.as_view(), name="units"), path("invited/", InvitedGuestView.as_view(), name="invited-info"), path("invitecheck/", CheckInvitationView.as_view(), name="invite-verify"), + path("invite/<int:person_id>/resend", ResendInvitationView.as_view(), name="invite-resend"), path("invite/", InvitationView.as_view(), name="invitation"), path("resend/<int:person_id>", ResendInvitationView.as_view(), name="invite-resend"), path("person/<int:id>", PersonView.as_view(), name="person-get"), diff --git a/gregui/api/views/invitation.py b/gregui/api/views/invitation.py index 1c6876d5..feed09dd 100644 --- a/gregui/api/views/invitation.py +++ b/gregui/api/views/invitation.py @@ -1,5 +1,6 @@ import datetime import logging +import uuid from enum import Enum from typing import Optional @@ -291,26 +292,25 @@ class ResendInvitationView(UpdateModelMixin, APIView): def patch(self, request, *args, **kwargs) -> Response: person_id = kwargs["person_id"] - active_invitation_links = InvitationLink.objects.filter(invitation__role__person__id=person_id, - expire__gte=now()) + invitation_links = InvitationLink.objects.filter(invitation__role__person__id=person_id) - if active_invitation_links.count() == 0: - # No active invitations, it is not expected that this endpoint is called if that is the case + if invitation_links.count() == 0: + # No invitation, not expected that the endpoint should be called in this case return Response(status=status.HTTP_400_BAD_REQUEST) - if active_invitation_links.count() > 1: - logger.warning(f"Person with ID {person_id} has multiple active invitation links") + if invitation_links.count() > 1: + logger.warning(f"Person with ID {person_id} has multiple invitation links") - for link in active_invitation_links: - # TODO Could also update the UUID of the existing invitation link and send it again. Not sure what is best, reusing the existing link-entry in the database or creating a new one as done here - link.expire = now() + for link in invitation_links: + link.uuid = uuid.uuid4() + link.expire = timezone.now() + datetime.timedelta(days=30) link.save() - invitationlink = InvitationLink.objects.create( - invitation=link.invitation, - expire=timezone.now() + datetime.timedelta(days=30), - ) + # invitationlink = InvitationLink.objects.create( + # invitation=link.invitation, + # expire=timezone.now() + datetime.timedelta(days=30), + # ) # TODO: send email to invited guest - print(invitationlink) + print(link) return Response(status=status.HTTP_200_OK) diff --git a/gregui/api/views/person.py b/gregui/api/views/person.py index 40761b9c..8e8e1bbd 100644 --- a/gregui/api/views/person.py +++ b/gregui/api/views/person.py @@ -46,8 +46,6 @@ class PersonView(APIView): } for role in person.roles.all() ], - "has_active_invitations": InvitationLink.objects.filter(invitation__role__person__id=person.id, - expire__gte=now()).count() > 0 } return JsonResponse(response) -- GitLab