Merge conflict

This commit is contained in:
zandercymatics 2024-11-20 09:02:19 -07:00
parent 20c0813f78
commit 908e06c8eb
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
7 changed files with 20 additions and 21 deletions

View file

@ -36,7 +36,6 @@
</form>
</section>
</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 %}">
<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">
@ -46,7 +45,6 @@
</a>
</section>
</div>
{% endif %}
</div>
<!-- ---------- MAIN TABLE ---------- -->

View file

@ -812,7 +812,7 @@ class MemberExportTest(MockDbForIndividualTests, MockEppLib):
@override_flag("organization_members", active=True)
@less_console_noise_decorator
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)
LogEntry.objects.create(
user=self.lebowski_user,

View file

@ -175,7 +175,7 @@ class MemberExport(BaseExport):
"additional_permissions_display",
"member_display",
"domain_info",
"source",
"type",
"invitation_date",
"invited_by",
]

View file

@ -280,10 +280,12 @@ class UserPortfolioPermissionModelAnnotation(BaseModelAnnotation):
F("user__last_login"), Value("YYYY-MM-DD"), function="to_char", output_field=TextField()
)
else:
# an array of domains, with id and name, colon separated
domain_query = Concat(
F("user__permissions__domain_id"),
Value(":"),
F("user__permissions__domain__name"),
# specify the output_field to ensure union has same column types
output_field=CharField(),
)
last_active_query = Cast(F("user__last_login"), output_field=TextField())
@ -299,7 +301,9 @@ class UserPortfolioPermissionModelAnnotation(BaseModelAnnotation):
),
"additional_permissions_display": F("additional_permissions"),
"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")),
# If first name or last name is present, use concatenation of first_name + " " + last_name
When(
Q(user__first_name__isnull=False) | Q(user__last_name__isnull=False),
then=Concat(
@ -308,16 +312,18 @@ class UserPortfolioPermissionModelAnnotation(BaseModelAnnotation):
Coalesce(F("user__last_name"), Value("")),
),
),
# If neither, use an empty string
default=Value(""),
output_field=CharField(),
),
"domain_info": ArrayAgg(
domain_query,
distinct=True,
# only include domains in portfolio
filter=Q(user__permissions__domain__isnull=False)
& 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(
object_id_query=cls.get_portfolio_invitation_id_query()
),
@ -452,13 +458,14 @@ class PortfolioInvitationModelAnnotation(BaseModelAnnotation):
"last_active": Value("Invited", output_field=TextField()),
"additional_permissions_display": F("additional_permissions"),
"member_display": F("email"),
# Use ArrayRemove to return an empty list when no domain invitations are found
"domain_info": ArrayRemoveNull(
ArrayAgg(
Subquery(domain_invitations.values("domain_info")),
distinct=True,
)
),
"source": Value("invitation", output_field=CharField()),
"type": Value("invitedmember", output_field=CharField()),
"invitation_date": cls.get_invitation_date_query(
object_id_query=Cast(OuterRef("id"), output_field=TextField())
),

View file

@ -66,7 +66,7 @@ class PortfolioMembersJson(PortfolioMembersPermission, View):
"additional_permissions_display",
"member_display",
"domain_info",
"source",
"type",
)
def initial_invitations_search(self, portfolio):
@ -83,7 +83,7 @@ class PortfolioMembersJson(PortfolioMembersPermission, View):
"additional_permissions_display",
"member_display",
"domain_info",
"source",
"type",
)
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
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
member_json = {
"id": item.get("id", ""),
"source": item.get("source", ""),
"id": item.get("id", ""), # id is id of UserPortfolioPermission or PortfolioInvitation
"type": item.get("type", ""), # source is member or invitedmember
"name": " ".join(filter(None, [item.get("first_name", ""), item.get("last_name", "")])),
"email": item.get("email_display", ""),
"member_display": item.get("member_display", ""),

View file

@ -461,14 +461,7 @@ class PortfolioMembersView(PortfolioMembersPermissionView, View):
def get(self, request):
"""Add additional context data to the template."""
# Get portfolio from session
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)
return render(request, "portfolio_members.html")
class NewMemberView(PortfolioMembersPermissionView, FormMixin):

View file

@ -175,9 +175,10 @@ class ExportMembersPortfolio(View):
def get(self, request, *args, **kwargs):
"""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"):
portfolio_display = str(request.session.get("portfolio")).replace(" ", "-")
portfolio_display = str(request.session.get("portfolio")).lower().replace(" ", "-")
response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = f'attachment; filename="members-for-{portfolio_display}.csv"'