diff --git a/src/registrar/assets/js/get-gov.js b/src/registrar/assets/js/get-gov.js
index 847696f33..adc3cbf66 100644
--- a/src/registrar/assets/js/get-gov.js
+++ b/src/registrar/assets/js/get-gov.js
@@ -1926,9 +1926,13 @@ class MembersTable extends LoadTableBase {
const row = document.createElement('tr');
+ let admin_tagHTML = ``;
+ if (member.is_admin)
+ admin_tagHTML = `Admin`
+
row.innerHTML = `
- ${member_email}
+ ${member_email} ${admin_tagHTML}
|
${last_active}
diff --git a/src/registrar/assets/sass/_theme/_tooltips.scss b/src/registrar/assets/sass/_theme/_tooltips.scss
index 3ab630dc0..ebdfff86b 100644
--- a/src/registrar/assets/sass/_theme/_tooltips.scss
+++ b/src/registrar/assets/sass/_theme/_tooltips.scss
@@ -28,3 +28,7 @@
#extended-logo .usa-tooltip__body {
font-weight: 400 !important;
}
+
+.usa-tags {
+ background-color: #005288;
+}
\ No newline at end of file
diff --git a/src/registrar/views/portfolio_members_json.py b/src/registrar/views/portfolio_members_json.py
index 4fb163926..ea78f01f6 100644
--- a/src/registrar/views/portfolio_members_json.py
+++ b/src/registrar/views/portfolio_members_json.py
@@ -6,6 +6,7 @@ from django.urls import reverse
from django.utils import timezone
from django.db.models import Q
+from registrar.models.portfolio_invitation import PortfolioInvitation
from registrar.models.user import User
from registrar.models.user_portfolio_permission import UserPortfolioPermission
@@ -13,6 +14,7 @@ from registrar.models.user_portfolio_permission import UserPortfolioPermission
import logging
from venv import logger
from registrar.management.commands.utility.terminal_helper import TerminalColors, TerminalHelper
+from registrar.models.utility.portfolio_helper import UserPortfolioRoleChoices
logger = logging.getLogger(__name__)
@@ -24,6 +26,17 @@ def get_portfolio_members_json(request):
objects = get_member_objects_from_request(request)
if(objects is not None):
member_ids = objects.values_list("id", flat=True)
+
+ portfolio = request.session.get("portfolio")
+ admin_ids = UserPortfolioPermission.objects.filter(
+ portfolio=portfolio,
+ roles__overlap=[
+ UserPortfolioRoleChoices.ORGANIZATION_ADMIN,
+ ],
+ ).values_list("user__id", flat=True)
+ portfolio_invitation_emails = PortfolioInvitation.objects.filter(portfolio=portfolio).values_list("email", flat=True)
+
+
unfiltered_total = member_ids.count()
objects = apply_search(objects, request)
@@ -34,7 +47,7 @@ def get_portfolio_members_json(request):
page_number = request.GET.get("page", 1)
page_obj = paginator.get_page(page_number)
members = [
- serialize_members(request, member, request.user) for member in page_obj.object_list
+ serialize_members(request, member, request.user, admin_ids, portfolio_invitation_emails) for member in page_obj.object_list
]
# DEVELOPER'S NOTE (9-20-24):
@@ -93,13 +106,13 @@ def get_member_objects_from_request(request):
# else:
# filter_condition = Q(portfolio=portfolio, creator=request.user)
- TerminalHelper.colorful_logger(logger.info, TerminalColors.OKGREEN, "getting permissions") # TODO: delete me
permissions = UserPortfolioPermission.objects.filter(
portfolio=portfolio
)
-
- TerminalHelper.colorful_logger(logger.info, TerminalColors.OKGREEN, f'permissions {permissions}') # TODO: delete me
- members = User.objects.filter(portfolio_permissions__in=permissions)
+
+ portfolio_invitation_emails = PortfolioInvitation.objects.filter(portfolio=portfolio).values_list("email", flat=True)
+
+ members = User.objects.filter(Q(portfolio_permissions__in=permissions) | Q(email__in=portfolio_invitation_emails))
TerminalHelper.colorful_logger(logger.info, TerminalColors.OKCYAN, f'members {members}') # TODO: delete me
return members
@@ -141,7 +154,35 @@ def apply_search(queryset, request):
# return queryset.order_by(sort_by)
-def serialize_members(request, member, user):
+
+
+# TODO: delete these...(failed experiment)
+# def get_admin_members(request):
+# portfolio = request.GET.get("portfolio")
+# # Filter UserPortfolioPermission objects related to the portfolio
+# admin_permissions = UserPortfolioPermission.objects.filter(
+# portfolio=portfolio, roles__contains=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN]
+# )
+
+# # Get the user objects associated with these permissions
+# admin_users = User.objects.filter(portfolio_permissions__in=admin_permissions)
+
+# return admin_users
+
+# def get_non_admin_members(request):
+# portfolio = request.GET.get("portfolio")
+# # Filter UserPortfolioPermission objects related to the portfolio that do NOT have the "Admin" role
+# non_admin_permissions = UserPortfolioPermission.objects.filter(portfolio=portfolio).exclude(
+# roles__contains=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN]
+# )
+
+# # Get the user objects associated with these permissions
+# non_admin_users = User.objects.filter(portfolio_permissions__in=non_admin_permissions)
+
+# return non_admin_users
+
+
+def serialize_members(request, member, user, admin_ids, portfolio_invitation_emails):
# ------- DELETABLE
# deletable_statuses = [
@@ -165,32 +206,32 @@ def serialize_members(request, member, user):
# If the user has view user permissions only, show the "View" link (no gear icon).
view_only = not user.has_edit_members_portfolio_permission
- # ------- ACTIVITY
- is_invited = member.verification_type == User.VerificationTypeChoices.INVITED
- last_active = "invited" if is_invited else "unknown"
+ # ------- USER STATUS
+ is_invited = member.email in portfolio_invitation_emails
+ last_active = "Invited" if is_invited else "Unknown"
if member.last_login:
last_active = member.last_login.strftime("%b. %d, %Y")
+
+ # portfolio = request.session.get("portfolio")
+ # roles = member.portfolio_role_summary(portfolio)
+ # TerminalHelper.colorful_logger(logger.info, TerminalColors.OKGREEN, f'roles {roles}') # TODO: delete me
+ # is_admin = 'Admin' in roles # TODO: use enums? Is there a better way to grab this?
+
+ # is_admin = member.has_edit_suborganization_portfolio_permission(portfolio)
+ # is_admin = member._has_portfolio_permission(portfolio, UserPortfolioRoleChoices.ORGANIZATION_ADMIN)
+
+ is_admin = member.id in admin_ids
+
+
# ------- SERIALIZE
return {
"id": member.id,
"name": member.get_formatted_name(),
"email": member.email,
+ "is_admin": is_admin,
"last_active": last_active,
"action_url": '#', #reverse("members", kwargs={"pk": member.id}), #TODO: Future ticket?
"action_label": ("View" if view_only else "Manage"),
"svg_icon": ("visibility" if view_only else "settings"),
}
-
-# return {
-# "id": domain.id,
-# "name": domain.name,
-# "expiration_date": domain.expiration_date,
-# "state": domain.state,
-# "state_display": domain.state_display(),
-# "get_state_help_text": domain.get_state_help_text(),
-# "action_url": reverse("domain", kwargs={"pk": domain.id}),
-# "action_label": ("View" if view_only else "Manage"),
-# "svg_icon": ("visibility" if view_only else "settings"),
-# "domain_info__sub_organization": suborganization_name,
-# }
|