// Copyright (C) The Arvados Authors. All rights reserved. // // SPDX-License-Identifier: AGPL-3.0 import * as React from 'react'; import { IconButton, Tabs, Tab, Typography, Grid, Tooltip } from '@material-ui/core'; import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles'; import { Transition } from 'react-transition-group'; import { ArvadosTheme } from '~/common/custom-theme'; import * as classnames from "classnames"; import { connect } from 'react-redux'; import { RootState } from '~/store/store'; import { CloseIcon } from '~/components/icon/icon'; import { EmptyResource } from '~/models/empty'; import { Dispatch } from "redux"; import { ResourceKind } from "~/models/resource"; import { ProjectDetails } from "./project-details"; import { CollectionDetails } from "./collection-details"; import { ProcessDetails } from "./process-details"; import { EmptyDetails } from "./empty-details"; import { DetailsData } from "./details-data"; import { DetailsResource } from "~/models/details"; import { getResource } from '~/store/resources/resources'; import { toggleDetailsPanel, SLIDE_TIMEOUT } from '~/store/details-panel/details-panel-action'; import { FileDetails } from '~/views-components/details-panel/file-details'; import { getNode } from '~/models/tree'; type CssRules = 'root' | 'container' | 'opened' | 'headerContainer' | 'headerIcon' | 'tabContainer'; const DRAWER_WIDTH = 320; const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ root: { background: theme.palette.background.paper, borderLeft: `1px solid ${theme.palette.divider}`, height: '100%', overflow: 'hidden', transition: `width ${SLIDE_TIMEOUT}ms ease`, width: 0, }, opened: { width: DRAWER_WIDTH, }, container: { maxWidth: 'none', width: DRAWER_WIDTH, }, headerContainer: { color: theme.palette.grey["600"], margin: `${theme.spacing.unit}px 0`, textAlign: 'center', }, headerIcon: { fontSize: '2.125rem', }, tabContainer: { overflow: 'auto', padding: theme.spacing.unit * 1, }, }); const EMPTY_RESOURCE: EmptyResource = { kind: undefined, name: 'Projects' }; const getItem = (res: DetailsResource): DetailsData => { if ('kind' in res) { switch (res.kind) { case ResourceKind.PROJECT: return new ProjectDetails(res); case ResourceKind.COLLECTION: return new CollectionDetails(res); case ResourceKind.PROCESS: return new ProcessDetails(res); default: return new EmptyDetails(res); } } else { return new FileDetails(res); } }; const mapStateToProps = ({ detailsPanel, resources, collectionPanelFiles }: RootState) => { const resource = getResource(detailsPanel.resourceUuid)(resources) as DetailsResource | undefined; const file = getNode(detailsPanel.resourceUuid)(collectionPanelFiles); return { isOpened: detailsPanel.isOpened, item: getItem(resource || (file && file.value) || EMPTY_RESOURCE), }; }; const mapDispatchToProps = (dispatch: Dispatch) => ({ onCloseDrawer: () => { dispatch(toggleDetailsPanel()); } }); export interface DetailsPanelDataProps { onCloseDrawer: () => void; isOpened: boolean; item: DetailsData; } type DetailsPanelProps = DetailsPanelDataProps & WithStyles; export const DetailsPanel = withStyles(styles)( connect(mapStateToProps, mapDispatchToProps)( class extends React.Component { state = { tabsValue: 0 }; handleChange = (event: any, value: boolean) => { this.setState({ tabsValue: value }); } render() { const { classes, isOpened } = this.props; return ( {this.renderContent()} ); } renderContent() { const { classes, onCloseDrawer, item } = this.props; const { tabsValue } = this.state; return {item.getIcon(classes.headerIcon)} {item.getTitle()} {tabsValue === 0 ? item.getDetails() : null} ; } } ) );