Browse Source

Adds the ability to upload whole folders to dashboard (#2334)

bdirito 4 years ago
parent
commit
4ad07f5f1b

+ 27 - 9
packages/@uppy/dashboard/src/components/AddFiles.js

@@ -5,6 +5,10 @@ class AddFiles extends Component {
     this.fileInput.click()
   }
 
+  triggerFolderInputClick = () => {
+    this.folderInput.click()
+  }
+
   onFileInputChange = (event) => {
     this.props.handleInputChange(event)
 
@@ -46,19 +50,20 @@ class AddFiles extends Component {
     )
   }
 
-  renderHiddenFileInput = () => {
+  renderHiddenInput = (isFolder, refCallback) => {
     return (
       <input
         class="uppy-Dashboard-input"
         hidden
         aria-hidden="true"
         tabindex={-1}
+        webkitdirectory={isFolder}
         type="file"
         name="files[]"
         multiple={this.props.maxNumberOfFiles !== 1}
         onchange={this.onFileInputChange}
         accept={this.props.allowedFileTypes}
-        ref={(ref) => { this.fileInput = ref }}
+        ref={refCallback}
       />
     )
   }
@@ -90,24 +95,36 @@ class AddFiles extends Component {
     )
   }
 
-  renderDropPasteBrowseTagline = () => {
+  renderBrowseButton = (text, onClickFn) => {
     const numberOfAcquirers = this.props.acquirers.length
-    const browse =
+    return (
       <button
         type="button"
         class="uppy-u-reset uppy-Dashboard-browse"
-        onclick={this.triggerFileInputClick}
+        onclick={onClickFn}
         data-uppy-super-focusable={numberOfAcquirers === 0}
       >
-        {this.props.i18n('browse')}
+        {text}
       </button>
+    )
+  }
+
+  renderDropPasteBrowseTagline = () => {
+    const numberOfAcquirers = this.props.acquirers.length
+    const browseFiles = this.renderBrowseButton(this.props.i18n('browseFiles'), this.triggerFileInputClick)
+    const browseFolders = this.renderBrowseButton(this.props.i18n('browseFolders'), this.triggerFolderInputClick)
+
+    // in order to keep the i18n CamelCase and options lower (as are defaults) we will want to transform a lower
+    // to Camel
+    const lowerFMSelectionType = this.props.fileManagerSelectionType
+    const camelFMSelectionType = lowerFMSelectionType.charAt(0).toUpperCase() + lowerFMSelectionType.slice(1)
 
     return (
       <div class="uppy-Dashboard-AddFiles-title">
         {
           numberOfAcquirers > 0
-            ? this.props.i18nArray('dropPasteImport', { browse })
-            : this.props.i18nArray('dropPaste', { browse })
+            ? this.props.i18nArray(`dropPasteImport${camelFMSelectionType}`, { browseFiles, browseFolders, browse: browseFiles })
+            : this.props.i18nArray(`dropPaste${camelFMSelectionType}`, { browseFiles, browseFolders, browse: browseFiles })
         }
       </div>
     )
@@ -157,7 +174,8 @@ class AddFiles extends Component {
   render () {
     return (
       <div class="uppy-Dashboard-AddFiles">
-        {this.renderHiddenFileInput()}
+        {this.renderHiddenInput(false, (ref) => { this.fileInput = ref })}
+        {this.renderHiddenInput(true, (ref) => { this.folderInput = ref })}
         {this.renderDropPasteBrowseTagline()}
         {this.props.acquirers.length > 0 && this.renderAcquirers(this.props.acquirers)}
         <div class="uppy-Dashboard-AddFiles-info">

+ 15 - 3
packages/@uppy/dashboard/src/index.js

@@ -68,10 +68,15 @@ module.exports = class Dashboard extends Plugin {
         saveChanges: 'Save changes',
         cancel: 'Cancel',
         myDevice: 'My Device',
-        dropPaste: 'Drop files here, paste or %{browse}',
-        dropPasteImport: 'Drop files here, paste, %{browse} or import from:',
+        dropPasteFiles: 'Drop files here, paste or %{browseFiles}',
+        dropPasteFolders: 'Drop files here, paste or %{browseFolders}',
+        dropPasteBoth: 'Drop files here, paste, %{browseFiles} or %{browseFolders}',
+        dropPasteImportFiles: 'Drop files here, paste, %{browseFiles} or import from:',
+        dropPasteImportFolders: 'Drop files here, paste, %{browseFolders} or import from:',
+        dropPasteImportBoth: 'Drop files here, paste, %{browseFiles}, %{browseFolders} or import from:',
         dropHint: 'Drop your files here',
-        browse: 'browse',
+        browseFiles: 'browse files',
+        browseFolders: 'browse folders',
         uploadComplete: 'Upload complete',
         uploadPaused: 'Upload paused',
         resumeUpload: 'Resume upload',
@@ -126,6 +131,7 @@ module.exports = class Dashboard extends Plugin {
       disableThumbnailGenerator: false,
       disablePageScrollWhenModalOpen: true,
       animateOpenClose: true,
+      fileManagerSelectionType: 'files',
       proudlyDisplayPoweredByUppy: true,
       onRequestCloseModal: () => this.closeModal(),
       showSelectedFiles: true,
@@ -839,6 +845,11 @@ module.exports = class Dashboard extends Plugin {
       theme = this.opts.theme
     }
 
+    if (['files', 'folders', 'both'].indexOf(this.opts.fileManagerSelectionType) < 0) {
+      this.opts.fileManagerSelectionType = 'files'
+      console.error(`Unsupported option for "fileManagerSelectionType". Using default of "${this.opts.fileManagerSelectionType}".`)
+    }
+
     return DashboardUI({
       state,
       isHidden: pluginState.isHidden,
@@ -900,6 +911,7 @@ module.exports = class Dashboard extends Plugin {
       width: this.opts.width,
       height: this.opts.height,
       showLinkToFileUploadResult: this.opts.showLinkToFileUploadResult,
+      fileManagerSelectionType: this.opts.fileManagerSelectionType,
       proudlyDisplayPoweredByUppy: this.opts.proudlyDisplayPoweredByUppy,
       hideCancelButton: this.opts.hideCancelButton,
       hideRetryButton: this.opts.hideRetryButton,

+ 1 - 0
packages/@uppy/dashboard/types/index.d.ts

@@ -38,6 +38,7 @@ declare module Dashboard {
     note?: string | null
     onRequestCloseModal?: () => void
     plugins?: string[]
+    fileManagerSelectionType?: 'files' | 'folders' | 'both';
     proudlyDisplayPoweredByUppy?: boolean
     showLinkToFileUploadResult?: boolean
     showProgressDetails?: boolean

+ 8 - 2
packages/@uppy/locales/src/en_US.js

@@ -17,6 +17,8 @@ en_US.strings = {
   authenticateWithTitle: 'Please authenticate with %{pluginName} to select files',
   back: 'Back',
   browse: 'browse',
+  browseFiles: 'browse files',
+  browseFolders: 'browse folders',
   cancel: 'Cancel',
   cancelUpload: 'Cancel upload',
   chooseFiles: 'Choose files',
@@ -36,8 +38,12 @@ en_US.strings = {
   done: 'Done',
   dropHereOr: 'Drop files here or %{browse}',
   dropHint: 'Drop your files here',
-  dropPaste: 'Drop files here, paste or %{browse}',
-  dropPasteImport: 'Drop files here, paste, %{browse} or import from:',
+  dropPasteBoth: 'Drop files here, paste, %{browseFiles} or %{browseFolders}',
+  dropPasteFiles: 'Drop files here, paste or %{browseFiles}',
+  dropPasteFolders: 'Drop files here, paste or %{browseFolders}',
+  dropPasteImportBoth: 'Drop files here, paste, %{browseFiles}, %{browseFolders} or import from:',
+  dropPasteImportFiles: 'Drop files here, paste, %{browseFiles} or import from:',
+  dropPasteImportFolders: 'Drop files here, paste, %{browseFolders} or import from:',
   editFile: 'Edit file',
   editing: 'Editing %{file}',
   emptyFolderAdded: 'No files were added from empty folder',

+ 5 - 0
website/src/docs/dashboard.md

@@ -88,6 +88,7 @@ uppy.use(Dashboard, {
   disableThumbnailGenerator: false,
   disablePageScrollWhenModalOpen: true,
   animateOpenClose: true,
+  fileManagerSelectionType: 'files',
   proudlyDisplayPoweredByUppy: true,
   onRequestCloseModal: () => this.closeModal(),
   showSelectedFiles: true,
@@ -257,6 +258,10 @@ Page scrolling is disabled by default when the Dashboard modal is open, so when
 
 Add light animations when the modal dialog is opened or closed, for a more satisfying user experience.
 
+### `fileManagerSelectionType: 'files'`
+
+Configure the type of selections allowed when browsing your file system via the file manager selection window. May be either 'files', 'folders', or 'both'. Selecting entire folders for upload may not be supported on all [browsers](https://caniuse.com/#feat=input-file-directory).
+
 ### `proudlyDisplayPoweredByUppy: true`
 
 Uppy is provided to the world for free by the team behind [Transloadit](https://transloadit.com). In return, we ask that you consider keeping a tiny Uppy logo at the bottom of the Dashboard, so that more people can discover and use Uppy.