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