From 24bce2ab043cace553363e5ce9a8e9055dac9ee8 Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Wed, 13 Nov 2019 11:08:19 +0100 Subject: [PATCH] Create generic ServiceListView and implement MailView --- musician/api.py | 2 + musician/models.py | 40 +++++++++++++++ musician/templates/musician/service_list.html | 28 +++++++++++ musician/templatetags/musician.py | 6 +++ musician/views.py | 49 +++++++++++++++++-- 5 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 musician/models.py create mode 100644 musician/templates/musician/service_list.html create mode 100644 musician/templatetags/musician.py diff --git a/musician/api.py b/musician/api.py index 5e36372..9ed19af 100644 --- a/musician/api.py +++ b/musician/api.py @@ -14,6 +14,8 @@ API_PATHS = { # services 'domain-list': 'domains/', + 'address-list': 'addresses/', + 'mailbox-list': 'mailboxes/', 'mailinglist-list': 'lists/', # ... TODO (@slamora) complete list of backend URLs } diff --git a/musician/models.py b/musician/models.py new file mode 100644 index 0000000..e88caa5 --- /dev/null +++ b/musician/models.py @@ -0,0 +1,40 @@ +class MailService: + name = 'address' + verbose_name = 'Mail' + fields = ('mail_address', 'aliases', 'type', 'type_detail') + + FORWARD = 'forward' + MAILBOX = 'mailbox' + + def __init__(self, data={}): + if self.verbose_name is None: + self.verbose_name = self.name + + self.data = data + + def get(self, key): + # retrieve attr of the object and if undefined get raw data + return getattr(self, key, self.data.get(key)) + + @property + def aliases(self): + return [ + name + '@' + self.data['domain']['name'] for name in self.data['names'][1:] + ] + + @property + def mail_address(self): + return self.data['names'][0] + '@' + self.data['domain']['name'] + + @property + def type(self): + if self.data['forward']: + return self.FORWARD + return self.MAILBOX + + @property + def type_detail(self): + if self.type == self.FORWARD: + return self.data['forward'] + # TODO(@slamora) retrieve mailbox usage + return {'usage': 0, 'total': 213} diff --git a/musician/templates/musician/service_list.html b/musician/templates/musician/service_list.html new file mode 100644 index 0000000..d413fc8 --- /dev/null +++ b/musician/templates/musician/service_list.html @@ -0,0 +1,28 @@ +{% extends "musician/base.html" %} +{% load i18n musician %} + +{% block content %} + +

{{ service.verbose_name }}

+

{{ service.description }}

+ + + + + {% for field_name in service.fields %} + + {% endfor %} + + + + {% for resource in object_list %} + + {% for field_name in service.fields %} + + {% endfor %} + + {% endfor %} + + {% include "musician/components/table_paginator.html" %} +
{{ field_name }}
{{ resource|get_item:field_name }}
+{% endblock %} diff --git a/musician/templatetags/musician.py b/musician/templatetags/musician.py new file mode 100644 index 0000000..181fd01 --- /dev/null +++ b/musician/templatetags/musician.py @@ -0,0 +1,6 @@ +from django.template.defaulttags import register + + +@register.filter +def get_item(dictionary, key): + return dictionary.get(key) diff --git a/musician/views.py b/musician/views.py index 240e287..709f393 100644 --- a/musician/views.py +++ b/musician/views.py @@ -1,4 +1,6 @@ +from django.core.exceptions import ImproperlyConfigured +from itertools import groupby from django.http import HttpResponseRedirect from django.shortcuts import render from django.urls import reverse_lazy @@ -12,6 +14,7 @@ from .auth import login as auth_login from .auth import logout as auth_logout from .forms import LoginForm from .mixins import CustomContextMixin, ExtendedPaginationMixin, UserTokenRequiredMixin +from .models import MailService class DashboardView(CustomContextMixin, UserTokenRequiredMixin, TemplateView): @@ -32,11 +35,51 @@ class DashboardView(CustomContextMixin, UserTokenRequiredMixin, TemplateView): class ServiceListView(CustomContextMixin, ExtendedPaginationMixin, UserTokenRequiredMixin, ListView): """Base list view to all services""" - pass + service = None + template_name = "musician/service_list.html" # TODO move to ServiceListView + + def get_queryset(self): + if self.service_class is None or self.service_class.name is None: + raise ImproperlyConfigured( + "ServiceListView requires a definiton of 'service'") + + return self.orchestra.retrieve_service_list(self.service_class.name) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context.update({ + 'service': self.service_class, + }) + return context -class MailView(CustomContextMixin, UserTokenRequiredMixin, TemplateView): - template_name = "musician/mail.html" +class MailView(ServiceListView): + service_class = MailService + + def get_queryset(self): + def retrieve_mailbox(value): + mailboxes = value.get('mailboxes') + + if len(mailboxes) == 0: + return '' + + return mailboxes[0]['id'] + + # group addresses with the same mailbox + raw_data = self.orchestra.retrieve_service_list( + self.service_class.name) + addresses = [] + for key, group in groupby(raw_data, retrieve_mailbox): + aliases = [] + data = {} + for thing in group: + aliases.append(thing.pop('name')) + data = thing + + data['names'] = aliases + addresses.append(MailService(data)) + + return addresses class MailingListsView(ServiceListView):