[ARVADOS-WORKBENCH2] updated: 1.1.4-621-g5a40b5b

Git user git at public.curoverse.com
Fri Aug 17 06:48:07 EDT 2018


Summary of changes:
 .../collection-panel-files.tsx                     | 66 +++++++++-------------
 .../file-upload-dialog/file-upload-dialog.tsx      | 52 +++++++++++++++++
 .../creator/collection-creator-action.ts           | 20 +++++++
 .../uploader/collection-uploader-actions.ts        | 44 ++++++++++++++-
 .../collection-panel-files.ts                      |  5 +-
 .../upload-collection-files-dialog.ts              | 29 ++++++++++
 src/views/workbench/workbench.tsx                  |  4 +-
 7 files changed, 175 insertions(+), 45 deletions(-)
 create mode 100644 src/components/file-upload-dialog/file-upload-dialog.tsx
 create mode 100644 src/views-components/upload-collection-files-dialog/upload-collection-files-dialog.ts

       via  5a40b5b582b25e410622da8b7e484fad757f6bd1 (commit)
      from  e13e7dd672160e4ab5569c24133f4f6032db4a9a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 5a40b5b582b25e410622da8b7e484fad757f6bd1
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date:   Fri Aug 17 12:47:53 2018 +0200

    Create collection files upload dialog
    
    Feature #14013
    
    Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>

diff --git a/src/components/collection-panel-files/collection-panel-files.tsx b/src/components/collection-panel-files/collection-panel-files.tsx
index 665758c..f9c1821 100644
--- a/src/components/collection-panel-files/collection-panel-files.tsx
+++ b/src/components/collection-panel-files/collection-panel-files.tsx
@@ -8,10 +8,6 @@ import { FileTreeData } from '../file-tree/file-tree-data';
 import { FileTree } from '../file-tree/file-tree';
 import { IconButton, Grid, Typography, StyleRulesCallback, withStyles, WithStyles, CardHeader, Card, Button } from '@material-ui/core';
 import { CustomizeTableIcon } from '../icon/icon';
-import { connect, DispatchProp } from "react-redux";
-import { Dispatch } from "redux";
-import { RootState } from "~/store/store";
-import { ServiceRepository } from "~/services/services";
 
 export interface CollectionPanelFilesProps {
     items: Array<TreeItem<FileTreeData>>;
@@ -40,44 +36,34 @@ const styles: StyleRulesCallback<CssRules> = theme => ({
     }
 });
 
-const renameFile = () => (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
-  services.collectionFilesService.renameTest();
-};
-
-
 export const CollectionPanelFiles =
-    connect()(
     withStyles(styles)(
-    ({ onItemMenuOpen, onOptionsMenuOpen, classes, dispatch, ...treeProps }: CollectionPanelFilesProps & DispatchProp & WithStyles<CssRules>) =>
-        <Card className={classes.root}>
-            <CardHeader
-                title="Files"
-                action={
-                    <Button onClick={
-                        () => {
-                            dispatch<any>(renameFile());
-                        }}
-                        variant='raised'
-                        color='primary'
-                        size='small'>
-                        Upload data
+        ({ onItemMenuOpen, onOptionsMenuOpen, onUploadDataClick, classes, ...treeProps }: CollectionPanelFilesProps & WithStyles<CssRules>) =>
+            <Card className={classes.root}>
+                <CardHeader
+                    title="Files"
+                    action={
+                        <Button onClick={onUploadDataClick}
+                            variant='raised'
+                            color='primary'
+                            size='small'>
+                            Upload data
                     </Button>
-                } />
-            <CardHeader
-                className={classes.cardSubheader}
-                action={
-                    <IconButton onClick={onOptionsMenuOpen}>
-                        <CustomizeTableIcon />
-                    </IconButton>
-                } />
-            <Grid container justify="space-between">
-                <Typography variant="caption" className={classes.nameHeader}>
-                    Name
+                    } />
+                <CardHeader
+                    className={classes.cardSubheader}
+                    action={
+                        <IconButton onClick={onOptionsMenuOpen}>
+                            <CustomizeTableIcon />
+                        </IconButton>
+                    } />
+                <Grid container justify="space-between">
+                    <Typography variant="caption" className={classes.nameHeader}>
+                        Name
                     </Typography>
-                <Typography variant="caption" className={classes.fileSizeHeader}>
-                    File size
+                    <Typography variant="caption" className={classes.fileSizeHeader}>
+                        File size
                     </Typography>
-            </Grid>
-            <FileTree onMenuOpen={onItemMenuOpen} {...treeProps} />
-        </Card>)
-);
+                </Grid>
+                <FileTree onMenuOpen={onItemMenuOpen} {...treeProps} />
+            </Card>);
diff --git a/src/components/file-upload-dialog/file-upload-dialog.tsx b/src/components/file-upload-dialog/file-upload-dialog.tsx
new file mode 100644
index 0000000..a764411
--- /dev/null
+++ b/src/components/file-upload-dialog/file-upload-dialog.tsx
@@ -0,0 +1,52 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { FileUpload } from "~/components/file-upload/file-upload";
+import { UploadFile } from '~/store/collections/uploader/collection-uploader-actions';
+import { Dialog, DialogTitle, DialogContent, DialogActions } from '@material-ui/core/';
+import { Button, CircularProgress } from '@material-ui/core';
+import { WithDialogProps } from '../../store/dialog/with-dialog';
+
+export interface FilesUploadDialogProps {
+    files: UploadFile[];
+    uploading: boolean;
+    onSubmit: () => void;
+    onChange: (files: File[]) => void;
+}
+
+export const FilesUploadDialog = (props: FilesUploadDialogProps & WithDialogProps<{}>) =>
+    <Dialog open={props.open}
+        disableBackdropClick={true}
+        disableEscapeKeyDown={true}
+        fullWidth={true}
+        maxWidth='sm'>
+        <DialogTitle>Upload data</DialogTitle>
+        <DialogContent>
+            <FileUpload
+                files={props.files}
+                disabled={props.uploading}
+                onDrop={props.onChange}
+            />
+        </DialogContent>
+        <DialogActions>
+            <Button
+                variant='flat'
+                color='primary'
+                disabled={props.uploading}
+                onClick={props.closeDialog}>
+                Cancel
+            </Button>
+            <Button
+                variant='contained'
+                color='primary'
+                type='submit'
+                onClick={props.onSubmit}
+                disabled={props.uploading}>
+                {props.uploading
+                    ? <CircularProgress size={20} />
+                    : 'Upload data'}
+            </Button>
+        </DialogActions>
+    </Dialog>;
\ No newline at end of file
diff --git a/src/store/collections/creator/collection-creator-action.ts b/src/store/collections/creator/collection-creator-action.ts
index a3a6bf8..f1044a9 100644
--- a/src/store/collections/creator/collection-creator-action.ts
+++ b/src/store/collections/creator/collection-creator-action.ts
@@ -43,4 +43,24 @@ export const createCollection = (collection: Partial<CollectionResource>, files:
             });
     };
 
+export const uploadCollectionFiles = (collectionUuid: string, files: File[]) =>
+    (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+        dispatch(collectionUploaderActions.START_UPLOAD());
+        return services.collectionService.uploadFiles(collectionUuid, files,
+            (fileId, loaded, total, currentTime) => {
+                dispatch(collectionUploaderActions.SET_UPLOAD_PROGRESS({ fileId, loaded, total, currentTime }));
+            })
+            .then(() => {
+                dispatch(collectionUploaderActions.CLEAR_UPLOAD());
+            });
+    };
+
+export const uploadCurrentCollectionFiles = (files: File[]) =>
+    (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+        const currentCollection = getState().collectionPanel.item;
+        if (currentCollection) {
+            return dispatch<any>(uploadCollectionFiles(currentCollection.uuid, files));
+        }
+    };
+
 export type CollectionCreateAction = UnionOf<typeof collectionCreateActions>;
diff --git a/src/store/collections/uploader/collection-uploader-actions.ts b/src/store/collections/uploader/collection-uploader-actions.ts
index f6b6bfa..bc3a0d1 100644
--- a/src/store/collections/uploader/collection-uploader-actions.ts
+++ b/src/store/collections/uploader/collection-uploader-actions.ts
@@ -3,6 +3,12 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import { default as unionize, ofType, UnionOf } from "unionize";
+import { Dispatch } from 'redux';
+import { RootState } from '~/store/store';
+import { ServiceRepository } from '~/services/services';
+import { dialogActions } from '~/store/dialog/dialog-actions';
+import { loadCollectionFiles } from '../../collection-panel/collection-panel-files/collection-panel-files-actions';
+import { snackbarActions } from "~/store/snackbar/snackbar-actions";
 
 export interface UploadFile {
     id: number;
@@ -21,8 +27,40 @@ export const collectionUploaderActions = unionize({
     SET_UPLOAD_PROGRESS: ofType<{ fileId: number, loaded: number, total: number, currentTime: number }>(),
     CLEAR_UPLOAD: ofType()
 }, {
-    tag: 'type',
-    value: 'payload'
-});
+        tag: 'type',
+        value: 'payload'
+    });
 
 export type CollectionUploaderAction = UnionOf<typeof collectionUploaderActions>;
+
+export const uploadCollectionFiles = (collectionUuid: string) =>
+    (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+        dispatch(collectionUploaderActions.START_UPLOAD());
+        const files = getState().collections.uploader.map(file => file.file);
+        return services.collectionService.uploadFiles(collectionUuid, files,
+            (fileId, loaded, total, currentTime) => {
+                dispatch(collectionUploaderActions.SET_UPLOAD_PROGRESS({ fileId, loaded, total, currentTime }));
+            })
+            .then(() => {
+                dispatch(collectionUploaderActions.CLEAR_UPLOAD());
+            });
+    };
+
+export const uploadCurrentCollectionFiles = () =>
+    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+        const currentCollection = getState().collectionPanel.item;
+        if (currentCollection) {
+            await dispatch<any>(uploadCollectionFiles(currentCollection.uuid));
+            dispatch<any>(loadCollectionFiles(currentCollection.uuid));
+            dispatch(closeUploadCollectionFilesDialog());
+            dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Data has been uploaded.', hideDuration: 2000 }));
+        }
+    };
+
+export const UPLOAD_COLLECTION_FILES_DIALOG = 'uploadCollectionFilesDialog';
+export const openUploadCollectionFilesDialog = () => (dispatch: Dispatch) => {
+    dispatch(collectionUploaderActions.CLEAR_UPLOAD());
+    dispatch<any>(dialogActions.OPEN_DIALOG({ id: UPLOAD_COLLECTION_FILES_DIALOG, data: {} }));
+};
+
+export const closeUploadCollectionFilesDialog = () => dialogActions.CLOSE_DIALOG({ id: UPLOAD_COLLECTION_FILES_DIALOG });
diff --git a/src/views-components/collection-panel-files/collection-panel-files.ts b/src/views-components/collection-panel-files/collection-panel-files.ts
index ae9b53e..21706e8 100644
--- a/src/views-components/collection-panel-files/collection-panel-files.ts
+++ b/src/views-components/collection-panel-files/collection-panel-files.ts
@@ -14,6 +14,7 @@ import { contextMenuActions } from "~/store/context-menu/context-menu-actions";
 import { ContextMenuKind } from "../context-menu/context-menu";
 import { Tree, getNodeChildren, getNode } from "~/models/tree";
 import { CollectionFileType } from "~/models/collection-file";
+import { openUploadCollectionFilesDialog } from '~/store/collections/uploader/collection-uploader-actions';
 
 const memoizedMapStateToProps = () => {
     let prevState: CollectionPanelFilesState;
@@ -32,7 +33,9 @@ const memoizedMapStateToProps = () => {
 };
 
 const mapDispatchToProps = (dispatch: Dispatch): Pick<CollectionPanelFilesProps, 'onUploadDataClick' | 'onCollapseToggle' | 'onSelectionToggle' | 'onItemMenuOpen' | 'onOptionsMenuOpen'> => ({
-    onUploadDataClick: () => { return; },
+    onUploadDataClick: () => {
+        dispatch<any>(openUploadCollectionFilesDialog());
+    },
     onCollapseToggle: (id) => {
         dispatch(collectionPanelFilesAction.TOGGLE_COLLECTION_FILE_COLLAPSE({ id }));
     },
diff --git a/src/views-components/upload-collection-files-dialog/upload-collection-files-dialog.ts b/src/views-components/upload-collection-files-dialog/upload-collection-files-dialog.ts
new file mode 100644
index 0000000..1f3a50e
--- /dev/null
+++ b/src/views-components/upload-collection-files-dialog/upload-collection-files-dialog.ts
@@ -0,0 +1,29 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { connect } from "react-redux";
+import { Dispatch, compose } from "redux";
+import { withDialog } from '~/store/dialog/with-dialog';
+import { FilesUploadDialog } from '~/components/file-upload-dialog/file-upload-dialog';
+import { RootState } from '../../store/store';
+import { uploadCurrentCollectionFiles, UPLOAD_COLLECTION_FILES_DIALOG, collectionUploaderActions } from '~/store/collections/uploader/collection-uploader-actions';
+
+const mapStateToProps = (state: RootState) => ({
+    files: state.collections.uploader,
+    uploading: state.collections.uploader.some(file => file.loaded < file.total)
+});
+
+const mapDispatchToProps = (dispatch: Dispatch) => ({
+    onSubmit: () => {
+        dispatch<any>(uploadCurrentCollectionFiles());
+    },
+    onChange: (files: File[]) => {
+        dispatch(collectionUploaderActions.SET_UPLOAD_FILES(files));
+    }
+});
+
+export const UploadCollectionFilesDialog = compose(
+    withDialog(UPLOAD_COLLECTION_FILES_DIALOG),
+    connect(mapStateToProps, mapDispatchToProps)
+)(FilesUploadDialog);
\ No newline at end of file
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index 58641fb..df304ae 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -49,6 +49,7 @@ import { MultipleFilesRemoveDialog } from '~/views-components/file-remove-dialog
 import { DialogCollectionCreateWithSelectedFile } from '~/views-components/create-collection-dialog-with-selected/create-collection-dialog-with-selected';
 import { COLLECTION_CREATE_DIALOG } from '~/views-components/dialog-create/dialog-collection-create';
 import { PROJECT_CREATE_DIALOG } from '~/views-components/dialog-create/dialog-project-create';
+import { UploadCollectionFilesDialog } from '~/views-components/upload-collection-files-dialog/upload-collection-files-dialog';
 
 const DRAWER_WITDH = 240;
 const APP_BAR_HEIGHT = 100;
@@ -228,7 +229,7 @@ export const Workbench = withStyles(styles)(
                         <main className={classes.contentWrapper}>
                             <div className={classes.content}>
                                 <Switch>
-                                    <Route path='/' exact render={() => <Redirect to={`/projects/${this.props.authService.getUuid()}`}  />} />
+                                    <Route path='/' exact render={() => <Redirect to={`/projects/${this.props.authService.getUuid()}`} />} />
                                     <Route path="/projects/:id" render={this.renderProjectPanel} />
                                     <Route path="/favorites" render={this.renderFavoritePanel} />
                                     <Route path="/collections/:id" render={this.renderCollectionPanel} />
@@ -245,6 +246,7 @@ export const Workbench = withStyles(styles)(
                         <FileRemoveDialog />
                         <MultipleFilesRemoveDialog />
                         <UpdateCollectionDialog />
+                        <UploadCollectionFilesDialog />
                         <CurrentTokenDialog
                             currentToken={this.props.currentToken}
                             open={this.state.isCurrentTokenDialogOpen}

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list