From 2e573b3465117d6542e539de7e78b3d84a3dbf76 Mon Sep 17 00:00:00 2001 From: "J.-S. Caux" <J.S.Caux@uva.nl> Date: Thu, 30 Jan 2020 08:06:20 +0100 Subject: [PATCH] Drafting/reworking/deleting (draft) composed messages now working --- apimail/api/views.py | 24 ++++++++-- apimail/models/account.py | 2 +- .../assets/vue/components/MessageComposer.vue | 15 ++++-- .../assets/vue/components/MessageContent.vue | 12 ++--- .../assets/vue/components/MessagesTable.vue | 47 +++++++++++++++---- apimail/urls.py | 10 ++++ 6 files changed, 87 insertions(+), 23 deletions(-) diff --git a/apimail/api/views.py b/apimail/api/views.py index 8fb9f8db5..f8c31e898 100644 --- a/apimail/api/views.py +++ b/apimail/api/views.py @@ -9,7 +9,7 @@ from django.shortcuts import get_object_or_404 from django.utils import timezone from rest_framework.generics import ( - CreateAPIView, ListAPIView, + CreateAPIView, DestroyAPIView, ListAPIView, RetrieveAPIView, UpdateAPIView) from rest_framework.permissions import AllowAny, IsAdminUser, IsAuthenticated from rest_framework.response import Response @@ -41,9 +41,9 @@ class UserEmailAccountAccessListAPIView(ListAPIView): def get_queryset(self): queryset = self.request.user.email_account_accesses.all() - if self.request.query_params.get('current', None): + if self.request.query_params.get('current', None) == 'true': queryset = queryset.current() - if self.request.query_params.get('cansend', None): + if self.request.query_params.get('cansend', None) == 'true': queryset = queryset.can_send() return queryset @@ -66,13 +66,29 @@ class ComposedMessageCreateAPIView(CreateAPIView): return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) +class ComposedMessageUpdateAPIView(UpdateAPIView): + queryset = ComposedMessage.objects.all() + serializer_class = ComposedMessageSerializer + lookup_field = 'uuid' + + +class ComposedMessageDestroyAPIView(DestroyAPIView): + permission_classes = (IsAuthenticated,) + serializer_class = ComposedMessageSerializer + lookup_field = 'uuid' + + def get_queryset(self): + return ComposedMessage.objects.filter_for_user(self.request.user) + + class ComposedMessageListAPIView(ListAPIView): + permission_classes = (IsAuthenticated,) serializer_class = ComposedMessageSerializer lookup_field = 'uuid' def get_queryset(self): queryset = ComposedMessage.objects.filter_for_user(self.request.user) - if self.request.query_params.get('draft', None): + if self.request.query_params.get('status', None) == 'draft': queryset = queryset.filter(status=ComposedMessage.STATUS_DRAFT) return queryset diff --git a/apimail/models/account.py b/apimail/models/account.py index d5906d123..c0537002d 100644 --- a/apimail/models/account.py +++ b/apimail/models/account.py @@ -53,7 +53,7 @@ class EmailAccountAccess(models.Model): date_from = models.DateField() date_until = models.DateField() - objects = EmailAccountAccessQuerySet() + objects = EmailAccountAccessQuerySet.as_manager() class Meta: ordering = ['account__email', 'user__last_name', '-date_until',] diff --git a/apimail/static/apimail/assets/vue/components/MessageComposer.vue b/apimail/static/apimail/assets/vue/components/MessageComposer.vue index 3546d6e5f..c5d203aec 100644 --- a/apimail/static/apimail/assets/vue/components/MessageComposer.vue +++ b/apimail/static/apimail/assets/vue/components/MessageComposer.vue @@ -185,15 +185,24 @@ export default { }, methods: { fetchCurrentAccounts () { - fetch('/mail/api/user_account_accesses?current&cansend') + fetch('/mail/api/user_account_accesses?current=true&cansend=true') .then(stream => stream.json()) .then(data => this.from_account_accesses = data.results) .catch(error => console.error(error)) }, saveMessage (status) { - fetch('/mail/api/composed_message/create', + var url = '/mail/api/composed_message' + var method = 'POST' + if (this.draftmessage) { // draft message exists, update + url += '/' + this.draftmessage.uuid + '/update' + method = 'PATCH' + } + else { + url += '/create' + } + fetch(url, { - method: 'POST', + method: method, headers: { "X-CSRFToken": csrftoken, "Content-Type": "application/json; charset=utf-8" diff --git a/apimail/static/apimail/assets/vue/components/MessageContent.vue b/apimail/static/apimail/assets/vue/components/MessageContent.vue index 7aaf8470f..6823393f4 100644 --- a/apimail/static/apimail/assets/vue/components/MessageContent.vue +++ b/apimail/static/apimail/assets/vue/components/MessageContent.vue @@ -25,9 +25,9 @@ no-close-on-backdrop > <message-composer :originalmessage="message" action="reply"></message-composer> - <template v-slot:modal-footer="{ cancel, }"> - <b-button size="sm" variant="danger" @click="cancel()"> - Cancel/close + <template v-slot:modal-footer="{ close, }"> + <b-button size="sm" variant="danger" @click="close()"> + Close </b-button> </template> </b-modal> @@ -49,9 +49,9 @@ no-close-on-backdrop > <message-composer :originalmessage="message" action="forward"></message-composer> - <template v-slot:modal-footer="{ cancel, }"> - <b-button variant="danger" @click="cancel()"> - Cancel + <template v-slot:modal-footer="{ close, }"> + <b-button variant="danger" @click="close()"> + Close </b-button> </template> </b-modal> diff --git a/apimail/static/apimail/assets/vue/components/MessagesTable.vue b/apimail/static/apimail/assets/vue/components/MessagesTable.vue index 920886fd9..a4d33108c 100644 --- a/apimail/static/apimail/assets/vue/components/MessagesTable.vue +++ b/apimail/static/apimail/assets/vue/components/MessagesTable.vue @@ -10,42 +10,51 @@ no-close-on-backdrop > <message-composer :draftmessage="draftMessageSelected"></message-composer> - <template v-slot:modal-footer="{ cancel, }"> - <b-button size="sm" variant="danger" @click="cancel()"> - Cancel/close + <template v-slot:modal-footer="{ close, }"> + <b-button size="sm" variant="danger" @click="close()"> + Close </b-button> </template> </b-modal> - <div v-if="draftmessages"> + <div v-if="draftMessages.length > 0" class="m-2 mb-4"> <h2>Message drafts to complete</h2> <table class="table"> <tr> <th>From</th> <th>To</th> <th>Subject</th> + <th>Status</th> <th>Actions</th> </tr> <tr - v-for="draftmsg in draftmessages" + v-for="draftmsg in draftMessages" > <td>{{ draftmsg.from_account }}</td> <td>{{ draftmsg.to_recipient }}</td> <td>{{ draftmsg.subject }}</td> + <td>{{ draftmsg.status }}</td> <td> <b-button @click="showReworkDraftModal(draftmsg)" + size="sm" variant="warning" > Rework draft </b-button> + <b-button + @click="deleteDraft(draftmsg.uuid)" + size="sm" + variant="danger" + > + Delete + </b-button> </td> </tr> </table> </div> - <h2>Click on an account to view messages</h2> <table class="table"> @@ -292,8 +301,9 @@ export default { return { accesses: null, accountSelected: null, - draftmessages: null, + draftMessages: [], draftMessageSelected: null, + queuedMessages: null, messages: [], perPage: 10, currentPage: 1, @@ -340,15 +350,31 @@ export default { .catch(error => console.error(error)) }, fetchDrafts () { - fetch('/mail/api/composed_messages?draft') + fetch('/mail/api/composed_messages?status=draft') .then(stream => stream.json()) - .then(data => this.draftmessages = data.results) + .then(data => this.draftMessages = data.results) .catch(error => console.error(error)) }, showReworkDraftModal (draftmsg) { this.draftMessageSelected = draftmsg this.$bvModal.show('modal-resumedraft') }, + deleteDraft (uuid) { + fetch('/mail/api/composed_message/' + uuid + '/delete', + { + method: 'DELETE', + headers: { + "X-CSRFToken": csrftoken, + } + } + ) + .then(response => { + if (response.ok) { + this.fetchDrafts() + } + }) + .catch(error => console.error(error)) + }, tagMessage (message, tag, action) { fetch('/mail/api/stored_message/' + message.uuid + '/tag', { @@ -422,6 +448,9 @@ export default { this.fetchAccounts() this.fetchTags() this.fetchDrafts() + this.$root.$on('bv::modal::hide', (bvEvent, modalId) => { + this.fetchDrafts() + }) }, watch: { accountSelected: function () { diff --git a/apimail/urls.py b/apimail/urls.py index 4ee92e16c..cfb68c000 100644 --- a/apimail/urls.py +++ b/apimail/urls.py @@ -32,6 +32,16 @@ urlpatterns = [ apiviews.ComposedMessageCreateAPIView.as_view(), name='composed_message_create' ), + path( # /mail/api/composed_message/<uuid>/update + 'composed_message/<uuid:uuid>/update', + apiviews.ComposedMessageUpdateAPIView.as_view(), + name='composed_message_update' + ), + path( # /mail/api/composed_message/<uuid>/delete + 'composed_message/<uuid:uuid>/delete', + apiviews.ComposedMessageDestroyAPIView.as_view(), + name='composed_message_delete' + ), path( # /mail/api/composed_messages 'composed_messages', apiviews.ComposedMessageListAPIView.as_view(), -- GitLab