20031: Remove redundant collection copy/move form initializations
[arvados-workbench2.git] / src / store / collections / collection-partial-move-actions.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { Dispatch } from "redux";
6 import { FormErrors, initialize, startSubmit, stopSubmit } from "redux-form";
7 import { CommonResourceServiceError, getCommonResourceServiceError } from "services/common-service/common-resource-service";
8 import { ServiceRepository } from "services/services";
9 import { filterCollectionFilesBySelection } from "store/collection-panel/collection-panel-files/collection-panel-files-state";
10 import { dialogActions } from "store/dialog/dialog-actions";
11 import { navigateTo } from "store/navigation/navigation-action";
12 import { progressIndicatorActions } from "store/progress-indicator/progress-indicator-actions";
13 import { resetPickerProjectTree } from "store/project-tree-picker/project-tree-picker-actions";
14 import { updateResources } from "store/resources/resources-actions";
15 import { SnackbarKind, snackbarActions } from "store/snackbar/snackbar-actions";
16 import { RootState } from "store/store";
17
18 export const COLLECTION_PARTIAL_MOVE_TO_NEW_COLLECTION = 'COLLECTION_PARTIAL_MOVE_TO_NEW_DIALOG';
19 export const COLLECTION_PARTIAL_MOVE_TO_SELECTED_COLLECTION = 'COLLECTION_PARTIAL_MOVE_TO_SELECTED_DIALOG';
20 export const COLLECTION_PARTIAL_MOVE_TO_SEPARATE_COLLECTIONS = 'COLLECTION_PARTIAL_MOVE_TO_SEPARATE_DIALOG';
21
22 export interface CollectionPartialMoveToNewCollectionFormData {
23     name: string;
24     description: string;
25     projectUuid: string;
26 }
27
28 export interface CollectionPartialMoveToExistingCollectionFormData {
29     destination: {uuid: string, path?: string};
30 }
31
32 export interface CollectionPartialMoveToSeparateCollectionsFormData {
33     name: string;
34     projectUuid: string;
35 }
36
37 export const openCollectionPartialMoveToNewCollectionDialog = () =>
38     (dispatch: Dispatch, getState: () => RootState) => {
39         const currentCollection = getState().collectionPanel.item;
40         if (currentCollection) {
41             const initialData = {
42                 name: `Files moved from: ${currentCollection.name}`,
43                 description: currentCollection.description,
44                 projectUuid: undefined
45             };
46             dispatch(initialize(COLLECTION_PARTIAL_MOVE_TO_NEW_COLLECTION, initialData));
47             dispatch<any>(resetPickerProjectTree());
48             dispatch(dialogActions.OPEN_DIALOG({ id: COLLECTION_PARTIAL_MOVE_TO_NEW_COLLECTION, data: {} }));
49         }
50     };
51
52 export const moveCollectionPartialToNewCollection = ({ name, description, projectUuid }: CollectionPartialMoveToNewCollectionFormData) =>
53     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
54         const state = getState();
55         // Get current collection
56         const sourceCollection = state.collectionPanel.item;
57
58         if (sourceCollection) {
59             try {
60                 dispatch(startSubmit(COLLECTION_PARTIAL_MOVE_TO_NEW_COLLECTION));
61                 dispatch(progressIndicatorActions.START_WORKING(COLLECTION_PARTIAL_MOVE_TO_NEW_COLLECTION));
62
63                 // Get selected files
64                 const paths = filterCollectionFilesBySelection(state.collectionPanelFiles, true)
65                     .map(file => file.id.replace(new RegExp(`(^${sourceCollection.uuid})`), ''));
66
67                 // Move files
68                 const updatedCollection = await services.collectionService.moveFiles(
69                     sourceCollection.uuid,
70                     sourceCollection.portableDataHash,
71                     paths,
72                     {
73                         name,
74                         description,
75                         ownerUuid: projectUuid,
76                         uuid: undefined,
77                     },
78                     '/',
79                     false
80                 );
81                 dispatch(updateResources([updatedCollection]));
82                 dispatch<any>(navigateTo(updatedCollection.uuid))
83
84                 dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_PARTIAL_MOVE_TO_NEW_COLLECTION }));
85                 dispatch(snackbarActions.OPEN_SNACKBAR({
86                     message: 'Files have been moved to selected collection.',
87                     hideDuration: 2000,
88                     kind: SnackbarKind.SUCCESS
89                 }));
90                 dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_PARTIAL_MOVE_TO_NEW_COLLECTION));
91             } catch (e) {
92                 const error = getCommonResourceServiceError(e);
93                 if (error === CommonResourceServiceError.UNKNOWN) {
94                     dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_PARTIAL_MOVE_TO_NEW_COLLECTION }));
95                     dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Could not move files to selected collection', hideDuration: 2000, kind: SnackbarKind.ERROR }));
96                 }
97                 dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_PARTIAL_MOVE_TO_NEW_COLLECTION));
98             }
99         }
100     };
101
102 export const openCollectionPartialMoveToExistingCollectionDialog = () =>
103     (dispatch: Dispatch, getState: () => RootState) => {
104         const currentCollection = getState().collectionPanel.item;
105         if (currentCollection) {
106             const initialData = {
107                 destination: {uuid: '', path: ''}
108             };
109             dispatch(initialize(COLLECTION_PARTIAL_MOVE_TO_SELECTED_COLLECTION, initialData));
110             dispatch<any>(resetPickerProjectTree());
111             dispatch(dialogActions.OPEN_DIALOG({ id: COLLECTION_PARTIAL_MOVE_TO_SELECTED_COLLECTION, data: {} }));
112         }
113     };
114
115 export const moveCollectionPartialToExistingCollection = ({ destination }: CollectionPartialMoveToExistingCollectionFormData) =>
116     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
117         const state = getState();
118         // Get current collection
119         const sourceCollection = state.collectionPanel.item;
120
121         if (sourceCollection && destination.uuid) {
122             try {
123                 dispatch(startSubmit(COLLECTION_PARTIAL_MOVE_TO_SELECTED_COLLECTION));
124                 dispatch(progressIndicatorActions.START_WORKING(COLLECTION_PARTIAL_MOVE_TO_SELECTED_COLLECTION));
125                 // Get selected files
126                 const paths = filterCollectionFilesBySelection(state.collectionPanelFiles, true)
127                     .map(file => file.id.replace(new RegExp(`(^${sourceCollection.uuid})`), ''));
128
129                 // Move files
130                 const updatedCollection = await services.collectionService.moveFiles(sourceCollection.uuid, sourceCollection.portableDataHash, paths, {uuid: destination.uuid}, destination.path || '/', false);
131                 dispatch(updateResources([updatedCollection]));
132
133                 dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_PARTIAL_MOVE_TO_SELECTED_COLLECTION }));
134                 dispatch(snackbarActions.OPEN_SNACKBAR({
135                     message: 'Files have been moved to selected collection.',
136                     hideDuration: 2000,
137                     kind: SnackbarKind.SUCCESS
138                 }));
139                 dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_PARTIAL_MOVE_TO_SELECTED_COLLECTION));
140             } catch (e) {
141                 const error = getCommonResourceServiceError(e);
142                 if (error === CommonResourceServiceError.UNKNOWN) {
143                     dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_PARTIAL_MOVE_TO_SELECTED_COLLECTION }));
144                     dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Could not copy this files to selected collection', hideDuration: 2000, kind: SnackbarKind.ERROR }));
145                 }
146                 dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_PARTIAL_MOVE_TO_SELECTED_COLLECTION));
147             }
148         }
149     };
150
151 export const openCollectionPartialMoveToSeparateCollectionsDialog = () =>
152     (dispatch: Dispatch, getState: () => RootState) => {
153         const currentCollection = getState().collectionPanel.item;
154         if (currentCollection) {
155             const initialData = {
156                 name: currentCollection.name,
157                 projectUuid: undefined
158             };
159             dispatch(initialize(COLLECTION_PARTIAL_MOVE_TO_SEPARATE_COLLECTIONS, initialData));
160             dispatch<any>(resetPickerProjectTree());
161             dispatch(dialogActions.OPEN_DIALOG({ id: COLLECTION_PARTIAL_MOVE_TO_SEPARATE_COLLECTIONS, data: {} }));
162         }
163     };
164
165 export const moveCollectionPartialToSeparateCollections = ({ name, projectUuid }: CollectionPartialMoveToSeparateCollectionsFormData) =>
166     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
167         const state = getState();
168         // Get current collection
169         const sourceCollection = state.collectionPanel.item;
170
171         if (sourceCollection) {
172             try {
173                 dispatch(startSubmit(COLLECTION_PARTIAL_MOVE_TO_SEPARATE_COLLECTIONS));
174                 dispatch(progressIndicatorActions.START_WORKING(COLLECTION_PARTIAL_MOVE_TO_SEPARATE_COLLECTIONS));
175
176                 // Get selected files
177                 const paths = filterCollectionFilesBySelection(state.collectionPanelFiles, true)
178                     .map(file => file.id.replace(new RegExp(`(^${sourceCollection.uuid})`), ''));
179
180                 // Move files
181                 const collections = await Promise.all(paths.map((path) =>
182                     services.collectionService.moveFiles(
183                         sourceCollection.uuid,
184                         sourceCollection.portableDataHash,
185                         [path],
186                         {
187                             name: `File split from collection ${name}${path}`,
188                             ownerUuid: projectUuid,
189                             uuid: undefined,
190                         },
191                         '/',
192                         false
193                     )
194                 ));
195                 dispatch(updateResources(collections));
196
197                 dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_PARTIAL_MOVE_TO_SEPARATE_COLLECTIONS }));
198                 dispatch(snackbarActions.OPEN_SNACKBAR({
199                     message: 'New collections created.',
200                     hideDuration: 2000,
201                     kind: SnackbarKind.SUCCESS
202                 }));
203                 dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_PARTIAL_MOVE_TO_SEPARATE_COLLECTIONS));
204             } catch (e) {
205                 const error = getCommonResourceServiceError(e);
206                 if (error === CommonResourceServiceError.UNIQUE_NAME_VIOLATION) {
207                     dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Collection from one or more files already exists', hideDuration: 2000, kind: SnackbarKind.ERROR }));
208                 } else if (error === CommonResourceServiceError.UNKNOWN) {
209                     dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_PARTIAL_MOVE_TO_SEPARATE_COLLECTIONS }));
210                     dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Could not create a copy of collection', hideDuration: 2000, kind: SnackbarKind.ERROR }));
211                 } else {
212                     dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_PARTIAL_MOVE_TO_SEPARATE_COLLECTIONS }));
213                     dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Collection has been copied but may contain incorrect files.', hideDuration: 2000, kind: SnackbarKind.ERROR }));
214                 }
215                 dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_PARTIAL_MOVE_TO_SEPARATE_COLLECTIONS));
216             }
217         }
218     };