22141: Display correct uuid, todo still returns search- prefixed tree id
[arvados.git] / services / workbench2 / src / views-components / projects-tree-picker / projects-tree-picker.tsx
index 773230d351fe1e491faa5f4dab49a81f375aff84..9eddc73446e2c958001112b08352f03c9d55761e 100644 (file)
@@ -19,12 +19,23 @@ import { TreeItem } from 'components/tree/tree';
 import { ProjectsTreePickerItem } from 'store/tree-picker/tree-picker-middleware';
 import { PublicFavoritesTreePicker } from './public-favorites-tree-picker';
 import { SearchInput } from 'components/search-input/search-input';
-import { withStyles, StyleRulesCallback, WithStyles } from '@material-ui/core';
+import { CustomStyleRulesCallback } from 'common/custom-theme';
+import { WithStyles } from '@mui/styles';
+import withStyles from '@mui/styles/withStyles';
 import { ArvadosTheme } from 'common/custom-theme';
+import { ResourceKind } from 'models/resource';
+import { CollectionFileType } from 'models/collection-file';
+import { DefaultView } from 'components/default-view/default-view';
+import { ProjectDetailsComponent } from 'views-components/details-panel/project-details';
+import { CollectionDetailsAttributes } from 'views/collection-panel/collection-panel';
+import { RootProjectDetailsComponent } from 'views-components/details-panel/root-project-details';
+import { DetailsAttribute } from 'components/details-attribute/details-attribute';
+import { formatFileSize } from 'common/formatters';
 
 export interface ToplevelPickerProps {
-    currentUuid?: string;
+    currentUuids?: string[];
     pickerId: string;
+    cascadeSelection: boolean;
     includeCollections?: boolean;
     includeDirectories?: boolean;
     includeFiles?: boolean;
@@ -48,7 +59,7 @@ const mapStateToProps = (state: RootState, props: ToplevelPickerProps): Projects
     const { search } = getProjectsTreePickerIds(props.pickerId);
     return {
         ...props,
-        projectSearch: state.treePickerSearch.projectSearchValues[search],
+        projectSearch: state.treePickerSearch.projectSearchValues[search] || state.treePickerSearch.collectionFilterValues[search],
         collectionFilter: state.treePickerSearch.collectionFilterValues[search],
     };
 };
@@ -80,34 +91,89 @@ const mapDispatchToProps = (dispatch: Dispatch, props: ToplevelPickerProps): (Pr
     }
 };
 
-type CssRules = 'pickerHeight' | 'searchFlex' | 'scrolledBox';
+type CssRules = 'pickerHeight' | 'searchFlex' | 'scrolledBox' | 'detailsBox' | 'twoCol';
 
-const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
+const styles: CustomStyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
     pickerHeight: {
         height: "100%",
-        display: "flex",
-        flexDirection: "column",
     },
     searchFlex: {
         display: "flex",
         justifyContent: "space-around",
-        paddingBottom: "1em"
+        height: "64px",
     },
     scrolledBox: {
-        overflow: "scroll"
+        overflow: "scroll",
+        width: "calc(100% - 320px)",
+        marginRight: "8px",
+        height: "100%",
+    },
+    twoCol: {
+        display: "flex",
+        flexDirection: "row",
+        height: "calc(100% - 64px)",
+    },
+    detailsBox: {
+        width: "320px",
+        height: "100%",
+        overflow: "scroll",
+        borderLeft: "1px solid rgba(0, 0, 0, 0.12)",
+        paddingLeft: "4px",
     }
 });
 
 type ProjectsTreePickerCombinedProps = ToplevelPickerProps & ProjectsTreePickerSearchProps & ProjectsTreePickerActionProps & DispatchProp & WithStyles<CssRules>;
 
+interface SelectionComponentState {
+    activeItem?: ProjectsTreePickerItem;
+}
+
+const Details = (props: { res?: ProjectsTreePickerItem }) => {
+    if (props.res) {
+        if ('kind' in props.res) {
+            switch (props.res.kind) {
+                case ResourceKind.PROJECT:
+                    return <ProjectDetailsComponent project={props.res} hideEdit={true} />
+                case ResourceKind.COLLECTION:
+                    return <CollectionDetailsAttributes item={props.res} />;
+                case ResourceKind.USER:
+                    return <RootProjectDetailsComponent rootProject={props.res} />;
+                    // case ResourceKind.PROCESS:
+                    //                         return new ProcessDetails(res);
+                    // case ResourceKind.WORKFLOW:
+                    //     return new WorkflowDetails(res);
+            }
+        } else if ('type' in props.res) {
+            if (props.res.type === CollectionFileType.FILE) {
+                return <>
+                <DetailsAttribute label='Type' value="File" />
+                <DetailsAttribute label='Size' value={formatFileSize(props.res.size)} />
+                </>;
+            } else {
+                return <DetailsAttribute label='Type' value="Directory" />
+            }
+        }
+    }
+    return <DefaultView messages={['Select a file or folder to view its details.']} />;
+};
+
+
 export const ProjectsTreePicker = connect(mapStateToProps, mapDispatchToProps)(
     withStyles(styles)(
         class FileInputComponent extends React.Component<ProjectsTreePickerCombinedProps> {
+            state: SelectionComponentState = {
+            };
 
             componentDidMount() {
                 const { home, shared, favorites, publicFavorites, search } = getProjectsTreePickerIds(this.props.pickerId);
 
-                this.props.dispatch<any>(initProjectsTreePicker(this.props.pickerId, this.props.currentUuid));
+                const preloadParams = this.props.currentUuids ? {
+                    selectedItemUuids: this.props.currentUuids,
+                    includeDirectories: !!this.props.includeDirectories,
+                    includeFiles: !!this.props.includeFiles,
+                    multi: !!this.props.showSelection,
+                } : undefined;
+                this.props.dispatch<any>(initProjectsTreePicker(this.props.pickerId, preloadParams));
 
                 this.props.dispatch(treePickerSearchActions.SET_TREE_PICKER_PROJECT_SEARCH({ pickerId: search, projectSearchValue: "" }));
                 this.props.dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: search, collectionFilterValue: "" }));
@@ -127,6 +193,13 @@ export const ProjectsTreePicker = connect(mapStateToProps, mapDispatchToProps)(
                 this.props.dispatch(treePickerActions.RESET_TREE_PICKER({ pickerId: publicFavorites }));
             }
 
+            setSelection(event: React.MouseEvent<HTMLElement>,
+                         item: TreeItem<ProjectsTreePickerItem>,
+                         pickerId: string) {
+                this.setState({activeItem: item.data});
+                console.log(item.data);
+            }
+
             render() {
                 const pickerId = this.props.pickerId;
                 const onProjectSearch = this.props.onProjectSearch;
@@ -134,48 +207,65 @@ export const ProjectsTreePicker = connect(mapStateToProps, mapDispatchToProps)(
 
                 const { home, shared, favorites, publicFavorites, search } = getProjectsTreePickerIds(pickerId);
                 const relatedTreePickers = getRelatedTreePickers(pickerId);
+                const _this = this;
                 const p = {
+                    cascadeSelection: this.props.cascadeSelection,
                     includeCollections: this.props.includeCollections,
                     includeDirectories: this.props.includeDirectories,
                     includeFiles: this.props.includeFiles,
                     showSelection: this.props.showSelection,
                     options: this.props.options,
-                    toggleItemActive: this.props.toggleItemActive,
+                    toggleItemActive: (event: React.MouseEvent<HTMLElement>,
+                                       item: TreeItem<ProjectsTreePickerItem>,
+                                       pickerId: string): void => {
+                                           _this.setSelection(event, item, pickerId);
+                                           if (_this.props.toggleItemActive) {
+                                               _this.props.toggleItemActive(event, item, pickerId);
+                                           }
+                                       },
                     toggleItemSelection: this.props.toggleItemSelection,
                     relatedTreePickers,
                     disableActivation,
                 };
-                return <div className={this.props.classes.pickerHeight} >
-                    <span className={this.props.classes.searchFlex}>
-                        <SearchInput value="" label="Search for a Project" selfClearProp='' onSearch={onProjectSearch} debounce={500} />
-                        {this.props.includeCollections &&
-                            <SearchInput value="" label="Filter Collections list in Projects" selfClearProp='' onSearch={onCollectionFilter} debounce={500} />}
-                    </span>
 
+
+                return <>
+                    <div className={this.props.classes.searchFlex}>
+                        <span data-cy="picker-dialog-project-search"><SearchInput value="" label="Project search" selfClearProp='' onSearch={onProjectSearch} debounce={500} width="18rem"  /></span>
+                {this.props.includeCollections &&
+                 <span data-cy="picker-dialog-collection-search" ><SearchInput value="" label="Collection search" selfClearProp='' onSearch={onCollectionFilter} debounce={500} width="18rem" /></span>}
+                </div>
+
+                <div className={this.props.classes.twoCol}>
                     <div className={this.props.classes.scrolledBox}>
                         {this.props.projectSearch ?
-                            <div data-cy="projects-tree-search-picker">
-                                <SearchProjectsPicker {...p} pickerId={search} />
-                            </div>
-                            :
-                            <>
-                                <div data-cy="projects-tree-home-tree-picker">
-                                    <HomeTreePicker {...p} pickerId={home} />
-                                </div>
-                                <div data-cy="projects-tree-shared-tree-picker">
-                                    <SharedTreePicker {...p} pickerId={shared} />
-                                </div>
-                                <div data-cy="projects-tree-public-favourites-tree-picker">
-                                    <PublicFavoritesTreePicker {...p} pickerId={publicFavorites} />
-                                </div>
-                                <div data-cy="projects-tree-favourites-tree-picker">
-                                    <FavoritesTreePicker {...p} pickerId={favorites} />
-                                </div>
-                            </>}
+                         <div data-cy="projects-tree-search-picker">
+                             <SearchProjectsPicker {...p} pickerId={search} />
+                         </div>
+                        :
+                         <>
+                             <div data-cy="projects-tree-home-tree-picker">
+                                 <HomeTreePicker {...p} pickerId={home} />
+                             </div>
+                        <div data-cy="projects-tree-shared-tree-picker">
+                            <SharedTreePicker {...p} pickerId={shared} />
+                        </div>
+                        <div data-cy="projects-tree-public-favourites-tree-picker">
+                            <PublicFavoritesTreePicker {...p} pickerId={publicFavorites} />
+                        </div>
+                        <div data-cy="projects-tree-favourites-tree-picker">
+                            <FavoritesTreePicker {...p} pickerId={favorites} />
+                        </div>
+                         </>}
+                    </div>
+
+                    <div className={this.props.classes.detailsBox} data-cy="picker-dialog-details">
+                        <Details res={this.state.activeItem} />
                     </div>
-                </div >;
+                </div>
+                </>;
             }
-        }));
+}));
 
 const getRelatedTreePickers = pipe(getProjectsTreePickerIds, values);
 const disableActivation = [SHARED_PROJECT_ID, FAVORITES_PROJECT_ID];