18984: Refactor default data table view, add active filters notice to default view
[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, ResourceLinkTailUsername, ResourceLinkHeadPermissionLevel, ResourceLinkTailPermissionLevel, ResourceLinkHead, ResourceLinkTail, ResourceLinkDelete, ResourceLinkTailAccountStatus, ResourceLinkTailIsVisible } 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, WithStyles, withStyles, StyleRulesCallback } from '@material-ui/core';
18 import { AddIcon, UserPanelIcon, KeyIcon } from 'components/icon/icon';
19 import { getUserUuid } from 'common/getuser';
20 import { GroupResource, isBuiltinGroup } from 'models/group';
21 import { ArvadosTheme } from 'common/custom-theme';
22
23 type CssRules = "root";
24
25 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
26     root: {
27         width: '100%',
28     }
29 });
30
31 export enum GroupDetailsPanelMembersColumnNames {
32     FULL_NAME = "Name",
33     USERNAME = "Username",
34     STATUS = "Account Status",
35     VISIBLE = "Visible to other members",
36     PERMISSION = "Permission",
37     REMOVE = "Remove",
38 }
39
40 export enum GroupDetailsPanelPermissionsColumnNames {
41     NAME = "Name",
42     PERMISSION = "Permission",
43     UUID = "UUID",
44     REMOVE = "Remove",
45 }
46
47 const MEMBERS_DEFAULT_MESSAGE = 'Members list is empty.';
48 const PERMISSIONS_DEFAULT_MESSAGE = 'Permissions list is empty.';
49
50 export const groupDetailsMembersPanelColumns: DataColumns<string> = [
51     {
52         name: GroupDetailsPanelMembersColumnNames.FULL_NAME,
53         selected: true,
54         configurable: true,
55         filters: createTree(),
56         render: uuid => <ResourceLinkTail uuid={uuid} />
57     },
58     {
59         name: GroupDetailsPanelMembersColumnNames.USERNAME,
60         selected: true,
61         configurable: true,
62         filters: createTree(),
63         render: uuid => <ResourceLinkTailUsername uuid={uuid} />
64     },
65     {
66         name: GroupDetailsPanelMembersColumnNames.STATUS,
67         selected: true,
68         configurable: true,
69         filters: createTree(),
70         render: uuid => <ResourceLinkTailAccountStatus uuid={uuid} />
71     },
72     {
73         name: GroupDetailsPanelMembersColumnNames.VISIBLE,
74         selected: true,
75         configurable: true,
76         filters: createTree(),
77         render: uuid => <ResourceLinkTailIsVisible uuid={uuid} />
78     },
79     {
80         name: GroupDetailsPanelMembersColumnNames.PERMISSION,
81         selected: true,
82         configurable: true,
83         filters: createTree(),
84         render: uuid => <ResourceLinkTailPermissionLevel uuid={uuid} />
85     },
86     {
87         name: GroupDetailsPanelMembersColumnNames.REMOVE,
88         selected: true,
89         configurable: true,
90         filters: createTree(),
91         render: uuid => <ResourceLinkDelete uuid={uuid} />
92     },
93 ];
94
95 export const groupDetailsPermissionsPanelColumns: DataColumns<string> = [
96     {
97         name: GroupDetailsPanelPermissionsColumnNames.NAME,
98         selected: true,
99         configurable: true,
100         filters: createTree(),
101         render: uuid => <ResourceLinkHead uuid={uuid} />
102     },
103     {
104         name: GroupDetailsPanelPermissionsColumnNames.PERMISSION,
105         selected: true,
106         configurable: true,
107         filters: createTree(),
108         render: uuid => <ResourceLinkHeadPermissionLevel uuid={uuid} />
109     },
110     {
111         name: GroupDetailsPanelPermissionsColumnNames.UUID,
112         selected: true,
113         configurable: true,
114         filters: createTree(),
115         render: uuid => <ResourceLinkHeadUuid uuid={uuid} />
116     },
117     {
118         name: GroupDetailsPanelPermissionsColumnNames.REMOVE,
119         selected: true,
120         configurable: true,
121         filters: createTree(),
122         render: uuid => <ResourceLinkDelete uuid={uuid} />
123     },
124 ];
125
126 const mapStateToProps = (state: RootState) => {
127     const groupUuid = getCurrentGroupDetailsPanelUuid(state.properties);
128     const group = getResource<GroupResource>(groupUuid || '')(state.resources);
129     const userUuid = getUserUuid(state);
130
131     return {
132         resources: state.resources,
133         groupCanManage: userUuid && !isBuiltinGroup(group?.uuid || '')
134                             ? group?.writableBy?.includes(userUuid)
135                             : false,
136     };
137 };
138
139 const mapDispatchToProps = {
140     onContextMenu: openContextMenu,
141     onAddUser: openAddGroupMembersDialog,
142 };
143
144 export interface GroupDetailsPanelProps {
145     onContextMenu: (event: React.MouseEvent<HTMLElement>, item: any) => void;
146     onAddUser: () => void;
147     resources: ResourcesState;
148     groupCanManage: boolean;
149 }
150
151 export const GroupDetailsPanel = withStyles(styles)(connect(
152     mapStateToProps, mapDispatchToProps
153 )(
154     class GroupDetailsPanel extends React.Component<GroupDetailsPanelProps & WithStyles<CssRules>> {
155         state = {
156           value: 0,
157         };
158
159         componentDidMount() {
160             this.setState({ value: 0 });
161         }
162
163         render() {
164             const { value } = this.state;
165             return (
166                 <Paper className={this.props.classes.root}>
167                   <Tabs value={value} onChange={this.handleChange} variant="fullWidth">
168                       <Tab data-cy="group-details-members-tab" label="MEMBERS" />
169                       <Tab data-cy="group-details-permissions-tab" label="PERMISSIONS" />
170                   </Tabs>
171                   {value === 0 &&
172                       <DataExplorer
173                           id={GROUP_DETAILS_MEMBERS_PANEL_ID}
174                           data-cy="group-members-data-explorer"
175                           onRowClick={noop}
176                           onRowDoubleClick={noop}
177                           onContextMenu={noop}
178                           contextMenuColumn={false}
179                           defaultViewIcon={UserPanelIcon}
180                           defaultViewMessages={[MEMBERS_DEFAULT_MESSAGE]}
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                           defaultViewIcon={KeyIcon}
208                           defaultViewMessages={[PERMISSIONS_DEFAULT_MESSAGE]}
209                           hideColumnSelector
210                           hideSearchInput
211                           paperProps={{
212                               elevation: 0,
213                           }} />
214                   }
215                 </Paper>
216             );
217         }
218
219         handleChange = (event: React.MouseEvent<HTMLElement>, value: number) => {
220             this.setState({ value });
221         }
222     }));