diff --git a/app/main/views/organisations.py b/app/main/views/organisations.py index dcf81dd62..44d4c068d 100644 --- a/app/main/views/organisations.py +++ b/app/main/views/organisations.py @@ -31,6 +31,7 @@ from app.main.forms import ( SetLetterBranding, ) from app.main.views.service_settings import get_branding_as_value_and_label +from app.models.organisation import Organisations from app.models.user import InvitedOrgUser, User from app.utils import user_has_permissions, user_is_platform_admin @@ -39,11 +40,9 @@ from app.utils import user_has_permissions, user_is_platform_admin @login_required @user_is_platform_admin def organisations(): - orgs = organisations_client.get_organisations() - return render_template( 'views/organisations/index.html', - organisations=orgs, + organisations=Organisations(), search_form=SearchByNameForm(), ) diff --git a/app/models/__init__.py b/app/models/__init__.py index 29cc7ea63..7675d4a81 100644 --- a/app/models/__init__.py +++ b/app/models/__init__.py @@ -1,3 +1,6 @@ +from abc import ABC, abstractmethod +from collections.abc import Sequence + from flask import abort @@ -12,6 +15,12 @@ class JSONModel(): def __bool__(self): return self._dict != {} + def __hash__(self): + return hash(self.id) + + def __eq__(self, other): + return self.id == other.id + def __getattr__(self, attr): if attr in self.ALLOWED_PROPERTIES: return self._dict[attr] @@ -27,5 +36,30 @@ class JSONModel(): abort(404) +class ModelList(ABC, Sequence): + + @property + @abstractmethod + def client(): + pass + + @property + @abstractmethod + def model(): + pass + + def __init__(self): + self.items = self.client() + + def __getitem__(self, index): + return self.model(self.items[index]) + + def __len__(self): + return len(self.items) + + def __add__(self, other): + return list(self) + list(other) + + class InviteTokenError(Exception): pass diff --git a/app/models/organisation.py b/app/models/organisation.py index 7f8a78116..b0c10f863 100644 --- a/app/models/organisation.py +++ b/app/models/organisation.py @@ -1,7 +1,7 @@ from flask import Markup, abort from werkzeug.utils import cached_property -from app.models import JSONModel +from app.models import JSONModel, ModelList from app.notify_client.organisations_api_client import organisations_client @@ -21,6 +21,7 @@ class Organisation(JSONModel): 'agreement_signed_version', 'domains', 'request_to_go_live_notes', + 'count_of_live_services', } @classmethod @@ -154,3 +155,8 @@ class Organisation(JSONModel): self.invited_users + self.active_users, key=lambda user: user.email_address.lower(), ) + + +class Organisations(ModelList): + client = organisations_client.get_organisations + model = Organisation diff --git a/app/models/service.py b/app/models/service.py index 32cea9f68..c606f907f 100644 --- a/app/models/service.py +++ b/app/models/service.py @@ -402,6 +402,10 @@ class Service(JSONModel): def organisation(self): return Organisation.from_service(self.id) + @property + def organisation_id(self): + return self._dict['organisation'] + @cached_property def inbound_number(self): return inbound_number_client.get_inbound_sms_number_for_service(self.id)['data'].get('number', '') diff --git a/app/models/user.py b/app/models/user.py index 210fdcb3e..0a1fb3ed2 100644 --- a/app/models/user.py +++ b/app/models/user.py @@ -1,12 +1,9 @@ -from collections.abc import Sequence -from itertools import chain - from flask import abort, current_app, request, session from flask_login import AnonymousUserMixin, UserMixin, login_user from notifications_python_client.errors import HTTPError from werkzeug.utils import cached_property -from app.models import JSONModel +from app.models import JSONModel, ModelList from app.models.organisation import Organisation from app.models.roles_and_permissions import ( all_permissions, @@ -247,29 +244,29 @@ class User(JSONModel, UserMixin): def orgs_and_services(self): return user_api_client.get_organisations_and_services_for_user(self.id) + @staticmethod + def sort_services(services): + return sorted(services, key=lambda service: service.name.lower()) + @property def services(self): - return sorted( - self.services_with_organisation + self.services_without_organisations, - key=lambda service: service.name.lower(), - ) + from app.models.service import Service + return self.sort_services([ + Service(service) for service in self.orgs_and_services['services'] + ]) @property def services_with_organisation(self): - from app.models.service import Service return [ - Service(service) for service in - next(chain( - org['services'] for org in self.orgs_and_services['organisations'] - ), []) + service for service in self.services + if self.belongs_to_organisation(service.organisation_id) ] @property def services_without_organisations(self): - from app.models.service import Service return [ - Service(service) for service in - self.orgs_and_services['services_without_organisations'] + service for service in self.services + if not self.belongs_to_organisation(service.organisation_id) ] @property @@ -290,17 +287,14 @@ class User(JSONModel, UserMixin): @property def live_services_not_belonging_to_users_organisations(self): - from app.models.service import Service - return [ - Service(service) - for service in self.orgs_and_services['services_without_organisations'] - if not service['restricted'] - ] + return self.sort_services( + set(self.live_services).union(self.services_without_organisations) + ) @property def organisations(self): return [ - Organisation.from_id(organisation['id']) + Organisation(organisation) for organisation in self.orgs_and_services['organisations'] ] @@ -594,22 +588,13 @@ class AnonymousUser(AnonymousUserMixin): return Organisation(None) -class Users(Sequence): +class Users(ModelList): client = user_api_client.get_users_for_service model = User def __init__(self, service_id): - self.users = self.client(service_id) - - def __getitem__(self, index): - return self.model(self.users[index]) - - def __len__(self): - return len(self.users) - - def __add__(self, other): - return list(self) + list(other) + self.items = self.client(service_id) class OrganisationUsers(Users): @@ -622,7 +607,7 @@ class InvitedUsers(Users): model = InvitedUser def __init__(self, service_id): - self.users = [ + self.items = [ user for user in self.client(service_id) if user['status'] != 'accepted' ] diff --git a/app/templates/views/choose-account.html b/app/templates/views/choose-account.html index d60f43156..9457f520e 100644 --- a/app/templates/views/choose-account.html +++ b/app/templates/views/choose-account.html @@ -22,8 +22,8 @@
- {{ org.live_services|length }} - live service{% if org.live_services|length != 1 %}s{% endif %} + {{ org.count_of_live_services }} + live service{% if org.count_of_live_services != 1 %}s{% endif %}
+ {{ org.count_of_live_services }} + live service{% if org.count_of_live_services != 1 %}s{% endif %} +
+ {% if not org.active %} - archived {% endif %}