mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-23 09:41:05 +02:00
Merge conflict
This commit is contained in:
parent
20c0813f78
commit
908e06c8eb
7 changed files with 20 additions and 21 deletions
|
@ -36,7 +36,6 @@
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
{% if member_count and member_count > 0 %}
|
|
||||||
<div class="section-outlined__utility-button mobile-lg:padding-right-105 {% if portfolio %} mobile:grid-col-12 desktop:grid-col-6 desktop:padding-left-3{% endif %}">
|
<div class="section-outlined__utility-button mobile-lg:padding-right-105 {% if portfolio %} mobile:grid-col-12 desktop:grid-col-6 desktop:padding-left-3{% endif %}">
|
||||||
<section aria-label="Domains report component" class="margin-top-205">
|
<section aria-label="Domains report component" class="margin-top-205">
|
||||||
<a href="{% url 'export_members_portfolio' %}" class="usa-button usa-button--unstyled usa-button--with-icon usa-button--justify-right" role="button">
|
<a href="{% url 'export_members_portfolio' %}" class="usa-button usa-button--unstyled usa-button--with-icon usa-button--justify-right" role="button">
|
||||||
|
@ -46,7 +45,6 @@
|
||||||
</a>
|
</a>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ---------- MAIN TABLE ---------- -->
|
<!-- ---------- MAIN TABLE ---------- -->
|
||||||
|
|
|
@ -812,7 +812,7 @@ class MemberExportTest(MockDbForIndividualTests, MockEppLib):
|
||||||
@override_flag("organization_members", active=True)
|
@override_flag("organization_members", active=True)
|
||||||
@less_console_noise_decorator
|
@less_console_noise_decorator
|
||||||
def test_member_export(self):
|
def test_member_export(self):
|
||||||
"""Tests the member export report"""
|
"""Tests the member export report by comparing the csv output."""
|
||||||
content_type = ContentType.objects.get_for_model(PortfolioInvitation)
|
content_type = ContentType.objects.get_for_model(PortfolioInvitation)
|
||||||
LogEntry.objects.create(
|
LogEntry.objects.create(
|
||||||
user=self.lebowski_user,
|
user=self.lebowski_user,
|
||||||
|
|
|
@ -175,7 +175,7 @@ class MemberExport(BaseExport):
|
||||||
"additional_permissions_display",
|
"additional_permissions_display",
|
||||||
"member_display",
|
"member_display",
|
||||||
"domain_info",
|
"domain_info",
|
||||||
"source",
|
"type",
|
||||||
"invitation_date",
|
"invitation_date",
|
||||||
"invited_by",
|
"invited_by",
|
||||||
]
|
]
|
||||||
|
|
|
@ -280,10 +280,12 @@ class UserPortfolioPermissionModelAnnotation(BaseModelAnnotation):
|
||||||
F("user__last_login"), Value("YYYY-MM-DD"), function="to_char", output_field=TextField()
|
F("user__last_login"), Value("YYYY-MM-DD"), function="to_char", output_field=TextField()
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
# an array of domains, with id and name, colon separated
|
||||||
domain_query = Concat(
|
domain_query = Concat(
|
||||||
F("user__permissions__domain_id"),
|
F("user__permissions__domain_id"),
|
||||||
Value(":"),
|
Value(":"),
|
||||||
F("user__permissions__domain__name"),
|
F("user__permissions__domain__name"),
|
||||||
|
# specify the output_field to ensure union has same column types
|
||||||
output_field=CharField(),
|
output_field=CharField(),
|
||||||
)
|
)
|
||||||
last_active_query = Cast(F("user__last_login"), output_field=TextField())
|
last_active_query = Cast(F("user__last_login"), output_field=TextField())
|
||||||
|
@ -299,7 +301,9 @@ class UserPortfolioPermissionModelAnnotation(BaseModelAnnotation):
|
||||||
),
|
),
|
||||||
"additional_permissions_display": F("additional_permissions"),
|
"additional_permissions_display": F("additional_permissions"),
|
||||||
"member_display": Case(
|
"member_display": Case(
|
||||||
|
# If email is present and not blank, use email
|
||||||
When(Q(user__email__isnull=False) & ~Q(user__email=""), then=F("user__email")),
|
When(Q(user__email__isnull=False) & ~Q(user__email=""), then=F("user__email")),
|
||||||
|
# If first name or last name is present, use concatenation of first_name + " " + last_name
|
||||||
When(
|
When(
|
||||||
Q(user__first_name__isnull=False) | Q(user__last_name__isnull=False),
|
Q(user__first_name__isnull=False) | Q(user__last_name__isnull=False),
|
||||||
then=Concat(
|
then=Concat(
|
||||||
|
@ -308,16 +312,18 @@ class UserPortfolioPermissionModelAnnotation(BaseModelAnnotation):
|
||||||
Coalesce(F("user__last_name"), Value("")),
|
Coalesce(F("user__last_name"), Value("")),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
# If neither, use an empty string
|
||||||
default=Value(""),
|
default=Value(""),
|
||||||
output_field=CharField(),
|
output_field=CharField(),
|
||||||
),
|
),
|
||||||
"domain_info": ArrayAgg(
|
"domain_info": ArrayAgg(
|
||||||
domain_query,
|
domain_query,
|
||||||
distinct=True,
|
distinct=True,
|
||||||
|
# only include domains in portfolio
|
||||||
filter=Q(user__permissions__domain__isnull=False)
|
filter=Q(user__permissions__domain__isnull=False)
|
||||||
& Q(user__permissions__domain__domain_info__portfolio=portfolio),
|
& Q(user__permissions__domain__domain_info__portfolio=portfolio),
|
||||||
),
|
),
|
||||||
"source": Value("permission", output_field=CharField()),
|
"type": Value("member", output_field=CharField()),
|
||||||
"invitation_date": PortfolioInvitationModelAnnotation.get_invitation_date_query(
|
"invitation_date": PortfolioInvitationModelAnnotation.get_invitation_date_query(
|
||||||
object_id_query=cls.get_portfolio_invitation_id_query()
|
object_id_query=cls.get_portfolio_invitation_id_query()
|
||||||
),
|
),
|
||||||
|
@ -452,13 +458,14 @@ class PortfolioInvitationModelAnnotation(BaseModelAnnotation):
|
||||||
"last_active": Value("Invited", output_field=TextField()),
|
"last_active": Value("Invited", output_field=TextField()),
|
||||||
"additional_permissions_display": F("additional_permissions"),
|
"additional_permissions_display": F("additional_permissions"),
|
||||||
"member_display": F("email"),
|
"member_display": F("email"),
|
||||||
|
# Use ArrayRemove to return an empty list when no domain invitations are found
|
||||||
"domain_info": ArrayRemoveNull(
|
"domain_info": ArrayRemoveNull(
|
||||||
ArrayAgg(
|
ArrayAgg(
|
||||||
Subquery(domain_invitations.values("domain_info")),
|
Subquery(domain_invitations.values("domain_info")),
|
||||||
distinct=True,
|
distinct=True,
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
"source": Value("invitation", output_field=CharField()),
|
"type": Value("invitedmember", output_field=CharField()),
|
||||||
"invitation_date": cls.get_invitation_date_query(
|
"invitation_date": cls.get_invitation_date_query(
|
||||||
object_id_query=Cast(OuterRef("id"), output_field=TextField())
|
object_id_query=Cast(OuterRef("id"), output_field=TextField())
|
||||||
),
|
),
|
||||||
|
|
|
@ -66,7 +66,7 @@ class PortfolioMembersJson(PortfolioMembersPermission, View):
|
||||||
"additional_permissions_display",
|
"additional_permissions_display",
|
||||||
"member_display",
|
"member_display",
|
||||||
"domain_info",
|
"domain_info",
|
||||||
"source",
|
"type",
|
||||||
)
|
)
|
||||||
|
|
||||||
def initial_invitations_search(self, portfolio):
|
def initial_invitations_search(self, portfolio):
|
||||||
|
@ -83,7 +83,7 @@ class PortfolioMembersJson(PortfolioMembersPermission, View):
|
||||||
"additional_permissions_display",
|
"additional_permissions_display",
|
||||||
"member_display",
|
"member_display",
|
||||||
"domain_info",
|
"domain_info",
|
||||||
"source",
|
"type",
|
||||||
)
|
)
|
||||||
|
|
||||||
def apply_search_term(self, queryset, request):
|
def apply_search_term(self, queryset, request):
|
||||||
|
@ -119,12 +119,12 @@ class PortfolioMembersJson(PortfolioMembersPermission, View):
|
||||||
view_only = not user.has_edit_members_portfolio_permission(portfolio) or not user_can_edit_other_users
|
view_only = not user.has_edit_members_portfolio_permission(portfolio) or not user_can_edit_other_users
|
||||||
|
|
||||||
is_admin = UserPortfolioRoleChoices.ORGANIZATION_ADMIN in (item.get("roles") or [])
|
is_admin = UserPortfolioRoleChoices.ORGANIZATION_ADMIN in (item.get("roles") or [])
|
||||||
action_url = reverse("member" if item["source"] == "permission" else "invitedmember", kwargs={"pk": item["id"]})
|
action_url = reverse(item["type"], kwargs={"pk": item["id"]})
|
||||||
|
|
||||||
# Serialize member data
|
# Serialize member data
|
||||||
member_json = {
|
member_json = {
|
||||||
"id": item.get("id", ""),
|
"id": item.get("id", ""), # id is id of UserPortfolioPermission or PortfolioInvitation
|
||||||
"source": item.get("source", ""),
|
"type": item.get("type", ""), # source is member or invitedmember
|
||||||
"name": " ".join(filter(None, [item.get("first_name", ""), item.get("last_name", "")])),
|
"name": " ".join(filter(None, [item.get("first_name", ""), item.get("last_name", "")])),
|
||||||
"email": item.get("email_display", ""),
|
"email": item.get("email_display", ""),
|
||||||
"member_display": item.get("member_display", ""),
|
"member_display": item.get("member_display", ""),
|
||||||
|
|
|
@ -461,14 +461,7 @@ class PortfolioMembersView(PortfolioMembersPermissionView, View):
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
"""Add additional context data to the template."""
|
"""Add additional context data to the template."""
|
||||||
# Get portfolio from session
|
return render(request, "portfolio_members.html")
|
||||||
portfolio = request.session.get("portfolio")
|
|
||||||
context = {}
|
|
||||||
if portfolio:
|
|
||||||
user_count = portfolio.portfolio_users.count()
|
|
||||||
invitation_count = PortfolioInvitation.objects.filter(portfolio=portfolio).count()
|
|
||||||
context.update({"member_count": user_count + invitation_count})
|
|
||||||
return render(request, "portfolio_members.html", context=context)
|
|
||||||
|
|
||||||
|
|
||||||
class NewMemberView(PortfolioMembersPermissionView, FormMixin):
|
class NewMemberView(PortfolioMembersPermissionView, FormMixin):
|
||||||
|
|
|
@ -175,9 +175,10 @@ class ExportMembersPortfolio(View):
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
"""Returns the members report"""
|
"""Returns the members report"""
|
||||||
|
|
||||||
portfolio_display = "portfolio"
|
# Swap the spaces for dashes to make the formatted name look prettier
|
||||||
|
portfolio_display = "organization"
|
||||||
if request.session.get("portfolio"):
|
if request.session.get("portfolio"):
|
||||||
portfolio_display = str(request.session.get("portfolio")).replace(" ", "-")
|
portfolio_display = str(request.session.get("portfolio")).lower().replace(" ", "-")
|
||||||
|
|
||||||
response = HttpResponse(content_type="text/csv")
|
response = HttpResponse(content_type="text/csv")
|
||||||
response["Content-Disposition"] = f'attachment; filename="members-for-{portfolio_display}.csv"'
|
response["Content-Disposition"] = f'attachment; filename="members-for-{portfolio_display}.csv"'
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue