1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import React, { useState } from 'react';
6 import { connect } from 'react-redux';
7 import { Grid, Typography } from '@mui/material';
8 import { RootState } from 'store/store';
9 import { CustomStyleRulesCallback } from 'common/custom-theme';
10 import { ArvadosTheme } from 'common/custom-theme';
11 import withStyles from '@mui/styles/withStyles';
12 import { WithStyles } from '@mui/styles';
13 import { getResource } from 'store/resources/resources';
14 import { DetailsAttribute } from 'components/details-attribute/details-attribute';
15 import { getPropertyChip } from 'views-components/resource-properties-form/property-chip';
16 import { ExpandChevronRight } from 'components/expand-chevron-right/expand-chevron-right';
17 import { CollapsibleDescription } from 'components/collapsible-description/collapsible-description';
18 import { CollectionResource } from 'models/collection';
19 import { ProjectResource } from 'models/project';
20 import { WorkflowResource } from 'models/workflow';
21 import { ResourceKind } from 'models/resource';
22 import { Process, getProcess } from 'store/processes/process';
23 import { ContainerRequestResource } from 'models/container-request';
24 import { ContainerResource } from 'models/container';
25 import { ProcessRuntimeStatus } from 'views-components/process-runtime-status/process-runtime-status';
26 import { isUserResource } from 'models/user';
27 import { getRegisteredWorkflowPanelData } from 'views-components/details-panel/workflow-details';
28 import { AuthState } from 'store/auth/auth-reducer';
29 import { DataTableDefaultView } from 'components/data-table-default-view/data-table-default-view';
30 import { getPropertyChips } from 'views-components/property-chips/get-property-chips';
32 type CssRules = 'root' | 'tag';
34 const styles: CustomStyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
39 flexDirection: 'column',
40 justifyContent: 'space-between',
41 padding: theme.spacing(1),
44 marginRight: theme.spacing(0.5),
45 marginBottom: theme.spacing(0.5),
49 type OverviewPanelProps = {
51 resource: ProjectResource | CollectionResource | ContainerRequestResource | WorkflowResource | undefined;
53 container?: ContainerResource;
54 detailsElement: React.ReactNode;
55 progressIndicator: string[];
56 } & WithStyles<CssRules>;
58 const mapStateToProps = (state: RootState): Pick<OverviewPanelProps, 'auth' |'resource' | 'container' | 'progressIndicator'> => {
59 const resource = getResource<any>(state.properties.currentRouteUuid)(state.resources);
60 const process = getProcess(resource?.uuid)(state.resources) || undefined;
63 resource: resource?.containerRequest ? process : resource,
64 container: process?.container,
65 progressIndicator: state.progressIndicator
69 export const OverviewPanel = connect(mapStateToProps)(withStyles(styles)((({ auth,resource, container, detailsElement, progressIndicator, classes }: OverviewPanelProps) => {
70 const working = progressIndicator.length > 0;
71 if (isUserResource(resource)) {
76 return <DataTableDefaultView />
80 const hasDescription = resource.description && resource.description.length > 0;
81 const [showDescription, setShowDescription] = useState(false);
83 React.useEffect(() => {
84 setShowDescription(false);
88 <section className={classes.root}>
90 {resource.kind === ResourceKind.CONTAINER_REQUEST && <Grid item xs={12}>
91 <ProcessRuntimeStatus runtimeStatus={container?.runtimeStatus} containerCount={resource.containerCount} />
93 <Grid item xs={12} md={12}>
96 button={hasDescription
97 ? <ExpandChevronRight expanded={showDescription} onClick={() => setShowDescription(!showDescription)} />
100 ? <CollapsibleDescription description={resource.description} showDescription={showDescription} />
101 : <Typography>No description available</Typography>}
103 <section data-cy='details-element'>
108 <PropertiesElement auth={auth} resource={resource} classes={classes} />
113 const PropertiesElement = ({auth, resource, classes}: { auth: AuthState, resource: ProjectResource | CollectionResource | ContainerRequestResource | WorkflowResource | undefined, classes: any }) => {
117 if (resource.kind === ResourceKind.WORKFLOW) {
118 const wfData = getRegisteredWorkflowPanelData(resource, auth);
119 if (Object.keys(wfData.gitprops).length === 0) {
122 return <section data-cy='resource-properties'>
123 {Object.keys(wfData.gitprops).map(k =>
124 getPropertyChip(k, wfData.gitprops[k], undefined, classes.tag)
128 if (typeof resource.properties === 'object' && Object.keys(resource.properties).length > 0) {
129 return getPropertyChips(resource, classes);