Setup routing for group details
[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: navigateToGroupDetails,
68     onNewGroup: openCreateGroupDialog,
69 };
70
71 export interface GroupsPanelProps {
72     onNewGroup: () => void;
73     onContextMenu: (event: React.MouseEvent<HTMLElement>, item: any) => void;
74     onRowDoubleClick: (item: string) => void;
75     resources: ResourcesState;
76 }
77
78 export const GroupsPanel = connect(
79     mapStateToProps, mapDispatchToProps
80 )(
81     class GroupsPanel extends React.Component<GroupsPanelProps> {
82
83         render() {
84             return (
85                 <DataExplorer
86                     id={GROUPS_PANEL_ID}
87                     onRowClick={noop}
88                     onRowDoubleClick={this.props.onRowDoubleClick}
89                     onContextMenu={this.handleContextMenu}
90                     contextMenuColumn={true}
91                     hideColumnSelector
92                     actions={
93                         <Grid container justify='flex-end'>
94                             <Button
95                                 variant="contained"
96                                 color="primary"
97                                 onClick={this.props.onNewGroup}>
98                                 <AddIcon /> New group
99                         </Button>
100                         </Grid>
101                     } />
102             );
103         }
104
105         handleContextMenu = (event: React.MouseEvent<HTMLElement>, resourceUuid: string) => {
106             const resource = getResource<GroupResource>(resourceUuid)(this.props.resources);
107             if (resource) {
108                 this.props.onContextMenu(event, {
109                     name: '',
110                     uuid: resource.uuid,
111                     ownerUuid: resource.ownerUuid,
112                     kind: resource.kind,
113                     menuKind: ContextMenuKind.GROUPS
114                 });
115             }
116         }
117     });
118
119
120 const GroupMembersCount = connect(
121     (state: RootState, props: { uuid: string }) => {
122
123         const permissions = filterResources((resource: LinkResource) =>
124             resource.kind === ResourceKind.LINK &&
125             resource.linkClass === LinkClass.PERMISSION &&
126             resource.headUuid === props.uuid
127         )(state.resources);
128
129         return {
130             children: permissions.length,
131         };
132
133     }
134 )(Typography);