Update group members implementation to match docs
[arvados-workbench2.git] / src / views / groups-panel / groups-panel.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import * as React from 'react';
6 import { connect } from 'react-redux';
7 import { Grid, Button, Typography } from "@material-ui/core";
8
9 import { DataExplorer } from "~/views-components/data-explorer/data-explorer";
10 import { DataColumns } from '~/components/data-table/data-table';
11 import { SortDirection } from '~/components/data-table/data-column';
12 import { ResourceOwner } from '~/views-components/data-explorer/renderers';
13 import { AddIcon } from '~/components/icon/icon';
14 import { ResourceName } from '~/views-components/data-explorer/renderers';
15 import { createTree } from '~/models/tree';
16 import { GROUPS_PANEL_ID, openCreateGroupDialog } from '~/store/groups-panel/groups-panel-actions';
17 import { noop } from 'lodash/fp';
18 import { ContextMenuKind } from '~/views-components/context-menu/context-menu';
19 import { getResource, ResourcesState, filterResources } from '~/store/resources/resources';
20 import { GroupResource } from '~/models/group';
21 import { RootState } from '~/store/store';
22 import { Dispatch } from 'redux';
23 import { openContextMenu } from '~/store/context-menu/context-menu-actions';
24 import { ResourceKind } from '~/models/resource';
25 import { LinkClass, LinkResource } from '~/models/link';
26 import { navigateToGroupDetails } from '~/store/navigation/navigation-action';
27
28 export enum GroupsPanelColumnNames {
29     GROUP = "Name",
30     OWNER = "Owner",
31     MEMBERS = "Members",
32 }
33
34 export const groupsPanelColumns: DataColumns<string> = [
35     {
36         name: GroupsPanelColumnNames.GROUP,
37         selected: true,
38         configurable: true,
39         sortDirection: SortDirection.ASC,
40         filters: createTree(),
41         render: uuid => <ResourceName uuid={uuid} />
42     },
43     {
44         name: GroupsPanelColumnNames.OWNER,
45         selected: true,
46         configurable: true,
47         filters: createTree(),
48         render: uuid => <ResourceOwner uuid={uuid} />,
49     },
50     {
51         name: GroupsPanelColumnNames.MEMBERS,
52         selected: true,
53         configurable: true,
54         filters: createTree(),
55         render: uuid => <GroupMembersCount uuid={uuid} />,
56     },
57 ];
58
59 const mapStateToProps = (state: RootState) => {
60     return {
61         resources: state.resources
62     };
63 };
64
65 const mapDispatchToProps = {
66     onContextMenu: openContextMenu,
67     onRowDoubleClick: (uuid: string) =>
68         navigateToGroupDetails(uuid),
69     onNewGroup: openCreateGroupDialog,
70 };
71
72 export interface GroupsPanelProps {
73     onNewGroup: () => void;
74     onContextMenu: (event: React.MouseEvent<HTMLElement>, item: any) => void;
75     onRowDoubleClick: (item: string) => void;
76     resources: ResourcesState;
77 }
78
79 export const GroupsPanel = connect(
80     mapStateToProps, mapDispatchToProps
81 )(
82     class GroupsPanel extends React.Component<GroupsPanelProps> {
83
84         render() {
85             return (
86                 <DataExplorer
87                     id={GROUPS_PANEL_ID}
88                     onRowClick={noop}
89                     onRowDoubleClick={this.props.onRowDoubleClick}
90                     onContextMenu={this.handleContextMenu}
91                     contextMenuColumn={true}
92                     hideColumnSelector
93                     actions={
94                         <Grid container justify='flex-end'>
95                             <Button
96                                 variant="contained"
97                                 color="primary"
98                                 onClick={this.props.onNewGroup}>
99                                 <AddIcon /> New group
100                         </Button>
101                         </Grid>
102                     } />
103             );
104         }
105
106         handleContextMenu = (event: React.MouseEvent<HTMLElement>, resourceUuid: string) => {
107             const resource = getResource<GroupResource>(resourceUuid)(this.props.resources);
108             if (resource) {
109                 this.props.onContextMenu(event, {
110                     name: '',
111                     uuid: resource.uuid,
112                     ownerUuid: resource.ownerUuid,
113                     kind: resource.kind,
114                     menuKind: ContextMenuKind.GROUPS
115                 });
116             }
117         }
118     });
119
120
121 const GroupMembersCount = connect(
122     (state: RootState, props: { uuid: string }) => {
123
124         const permissions = filterResources((resource: LinkResource) =>
125             resource.kind === ResourceKind.LINK &&
126             resource.linkClass === LinkClass.PERMISSION &&
127             resource.tailUuid === props.uuid
128         )(state.resources);
129
130         return {
131             children: permissions.length,
132         };
133
134     }
135 )(Typography);