18123: Add tests for hide group member and rename/delete group.
[arvados-workbench2.git] / src / views / group-details-panel / group-details-panel.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React from 'react';
6 import { connect } from 'react-redux';
7
8 import { DataExplorer } from "views-components/data-explorer/data-explorer";
9 import { DataColumns } from 'components/data-table/data-table';
10 import { ResourceLinkHeadUuid, ResourceLinkTailUuid, ResourceLinkTailEmail, ResourceLinkTailUsername, ResourceLinkHeadPermissionLevel, ResourceLinkTailPermissionLevel, ResourceLinkHead, ResourceLinkTail, ResourceLinkDelete, ResourceLinkTailIsActive, ResourceLinkTailIsHidden } from 'views-components/data-explorer/renderers';
11 import { createTree } from 'models/tree';
12 import { noop } from 'lodash/fp';
13 import { RootState } from 'store/store';
14 import { GROUP_DETAILS_MEMBERS_PANEL_ID, GROUP_DETAILS_PERMISSIONS_PANEL_ID, openAddGroupMembersDialog, getCurrentGroupDetailsPanelUuid } from 'store/group-details-panel/group-details-panel-actions';
15 import { openContextMenu } from 'store/context-menu/context-menu-actions';
16 import { ResourcesState, getResource } from 'store/resources/resources';
17 import { Grid, Button, Tabs, Tab, Paper } from '@material-ui/core';
18 import { AddIcon } from 'components/icon/icon';
19 import { getUserUuid } from 'common/getuser';
20 import { GroupResource } from 'models/group';
21
22 export enum GroupDetailsPanelMembersColumnNames {
23     FULL_NAME = "Name",
24     USERNAME = "Username",
25     EMAIL = "Email",
26     ACTIVE = "User Active",
27     HIDDEN = "Member Hidden",
28     PERMISSION = "Permission",
29     UUID = "UUID",
30     REMOVE = "Remove",
31 }
32
33 export enum GroupDetailsPanelPermissionsColumnNames {
34     NAME = "Name",
35     PERMISSION = "Permission",
36     UUID = "UUID",
37     REMOVE = "Remove",
38 }
39
40 export const groupDetailsMembersPanelColumns: DataColumns<string> = [
41     {
42         name: GroupDetailsPanelMembersColumnNames.FULL_NAME,
43         selected: true,
44         configurable: true,
45         filters: createTree(),
46         render: uuid => <ResourceLinkTail uuid={uuid} />
47     },
48     {
49         name: GroupDetailsPanelMembersColumnNames.USERNAME,
50         selected: true,
51         configurable: true,
52         filters: createTree(),
53         render: uuid => <ResourceLinkTailUsername uuid={uuid} />
54     },
55     {
56         name: GroupDetailsPanelMembersColumnNames.EMAIL,
57         selected: true,
58         configurable: true,
59         filters: createTree(),
60         render: uuid => <ResourceLinkTailEmail uuid={uuid} />
61     },
62     {
63         name: GroupDetailsPanelMembersColumnNames.ACTIVE,
64         selected: true,
65         configurable: true,
66         filters: createTree(),
67         render: uuid => <ResourceLinkTailIsActive uuid={uuid} />
68     },
69     {
70         name: GroupDetailsPanelMembersColumnNames.HIDDEN,
71         selected: true,
72         configurable: true,
73         filters: createTree(),
74         render: uuid => <ResourceLinkTailIsHidden uuid={uuid} />
75     },
76     {
77         name: GroupDetailsPanelMembersColumnNames.PERMISSION,
78         selected: true,
79         configurable: true,
80         filters: createTree(),
81         render: uuid => <ResourceLinkTailPermissionLevel uuid={uuid} />
82     },
83     {
84         name: GroupDetailsPanelMembersColumnNames.UUID,
85         selected: true,
86         configurable: true,
87         filters: createTree(),
88         render: uuid => <ResourceLinkTailUuid uuid={uuid} />
89     },
90     {
91         name: GroupDetailsPanelMembersColumnNames.REMOVE,
92         selected: true,
93         configurable: true,
94         filters: createTree(),
95         render: uuid => <ResourceLinkDelete uuid={uuid} />
96     },
97 ];
98
99 export const groupDetailsPermissionsPanelColumns: DataColumns<string> = [
100     {
101         name: GroupDetailsPanelPermissionsColumnNames.NAME,
102         selected: true,
103         configurable: true,
104         filters: createTree(),
105         render: uuid => <ResourceLinkHead uuid={uuid} />
106     },
107     {
108         name: GroupDetailsPanelPermissionsColumnNames.PERMISSION,
109         selected: true,
110         configurable: true,
111         filters: createTree(),
112         render: uuid => <ResourceLinkHeadPermissionLevel uuid={uuid} />
113     },
114     {
115         name: GroupDetailsPanelPermissionsColumnNames.UUID,
116         selected: true,
117         configurable: true,
118         filters: createTree(),
119         render: uuid => <ResourceLinkHeadUuid uuid={uuid} />
120     },
121     {
122         name: GroupDetailsPanelPermissionsColumnNames.REMOVE,
123         selected: true,
124         configurable: true,
125         filters: createTree(),
126         render: uuid => <ResourceLinkDelete uuid={uuid} />
127     },
128 ];
129
130 const mapStateToProps = (state: RootState) => {
131     const groupUuid = getCurrentGroupDetailsPanelUuid(state.properties);
132     const group = getResource<GroupResource>(groupUuid || '')(state.resources);
133     const userUuid = getUserUuid(state);
134
135     return {
136         resources: state.resources,
137         groupCanManage: userUuid ? group?.writableBy?.includes(userUuid) : false,
138     };
139 };
140
141 const mapDispatchToProps = {
142     onContextMenu: openContextMenu,
143     onAddUser: openAddGroupMembersDialog,
144 };
145
146 export interface GroupDetailsPanelProps {
147     onContextMenu: (event: React.MouseEvent<HTMLElement>, item: any) => void;
148     onAddUser: () => void;
149     resources: ResourcesState;
150     groupCanManage: boolean;
151 }
152
153 export const GroupDetailsPanel = connect(
154     mapStateToProps, mapDispatchToProps
155 )(
156     class GroupDetailsPanel extends React.Component<GroupDetailsPanelProps> {
157         state = {
158           value: 0,
159         };
160
161         componentDidMount() {
162             this.setState({ value: 0 });
163         }
164
165         render() {
166             const { value } = this.state;
167             return (
168                 <Paper>
169                   <Tabs value={value} onChange={this.handleChange} variant="fullWidth">
170                       <Tab data-cy="group-details-members-tab" label="MEMBERS" />
171                       <Tab data-cy="group-details-permissions-tab" label="PERMISSIONS" />
172                   </Tabs>
173                   {value === 0 &&
174                       <DataExplorer
175                           id={GROUP_DETAILS_MEMBERS_PANEL_ID}
176                           data-cy="group-members-data-explorer"
177                           onRowClick={noop}
178                           onRowDoubleClick={noop}
179                           onContextMenu={noop}
180                           contextMenuColumn={false}
181                           hideColumnSelector
182                           hideSearchInput
183                           actions={
184                                 this.props.groupCanManage &&
185                                 <Grid container justify='flex-end'>
186                                     <Button
187                                       data-cy="group-member-add"
188                                       variant="contained"
189                                       color="primary"
190                                       onClick={this.props.onAddUser}>
191                                       <AddIcon /> Add user
192                                     </Button>
193                                 </Grid>
194                           }
195                           paperProps={{
196                               elevation: 0,
197                           }} />
198                   }
199                   {value === 1 &&
200                       <DataExplorer
201                           id={GROUP_DETAILS_PERMISSIONS_PANEL_ID}
202                           data-cy="group-permissions-data-explorer"
203                           onRowClick={noop}
204                           onRowDoubleClick={noop}
205                           onContextMenu={noop}
206                           contextMenuColumn={false}
207                           hideColumnSelector
208                           hideSearchInput
209                           paperProps={{
210                               elevation: 0,
211                           }} />
212                   }
213                 </Paper>
214             );
215         }
216
217         handleChange = (event: React.MouseEvent<HTMLElement>, value: number) => {
218             this.setState({ value });
219         }
220     });