diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 0e8e4847a..144d1fcab 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -3791,6 +3791,7 @@ class WaffleFlagAdmin(FlagAdmin): if extra_context is None: extra_context = {} extra_context["dns_prototype_flag"] = flag_is_active_for_user(request.user, "dns_prototype_flag") + extra_context["organization_member"] = flag_is_active_for_user(request.user, "organization_member") return super().changelist_view(request, extra_context=extra_context) diff --git a/src/registrar/assets/src/js/getgov/portfolio-member-page.js b/src/registrar/assets/src/js/getgov/portfolio-member-page.js index ac0b7cffe..98bcf7d03 100644 --- a/src/registrar/assets/src/js/getgov/portfolio-member-page.js +++ b/src/registrar/assets/src/js/getgov/portfolio-member-page.js @@ -49,7 +49,7 @@ export function initPortfolioMemberPageToggle() { * on the Add New Member page. */ export function initAddNewMemberPageListeners() { - add_member_form = document.getElementById("add_member_form") + let add_member_form = document.getElementById("add_member_form") if (!add_member_form){ return; } diff --git a/src/registrar/context_processors.py b/src/registrar/context_processors.py index c1547ad88..5a526f86f 100644 --- a/src/registrar/context_processors.py +++ b/src/registrar/context_processors.py @@ -107,6 +107,8 @@ def is_widescreen_mode(request): "/no-organization-requests/", "/no-organization-domains/", "/domain-request/", + # "/members/", + # "/member/" ] is_widescreen = any(path in request.path for path in widescreen_paths) or request.path == "/" is_portfolio_widescreen = bool( diff --git a/src/registrar/forms/portfolio.py b/src/registrar/forms/portfolio.py index 65911200b..92fd23906 100644 --- a/src/registrar/forms/portfolio.py +++ b/src/registrar/forms/portfolio.py @@ -4,7 +4,7 @@ import logging from django import forms from django.core.validators import RegexValidator from django.core.validators import MaxLengthValidator - +from django.utils.safestring import mark_safe from registrar.models import ( PortfolioInvitation, UserPortfolioPermission, @@ -109,13 +109,13 @@ class PortfolioSeniorOfficialForm(forms.ModelForm): cleaned_data.pop("full_name", None) return cleaned_data - -class BasePortfolioMemberForm(forms.ModelForm): +class BasePortfolioMemberForm(forms.Form): + required_star = '*' + role = forms.ChoiceField( - label="Select permission", choices=[ - (UserPortfolioRoleChoices.ORGANIZATION_ADMIN.value, "Admin Access"), - (UserPortfolioRoleChoices.ORGANIZATION_MEMBER.value, "Basic Access") + (UserPortfolioRoleChoices.ORGANIZATION_ADMIN.value, "Admin access"), + (UserPortfolioRoleChoices.ORGANIZATION_MEMBER.value, "Basic access") ], widget=forms.RadioSelect, required=True, @@ -123,12 +123,12 @@ class BasePortfolioMemberForm(forms.ModelForm): "required": "Member access level is required", }, ) - # Permissions for admins + domain_request_permissions_admin = forms.ChoiceField( - label="Select permission", + label=mark_safe(f"Select permission {required_star}"), choices=[ (UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value, "View all requests"), - (UserPortfolioPermissionChoices.EDIT_REQUESTS.value, "Create and edit requests") + (UserPortfolioPermissionChoices.EDIT_REQUESTS.value, "View all requests plus create requests"), ], widget=forms.RadioSelect, required=False, @@ -136,11 +136,12 @@ class BasePortfolioMemberForm(forms.ModelForm): "required": "Admin domain request permission is required", }, ) + member_permissions_admin = forms.ChoiceField( - label="Select permission", + label=mark_safe(f"Select permission {required_star}"), choices=[ (UserPortfolioPermissionChoices.VIEW_MEMBERS.value, "View all members"), - (UserPortfolioPermissionChoices.EDIT_MEMBERS.value, "Create and edit members") + (UserPortfolioPermissionChoices.EDIT_MEMBERS.value, "View all members plus manage members"), ], widget=forms.RadioSelect, required=False, @@ -148,11 +149,13 @@ class BasePortfolioMemberForm(forms.ModelForm): "required": "Admin member permission is required", }, ) + domain_request_permissions_member = forms.ChoiceField( - label="Select permission", + label=mark_safe(f"Select permission {required_star}"), choices=[ - (UserPortfolioPermissionChoices.VIEW_MEMBERS.value, "View all members"), - (UserPortfolioPermissionChoices.EDIT_MEMBERS.value, "Create and edit members") + (UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value, "View all requests"), + (UserPortfolioPermissionChoices.EDIT_REQUESTS.value, "View all requests plus create requests"), + ("no_access", "No access"), ], widget=forms.RadioSelect, required=False, @@ -161,8 +164,6 @@ class BasePortfolioMemberForm(forms.ModelForm): }, ) - # this form dynamically shows/hides some fields, depending on what - # was selected prior. This toggles which field is required or not. ROLE_REQUIRED_FIELDS = { UserPortfolioRoleChoices.ORGANIZATION_ADMIN: [ "domain_request_permissions_admin", @@ -173,10 +174,19 @@ class BasePortfolioMemberForm(forms.ModelForm): ], } + def __init__(self, *args, instance=None, **kwargs): + self.instance = instance + # If we have an instance, set initial + if instance: + kwargs['initial'] = self._map_instance_to_form(instance) + + super().__init__(*args, **kwargs) + def _map_instance_to_form(self, instance): """Maps model instance data to form fields""" if not instance: return {} + mapped_data = {} # Map roles with priority for admin if instance.roles: @@ -192,37 +202,16 @@ class BasePortfolioMemberForm(forms.ModelForm): mapped_data['domain_request_permissions_admin'] = UserPortfolioPermissionChoices.EDIT_REQUESTS.value elif UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value in perms: mapped_data['domain_request_permissions_admin'] = UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value + else: + mapped_data["member_permissions_admin"] = "no_access" if UserPortfolioPermissionChoices.EDIT_MEMBERS.value in perms: mapped_data['member_permissions_admin'] = UserPortfolioPermissionChoices.EDIT_MEMBERS.value elif UserPortfolioPermissionChoices.VIEW_MEMBERS.value in perms: mapped_data['member_permissions_admin'] = UserPortfolioPermissionChoices.VIEW_MEMBERS.value - + return mapped_data - def _map_form_to_instance(self, instance): - """Maps form data to model instance""" - if not self.is_valid(): - return - - role = self.cleaned_data.get("role") - domain_request_permissions_member = self.cleaned_data.get("domain_request_permissions_member") - domain_request_permissions_admin = self.cleaned_data.get('domain_request_permissions_admin') - member_permissions_admin = self.cleaned_data.get('member_permissions_admin') - - instance.roles = [role] - additional_permissions = [] - if domain_request_permissions_member: - additional_permissions.append(domain_request_permissions_member) - elif domain_request_permissions_admin: - additional_permissions.append(domain_request_permissions_admin) - - if member_permissions_admin: - additional_permissions.append(member_permissions_admin) - - instance.additional_permissions = additional_permissions - return instance - def clean(self): cleaned_data = super().clean() role = cleaned_data.get("role") @@ -239,6 +228,27 @@ class BasePortfolioMemberForm(forms.ModelForm): return cleaned_data + def save(self): + """Save the form data to the instance""" + if not self.instance: + raise ValueError("Cannot save form without instance") + + role = self.cleaned_data.get("role") + self.instance.roles = [self.cleaned_data["role"]] + + additional_permissions = [] + if self.cleaned_data.get("domain_request_permissions_member") and self.cleaned_data["domain_request_permissions_member"] != "no_access": + additional_permissions.append(self.cleaned_data["domain_request_permissions_member"]) + elif self.cleaned_data.get("domain_request_permissions_admin"): + additional_permissions.append(self.cleaned_data["domain_request_permissions_admin"]) + + if self.cleaned_data.get("member_permissions_admin"): + additional_permissions.append(self.cleaned_data["member_permissions_admin"]) + self.instance.additional_permissions = additional_permissions + + self.instance.save() + return self.instance + class PortfolioMemberForm(BasePortfolioMemberForm): """ @@ -250,6 +260,7 @@ class PortfolioMemberForm(BasePortfolioMemberForm): "roles", "additional_permissions", ] + def __init__(self, *args, instance=None, **kwargs): super().__init__(*args, **kwargs) self.fields['role'].descriptions = { @@ -258,14 +269,6 @@ class PortfolioMemberForm(BasePortfolioMemberForm): } self.instance = instance self.initial = self._map_instance_to_form(self.instance) - - def save(self): - """Save form data to instance""" - if not self.instance: - self.instance = self.Meta.model() - self._map_form_to_instance(self.instance) - self.instance.save() - return self.instance class PortfolioInvitedMemberForm(BasePortfolioMemberForm): diff --git a/src/registrar/templates/django/forms/widgets/multiple_input.html b/src/registrar/templates/django/forms/widgets/multiple_input.html index 76e19b169..cc0e11989 100644 --- a/src/registrar/templates/django/forms/widgets/multiple_input.html +++ b/src/registrar/templates/django/forms/widgets/multiple_input.html @@ -21,7 +21,7 @@ {% if field and field.field and field.field.descriptions %} {% with description=field.field.descriptions|get_dict_value:option.value %} {% if description %} -
{{ description }}
+{{ description }}
{% endif %} {% endwith %} {% endif %} diff --git a/src/registrar/templates/portfolio_member_permissions.html b/src/registrar/templates/portfolio_member_permissions.html index a5f1731d0..f1db5941c 100644 --- a/src/registrar/templates/portfolio_member_permissions.html +++ b/src/registrar/templates/portfolio_member_permissions.html @@ -9,6 +9,7 @@ {% endblock %} {% block portfolio_content %} +{% include "includes/form_errors.html" with form=form %}