20031: Add type for collection file operation location for form field
authorStephen Smith <stephen@curii.com>
Tue, 25 Apr 2023 14:52:10 +0000 (10:52 -0400)
committerStephen Smith <stephen@curii.com>
Tue, 25 Apr 2023 14:52:10 +0000 (10:52 -0400)
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen@curii.com>

src/store/collections/collection-partial-copy-actions.ts
src/store/collections/collection-partial-move-actions.ts
src/store/tree-picker/tree-picker-actions.ts
src/views-components/form-fields/collection-form-fields.tsx
src/views-components/projects-tree-picker/tree-picker-field.tsx

index 08b96655e2557a213904a7aac2007ea258958803..f9ecb5cafa5487cd43070573f1465ff60b3b0d6c 100644 (file)
@@ -12,6 +12,7 @@ import { filterCollectionFilesBySelection } from '../collection-panel/collection
 import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
 import { getCommonResourceServiceError, CommonResourceServiceError } from 'services/common-service/common-resource-service';
 import { progressIndicatorActions } from "store/progress-indicator/progress-indicator-actions";
+import { FileOperationLocation } from "store/tree-picker/tree-picker-actions";
 import { updateResources } from 'store/resources/resources-actions';
 import { navigateTo } from 'store/navigation/navigation-action';
 
@@ -26,7 +27,7 @@ export interface CollectionPartialCopyToNewCollectionFormData {
 }
 
 export interface CollectionPartialCopyToExistingCollectionFormData {
-    destination: {uuid: string, path?: string};
+    destination: FileOperationLocation;
 }
 
 export interface CollectionPartialCopyToSeparateCollectionsFormData {
@@ -122,7 +123,7 @@ export const copyCollectionPartialToExistingCollection = ({ destination }: Colle
         // Get current collection
         const sourceCollection = state.collectionPanel.item;
 
-        if (sourceCollection && destination.uuid) {
+        if (sourceCollection && destination && destination.uuid) {
             try {
                 dispatch(startSubmit(COLLECTION_PARTIAL_COPY_TO_SELECTED_COLLECTION));
                 dispatch(progressIndicatorActions.START_WORKING(COLLECTION_PARTIAL_COPY_TO_SELECTED_COLLECTION));
index dbf0a96a3f23cadb3eb9a3c6f56c430602759d66..44e6a9bfe2a94720b4ecfc6db81409bac2e21993 100644 (file)
@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import { Dispatch } from "redux";
-import { FormErrors, initialize, startSubmit, stopSubmit } from "redux-form";
+import { initialize, startSubmit } from "redux-form";
 import { CommonResourceServiceError, getCommonResourceServiceError } from "services/common-service/common-resource-service";
 import { ServiceRepository } from "services/services";
 import { filterCollectionFilesBySelection } from "store/collection-panel/collection-panel-files/collection-panel-files-state";
@@ -14,6 +14,7 @@ import { resetPickerProjectTree } from "store/project-tree-picker/project-tree-p
 import { updateResources } from "store/resources/resources-actions";
 import { SnackbarKind, snackbarActions } from "store/snackbar/snackbar-actions";
 import { RootState } from "store/store";
+import { FileOperationLocation } from "store/tree-picker/tree-picker-actions";
 
 export const COLLECTION_PARTIAL_MOVE_TO_NEW_COLLECTION = 'COLLECTION_PARTIAL_MOVE_TO_NEW_DIALOG';
 export const COLLECTION_PARTIAL_MOVE_TO_SELECTED_COLLECTION = 'COLLECTION_PARTIAL_MOVE_TO_SELECTED_DIALOG';
@@ -26,7 +27,7 @@ export interface CollectionPartialMoveToNewCollectionFormData {
 }
 
 export interface CollectionPartialMoveToExistingCollectionFormData {
-    destination: {uuid: string, path?: string};
+    destination: FileOperationLocation;
 }
 
 export interface CollectionPartialMoveToSeparateCollectionsFormData {
index b8003aa1c29ed045c81eb621ba62d8826bd271fc..505e0622e757e00f72b53f0d7a905d0d0e1b9394 100644 (file)
@@ -4,7 +4,7 @@
 
 import { unionize, ofType, UnionOf } from "common/unionize";
 import { TreeNode, initTreeNode, getNodeDescendants, TreeNodeStatus, getNode, TreePickerId, Tree } from 'models/tree';
-import { CollectionFileType, createCollectionFilesTree } from "models/collection-file";
+import { CollectionFileType, createCollectionFilesTree, getCollectionResourceCollectionUuid } from "models/collection-file";
 import { Dispatch } from 'redux';
 import { RootState } from 'store/store';
 import { getUserUuid } from "common/getuser";
@@ -482,3 +482,32 @@ const buildParams = (ownerUuid: string) => {
             .getOrder()
     };
 };
+
+/**
+ * Given a tree picker item, return collection uuid and path
+ *   if the item represents a valid target/destination location
+ */
+export type FileOperationLocation = {
+    uuid: string;
+    path: 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) {
+            return {
+                uuid,
+                path: [item.path, item.name].join('/')
+            };
+        } else {
+            return undefined;
+        }
+    } else {
+        return undefined;
+    }
+};
index 0faa59b5223cf92355f7faa2ea5f3fb3a74682c0..23a44965c0eac305a09da1c4545b44b772a883bc 100644 (file)
@@ -59,7 +59,7 @@ export const CollectionPickerField = (props: PickerIdProp) =>
         component={CollectionTreePickerField}
         validate={COLLECTION_PROJECT_VALIDATION} />;
 
-const validateDirectory = (val) => (val ? undefined : ERROR_MESSAGE);
+const validateDirectory = (val) => (val && val.uuid ? undefined : ERROR_MESSAGE);
 
 export const DirectoryPickerField = (props: PickerIdProp) =>
     <Field
index 1414d18fd740e62510e6a46d57adb4e67c5875d8..d1ff0a0dbc45339dbb9418a2b3ca5b6cfe8011a0 100644 (file)
@@ -9,8 +9,7 @@ import { WrappedFieldProps } from 'redux-form';
 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 { CollectionFileType, getCollectionResourceCollectionUuid } from "models/collection-file";
-import { ResourceKind } from "models/resource";
+import { getFileOperationLocation } from "store/tree-picker/tree-picker-actions";
 
 export const ProjectTreePickerField = (props: WrappedFieldProps & PickerIdProp) =>
     <div style={{ display: 'flex', minHeight: 0, flexDirection: 'column' }}>
@@ -46,20 +45,8 @@ export const CollectionTreePickerField = (props: WrappedFieldProps & PickerIdPro
     </div>;
 
 const handleDirectoryChange = (props: WrappedFieldProps) =>
-    (_: any, data: TreeItem<ProjectsTreePickerItem>) => {
-        if ('kind' in data.data && data.data.kind === ResourceKind.COLLECTION) {
-            props.input.onChange({
-                uuid: data.data.uuid,
-                path: '/'
-            });
-        } else if ('type' in data.data && data.data.type === CollectionFileType.DIRECTORY) {
-            props.input.onChange({
-                uuid: getCollectionResourceCollectionUuid(data.data.id),
-                path: [data.data.path, data.data.name].join('/')
-            });
-        } else {
-            props.input.onChange('');
-        }
+    (_: any, { data }: TreeItem<ProjectsTreePickerItem>) => {
+        props.input.onChange(getFileOperationLocation(data) || '');
     }
 
 export const DirectoryTreePickerField = (props: WrappedFieldProps & PickerIdProp) =>