18123: List all permission links in group members list & cleanup.
[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 { ResourceUuid, ResourceEmail, ResourceUsername, ResourceLinkName, ResourceLinkHead, ResourceLinkTail } 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 } 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
22 export enum GroupDetailsPanelMembersColumnNames {
23     FULL_NAME = "Name",
24     UUID = "UUID",
25     EMAIL = "Email",
26     USERNAME = "Username",
27 }
28
29 export enum GroupDetailsPanelPermissionsColumnNames {
30     HEAD = "Head",
31     NAME = "Name",
32     UUID = "UUID",
33 }
34
35 export const groupDetailsMembersPanelColumns: DataColumns<string> = [
36     {
37         name: GroupDetailsPanelMembersColumnNames.FULL_NAME,
38         selected: true,
39         configurable: true,
40         filters: createTree(),
41         render: uuid => <ResourceLinkTail uuid={uuid} />
42     },
43     {
44         name: GroupDetailsPanelMembersColumnNames.USERNAME,
45         selected: true,
46         configurable: true,
47         filters: createTree(),
48         render: uuid => <ResourceUsername uuid={uuid} />
49     },
50     {
51         name: GroupDetailsPanelMembersColumnNames.UUID,
52         selected: true,
53         configurable: true,
54         filters: createTree(),
55         render: uuid => <ResourceUuid uuid={uuid} />
56     },
57     {
58         name: GroupDetailsPanelMembersColumnNames.EMAIL,
59         selected: true,
60         configurable: true,
61         filters: createTree(),
62         render: uuid => <ResourceEmail uuid={uuid} />
63     },
64 ];
65
66 export const groupDetailsPermissionsPanelColumns: DataColumns<string> = [
67     {
68         name: GroupDetailsPanelPermissionsColumnNames.HEAD,
69         selected: true,
70         configurable: true,
71         filters: createTree(),
72         render: uuid => <ResourceLinkHead uuid={uuid} />
73     },
74     {
75         name: GroupDetailsPanelPermissionsColumnNames.NAME,
76         selected: true,
77         configurable: true,
78         filters: createTree(),
79         render: uuid => <ResourceLinkName uuid={uuid} />
80     },
81     {
82         name: GroupDetailsPanelPermissionsColumnNames.UUID,
83         selected: true,
84         configurable: true,
85         filters: createTree(),
86         render: uuid => <ResourceUuid uuid={uuid} />
87     },
88 ];
89
90 const mapStateToProps = (state: RootState) => {
91     return {
92         resources: state.resources
93     };
94 };
95
96 const mapDispatchToProps = {
97     onContextMenu: openContextMenu,
98     onAddUser: openAddGroupMembersDialog,
99 };
100
101 export interface GroupDetailsPanelProps {
102     onContextMenu: (event: React.MouseEvent<HTMLElement>, item: any) => void;
103     onAddUser: () => void;
104     resources: ResourcesState;
105 }
106
107 export const GroupDetailsPanel = connect(
108     mapStateToProps, mapDispatchToProps
109 )(
110     class GroupDetailsPanel extends React.Component<GroupDetailsPanelProps> {
111         state = {
112           value: 0,
113         };
114
115         componentDidMount() {
116             this.setState({ value: 0 });
117         }
118
119         render() {
120             const { value } = this.state;
121             return (
122                 <Paper>
123                   <Tabs value={value} onChange={this.handleChange} variant="fullWidth">
124                       <Tab label="MEMBERS" />
125                       <Tab label="PERMISSIONS" />
126                   </Tabs>
127                   {value === 0 &&
128                       <DataExplorer
129                           id={GROUP_DETAILS_MEMBERS_PANEL_ID}
130                           onRowClick={noop}
131                           onRowDoubleClick={noop}
132                           onContextMenu={this.handleContextMenu}
133                           contextMenuColumn={true}
134                           hideColumnSelector
135                           hideSearchInput
136                           actions={
137                               <Grid container justify='flex-end'>
138                                   <Button
139                                       variant="contained"
140                                       color="primary"
141                                       onClick={this.props.onAddUser}>
142                                       <AddIcon /> Add user
143                               </Button>
144                               </Grid>
145                           }
146                           paperProps={{
147                               elevation: 0,
148                           }} />
149                   }
150                   {value === 1 &&
151                       <DataExplorer
152                           id={GROUP_DETAILS_PERMISSIONS_PANEL_ID}
153                           onRowClick={noop}
154                           onRowDoubleClick={noop}
155                           onContextMenu={this.handleContextMenu}
156                           contextMenuColumn={true}
157                           hideColumnSelector
158                           hideSearchInput
159                           actions={
160                               <Grid container justify='flex-end'>
161                                   <Button
162                                       variant="contained"
163                                       color="primary"
164                                       onClick={this.props.onAddUser}>
165                                       <AddIcon /> Add user
166                               </Button>
167                               </Grid>
168                           }
169                           paperProps={{
170                               elevation: 0,
171                           }} />
172                   }
173                 </Paper>
174             );
175         }
176
177         handleContextMenu = (event: React.MouseEvent<HTMLElement>, resourceUuid: string) => {
178             const resource = getResource<PermissionResource>(resourceUuid)(this.props.resources);
179             if (resource) {
180                 this.props.onContextMenu(event, {
181                     name: '',
182                     uuid: resource.uuid,
183                     ownerUuid: resource.ownerUuid,
184                     kind: resource.kind,
185                     menuKind: ContextMenuKind.GROUP_MEMBER
186                 });
187             }
188         }
189
190         handleChange = (event: React.MouseEvent<HTMLElement>, value: number) => {
191             this.setState({ value });
192         }
193     });