18123: Add group details permissions columns and tweaked renderers
authorStephen Smith <stephen@curii.com>
Wed, 13 Oct 2021 12:34:24 +0000 (08:34 -0400)
committerStephen Smith <stephen@curii.com>
Fri, 19 Nov 2021 19:36:15 +0000 (14:36 -0500)
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen@curii.com>

src/store/group-details-panel/group-details-panel-actions.ts
src/store/group-details-panel/group-details-panel-members-middleware-service.ts [moved from src/store/group-details-panel/group-details-panel-middleware-service.ts with 64% similarity]
src/store/group-details-panel/group-details-panel-permissions-middleware-service.ts [new file with mode: 0644]
src/store/store.ts
src/store/workbench/workbench-actions.ts
src/views-components/data-explorer/renderers.tsx
src/views/group-details-panel/group-details-panel.tsx

index 5a190a5f94e1fe0594ef23006770303056ae739e..e71f75f36c21e7cd5c22eb6e98bc01b6eafecd8c 100644 (file)
@@ -18,26 +18,26 @@ import { PermissionResource } from 'models/permission';
 import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
 import { UserResource, getUserDisplayName } from 'models/user';
 
-export const GROUP_DETAILS_PANEL_ID = 'groupMembersPanel';
-export const GROUP_PERMISSIONS_PANEL_ID = 'groupPermissionsPanel';
+export const GROUP_DETAILS_MEMBERS_PANEL_ID = 'groupDetailsMembersPanel';
+export const GROUP_DETAILS_PERMISSIONS_PANEL_ID = 'groupDetailsPermissionsPanel';
 export const ADD_GROUP_MEMBERS_DIALOG = 'addGrupMembers';
 export const ADD_GROUP_MEMBERS_FORM = 'addGrupMembers';
 export const ADD_GROUP_MEMBERS_USERS_FIELD_NAME = 'users';
 export const MEMBER_ATTRIBUTES_DIALOG = 'memberAttributesDialog';
 export const MEMBER_REMOVE_DIALOG = 'memberRemoveDialog';
 
-export const GroupMembersPanelActions = bindDataExplorerActions(GROUP_DETAILS_PANEL_ID);
-export const GroupPermissionsPanelActions = bindDataExplorerActions(GROUP_PERMISSIONS_PANEL_ID);
+export const GroupMembersPanelActions = bindDataExplorerActions(GROUP_DETAILS_MEMBERS_PANEL_ID);
+export const GroupPermissionsPanelActions = bindDataExplorerActions(GROUP_DETAILS_PERMISSIONS_PANEL_ID);
 
 export const loadGroupDetailsPanel = (groupUuid: string) =>
     (dispatch: Dispatch) => {
-        dispatch(propertiesActions.SET_PROPERTY({ key: GROUP_DETAILS_PANEL_ID, value: groupUuid }));
+        dispatch(propertiesActions.SET_PROPERTY({ key: GROUP_DETAILS_MEMBERS_PANEL_ID, value: groupUuid }));
         dispatch(GroupMembersPanelActions.REQUEST_ITEMS());
-        dispatch(propertiesActions.SET_PROPERTY({ key: GROUP_PERMISSIONS_PANEL_ID, value: groupUuid }));
+        dispatch(propertiesActions.SET_PROPERTY({ key: GROUP_DETAILS_PERMISSIONS_PANEL_ID, value: groupUuid }));
         dispatch(GroupPermissionsPanelActions.REQUEST_ITEMS());
     };
 
-export const getCurrentGroupDetailsPanelUuid = getProperty<string>(GROUP_DETAILS_PANEL_ID);
+export const getCurrentGroupDetailsPanelUuid = getProperty<string>(GROUP_DETAILS_MEMBERS_PANEL_ID);
 
 export interface AddGroupMembersFormData {
     [ADD_GROUP_MEMBERS_USERS_FIELD_NAME]: Participant[];
similarity index 64%
rename from src/store/group-details-panel/group-details-panel-middleware-service.ts
rename to src/store/group-details-panel/group-details-panel-members-middleware-service.ts
index 67f72391f3adb567166500e468d6111f918b308b..e295579a102dd22accd5d21953b7020afbbab2bf 100644 (file)
@@ -10,10 +10,10 @@ import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
 import { getDataExplorer } from "store/data-explorer/data-explorer-reducer";
 import { FilterBuilder } from 'services/api/filter-builder';
 import { updateResources } from 'store/resources/resources-actions';
-import { getCurrentGroupDetailsPanelUuid, GroupMembersPanelActions, GroupPermissionsPanelActions } from 'store/group-details-panel/group-details-panel-actions';
+import { getCurrentGroupDetailsPanelUuid, GroupMembersPanelActions } from 'store/group-details-panel/group-details-panel-actions';
 import { LinkClass } from 'models/link';
 
-export class GroupDetailsPanelMiddlewareService extends DataExplorerMiddlewareService {
+export class GroupDetailsPanelMembersMiddlewareService extends DataExplorerMiddlewareService {
 
     constructor(private services: ServiceRepository, id: string) {
         super(id);
@@ -26,41 +26,26 @@ export class GroupDetailsPanelMiddlewareService extends DataExplorerMiddlewareSe
             api.dispatch(groupsDetailsPanelDataExplorerIsNotSet());
         } else {
             try {
-                const permissionsIn = await this.services.permissionService.list({
+                const permissions = await this.services.permissionService.list({
                     filters: new FilterBuilder()
                         .addEqual('head_uuid', groupUuid)
                         .addEqual('link_class', LinkClass.PERMISSION)
                         .getFilters()
                 });
-                api.dispatch(updateResources(permissionsIn.items));
-                const permissionsOut = await this.services.permissionService.list({
-                    filters: new FilterBuilder()
-                        .addEqual('tail_uuid', groupUuid)
-                        .addEqual('link_class', LinkClass.PERMISSION)
-                        .getFilters()
-                });
-                api.dispatch(updateResources(permissionsOut.items));
+                api.dispatch(updateResources(permissions.items));
+
                 const users = await this.services.userService.list({
                     filters: new FilterBuilder()
-                        .addIn('uuid', permissionsIn.items.map(item => item.tailUuid))
-                        .getFilters(),
-                    count: "none"
-                });
-                const usersOut = await this.services.userService.list({
-                    filters: new FilterBuilder()
-                        .addIn('uuid', permissionsOut.items.map(item => item.tailUuid))
+                        .addIn('uuid', permissions.items.map(item => item.tailUuid))
                         .getFilters(),
                     count: "none"
                 });
+                api.dispatch(updateResources(users.items));
+
                 api.dispatch(GroupMembersPanelActions.SET_ITEMS({
-                    ...listResultsToDataExplorerItemsMeta(permissionsIn),
+                    ...listResultsToDataExplorerItemsMeta(permissions),
                     items: users.items.map(item => item.uuid),
                 }));
-                api.dispatch(GroupPermissionsPanelActions.SET_ITEMS({
-                    ...listResultsToDataExplorerItemsMeta(permissionsOut),
-                    items: usersOut.items.map(item => item.uuid),
-                }));
-                api.dispatch(updateResources(users.items));
             } catch (e) {
                 api.dispatch(couldNotFetchGroupDetailsContents());
             }
diff --git a/src/store/group-details-panel/group-details-panel-permissions-middleware-service.ts b/src/store/group-details-panel/group-details-panel-permissions-middleware-service.ts
new file mode 100644 (file)
index 0000000..91bff1e
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { Dispatch, MiddlewareAPI } from "redux";
+import { DataExplorerMiddlewareService, listResultsToDataExplorerItemsMeta } from "store/data-explorer/data-explorer-middleware-service";
+import { RootState } from "store/store";
+import { ServiceRepository } from "services/services";
+import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
+import { getDataExplorer } from "store/data-explorer/data-explorer-reducer";
+import { FilterBuilder } from 'services/api/filter-builder';
+import { updateResources } from 'store/resources/resources-actions';
+import { getCurrentGroupDetailsPanelUuid, GroupPermissionsPanelActions } from 'store/group-details-panel/group-details-panel-actions';
+import { LinkClass } from 'models/link';
+
+export class GroupDetailsPanelPermissionsMiddlewareService extends DataExplorerMiddlewareService {
+
+    constructor(private services: ServiceRepository, id: string) {
+        super(id);
+    }
+
+    async requestItems(api: MiddlewareAPI<Dispatch, RootState>) {
+        const dataExplorer = getDataExplorer(api.getState().dataExplorer, this.getId());
+        const groupUuid = getCurrentGroupDetailsPanelUuid(api.getState().properties);
+        if (!dataExplorer || !groupUuid) {
+            api.dispatch(groupsDetailsPanelDataExplorerIsNotSet());
+        } else {
+            try {
+                const permissions = await this.services.permissionService.list({
+                    filters: new FilterBuilder()
+                        .addEqual('tail_uuid', groupUuid)
+                        .addEqual('link_class', LinkClass.PERMISSION)
+                        .getFilters()
+                });
+                api.dispatch(updateResources(permissions.items));
+
+                const users = await this.services.userService.list({
+                    filters: new FilterBuilder()
+                        .addIn('uuid', permissions.items.map(item => item.headUuid))
+                        .getFilters(),
+                    count: "none"
+                });
+                api.dispatch(updateResources(users.items));
+
+                const collections = await this.services.collectionService.list({
+                    filters: new FilterBuilder()
+                        .addIn('uuid', permissions.items.map(item => item.headUuid))
+                        .getFilters(),
+                    count: "none"
+                });
+                api.dispatch(updateResources(collections.items));
+
+                const projects = await this.services.projectService.list({
+                    filters: new FilterBuilder()
+                        .addIn('uuid', permissions.items.map(item => item.headUuid))
+                        .getFilters(),
+                    count: "none"
+                });
+                api.dispatch(updateResources(projects.items));
+
+                api.dispatch(GroupPermissionsPanelActions.SET_ITEMS({
+                    ...listResultsToDataExplorerItemsMeta(permissions),
+                    items: permissions.items.map(item => item.uuid),
+                }));
+            } catch (e) {
+                api.dispatch(couldNotFetchGroupDetailsContents());
+            }
+        }
+    }
+}
+
+const groupsDetailsPanelDataExplorerIsNotSet = () =>
+    snackbarActions.OPEN_SNACKBAR({
+        message: 'Group permissions panel is not ready.',
+        kind: SnackbarKind.ERROR
+    });
+
+const couldNotFetchGroupDetailsContents = () =>
+    snackbarActions.OPEN_SNACKBAR({
+        message: 'Could not fetch group permissions.',
+        kind: SnackbarKind.ERROR
+    });
index 59a0cb12eebbb560e4056b07289f2bbd2a96901b..688c8a0564e414dd7eecbffd70ec556debf1ac13 100644 (file)
@@ -51,8 +51,9 @@ import { UserMiddlewareService } from 'store/users/user-panel-middleware-service
 import { USERS_PANEL_ID } from 'store/users/users-actions';
 import { GroupsPanelMiddlewareService } from 'store/groups-panel/groups-panel-middleware-service';
 import { GROUPS_PANEL_ID } from 'store/groups-panel/groups-panel-actions';
-import { GroupDetailsPanelMiddlewareService } from 'store/group-details-panel/group-details-panel-middleware-service';
-import { GROUP_DETAILS_PANEL_ID } from 'store/group-details-panel/group-details-panel-actions';
+import { GroupDetailsPanelMembersMiddlewareService } from 'store/group-details-panel/group-details-panel-members-middleware-service';
+import { GroupDetailsPanelPermissionsMiddlewareService } from 'store/group-details-panel/group-details-panel-permissions-middleware-service';
+import { GROUP_DETAILS_MEMBERS_PANEL_ID, GROUP_DETAILS_PERMISSIONS_PANEL_ID } from 'store/group-details-panel/group-details-panel-actions';
 import { LINK_PANEL_ID } from 'store/link-panel/link-panel-actions';
 import { LinkMiddlewareService } from 'store/link-panel/link-panel-middleware-service';
 import { API_CLIENT_AUTHORIZATION_PANEL_ID } from 'store/api-client-authorizations/api-client-authorizations-actions';
@@ -116,8 +117,11 @@ export function configureStore(history: History, services: ServiceRepository, co
     const groupsPanelMiddleware = dataExplorerMiddleware(
         new GroupsPanelMiddlewareService(services, GROUPS_PANEL_ID)
     );
-    const groupDetailsPanelMiddleware = dataExplorerMiddleware(
-        new GroupDetailsPanelMiddlewareService(services, GROUP_DETAILS_PANEL_ID)
+    const groupDetailsPanelMembersMiddleware = dataExplorerMiddleware(
+        new GroupDetailsPanelMembersMiddlewareService(services, GROUP_DETAILS_MEMBERS_PANEL_ID)
+    );
+    const groupDetailsPanelPermissionsMiddleware = dataExplorerMiddleware(
+        new GroupDetailsPanelPermissionsMiddlewareService(services, GROUP_DETAILS_PERMISSIONS_PANEL_ID)
     );
     const linkPanelMiddleware = dataExplorerMiddleware(
         new LinkMiddlewareService(services, LINK_PANEL_ID)
@@ -157,7 +161,8 @@ export function configureStore(history: History, services: ServiceRepository, co
         workflowPanelMiddleware,
         userPanelMiddleware,
         groupsPanelMiddleware,
-        groupDetailsPanelMiddleware,
+        groupDetailsPanelMembersMiddleware,
+        groupDetailsPanelPermissionsMiddleware,
         linkPanelMiddleware,
         apiClientAuthorizationMiddlewareService,
         publicFavoritesMiddleware,
index 1ee0a9f88625fe7ba3b5746db29a81c418bfa708..9c89d19932b78a14670c0dea5ef2422cceb3cde1 100644 (file)
@@ -88,7 +88,7 @@ import { apiClientAuthorizationPanelColumns } from 'views/api-client-authorizati
 import * as groupPanelActions from 'store/groups-panel/groups-panel-actions';
 import { groupsPanelColumns } from 'views/groups-panel/groups-panel';
 import * as groupDetailsPanelActions from 'store/group-details-panel/group-details-panel-actions';
-import { groupDetailsPanelColumns } from 'views/group-details-panel/group-details-panel';
+import { groupDetailsMembersPanelColumns, groupDetailsPermissionsPanelColumns } from 'views/group-details-panel/group-details-panel';
 import { DataTableFetchMode } from "components/data-table/data-table";
 import { loadPublicFavoritePanel, publicFavoritePanelActions } from 'store/public-favorites-panel/public-favorites-action';
 import { publicFavoritePanelColumns } from 'views/public-favorites-panel/public-favorites-panel';
@@ -136,8 +136,8 @@ export const loadWorkbench = () =>
             dispatch(searchResultsPanelActions.SET_COLUMNS({ columns: searchResultsPanelColumns }));
             dispatch(userBindedActions.SET_COLUMNS({ columns: userPanelColumns }));
             dispatch(groupPanelActions.GroupsPanelActions.SET_COLUMNS({ columns: groupsPanelColumns }));
-            dispatch(groupDetailsPanelActions.GroupMembersPanelActions.SET_COLUMNS({ columns: groupDetailsPanelColumns }));
-            dispatch(groupDetailsPanelActions.GroupPermissionsPanelActions.SET_COLUMNS({ columns: groupDetailsPanelColumns }));
+            dispatch(groupDetailsPanelActions.GroupMembersPanelActions.SET_COLUMNS({ columns: groupDetailsMembersPanelColumns }));
+            dispatch(groupDetailsPanelActions.GroupPermissionsPanelActions.SET_COLUMNS({ columns: groupDetailsPermissionsPanelColumns }));
             dispatch(linkPanelActions.SET_COLUMNS({ columns: linkPanelColumns }));
             dispatch(apiClientAuthorizationsActions.SET_COLUMNS({ columns: apiClientAuthorizationPanelColumns }));
             dispatch(collectionsContentAddressActions.SET_COLUMNS({ columns: collectionContentAddressPanelColumns }));
index ef8f70d47682543734af4d5ad13ef24a2e354c4f..6766d4c00fad4046022ef53b3b5c5aca064cfd80 100644 (file)
@@ -20,7 +20,7 @@ import { WorkflowResource } from 'models/workflow';
 import { ResourceStatus as WorkflowStatus } from 'views/workflow-panel/workflow-panel-view';
 import { getUuidPrefix, openRunProcess } from 'store/workflow-panel/workflow-panel-actions';
 import { openSharingDialog } from 'store/sharing-dialog/sharing-dialog-actions';
-import { getUserFullname, User, UserResource } from 'models/user';
+import { getUserFullname, getUserDisplayName, User, UserResource } from 'models/user';
 import { toggleIsActive, toggleIsAdmin } from 'store/users/users-actions';
 import { LinkResource } from 'models/link';
 import { navigateTo } from 'store/navigation/navigation-action';
@@ -286,45 +286,50 @@ export const ResourceLinkClass = connect(
         return resource || { linkClass: '' };
     })(renderLinkClass);
 
-const renderLinkTail = (dispatch: Dispatch, item: { uuid: string, tailUuid: string, tailKind: string }) => {
-    const currentLabel = resourceLabel(item.tailKind);
-    const isUnknow = currentLabel === "Unknown";
-    return (<div>
-        {!isUnknow ? (
-            renderLink(dispatch, item.tailUuid, currentLabel)
-        ) : (
-                <Typography noWrap color="default">
-                    {item.tailUuid}
-                </Typography>
-            )}
-    </div>);
-};
-
-const renderLink = (dispatch: Dispatch, uuid: string, label: string) =>
-    <Typography noWrap color="primary" style={{ 'cursor': 'pointer' }} onClick={() => dispatch<any>(navigateTo(uuid))}>
-        {label}: {uuid}
+// const renderLinkTail = (dispatch: Dispatch, item: { uuid: string, tailUuid: string, tailKind: string }) => {
+//     const currentLabel = resourceLabel(item.tailKind);
+//     const isUnknow = currentLabel === "Unknown";
+//     return (<div>
+//         {!isUnknow ? (
+//             renderLink(dispatch, item.tailUuid, "name", currentLabel)
+//         ) : (
+//                 <Typography noWrap color="default">
+//                     {item.tailUuid}
+//                 </Typography>
+//             )}
+//     </div>);
+// };
+
+const renderLink = (dispatch: Dispatch, item: Resource) => {
+    const name = (item as LinkResource).name;
+    const fullName = getUserDisplayName(item as UserResource);
+
+    return <Typography noWrap color="primary" style={{ 'cursor': 'pointer' }} onClick={() => dispatch<any>(navigateTo(item.uuid))}>
+        {resourceLabel(item.kind)}: {name || fullName || item.uuid}
     </Typography>;
+}
 
 export const ResourceLinkTail = connect(
     (state: RootState, props: { uuid: string }) => {
         const resource = getResource<LinkResource>(props.uuid)(state.resources);
+        const tailResource = getResource<Resource>(resource?.tailUuid || '')(state.resources);
+
         return {
-            item: resource || { uuid: '', tailUuid: '', tailKind: ResourceKind.NONE }
+            item: tailResource || { uuid: resource?.tailUuid || '', kind: resource?.headKind || ResourceKind.NONE }
         };
-    })((props: { item: any } & DispatchProp<any>) =>
-        renderLinkTail(props.dispatch, props.item));
-
-const renderLinkHead = (dispatch: Dispatch, item: { uuid: string, headUuid: string, headKind: ResourceKind }) =>
-    renderLink(dispatch, item.headUuid, resourceLabel(item.headKind));
+    })((props: { item: Resource } & DispatchProp<any>) =>
+        renderLink(props.dispatch, props.item));
 
 export const ResourceLinkHead = connect(
     (state: RootState, props: { uuid: string }) => {
         const resource = getResource<LinkResource>(props.uuid)(state.resources);
+        const headResource = getResource<Resource>(resource?.headUuid || '')(state.resources);
+
         return {
-            item: resource || { uuid: '', headUuid: '', headKind: ResourceKind.NONE }
+            item: headResource || { uuid: resource?.headUuid || '', kind: resource?.headKind || ResourceKind.NONE }
         };
-    })((props: { item: any } & DispatchProp<any>) =>
-        renderLinkHead(props.dispatch, props.item));
+    })((props: { item: Resource } & DispatchProp<any>) =>
+        renderLink(props.dispatch, props.item));
 
 export const ResourceLinkUuid = connect(
     (state: RootState, props: { uuid: string }) => {
index 3885ec18f59e216480edcd2dd5c6caa60aa56e4f..3baff57973544c6ef96c7d3c9e912147fc82aa91 100644 (file)
@@ -7,11 +7,11 @@ import { connect } from 'react-redux';
 
 import { DataExplorer } from "views-components/data-explorer/data-explorer";
 import { DataColumns } from 'components/data-table/data-table';
-import { ResourceFullName, ResourceUuid, ResourceEmail, ResourceUsername } from 'views-components/data-explorer/renderers';
+import { ResourceFullName, ResourceUuid, ResourceEmail, ResourceUsername, ResourceLinkName, ResourceLinkHead, ResourceName } from 'views-components/data-explorer/renderers';
 import { createTree } from 'models/tree';
 import { noop } from 'lodash/fp';
 import { RootState } from 'store/store';
-import { GROUP_DETAILS_PANEL_ID, GROUP_PERMISSIONS_PANEL_ID, openAddGroupMembersDialog } from 'store/group-details-panel/group-details-panel-actions';
+import { GROUP_DETAILS_MEMBERS_PANEL_ID, GROUP_DETAILS_PERMISSIONS_PANEL_ID, openAddGroupMembersDialog } from 'store/group-details-panel/group-details-panel-actions';
 import { openContextMenu } from 'store/context-menu/context-menu-actions';
 import { ResourcesState, getResource } from 'store/resources/resources';
 import { ContextMenuKind } from 'views-components/context-menu/context-menu';
@@ -19,37 +19,43 @@ import { PermissionResource } from 'models/permission';
 import { Grid, Button, Tabs, Tab, Paper } from '@material-ui/core';
 import { AddIcon } from 'components/icon/icon';
 
-export enum GroupDetailsPanelColumnNames {
+export enum GroupDetailsPanelMembersColumnNames {
     FULL_NAME = "Name",
     UUID = "UUID",
     EMAIL = "Email",
     USERNAME = "Username",
 }
 
-export const groupDetailsPanelColumns: DataColumns<string> = [
+export enum GroupDetailsPanelPermissionsColumnNames {
+    HEAD = "Head",
+    NAME = "Name",
+    UUID = "UUID",
+}
+
+export const groupDetailsMembersPanelColumns: DataColumns<string> = [
     {
-        name: GroupDetailsPanelColumnNames.FULL_NAME,
+        name: GroupDetailsPanelMembersColumnNames.FULL_NAME,
         selected: true,
         configurable: true,
         filters: createTree(),
         render: uuid => <ResourceFullName uuid={uuid} />
     },
     {
-        name: GroupDetailsPanelColumnNames.USERNAME,
+        name: GroupDetailsPanelMembersColumnNames.USERNAME,
         selected: true,
         configurable: true,
         filters: createTree(),
         render: uuid => <ResourceUsername uuid={uuid} />
     },
     {
-        name: GroupDetailsPanelColumnNames.UUID,
+        name: GroupDetailsPanelMembersColumnNames.UUID,
         selected: true,
         configurable: true,
         filters: createTree(),
         render: uuid => <ResourceUuid uuid={uuid} />
     },
     {
-        name: GroupDetailsPanelColumnNames.EMAIL,
+        name: GroupDetailsPanelMembersColumnNames.EMAIL,
         selected: true,
         configurable: true,
         filters: createTree(),
@@ -57,6 +63,30 @@ export const groupDetailsPanelColumns: DataColumns<string> = [
     },
 ];
 
+export const groupDetailsPermissionsPanelColumns: DataColumns<string> = [
+    {
+        name: GroupDetailsPanelPermissionsColumnNames.HEAD,
+        selected: true,
+        configurable: true,
+        filters: createTree(),
+        render: uuid => <ResourceLinkHead uuid={uuid} />
+    },
+    {
+        name: GroupDetailsPanelPermissionsColumnNames.NAME,
+        selected: true,
+        configurable: true,
+        filters: createTree(),
+        render: uuid => <ResourceLinkName uuid={uuid} />
+    },
+    {
+        name: GroupDetailsPanelPermissionsColumnNames.UUID,
+        selected: true,
+        configurable: true,
+        filters: createTree(),
+        render: uuid => <ResourceUuid uuid={uuid} />
+    },
+];
+
 const mapStateToProps = (state: RootState) => {
     return {
         resources: state.resources
@@ -90,13 +120,13 @@ export const GroupDetailsPanel = connect(
             const { value } = this.state;
             return (
                 <Paper>
-                  <Tabs value={value} onChange={this.handleChange} fullWidth>
+                  <Tabs value={value} onChange={this.handleChange} variant="fullWidth">
                       <Tab label="MEMBERS" />
                       <Tab label="PERMISSIONS" />
                   </Tabs>
                   {value === 0 &&
                       <DataExplorer
-                          id={GROUP_DETAILS_PANEL_ID}
+                          id={GROUP_DETAILS_MEMBERS_PANEL_ID}
                           onRowClick={noop}
                           onRowDoubleClick={noop}
                           onContextMenu={this.handleContextMenu}
@@ -119,7 +149,7 @@ export const GroupDetailsPanel = connect(
                   }
                   {value === 1 &&
                       <DataExplorer
-                          id={GROUP_PERMISSIONS_PANEL_ID}
+                          id={GROUP_DETAILS_PERMISSIONS_PANEL_ID}
                           onRowClick={noop}
                           onRowDoubleClick={noop}
                           onContextMenu={this.handleContextMenu}