group access_dropdown.vue - add custom roles section
## Context | | | |---|---| | **Phase** | 5 of 6 | | **Parallel with** | https://gitlab.com/gitlab-org/gitlab/-/work_items/594887+ <br> https://gitlab.com/gitlab-org/gitlab/-/work_items/594888+ <br> https://gitlab.com/gitlab-org/gitlab/-/work_items/594889+ | | **Blocked by** | https://gitlab.com/gitlab-org/gitlab/-/work_items/594882+ <br> https://gitlab.com/gitlab-org/gitlab/-/work_items/594885+ <br> https://gitlab.com/gitlab-org/gitlab/-/work_items/594886+ | | **Unblocks** | https://gitlab.com/gitlab-org/gitlab/-/work_items/594891+ | ## Summary Add custom role selection support to the group-level settings access dropdown (`app/assets/javascripts/groups/settings/components/access_dropdown.vue`), enabling custom roles to be selected when configuring group-level protected branches. ## Background Group settings has its own access dropdown component, separate from the project settings one. It currently supports Roles, Groups, and Users — but no Deploy Keys or Custom Roles. The component is used in the group protected branches settings page. This component fetches sub-groups (not project groups) and optionally users. Custom roles for the group must be fetched from the same `GET /groups/:id/member_roles` endpoint used by the project dropdown. The groups dropdown uses `app/assets/javascripts/groups/settings/constants.js` for `LEVEL_TYPES` (updated in Issue 12). ## Relevant files - `app/assets/javascripts/groups/settings/components/access_dropdown.vue` (352 lines) - `app/assets/javascripts/groups/settings/constants.js` — `LEVEL_TYPES` (updated in Issue 12) - `app/assets/javascripts/groups/settings/api/access_dropdown_api.js` — has `getSubGroups` and `getUsers` ## Changes required ### New EE API utility (if not reusing Issue 11's file) Add `getMemberRoles` to `ee/app/assets/javascripts/groups/settings/api/access_dropdown_api.js` (create if not exists): ```javascript import axios from '~/lib/utils/axios_utils'; const BASE_PATH = '/api/v4/groups'; export const getMemberRoles = (groupId) => { return axios.get(`${gon.relative_url_root || ''}${BASE_PATH}/${groupId}/member_roles`); }; ``` ### Data ```javascript data() { return { // ...existing customRoles: [], selected: { [LEVEL_TYPES.ROLE]: [], [LEVEL_TYPES.GROUP]: [], [LEVEL_TYPES.USER]: [], [LEVEL_TYPES.MEMBER_ROLE]: [], // add }, }; }, ``` ### `getData()` method When `hasLicense`, add `getMemberRoles(groupId)` to the `Promise.all` call. The group ID can be obtained from a prop or `gon.current_group_id`. ### `consolidateData()` method Populate `this.customRoles` from the response, tagging with `type: LEVEL_TYPES.MEMBER_ROLE`. ### `setDataForSave()`, `selection`, `setSelected()`, `toggleLabel` Apply identical changes to those in Issues 13 and 14 for the project dropdown: - `setDataForSave`: detect `member_role_id`, check before `access_level` - `selection`: include `getDataForSave(LEVEL_TYPES.MEMBER_ROLE, 'member_role_id')` - `setSelected`: restore custom role selection from preselected items - `toggleLabel`: add "N custom roles" count ### Template Add "Custom Roles" section between Roles and Groups, mirroring the project dropdown template changes in Issue 13. ```html <template v-if="customRoles.length"> <gl-dropdown-section-header>{{ $options.i18n.customRolesSectionHeader }}</gl-dropdown-section-header> <gl-dropdown-item v-for="role in customRoles" :key="`member-role-${role.id}`" data-testid="member-role-dropdown-item" is-check-item :is-checked="isSelected(role)" @click.capture.native.stop="onItemClick(role)" > {{ role.name }} </gl-dropdown-item> <gl-dropdown-divider v-if="groups.length || users.length" /> </template> ``` ## Notes - The group dropdown does not support Deploy Keys — the `canAdminContainer` guard used in the project dropdown does not apply here in the same way. Check what condition gates the custom roles fetch (likely just `hasLicense`) - Group ID: The group dropdown does not currently have a `gon.current_group_id` equivalent wired up universally — check how the component is instantiated in the group settings page and pass the group ID via prop if necessary - Coordinate with Issue 8 (group API) to ensure the save payload `{ member_role_id: N }` is accepted by the group protected branches API ## Testing - Jest: custom roles section renders when `customRoles` has items - Jest: `getMemberRoles` called when `hasLicense` is true - Jest: `setDataForSave` correctly identifies `member_role_id` items (checks before `access_level`) - Jest: `selection` includes `{ member_role_id: N }` for selected custom roles - Jest: `setSelected` restores custom role selection from preselected items - Jest: `toggleLabel` shows "1 custom role" / "N custom roles" ## Dependencies - Issue 8 (group API) — backend must accept `member_role_id` for group protected branches - Issue 12 (`MEMBER_ROLE` constant in groups constants) - Issues 13 & 14 patterns (use same approach, different component file) ## Labels
issue