dispatch(progressIndicatorActions.START_WORKING(COLLECTION_PARTIAL_COPY_TO_SELECTED_COLLECTION));
// Copy files
- const updatedCollection = await services.collectionService.copyFiles(fileSelection.collection.portableDataHash, fileSelection.selectedPaths, {uuid: formData.destination.uuid}, formData.destination.path || '/', false);
+ const updatedCollection = await services.collectionService.copyFiles(
+ fileSelection.collection.portableDataHash,
+ fileSelection.selectedPaths,
+ {uuid: formData.destination.uuid},
+ formData.destination.subpath || '/',
+ false
+ );
dispatch(updateResources([updatedCollection]));
dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_PARTIAL_COPY_TO_SELECTED_COLLECTION }));
fileSelection.collection.portableDataHash,
fileSelection.selectedPaths,
{uuid: formData.destination.uuid},
- formData.destination.path || '/', false
+ formData.destination.subpath || '/', false
);
dispatch(updateResources([updatedCollection]));
import { sortFilesTree } from "services/collection-service/collection-service-files-response";
import { GroupClass, GroupResource } from "models/group";
import { CollectionResource } from "models/collection";
+import { getResource } from "store/resources/resources";
+import { updateResources } from "store/resources/resources-actions";
export const treePickerActions = unionize({
LOAD_TREE_PICKER_NODE: ofType<{ id: string, pickerId: string }>(),
const itemLimit = 200;
const { items, itemsAvailable } = await services.groupsService.contents((loadShared || searchProjects) ? '' : id, { filters, excludeHomeProject: loadShared || undefined, limit: itemLimit });
+ dispatch<any>(updateResources(items));
if (itemsAvailable > itemLimit) {
items.push({
* if the item represents a valid target/destination location
*/
export type FileOperationLocation = {
+ name: string;
uuid: string;
- path: string;
+ pdh?: string;
+ subpath: string;
}
-export const getFileOperationLocation = (item: ProjectsTreePickerItem): FileOperationLocation | undefined => {
- if ('kind' in item && item.kind === ResourceKind.COLLECTION) {
- return {
- uuid: item.uuid,
- path: '/'
- };
- } else if ('type' in item && item.type === CollectionFileType.DIRECTORY) {
- const uuid = getCollectionResourceCollectionUuid(item.id);
- if (uuid) {
+export const getFileOperationLocation = (item: ProjectsTreePickerItem) =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository): Promise<FileOperationLocation | undefined> => {
+ if ('kind' in item && item.kind === ResourceKind.COLLECTION) {
return {
- uuid,
- path: [item.path, item.name].join('/')
+ name: item.name,
+ uuid: item.uuid,
+ pdh: item.portableDataHash,
+ subpath: '/',
};
- } else {
- return undefined;
+ } else if ('type' in item && item.type === CollectionFileType.DIRECTORY) {
+ const uuid = getCollectionResourceCollectionUuid(item.id);
+ if (uuid) {
+ const collection = getResource<CollectionResource>(uuid)(getState().resources);
+ if (collection) {
+ const itemPath = [item.path, item.name].join('/');
+
+ return {
+ name: item.name,
+ uuid,
+ pdh: collection.portableDataHash,
+ subpath: itemPath,
+ };
+ }
+ }
}
- } else {
return undefined;
- }
-};
+ };
/**
* Create an expanded tree picker subtree from array of nested projects/collection
<Field
name="destination"
pickerId={props.pickerId}
- component={DirectoryTreePickerField}
+ component={DirectoryTreePickerField as any}
validate={validateDirectory} />;
interface StorageClassesProps {
import { ProjectsTreePicker } from 'views-components/projects-tree-picker/projects-tree-picker';
import { ProjectsTreePickerItem } from 'store/tree-picker/tree-picker-middleware';
import { PickerIdProp } from 'store/tree-picker/picker-id';
-import { getFileOperationLocation } from "store/tree-picker/tree-picker-actions";
+import { FileOperationLocation, getFileOperationLocation } from "store/tree-picker/tree-picker-actions";
+import { connect } from "react-redux";
+import { Dispatch } from "redux";
export const ProjectTreePickerField = (props: WrappedFieldProps & PickerIdProp) =>
<div style={{ display: 'flex', minHeight: 0, flexDirection: 'column' }}>
</div>
</div>;
-const handleDirectoryChange = (props: WrappedFieldProps) =>
- (_: any, { data }: TreeItem<ProjectsTreePickerItem>) => {
- props.input.onChange(getFileOperationLocation(data) || '');
- }
+type ProjectsTreePickerActionProps = {
+ getFileOperationLocation: (item: ProjectsTreePickerItem) => Promise<FileOperationLocation | undefined>;
+}
-export const DirectoryTreePickerField = (props: WrappedFieldProps & PickerIdProp) =>
- <div style={{ display: 'flex', minHeight: 0, flexDirection: 'column' }}>
- <div style={{ flexBasis: '275px', flexShrink: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }}>
- <ProjectsTreePicker
- currentUuid={props.input.value.uuid}
- pickerId={props.pickerId}
- toggleItemActive={handleDirectoryChange(props)}
- options={{ showOnlyOwned: false, showOnlyWritable: true }}
- includeCollections
- includeDirectories />
- {props.meta.dirty && props.meta.error &&
- <Typography variant='caption' color='error'>
- {props.meta.error}
- </Typography>}
- </div>
- </div>;
+const projectsTreePickerMapDispatchToProps = (dispatch: Dispatch): ProjectsTreePickerActionProps => ({
+ getFileOperationLocation: (item: ProjectsTreePickerItem) => dispatch<any>(getFileOperationLocation(item)),
+});
+
+type ProjectsTreePickerCombinedProps = ProjectsTreePickerActionProps & WrappedFieldProps & PickerIdProp;
+
+export const DirectoryTreePickerField = connect(null, projectsTreePickerMapDispatchToProps)(
+ class DirectoryTreePickerFieldComponent extends React.Component<ProjectsTreePickerCombinedProps> {
+
+ handleDirectoryChange = (props: WrappedFieldProps) =>
+ async (_: any, { data }: TreeItem<ProjectsTreePickerItem>) => {
+ const location = await this.props.getFileOperationLocation(data);
+ props.input.onChange(location || '');
+ }
+
+ render() {
+ return <div style={{ display: 'flex', minHeight: 0, flexDirection: 'column' }}>
+ <div style={{ flexBasis: '275px', flexShrink: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }}>
+ <ProjectsTreePicker
+ currentUuid={this.props.input.value.uuid}
+ pickerId={this.props.pickerId}
+ toggleItemActive={this.handleDirectoryChange(this.props)}
+ options={{ showOnlyOwned: false, showOnlyWritable: true }}
+ includeCollections
+ includeDirectories />
+ {this.props.meta.dirty && this.props.meta.error &&
+ <Typography variant='caption' color='error'>
+ {this.props.meta.error}
+ </Typography>}
+ </div>
+ </div>;
+ }
+ });
} from 'models/workflow';
import { GenericInputProps, GenericInput } from './generic-input';
import { ProjectsTreePicker } from 'views-components/projects-tree-picker/projects-tree-picker';
-import { initProjectsTreePicker } from 'store/tree-picker/tree-picker-actions';
+import { FileOperationLocation, getFileOperationLocation, initProjectsTreePicker } from 'store/tree-picker/tree-picker-actions';
import { TreeItem } from 'components/tree/tree';
import { ProjectsTreePickerItem } from 'store/tree-picker/tree-picker-middleware';
-import { CollectionResource } from 'models/collection';
-import { ResourceKind } from 'models/resource';
import { ERROR_MESSAGE } from 'validators/require';
+import { Dispatch } from 'redux';
export interface DirectoryInputProps {
input: DirectoryCommandInputParameter;
const format = (value?: Directory) => value ? value.basename : '';
-const parse = (directory: CollectionResource): Directory => ({
+const parse = (directory: FileOperationLocation): Directory => ({
class: CWLType.DIRECTORY,
- location: `keep:${directory.portableDataHash}`,
+ location: `keep:${directory.pdh}${directory.subpath}`,
basename: directory.name,
});
interface DirectoryInputComponentState {
open: boolean;
- directory?: CollectionResource;
+ directory?: FileOperationLocation;
}
-const DirectoryInputComponent = connect()(
- class FileInputComponent extends React.Component<GenericInputProps & DispatchProp & {
+interface DirectoryInputActionProps {
+ initProjectsTreePicker: (pickerId: string) => void;
+ getFileOperationLocation: (item: ProjectsTreePickerItem) => Promise<FileOperationLocation | undefined>;
+}
+
+const mapDispatchToProps = (dispatch: Dispatch): DirectoryInputActionProps => ({
+ initProjectsTreePicker: (pickerId: string) => dispatch<any>(initProjectsTreePicker(pickerId)),
+ getFileOperationLocation: (item: ProjectsTreePickerItem) => dispatch<any>(getFileOperationLocation(item)),
+});
+
+const DirectoryInputComponent = connect(null, mapDispatchToProps)(
+ class FileInputComponent extends React.Component<GenericInputProps & DirectoryInputActionProps & DispatchProp & {
options?: { showOnlyOwned: boolean, showOnlyWritable: boolean };
}, DirectoryInputComponentState> {
state: DirectoryInputComponentState = {
};
componentDidMount() {
- this.props.dispatch<any>(
- initProjectsTreePicker(this.props.commandInput.id));
+ this.props.initProjectsTreePicker(this.props.commandInput.id);
}
render() {
this.props.input.onChange(this.state.directory);
}
- setDirectory = (_: {}, { data }: TreeItem<ProjectsTreePickerItem>) => {
- if ('kind' in data && data.kind === ResourceKind.COLLECTION) {
- this.setState({ directory: data });
- } else {
- this.setState({ directory: undefined });
- }
+ setDirectory = async (_: {}, { data: item }: TreeItem<ProjectsTreePickerItem>) => {
+ const location = await this.props.getFileOperationLocation(item);
+ this.setState({ directory: location });
}
renderInput() {
<ProjectsTreePicker
pickerId={this.props.commandInput.id}
includeCollections
+ includeDirectories
options={this.props.options}
toggleItemActive={this.setDirectory} />
</div>