Skip to content

Swap button for dropdowns in group members page

What does this MR do and why?

In the group members page, we replaced the buttons in the right side of the table for dropdowns. This is in preparation for adding one more action, Disable two-factor authentication, to this dropdown. See &9484 (closed)

The size of this MR is big, so to facilitate the review I have broken into a series of commits. Sequence of commits:

  1. Replace buttons by dropdowns
  2. Rename files
  3. Improve test coverage
  4. Fix failing rspecs

It maybe simpler to look at the changes on each of the individual commits.

Closes: #385614 (closed)

Screenshots or screen recordings

Before

image

After

The content of the dropdowns are shown only when clicked. The screenshot has been prepared to show the differences.

image

Notice the buttons in the other tabs (Groups, Invited and Access requests) still shows actions in the form of buttons.

How to set up and validate locally

Go to the Flightjs group members page: https://gdk.test:3443/groups/flightjs/-/group_members

To display the three possible buttons, you can apply this patch (expand the the collapsible section).

Click to expand
diff --git a/app/assets/javascripts/members/index.js b/app/assets/javascripts/members/index.js
index 359239c5c0c..95dd56496db 100644
--- a/app/assets/javascripts/members/index.js
+++ b/app/assets/javascripts/members/index.js
@@ -22,7 +22,386 @@ export const initMembersApp = (el, options) => {
     canFilterByEnterprise,
     exportCsvPath,
     ...vuexStoreAttributes
-  } = parseDataAttributes(el);
+  } = {
+    user: {
+      members: [
+        {
+          id: 427,
+          createdAt: '2022-12-21T09:41:46.229Z',
+          expiresAt: null,
+          requestedAt: null,
+          createdBy: {
+            name: 'Super Administrator',
+            webUrl: 'https://gdk.test:3443/root',
+          },
+          canUpdate: true,
+          canRemove: true,
+          isLastOwner: false,
+          isDirectMember: true,
+          accessLevel: {
+            stringValue: 'Owner',
+            integerValue: 50,
+          },
+          source: {
+            id: 31,
+            fullName: 'Flightjs',
+            webUrl: 'https://gdk.test:3443/groups/flightjs',
+          },
+          type: 'GroupMember',
+          validRoles: {
+            Guest: 10,
+            Reporter: 20,
+            Developer: 30,
+            Maintainer: 40,
+            Owner: 50,
+            'Minimal Access': 5,
+          },
+          user: {
+            id: 29,
+            username: 'reported_user_7',
+            name: 'Brianna Lehner',
+            avatarUrl:
+              'https://secure.gravatar.com/avatar/70bdca730b2045df686f396eb4231d06?s=80&d=identicon',
+            webUrl: 'https://gdk.test:3443/reported_user_7',
+            showStatus: false,
+            availability: null,
+            createdAt: '2022-05-12T15:51:03.084Z',
+            lastActivityOn: '2022-12-21',
+            blocked: false,
+            isBot: false,
+            twoFactorEnabled: false,
+            oncallSchedules: [],
+            escalationPolicies: [],
+          },
+          state: 0,
+          usingLicense: false,
+          groupSso: false,
+          groupManagedAccount: false,
+          canOverride: false,
+          isOverridden: false,
+          provisionedByThisGroup: false,
+          canUnban: true,
+          banned: false,
+        },
+        {
+          id: 5,
+          createdAt: '2022-05-12T15:49:37.605Z',
+          expiresAt: null,
+          requestedAt: null,
+          canUpdate: true,
+          canRemove: true,
+          isLastOwner: false,
+          isDirectMember: true,
+          accessLevel: {
+            stringValue: 'Owner',
+            integerValue: 50,
+          },
+          source: {
+            id: 31,
+            fullName: 'Flightjs',
+            webUrl: 'https://gdk.test:3443/groups/flightjs',
+          },
+          type: 'GroupMember',
+          validRoles: {
+            Guest: 10,
+            Reporter: 20,
+            Developer: 30,
+            Maintainer: 40,
+            Owner: 50,
+            'Minimal Access': 5,
+          },
+          user: {
+            id: 1,
+            username: 'root',
+            name: 'Super Administrator',
+            avatarUrl:
+              'https://secure.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+            webUrl: 'https://gdk.test:3443/root',
+            showStatus: false,
+            availability: null,
+            createdAt: '2022-05-12T15:49:00.637Z',
+            lastActivityOn: '2022-12-23',
+            blocked: false,
+            isBot: false,
+            twoFactorEnabled: true,
+            oncallSchedules: [],
+            escalationPolicies: [],
+          },
+          state: 0,
+          usingLicense: false,
+          groupSso: false,
+          groupManagedAccount: false,
+          canOverride: false,
+          isOverridden: false,
+          provisionedByThisGroup: false,
+          canUnban: true,
+          banned: false,
+        },
+        {
+          id: 464,
+          createdAt: '2022-12-23T08:10:29.965Z',
+          expiresAt: null,
+          requestedAt: null,
+          createdBy: {
+            name: 'Super Administrator',
+            webUrl: 'https://gdk.test:3443/root',
+          },
+          canUpdate: true,
+          canRemove: false,
+          isLastOwner: false,
+          isDirectMember: true,
+          accessLevel: {
+            stringValue: 'Owner',
+            integerValue: 50,
+          },
+          source: {
+            id: 31,
+            fullName: 'Flightjs',
+            webUrl: 'https://gdk.test:3443/groups/flightjs',
+          },
+          type: 'GroupMember',
+          validRoles: {
+            Guest: 10,
+            Reporter: 20,
+            Developer: 30,
+            Maintainer: 40,
+            Owner: 50,
+            'Minimal Access': 5,
+          },
+          user: {
+            id: 376,
+            username: 'bob',
+            name: 'bob Doe',
+            avatarUrl:
+              'https://secure.gravatar.com/avatar/c44142baacdd839e36e569ff5c7cbe10?s=80&d=identicon',
+            webUrl: 'https://gdk.test:3443/bob',
+            showStatus: false,
+            availability: null,
+            createdAt: '2022-11-22T13:22:09.290Z',
+            lastActivityOn: '2022-11-22',
+            blocked: false,
+            isBot: false,
+            twoFactorEnabled: false,
+            oncallSchedules: [],
+            escalationPolicies: [],
+          },
+          state: 0,
+          usingLicense: false,
+          groupSso: false,
+          groupManagedAccount: false,
+          canOverride: true,
+          isOverridden: false,
+          provisionedByThisGroup: false,
+          canUnban: true,
+          banned: false,
+        },
+      ],
+      pagination: {
+        currentPage: 1,
+        perPage: 50,
+        totalItems: 7,
+        paramName: 'page',
+        params: {
+          invited_members_page: null,
+          search_invited: null,
+        },
+      },
+      memberPath: '/groups/flightjs/-/group_members/:id',
+      ldapOverridePath: '/groups/flightjs/-/group_members/:id/override',
+    },
+    group: {
+      members: [
+        {
+          id: 1,
+          createdAt: '2022-12-09T16:43:36.404Z',
+          expiresAt: null,
+          accessLevel: {
+            stringValue: 'Guest',
+            integerValue: 10,
+          },
+          validRoles: {
+            Guest: 10,
+            Reporter: 20,
+            Developer: 30,
+            Maintainer: 40,
+            Owner: 50,
+          },
+          sharedWithGroup: {
+            avatarUrl: null,
+            webUrl: 'https://gdk.test:3443/groups/2fa_enforced',
+            id: 184,
+            name: '2fa_enforced',
+            fullPath: '2fa_enforced',
+            fullName: '2fa_enforced',
+          },
+          canUpdate: true,
+          canRemove: true,
+          isDirectMember: true,
+          source: {
+            id: 31,
+            fullName: 'Flightjs',
+            webUrl: 'https://gdk.test:3443/groups/flightjs',
+          },
+        },
+      ],
+      pagination: {
+        currentPage: null,
+        perPage: null,
+        totalItems: 1,
+        paramName: null,
+        params: {},
+      },
+      memberPath: '/groups/flightjs/-/group_links/:id',
+    },
+    invite: {
+      members: [
+        {
+          id: 428,
+          createdAt: '2022-12-21T09:45:30.481Z',
+          expiresAt: null,
+          requestedAt: null,
+          createdBy: {
+            name: 'Super Administrator',
+            webUrl: 'https://gdk.test:3443/root',
+          },
+          canUpdate: true,
+          canRemove: true,
+          isLastOwner: false,
+          isDirectMember: true,
+          accessLevel: {
+            stringValue: 'Guest',
+            integerValue: 10,
+          },
+          source: {
+            id: 31,
+            fullName: 'Flightjs',
+            webUrl: 'https://gdk.test:3443/groups/flightjs',
+          },
+          type: 'GroupMember',
+          validRoles: {
+            Guest: 10,
+            Reporter: 20,
+            Developer: 30,
+            Maintainer: 40,
+            Owner: 50,
+            'Minimal Access': 5,
+          },
+          state: 0,
+          invite: {
+            email: 'rubocom@a.com',
+            avatarUrl:
+              'https://secure.gravatar.com/avatar/848c9b3f4de106b3ce6be82279ef9d50?s=80&d=identicon',
+            canResend: true,
+            userState: null,
+          },
+          usingLicense: null,
+          groupSso: false,
+          groupManagedAccount: false,
+          canOverride: false,
+          isOverridden: false,
+          provisionedByThisGroup: false,
+          canUnban: true,
+          banned: false,
+        },
+      ],
+      pagination: {
+        currentPage: 1,
+        perPage: 50,
+        totalItems: 1,
+        paramName: 'invited_members_page',
+        params: {
+          page: null,
+        },
+      },
+      memberPath: '/groups/flightjs/-/group_members/:id',
+      ldapOverridePath: '/groups/flightjs/-/group_members/:id/override',
+    },
+    accessRequest: {
+      members: [
+        {
+          id: 426,
+          createdAt: '2022-12-21T09:39:47.359Z',
+          expiresAt: null,
+          requestedAt: '2022-12-21T09:39:47.344Z',
+          canUpdate: true,
+          canRemove: true,
+          isLastOwner: false,
+          isDirectMember: true,
+          accessLevel: {
+            stringValue: 'Developer',
+            integerValue: 30,
+          },
+          source: {
+            id: 31,
+            fullName: 'Flightjs',
+            webUrl: 'https://gdk.test:3443/groups/flightjs',
+          },
+          type: 'GroupMember',
+          validRoles: {
+            Guest: 10,
+            Reporter: 20,
+            Developer: 30,
+            Maintainer: 40,
+            Owner: 50,
+            'Minimal Access': 5,
+          },
+          user: {
+            id: 21,
+            username: 'charles',
+            name: 'Young Murphy',
+            avatarUrl:
+              'https://secure.gravatar.com/avatar/14e9bcc5b5bb1065bbc505338d4ce54d?s=80&d=identicon',
+            webUrl: 'https://gdk.test:3443/charles',
+            showStatus: false,
+            availability: null,
+            createdAt: '2022-05-12T15:49:02.547Z',
+            lastActivityOn: '2022-12-21',
+            blocked: false,
+            isBot: false,
+            twoFactorEnabled: true,
+            oncallSchedules: [],
+            escalationPolicies: [],
+          },
+          state: 0,
+          usingLicense: false,
+          groupSso: false,
+          groupManagedAccount: false,
+          canOverride: false,
+          isOverridden: false,
+          provisionedByThisGroup: false,
+          canUnban: true,
+          banned: false,
+        },
+      ],
+      pagination: {
+        currentPage: null,
+        perPage: null,
+        totalItems: 1,
+        paramName: null,
+        params: {},
+      },
+      memberPath: '/groups/flightjs/-/group_members/:id',
+      ldapOverridePath: '/groups/flightjs/-/group_members/:id/override',
+    },
+    sourceId: 31,
+    canManageMembers: true,
+    canManageAccessRequests: true,
+    canExportMembers: true,
+    exportCsvPath: '/groups/flightjs/-/group_members/export_csv',
+    canFilterByEnterprise: true,
+    banned: {
+      members: [],
+      pagination: {
+        currentPage: null,
+        perPage: null,
+        totalItems: 0,
+        paramName: null,
+        params: {},
+      },
+      memberPath: '/groups/flightjs/-/group_members/:id',
+      ldapOverridePath: '/groups/flightjs/-/group_members/:id/override',
+    },
+  };
 
   const modules = Object.keys(MEMBER_TYPES).reduce((accumulator, namespace) => {
     const namespacedOptions = options[namespace];

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Eduardo Sanz García

Merge request reports