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