Browse Source

More Dashboard refactors, i18n strings, global progress indicator

Artur Paikin 8 years ago
parent
commit
1856c25ba0

+ 1 - 0
src/core/Core.js

@@ -38,6 +38,7 @@ export default class Core {
     this.updateMeta = this.updateMeta.bind(this)
     this.initSocket = this.initSocket.bind(this)
     this.log = this.log.bind(this)
+    this.addFile = this.addFile.bind(this)
 
     this.bus = this.emitter = ee()
     this.on = this.bus.on.bind(this.bus)

+ 1 - 1
src/locales/en_US.js

@@ -30,7 +30,7 @@ en_US.strings = {
   copyLinkToClipboardFallback: 'Copy the URL below',
   done: 'Done',
   localDisk: 'Local Disk',
-  dropPasteImport: 'Drop files here, paste or import from',
+  dropPasteImport: 'Drop files here, paste or import from:',
   fileProgress: 'File progress: upload speed and ETA',
   numberOfSelectedFiles: 'Number of selected files',
   uploadAllNewFiles: 'Upload all new files'

+ 3 - 1
src/locales/ru_RU.js

@@ -9,7 +9,9 @@ ru_RU.strings = {
     1: 'Выбрано %{smart_count} файла',
     2: 'Выбрано %{smart_count} файлов'
   },
-  upload: 'Загрузить'
+  upload: 'Загрузить',
+  localDisk: 'Диск',
+  dropPasteImport: 'Перенесите файлы сюда, вставьте из буфера обмена или импортируйте:'
 }
 
 ru_RU.pluralize = function (n) {

+ 21 - 15
src/plugins/Dashboard/Dashboard.js

@@ -1,15 +1,15 @@
 import html from '../../core/html'
-import { isTouchDevice, toArray } from '../../core/Utils'
 import FileList from './FileList'
 import Tabs from './Tabs'
 import FileCard from './FileCard'
+import { isTouchDevice, toArray } from '../../core/Utils'
 import { closeIcon } from './icons'
 
 export default function Dashboard (props) {
   // http://dev.edenspiekermann.com/2016/02/11/introducing-accessible-modal-dialog
 
   const state = props.state
-
+  const totalProgress = state.totalProgress
   const files = state.files
   const modal = state.modal
 
@@ -58,7 +58,6 @@ export default function Dashboard (props) {
     const files = toArray(ev.target.files)
 
     files.forEach((file) => {
-      // log(file)
       props.bus.emit('file-add', {
         source: props.id,
         name: file.name,
@@ -72,15 +71,19 @@ export default function Dashboard (props) {
                           ${isTouchDevice() ? 'Uppy--isTouchDevice' : ''}
                           ${!props.inline ? 'UppyDashboard--modal' : ''}"
                    aria-hidden="${props.inline ? 'false' : modal.isHidden}"
-                   aria-label="Uppy Dialog Window (Press escape to close)"
-                   role="dialog">
+                   aria-label="${!props.inline
+                                 ? props.i18n('dashboardWindowTitle')
+                                 : props.i18n('dashboardTitle')
+                               }"
+                   role="dialog"
+                   onpaste=${props.onPaste}>
 
     <div class="UppyDashboard-overlay"
          onclick=${props.hideModal}></div>
 
     <button class="UppyDashboard-close"
-            aria-label="Close Uppy modal"
-            title="Close Uppy modal"
+            aria-label="${props.i18n('closeModal')}"
+            title="${props.i18n('closeModal')}"
             onclick=${props.hideModal}>${closeIcon()}</button>
 
     <div class="UppyDashboard-inner" tabindex="0">
@@ -91,7 +94,8 @@ export default function Dashboard (props) {
           acquirers: acquirers,
           container: props.container,
           panelSelectorPrefix: props.panelSelectorPrefix,
-          showPanel: props.showPanel
+          showPanel: props.showPanel,
+          i18n: props.i18n
         })}
 
         ${FileCard({
@@ -99,32 +103,34 @@ export default function Dashboard (props) {
           fileCardFor: modal.fileCardFor,
           done: fileCardDone,
           metaFields: state.metaFields,
-          pauseUpload: pauseUpload,
-          log: props.log
+          log: props.log,
+          i18n: props.i18n
         })}
 
         ${FileList({
           files: files,
           showFileCard: showFileCard,
           showProgressDetails: props.showProgressDetails,
+          totalProgress: totalProgress,
           info: info,
           i18n: props.i18n,
           log: props.log,
           removeFile: removeFile,
           pauseAll: props.pauseAll,
           resumeAll: props.resumeAll,
+          pauseUpload: pauseUpload,
           startUpload: startUpload
         })}
 
         ${acquirers.map((target) => {
           return html`<div class="UppyDashboardContent-panel"
-                         id="${props.panelSelectorPrefix}--${target.id}"
-                         role="tabpanel"
-                         aria-hidden="${target.isHidden}">
+                           id="${props.panelSelectorPrefix}--${target.id}"
+                           role="tabpanel"
+                           aria-hidden="${target.isHidden}">
              <div class="UppyDashboardContent-bar">
-               <h2 class="UppyDashboardContent-title">Import From ${target.name}</h2>
+               <h2 class="UppyDashboardContent-title">${props.i18n('importFrom')} ${target.name}</h2>
                <button class="UppyDashboardContent-back"
-                       onclick=${props.hideAllPanels}>Done</button>
+                       onclick=${props.hideAllPanels}>${props.i18n('done')}</button>
              </div>
             ${target.render(state)}
           </div>`

+ 0 - 5
src/plugins/Dashboard/FileCard.js

@@ -24,11 +24,6 @@ export default function fileCard (props) {
     meta[name] = value
   }
 
-  // function done () {
-  //   bus.emit('core:update-meta', meta, file.id)
-  //   bus.emit('dashboard:file-card')
-  // }
-
   function renderMetaFields (file) {
     const metaFields = props.metaFields || []
     return metaFields.map((field) => {

+ 2 - 2
src/plugins/Dashboard/FileItem.js

@@ -82,8 +82,8 @@ export default function fileItem (props) {
           </button>
           ${props.showProgressDetails
             ? html`<div class="UppyDashboardItem-progressInfo"
-                   title="File progress: upload speed and ETA"
-                   aria-label="File progress: upload speed and ETA">
+                   title="${props.i18n('localDisk')}"
+                   aria-label="${props.i18n('localDisk')}">
                 ${!file.isPaused && !isUploaded
                   ? html`<span>${getETA(file.progress)} ・ ↑ ${prettyBytes(getSpeed(file.progress))}/s</span>`
                   : null

+ 2 - 2
src/plugins/Dashboard/FileItemProgress.js

@@ -7,8 +7,8 @@ export default function (props) {
   return html`
       <svg class="UppyIcon UppyIcon-progressCircle" width="25" height="25" viewBox="0 0 44 44">
         <g class="progress-group">
-          <circle class="bg" r="15" cx="22" cy="22" stroke-width="4" fill="none" />
-          <circle class="progress" r="15" cx="22" cy="22" transform="rotate(-90, 22, 22)" stroke-width="4" fill="none" stroke-dasharray="100" stroke-dashoffset="${100 - props.progress}" />
+          <circle class="bg" r="15" cx="22" cy="22" stroke-width="3" fill="none" />
+          <circle class="progress" r="15" cx="22" cy="22" transform="rotate(-90, 22, 22)" stroke-width="3" fill="none" stroke-dasharray="100" stroke-dashoffset="${100 - props.progress}" />
         </g>
         <polygon class="play" transform="translate(6, 5.5)" points="13 21.6666667 13 11 21 16.3333333" />
         <g transform="translate(18, 17)" class="pause">

+ 29 - 35
src/plugins/Dashboard/FileList.js

@@ -1,9 +1,8 @@
 import html from '../../core/html'
 import FileItem from './FileItem'
+import TotalProgress from './TotalProgress'
 import { dashboardBgIcon,
-         uploadIcon,
-         iconPause,
-         iconResume } from './icons'
+         uploadIcon } from './icons'
 
 export default (props) => {
   const files = props.files
@@ -14,9 +13,9 @@ export default (props) => {
   const uploadStartedFiles = Object.keys(files).filter((file) => {
     return files[file].progress.uploadStarted
   })
-  const completeFiles = Object.keys(files).filter((file) => {
-    return files[file].progress.uploadComplete
-  })
+  // const completeFiles = Object.keys(files).filter((file) => {
+  //   return files[file].progress.uploadComplete
+  // })
   const inProgressFiles = Object.keys(files).filter((file) => {
     return !files[file].progress.uploadComplete &&
            files[file].progress.uploadStarted &&
@@ -24,31 +23,11 @@ export default (props) => {
   })
 
   const uploadStartedFilesCount = uploadStartedFiles.length
-  const completeFilesCount = completeFiles.length
+  // const completeFilesCount = completeFiles.length
   const inProgressFilesCount = inProgressFiles.length
   const totalFileCount = Object.keys(files).length
   const newFileCount = newFiles.length
 
-  const renderPauseResume = () => {
-    if (uploadStartedFilesCount > 0) {
-      if (inProgressFilesCount > 0) {
-        return html`<button class="UppyDashboard-pauseResume
-                                   UppyButton--circular
-                                   UppyButton--yellow
-                                   UppyButton--sizeS"
-                            onclick=${() => props.pauseAll()}>${iconPause()}</button>`
-      }
-
-      if (uploadStartedFilesCount !== completeFilesCount) {
-        return html`<button class="UppyDashboard-pauseResume
-                                   UppyButton--circular
-                                   UppyButton--green
-                                   UppyButton--sizeS"
-                            onclick=${() => props.resumeAll()}>${iconResume()}</button>`
-      }
-    }
-  }
-
   return html`<div class="UppyDashboard-files">
     <ul class="UppyDashboard-filesInner">
       ${totalFileCount === 0
@@ -63,24 +42,39 @@ export default (props) => {
           info: props.info,
           log: props.log,
           i18n: props.i18n,
-          removeFile: props.removeFile
+          removeFile: props.removeFile,
+          pauseUpload: props.pauseUpload
         })
       })}
     </ul>
     <div class="UppyDashboard-actions">
-      ${renderPauseResume()}
       ${!props.autoProceed && newFileCount > 0
-        ? html`<button class="UppyButton--circular UppyButton--blue UppyButton--sizeM UppyDashboard-upload"
+        ? html`<div class="UppyDashboard-actionsItem">
+          <button class="UppyButton--circular
+                              UppyButton--blue
+                              UppyButton--sizeM
+                              UppyDashboard-upload"
                        type="button"
-                       title="Upload all files"
-                       aria-label="Upload all files"
+                       title="${props.i18n('uploadAllNewFiles')}"
+                       aria-label="${props.i18n('uploadAllNewFiles')}"
                        onclick=${props.startUpload}>
                   ${uploadIcon()}
                   <sup class="UppyDashboard-uploadCount"
-                       title="Number of selected files"
-                       aria-label="Number of selected files">
+                       title="${props.i18n('numberOfSelectedFiles')}"
+                       aria-label="${props.i18n('numberOfSelectedFiles')}">
                         ${newFileCount}</sup>
-               </button>`
+          </button>
+        </div>`
+        : null
+      }
+      ${uploadStartedFilesCount > 0
+        ? TotalProgress({
+          totalProgress: props.totalProgress,
+          isAllPaused: inProgressFilesCount === 0,
+          isAllComplete: props.totalProgress === 100,
+          pauseAll: props.pauseAll,
+          resumeAll: props.resumeAll
+        })
         : null
       }
     </div>

+ 2 - 2
src/plugins/Dashboard/Tabs.js

@@ -3,7 +3,7 @@ import { localIcon } from './icons'
 
 export default (props) => {
   return html`<div class="UppyDashboardTabs">
-    <h3 class="UppyDashboardTabs-title">Drop files here, paste or import from</h3>
+    <h3 class="UppyDashboardTabs-title">${props.i18n('dropPasteImport')}</h3>
     <nav>
       <ul class="UppyDashboardTabs-list" role="tablist">
         <li class="UppyDashboardTab">
@@ -15,7 +15,7 @@ export default (props) => {
                     input.click()
                   }}>
             ${localIcon()}
-            <h5 class="UppyDashboardTab-name">Local Disk</h5>
+            <h5 class="UppyDashboardTab-name">${props.i18n('localDisk')}</h5>
           </button>
           <input class="UppyDashboard-input" type="file" name="files[]" multiple="true"
                  onchange=${props.localInputChange} />

+ 52 - 0
src/plugins/Dashboard/TotalProgress.js

@@ -0,0 +1,52 @@
+import html from '../../core/html'
+
+export default (props) => {
+  // if (uploadStartedFilesCount > 0) {
+    // if (inProgressFilesCount > 0) {
+    //   return html`<button class="UppyDashboard-pauseResume
+    //                              UppyButton--circular
+    //                              UppyButton--yellow
+    //                              UppyButton--sizeS"
+    //                       onclick=${() => props.pauseAll()}>${iconPause()}</button>`
+    // }
+    //
+    // if (uploadStartedFilesCount !== completeFilesCount) {
+    //   return html`<button class="UppyDashboard-pauseResume
+    //                              UppyButton--circular
+    //                              UppyButton--green
+    //                              UppyButton--sizeS"
+    //                       onclick=${() => props.resumeAll()}>${iconResume()}</button>`
+    // }
+
+  const togglePauseResume = (isAllPaused) => {
+    if (isAllPaused) {
+      return props.resumeAll()
+    }
+    return props.pauseAll()
+  }
+
+  return html`
+    <div class="UppyDashboard-actionsItem">
+      <button class="UppyTotalProgress
+                    ${props.isAllPaused ? 'UppyTotalProgress--is-paused' : ''}
+                    ${props.isAllComplete ? 'UppyTotalProgress--is-complete' : ''}"
+              onclick=${(ev) => {
+                if (props.isAllComplete) return
+                togglePauseResume(props.isAllPaused)
+              }}>
+          <svg width="25" height="25" viewBox="0 0 44 44" class="UppyIcon">
+            <g class="progress-group">
+              <circle r="15" cx="22" cy="22" stroke-width="3" fill="none" class="bg"/>
+              <circle r="15" cx="22" cy="22" transform="rotate(-90, 22, 22)" stroke-width="3" fill="none" stroke-dasharray="100" stroke-dashoffset="${100 - props.totalProgress || 100}" class="progress"/>
+            </g>
+            <polygon transform="translate(6, 5.5)" points="13 21.6666667 13 11 21 16.3333333" class="play"/>
+            <g transform="translate(18, 17)" class="pause">
+              <rect x="0" y="0" width="2" height="10" rx="0"/>
+              <rect x="6" y="0" width="2" height="10" rx="0"/>
+            </g>
+            <polygon transform="translate(6, 7)" points="14 22.5 7 15.2457065 8.99985857 13.1732815 14 18.3547104 22.9729883 9 25 11.1005634" class="check"/>
+        </svg>
+      </button>
+      <span class="UppyTotalProgress-info">${props.totalProgress || 0}%</span>
+    </div>`
+}

+ 13 - 10
src/plugins/Dashboard/index.js

@@ -33,6 +33,9 @@ export default class DashboardUI extends Plugin {
     this.hideAllPanels = this.hideAllPanels.bind(this)
     this.showPanel = this.showPanel.bind(this)
     this.initEvents = this.initEvents.bind(this)
+    this.handlePaste = this.handlePaste.bind(this)
+    // this.handleInputChange = this.handleInputChange.bind(this)
+    this.handleDrop = this.handleDrop.bind(this)
     this.pauseAll = this.pauseAll.bind(this)
     this.resumeAll = this.resumeAll.bind(this)
     this.render = this.render.bind(this)
@@ -143,7 +146,7 @@ export default class DashboardUI extends Plugin {
   }
 
   initEvents () {
-    const modal = document.querySelector(`${this.opts.target} .UppyDashboard`)
+    // const dashboardEl = document.querySelector(`${this.opts.target} .UppyDashboard`)
     // Modal open button
     const showModalTrigger = document.querySelector(this.opts.trigger)
     showModalTrigger.addEventListener('click', this.showModal)
@@ -156,21 +159,20 @@ export default class DashboardUI extends Plugin {
     })
 
     // Close on click outside modal or close buttons
-    document.addEventListener('click', (e) => {
-      if (e.target.classList.contains('js-UppyDashboard-close')) {
-        this.hideModal()
-      }
-    })
+    // document.addEventListener('click', (e) => {
+    //   if (e.target.classList.contains('js-UppyDashboard-close')) {
+    //     this.hideModal()
+    //   }
+    // })
 
     // Drag Drop
-    dragDrop(`${this.opts.target} .UppyDashboard`, (files) => {
+    dragDrop(this.el, (files) => {
       this.handleDrop(files)
-      this.core.log(files)
     })
 
     // @TODO Exprimental, work in progress
     // Paste from clipboard
-    modal.addEventListener('paste', this.handlePaste.bind(this))
+    // dashboardEl.addEventListener('paste', this.handlePaste.bind(this))
   }
 
   // @TODO Exprimental, work in progress
@@ -252,7 +254,8 @@ export default class DashboardUI extends Plugin {
       panelSelectorPrefix: this.opts.panelSelectorPrefix,
       showProgressDetails: this.opts.showProgressDetails,
       inline: this.opts.inline,
-      handleInputChange: this.handleInputChange,
+      // onInputChange: this.handleInputChange,
+      onPaste: this.handlePaste,
       showPanel: this.showPanel,
       hideAllPanels: this.hideAllPanels,
       log: this.core.log,

+ 92 - 12
src/scss/_dashboard.scss

@@ -287,22 +287,16 @@
 
 .UppyDashboard.drag .UppyDashboard-innerWrap  {
   border-color: lighten($color-gray, 5%);
-  background-color: darken($color-white, 5%)
+  background-color: darken($color-white, 10%)
 }
 
 .UppyDashboard-list {
   @include clearfix;
   margin: 0;
   padding: 0;
-  // height: 100%;
-  // overflow: auto;
 }
 
 .UppyDashboard-bgIcon {
-  // display: flex;
-  // align-items: center;
-  // justify-content: center;
-  // height: 100%;
   width: 250px;
   position: absolute;
   top: 50%;
@@ -469,8 +463,8 @@
 
 .UppyDashboardItem-progressBtn {
   @include reset-button;
-  width: 60px;
-  height: 60px;
+  width: 70px;
+  height: 70px;
   opacity: 0.9;
   cursor: pointer;
 }
@@ -563,6 +557,92 @@
   }
 }
 
+
+
+
+.UppyTotalProgress {
+  @include reset-button;
+  width: 70px;
+  height: 70px;
+  cursor: pointer;
+}
+
+.UppyTotalProgress .UppyIcon {
+  width: 100%;
+  height: 100%;
+}
+
+.UppyTotalProgress .bg {
+  stroke: rgba($color-cornflower-blue, 0.3);
+  transition: all 0.2s;
+  opacity: 1;
+}
+
+.UppyTotalProgress .progress {
+  stroke: $color-cornflower-blue;
+  transition: stroke-dashoffset .5s ease-out;
+  opacity: 1;
+}
+
+.UppyTotalProgress .play {
+  stroke: $color-cornflower-blue;
+  fill: $color-cornflower-blue;
+  transition: all 0.2s;
+  opacity: 0;
+}
+
+.UppyTotalProgress .pause {
+  stroke: $color-cornflower-blue;
+  fill: $color-cornflower-blue;
+  transition: all 0.2s;
+  opacity: 1;
+}
+
+.UppyTotalProgress .check {
+  fill: $color-white;
+  transition: all 0.2s;
+  opacity: 0;
+}
+
+.UppyTotalProgress--is-paused {
+  .pause {
+    opacity: 0;
+  }
+  .play {
+    opacity: 1;
+  }
+}
+
+.UppyTotalProgress--is-complete {
+  cursor: default;
+
+  .pause, .play {
+    opacity: 0;
+  }
+
+  .bg {
+    stroke: $color-green;
+    opacity: 1;
+  }
+
+  .progress {
+    stroke: $color-green;
+    fill: $color-green;
+    opacity: 1;
+  }
+  .check {
+    opacity: 1;
+  }
+}
+
+.UppyTotalProgress-info {
+  font-size: 10px;
+  color: $color-asphalt-gray;
+}
+
+
+
+
 .UppyDashboardItem-progressNum {
   position: relative;
   z-index: $zIndex-2;
@@ -577,14 +657,14 @@
 }
 
 .UppyDashboard-actions {
-  width: 60px;
+  width: 70px;
   text-align: center;
   position: absolute;
   bottom: 25px;
   right: 25px;
 }
 
-.UppyDashboard-actions button {
+.UppyDashboard-actionsItem {
   margin-bottom: 15px;
 }
 
@@ -599,7 +679,7 @@
 
 .UppyDashboard-upload .UppyIcon {
   position: relative;
-  top: 2px;
+  top: 1px;
   width: 50%;
 }