1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import React from 'react';
6 import { connect, DispatchProp } from 'react-redux';
7 import { memoize } from 'lodash/fp';
8 import { Field } from 'redux-form';
9 import { Input, Dialog, DialogTitle, DialogContent, DialogActions, Button } from '@material-ui/core';
12 DirectoryCommandInputParameter,
15 } from 'models/workflow';
16 import { GenericInputProps, GenericInput } from './generic-input';
17 import { ProjectsTreePicker } from 'views-components/projects-tree-picker/projects-tree-picker';
18 import { initProjectsTreePicker } from 'store/tree-picker/tree-picker-actions';
19 import { TreeItem } from 'components/tree/tree';
20 import { ProjectsTreePickerItem } from 'store/tree-picker/tree-picker-middleware';
21 import { CollectionResource } from 'models/collection';
22 import { ResourceKind } from 'models/resource';
23 import { ERROR_MESSAGE } from 'validators/require';
25 export interface DirectoryInputProps {
26 input: DirectoryCommandInputParameter;
27 options?: { showOnlyOwned: boolean, showOnlyWritable: boolean };
29 export const DirectoryInput = ({ input, options }: DirectoryInputProps) =>
33 component={DirectoryInputComponent as any}
39 validate={getValidation(input)} />;
41 const format = (value?: Directory) => value ? value.basename : '';
43 const parse = (directory: CollectionResource): Directory => ({
44 class: CWLType.DIRECTORY,
45 location: `keep:${directory.portableDataHash}`,
46 basename: directory.name,
49 const getValidation = memoize(
50 (input: DirectoryCommandInputParameter) => ([
51 isRequiredInput(input)
52 ? (directory?: Directory) => directory ? undefined : ERROR_MESSAGE
57 interface DirectoryInputComponentState {
59 directory?: CollectionResource;
62 const DirectoryInputComponent = connect()(
63 class FileInputComponent extends React.Component<GenericInputProps & DispatchProp & {
64 options?: { showOnlyOwned: boolean, showOnlyWritable: boolean };
65 }, DirectoryInputComponentState> {
66 state: DirectoryInputComponentState = {
71 this.props.dispatch<any>(
72 initProjectsTreePicker(this.props.commandInput.id));
83 this.setState({ open: true });
87 this.setState({ open: false });
92 this.props.input.onChange(this.state.directory);
95 setDirectory = (_: {}, { data }: TreeItem<ProjectsTreePickerItem>) => {
96 if ('kind' in data && data.kind === ResourceKind.COLLECTION) {
97 this.setState({ directory: data });
99 this.setState({ directory: undefined });
109 value={props.input.value}
110 error={props.meta.touched && !!props.meta.error}
111 disabled={props.commandInput.disabled}
112 onClick={!this.props.commandInput.disabled ? this.openDialog : undefined}
113 onKeyPress={!this.props.commandInput.disabled ? this.openDialog : undefined} />}
119 open={this.state.open}
120 onClose={this.closeDialog}
122 data-cy="choose-a-directory-dialog"
124 <DialogTitle>Choose a directory</DialogTitle>
127 pickerId={this.props.commandInput.id}
129 options={this.props.options}
130 toggleItemActive={this.setDirectory} />
133 <Button onClick={this.closeDialog}>Cancel</Button>
135 disabled={!this.state.directory}
138 onClick={this.submit}>Ok</Button>