1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import * as React from 'react';
6 import { ProjectPanelItem } from './project-panel-item';
7 import { Grid, Typography, Button, StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
8 import { formatDate, formatFileSize } from '../../common/formatters';
9 import { DataExplorer } from "../../views-components/data-explorer/data-explorer";
10 import { DispatchProp, connect } from 'react-redux';
11 import { DataColumns } from '../../components/data-table/data-table';
12 import { RouteComponentProps } from 'react-router';
13 import { RootState } from '../../store/store';
14 import { DataTableFilterItem } from '../../components/data-table-filters/data-table-filters';
15 import { ContainerRequestState } from '../../models/container-request';
16 import { SortDirection } from '../../components/data-table/data-column';
17 import { ResourceKind } from '../../models/resource';
18 import { resourceLabel } from '../../common/labels';
19 import { ProjectIcon, CollectionIcon, ProcessIcon, DefaultIcon } from '../../components/icon/icon';
20 import { ArvadosTheme } from '../../common/custom-theme';
22 type CssRules = "toolbar" | "button";
24 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
26 paddingBottom: theme.spacing.unit * 3,
30 marginLeft: theme.spacing.unit
34 const renderName = (item: ProjectPanelItem) =>
35 <Grid container alignItems="center" wrap="nowrap" spacing={16}>
40 <Typography color="primary">
47 const renderIcon = (item: ProjectPanelItem) => {
49 case ResourceKind.Project:
50 return <ProjectIcon />;
51 case ResourceKind.Collection:
52 return <CollectionIcon />;
53 case ResourceKind.Process:
54 return <ProcessIcon />;
56 return <DefaultIcon />;
60 const renderDate = (date: string) => {
61 return <Typography noWrap>{formatDate(date)}</Typography>;
64 const renderFileSize = (fileSize?: number) =>
66 {formatFileSize(fileSize)}
69 const renderOwner = (owner: string) =>
70 <Typography noWrap color="primary" >
74 const renderType = (type: string) =>
79 const renderStatus = (item: ProjectPanelItem) =>
80 <Typography noWrap align="center" >
84 export enum ProjectPanelColumnNames {
89 FILE_SIZE = "File size",
90 LAST_MODIFIED = "Last modified"
93 export interface ProjectPanelFilter extends DataTableFilterItem {
94 type: ResourceKind | ContainerRequestState;
97 export const columns: DataColumns<ProjectPanelItem, ProjectPanelFilter> = [
99 name: ProjectPanelColumnNames.NAME,
101 sortDirection: SortDirection.Asc,
110 name: ContainerRequestState.Committed,
112 type: ContainerRequestState.Committed
115 name: ContainerRequestState.Final,
117 type: ContainerRequestState.Final
120 name: ContainerRequestState.Uncommitted,
122 type: ContainerRequestState.Uncommitted
125 render: renderStatus,
129 name: ProjectPanelColumnNames.TYPE,
133 name: resourceLabel(ResourceKind.Collection),
135 type: ResourceKind.Collection
138 name: resourceLabel(ResourceKind.Process),
140 type: ResourceKind.Process
143 name: resourceLabel(ResourceKind.Project),
145 type: ResourceKind.Project
148 render: item => renderType(item.kind),
152 name: ProjectPanelColumnNames.OWNER,
154 render: item => renderOwner(item.owner),
158 name: ProjectPanelColumnNames.FILE_SIZE,
160 render: item => renderFileSize(item.fileSize),
164 name: ProjectPanelColumnNames.LAST_MODIFIED,
166 sortDirection: SortDirection.None,
167 render: item => renderDate(item.lastModified),
172 export const PROJECT_PANEL_ID = "projectPanel";
174 interface ProjectPanelDataProps {
175 currentItemId: string;
178 interface ProjectPanelActionProps {
179 onItemClick: (item: ProjectPanelItem) => void;
180 onContextMenu: (event: React.MouseEvent<HTMLElement>, item: ProjectPanelItem) => void;
181 onDialogOpen: (ownerUuid: string) => void;
182 onItemDoubleClick: (item: ProjectPanelItem) => void;
183 onItemRouteChange: (itemId: string) => void;
186 type ProjectPanelProps = ProjectPanelDataProps & ProjectPanelActionProps & DispatchProp
187 & WithStyles<CssRules> & RouteComponentProps<{ id: string }>;
189 export const ProjectPanel = withStyles(styles)(
190 connect((state: RootState) => ({ currentItemId: state.projects.currentItemId }))(
191 class extends React.Component<ProjectPanelProps> {
193 const { classes } = this.props;
195 <div className={classes.toolbar}>
196 <Button color="primary" variant="raised" className={classes.button}>
199 <Button color="primary" variant="raised" className={classes.button}>
202 <Button color="primary" onClick={this.handleNewProjectClick} variant="raised" className={classes.button}>
207 id={PROJECT_PANEL_ID}
208 onRowClick={this.props.onItemClick}
209 onRowDoubleClick={this.props.onItemDoubleClick}
210 onContextMenu={this.props.onContextMenu}
211 extractKey={(item: ProjectPanelItem) => item.uuid} />
215 handleNewProjectClick = () => {
216 this.props.onDialogOpen(this.props.currentItemId);
218 componentWillReceiveProps({ match, currentItemId, onItemRouteChange }: ProjectPanelProps) {
219 if (match.params.id !== currentItemId) {
220 onItemRouteChange(match.params.id);