-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create User Groups list details drawer (#1692)
* feat: create user details view * feat: create group details drawer * fix: use events context for user groups drawer
- Loading branch information
1 parent
49a1b89
commit 0cd326e
Showing
7 changed files
with
307 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
117 changes: 117 additions & 0 deletions
117
src/smart-components/access-management/GroupDetailsDrawer.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import { | ||
Drawer, | ||
DrawerActions, | ||
DrawerCloseButton, | ||
DrawerContent, | ||
DrawerContentBody, | ||
DrawerHead, | ||
DrawerPanelContent, | ||
Icon, | ||
Popover, | ||
Tab, | ||
TabTitleText, | ||
Tabs, | ||
Title, | ||
} from '@patternfly/react-core'; | ||
import React, { useEffect } from 'react'; | ||
import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons'; | ||
import { useIntl } from 'react-intl'; | ||
import messages from '../../Messages'; | ||
import { Group } from '../../redux/reducers/group-reducer'; | ||
import GroupDetailsRolesView from './GroupDetailsRolesView'; | ||
import GroupDetailsServiceAccountsView from './GroupDetailsServiceAccountsView'; | ||
import GroupDetailsUsersView from './GroupDetailsUsersView'; | ||
import { EventTypes, useDataViewEventsContext } from '@patternfly/react-data-view'; | ||
|
||
interface GroupDetailsProps { | ||
focusedGroup?: Group; | ||
drawerRef: React.RefObject<HTMLDivElement>; | ||
onClose: () => void; | ||
ouiaId: string; | ||
} | ||
|
||
const GroupDetailsDrawerContent: React.FunctionComponent<GroupDetailsProps> = ({ focusedGroup, drawerRef, onClose, ouiaId }) => { | ||
const [activeTabKey, setActiveTabKey] = React.useState<string | number>(0); | ||
const intl = useIntl(); | ||
|
||
return ( | ||
<DrawerPanelContent> | ||
<DrawerHead> | ||
<Title headingLevel="h2"> | ||
<span tabIndex={focusedGroup ? 0 : -1} ref={drawerRef}>{`${focusedGroup?.name}`}</span> | ||
</Title> | ||
<DrawerActions> | ||
<DrawerCloseButton onClick={onClose} /> | ||
</DrawerActions> | ||
</DrawerHead> | ||
<Tabs isFilled activeKey={activeTabKey} onSelect={(_, tabIndex) => setActiveTabKey(tabIndex)}> | ||
<Tab eventKey={0} title={intl.formatMessage(messages.users)}> | ||
{focusedGroup && <GroupDetailsUsersView groupId={focusedGroup.uuid} ouiaId={`${ouiaId}-users-view`} />} | ||
</Tab> | ||
<Tab eventKey={1} title={intl.formatMessage(messages.serviceAccounts)}> | ||
{focusedGroup && <GroupDetailsServiceAccountsView groupId={focusedGroup.uuid} ouiaId={`${ouiaId}-service-accounts-view`} />} | ||
</Tab> | ||
<Tab | ||
eventKey={2} | ||
title={ | ||
<TabTitleText> | ||
{intl.formatMessage(messages.assignedRoles)} | ||
<Popover | ||
triggerAction="hover" | ||
position="top-end" | ||
headerContent={intl.formatMessage(messages.assignedRoles)} | ||
bodyContent={intl.formatMessage(messages.assignedRolesDescription)} | ||
> | ||
<Icon className="pf-v5-u-pl-sm" isInline> | ||
<OutlinedQuestionCircleIcon /> | ||
</Icon> | ||
</Popover> | ||
</TabTitleText> | ||
} | ||
> | ||
{focusedGroup && <GroupDetailsRolesView groupId={focusedGroup.uuid} ouiaId={`${ouiaId}-assigned-roles-view`} />} | ||
</Tab> | ||
</Tabs> | ||
</DrawerPanelContent> | ||
); | ||
}; | ||
|
||
interface DetailDrawerProps { | ||
setFocusedGroup: (group: Group | undefined) => void; | ||
focusedGroup?: Group; | ||
children: React.ReactNode; | ||
ouiaId: string; | ||
} | ||
|
||
const GroupDetailsDrawer: React.FunctionComponent<DetailDrawerProps> = ({ focusedGroup, setFocusedGroup, children, ouiaId }) => { | ||
const drawerRef = React.useRef<HTMLDivElement>(null); | ||
const context = useDataViewEventsContext(); | ||
|
||
useEffect(() => { | ||
const unsubscribe = context.subscribe(EventTypes.rowClick, (group: Group | undefined) => { | ||
setFocusedGroup(group); | ||
drawerRef.current?.focus(); | ||
}); | ||
|
||
return () => unsubscribe(); | ||
}, [drawerRef]); | ||
|
||
return ( | ||
<Drawer isExpanded={Boolean(focusedGroup)} onExpand={() => drawerRef.current?.focus()} data-ouia-component-id={ouiaId}> | ||
<DrawerContent | ||
panelContent={ | ||
<GroupDetailsDrawerContent | ||
ouiaId={`${ouiaId}-panel-content`} | ||
focusedGroup={focusedGroup} | ||
drawerRef={drawerRef} | ||
onClose={() => setFocusedGroup(undefined)} | ||
/> | ||
} | ||
> | ||
<DrawerContentBody hasPadding>{children}</DrawerContentBody> | ||
</DrawerContent> | ||
</Drawer> | ||
); | ||
}; | ||
|
||
export default GroupDetailsDrawer; |
42 changes: 42 additions & 0 deletions
42
src/smart-components/access-management/GroupDetailsRolesView.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { DataView, DataViewTable } from '@patternfly/react-data-view'; | ||
import React, { useCallback, useEffect } from 'react'; | ||
import { useDispatch, useSelector } from 'react-redux'; | ||
import { RBACStore } from '../../redux/store'; | ||
import messages from '../../Messages'; | ||
import { useIntl } from 'react-intl'; | ||
import { fetchRolesForGroup } from '../../redux/actions/group-actions'; | ||
|
||
interface GroupRolesViewProps { | ||
groupId: string; | ||
ouiaId: string; | ||
} | ||
|
||
const GroupDetailsRolesView: React.FunctionComponent<GroupRolesViewProps> = ({ groupId, ouiaId }) => { | ||
const dispatch = useDispatch(); | ||
const intl = useIntl(); | ||
const GROUP_ROLES_COLUMNS: string[] = [intl.formatMessage(messages.roles), intl.formatMessage(messages.workspace)]; | ||
|
||
const roles = useSelector((state: RBACStore) => state.groupReducer?.selectedGroup?.roles?.data || []); | ||
|
||
const fetchData = useCallback(() => { | ||
dispatch(fetchRolesForGroup(groupId, { limit: 1000 })); | ||
}, [dispatch, groupId]); | ||
|
||
useEffect(() => { | ||
fetchData(); | ||
}, [fetchData]); | ||
|
||
const rows = roles.map((role: any) => ({ | ||
row: [role.display_name, '?'], // TODO: Update once API provides workspace data | ||
})); | ||
|
||
return ( | ||
<div className="pf-v5-u-pt-md"> | ||
<DataView ouiaId={ouiaId}> | ||
<DataViewTable variant="compact" aria-label="GroupRolesView" ouiaId={`${ouiaId}-table`} columns={GROUP_ROLES_COLUMNS} rows={rows} /> | ||
</DataView> | ||
</div> | ||
); | ||
}; | ||
|
||
export default GroupDetailsRolesView; |
52 changes: 52 additions & 0 deletions
52
src/smart-components/access-management/GroupDetailsServiceAccountsView.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { DataView, DataViewTable } from '@patternfly/react-data-view'; | ||
import React, { useCallback, useEffect } from 'react'; | ||
import { useDispatch, useSelector } from 'react-redux'; | ||
import { RBACStore } from '../../redux/store'; | ||
import messages from '../../Messages'; | ||
import { useIntl } from 'react-intl'; | ||
import { fetchServiceAccountsForGroup } from '../../redux/actions/group-actions'; | ||
|
||
interface GroupDetailsServiceAccountsViewProps { | ||
groupId: string; | ||
ouiaId: string; | ||
} | ||
|
||
const GroupDetailsServiceAccountsView: React.FunctionComponent<GroupDetailsServiceAccountsViewProps> = ({ groupId, ouiaId }) => { | ||
const dispatch = useDispatch(); | ||
const intl = useIntl(); | ||
const GROUP_SERVICE_ACCOUNTS_COLUMNS: string[] = [ | ||
intl.formatMessage(messages.name), | ||
intl.formatMessage(messages.clientId), | ||
intl.formatMessage(messages.owner), | ||
]; | ||
|
||
const serviceAccounts = useSelector((state: RBACStore) => state.groupReducer?.selectedGroup?.serviceAccounts?.data || []); | ||
|
||
const fetchData = useCallback(() => { | ||
dispatch(fetchServiceAccountsForGroup(groupId, { limit: 1000 })); | ||
}, [dispatch, groupId]); | ||
|
||
useEffect(() => { | ||
fetchData(); | ||
}, [fetchData]); | ||
|
||
const rows = serviceAccounts.map((serviceAccount: any) => ({ | ||
row: [serviceAccount.name, serviceAccount.clientId, serviceAccount.owner], | ||
})); | ||
|
||
return ( | ||
<div className="pf-v5-u-pt-md"> | ||
<DataView ouiaId={ouiaId}> | ||
<DataViewTable | ||
variant="compact" | ||
aria-label="GroupServiceAccountsView" | ||
ouiaId={`${ouiaId}-table`} | ||
columns={GROUP_SERVICE_ACCOUNTS_COLUMNS} | ||
rows={rows} | ||
/> | ||
</DataView> | ||
</div> | ||
); | ||
}; | ||
|
||
export default GroupDetailsServiceAccountsView; |
46 changes: 46 additions & 0 deletions
46
src/smart-components/access-management/GroupDetailsUsersView.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { DataView, DataViewTable } from '@patternfly/react-data-view'; | ||
import React, { useCallback, useEffect } from 'react'; | ||
import { useDispatch, useSelector } from 'react-redux'; | ||
import { RBACStore } from '../../redux/store'; | ||
import messages from '../../Messages'; | ||
import { useIntl } from 'react-intl'; | ||
import { fetchMembersForGroup } from '../../redux/actions/group-actions'; | ||
|
||
interface GroupDetailsUsersViewProps { | ||
groupId: string; | ||
ouiaId: string; | ||
} | ||
|
||
const GroupDetailsUsersView: React.FunctionComponent<GroupDetailsUsersViewProps> = ({ groupId, ouiaId }) => { | ||
const dispatch = useDispatch(); | ||
const intl = useIntl(); | ||
const GROUP_USERS_COLUMNS: string[] = [ | ||
intl.formatMessage(messages.username), | ||
intl.formatMessage(messages.firstName), | ||
intl.formatMessage(messages.lastName), | ||
]; | ||
|
||
const serviceAccounts = useSelector((state: RBACStore) => state.groupReducer?.selectedGroup?.members?.data || []); | ||
|
||
const fetchData = useCallback(() => { | ||
dispatch(fetchMembersForGroup(groupId, { limit: 1000 })); | ||
}, [dispatch, groupId]); | ||
|
||
useEffect(() => { | ||
fetchData(); | ||
}, [fetchData]); | ||
|
||
const rows = serviceAccounts.map((user: any) => ({ | ||
row: [user.username, user.first_name, user.last_name], // TODO: Last name is not showing (fix this) | ||
})); | ||
|
||
return ( | ||
<div className="pf-v5-u-pt-md"> | ||
<DataView ouiaId={ouiaId}> | ||
<DataViewTable variant="compact" aria-label="GroupDetailsUsersView" ouiaId={`${ouiaId}-table`} columns={GROUP_USERS_COLUMNS} rows={rows} /> | ||
</DataView> | ||
</div> | ||
); | ||
}; | ||
|
||
export default GroupDetailsUsersView; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.