Dashboard.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. const { h } = require('preact')
  2. const classNames = require('classnames')
  3. const isDragDropSupported = require('@uppy/utils/lib/isDragDropSupported')
  4. const FileList = require('./FileList')
  5. const AddFiles = require('./AddFiles')
  6. const AddFilesPanel = require('./AddFilesPanel')
  7. const PickerPanelContent = require('./PickerPanelContent')
  8. const EditorPanel = require('./EditorPanel')
  9. const PanelTopBar = require('./PickerPanelTopBar')
  10. const FileCard = require('./FileCard')
  11. const Slide = require('./Slide')
  12. // http://dev.edenspiekermann.com/2016/02/11/introducing-accessible-modal-dialog
  13. // https://github.com/ghosh/micromodal
  14. const WIDTH_XL = 900
  15. const WIDTH_LG = 700
  16. const WIDTH_MD = 576
  17. const HEIGHT_MD = 400
  18. module.exports = function Dashboard (props) {
  19. const noFiles = props.totalFileCount === 0
  20. const isSizeMD = props.containerWidth > WIDTH_MD
  21. const wrapperClassName = classNames({
  22. 'uppy-Root': props.isTargetDOMEl,
  23. })
  24. const dashboardClassName = classNames({
  25. 'uppy-Dashboard': true,
  26. 'uppy-Dashboard--isDisabled': props.disabled,
  27. 'uppy-Dashboard--animateOpenClose': props.animateOpenClose,
  28. 'uppy-Dashboard--isClosing': props.isClosing,
  29. 'uppy-Dashboard--isDraggingOver': props.isDraggingOver,
  30. 'uppy-Dashboard--modal': !props.inline,
  31. 'uppy-size--md': props.containerWidth > WIDTH_MD,
  32. 'uppy-size--lg': props.containerWidth > WIDTH_LG,
  33. 'uppy-size--xl': props.containerWidth > WIDTH_XL,
  34. 'uppy-size--height-md': props.containerHeight > HEIGHT_MD,
  35. 'uppy-Dashboard--isAddFilesPanelVisible': props.showAddFilesPanel,
  36. 'uppy-Dashboard--isInnerWrapVisible': props.areInsidesReadyToBeVisible,
  37. })
  38. // Important: keep these in sync with the percent width values in `src/components/FileItem/index.scss`.
  39. let itemsPerRow = 1 // mobile
  40. if (props.containerWidth > WIDTH_XL) {
  41. itemsPerRow = 5
  42. } else if (props.containerWidth > WIDTH_LG) {
  43. itemsPerRow = 4
  44. } else if (props.containerWidth > WIDTH_MD) {
  45. itemsPerRow = 3
  46. }
  47. const showFileList = props.showSelectedFiles && !noFiles
  48. const numberOfFilesForRecovery = props.recoveredState ? Object.keys(props.recoveredState.files).length : null
  49. const numberOfGhosts = props.files ? Object.keys(props.files).filter((fileID) => props.files[fileID].isGhost).length : null
  50. const renderRestoredText = () => {
  51. if (numberOfGhosts > 0) {
  52. return props.i18n('recoveredXFiles', {
  53. smart_count: numberOfGhosts,
  54. })
  55. }
  56. return props.i18n('recoveredAllFiles')
  57. }
  58. const dashboard = (
  59. <div
  60. className={dashboardClassName}
  61. data-uppy-theme={props.theme}
  62. data-uppy-num-acquirers={props.acquirers.length}
  63. data-uppy-drag-drop-supported={!props.disableLocalFiles && isDragDropSupported()}
  64. aria-hidden={props.inline ? 'false' : props.isHidden}
  65. aria-disabled={props.disabled}
  66. aria-label={!props.inline ? props.i18n('dashboardWindowTitle') : props.i18n('dashboardTitle')}
  67. onPaste={props.handlePaste}
  68. onDragOver={props.handleDragOver}
  69. onDragLeave={props.handleDragLeave}
  70. onDrop={props.handleDrop}
  71. >
  72. <div
  73. aria-hidden="true"
  74. className="uppy-Dashboard-overlay"
  75. tabIndex={-1}
  76. onClick={props.handleClickOutside}
  77. />
  78. <div
  79. className="uppy-Dashboard-inner"
  80. aria-modal={!props.inline && 'true'}
  81. role={!props.inline && 'dialog'}
  82. style={{
  83. width: props.inline && props.width ? props.width : '',
  84. height: props.inline && props.height ? props.height : '',
  85. }}
  86. >
  87. {!props.inline ? (
  88. <button
  89. className="uppy-u-reset uppy-Dashboard-close"
  90. type="button"
  91. aria-label={props.i18n('closeModal')}
  92. title={props.i18n('closeModal')}
  93. onClick={props.closeModal}
  94. >
  95. <span aria-hidden="true">&times;</span>
  96. </button>
  97. ) : null}
  98. <div className="uppy-Dashboard-innerWrap">
  99. <div className="uppy-Dashboard-dropFilesHereHint">
  100. {props.i18n('dropHint')}
  101. </div>
  102. {showFileList && <PanelTopBar {...props} />}
  103. {numberOfFilesForRecovery && (
  104. <div className="uppy-Dashboard-serviceMsg">
  105. <svg className="uppy-Dashboard-serviceMsg-icon" aria-hidden="true" focusable="false" width="21" height="16" viewBox="0 0 24 19">
  106. <g transform="translate(0 -1)" fill="none" fillRule="evenodd">
  107. <path d="M12.857 1.43l10.234 17.056A1 1 0 0122.234 20H1.766a1 1 0 01-.857-1.514L11.143 1.429a1 1 0 011.714 0z" fill="#FFD300" />
  108. <path fill="#000" d="M11 6h2l-.3 8h-1.4z" />
  109. <circle fill="#000" cx="12" cy="17" r="1" />
  110. </g>
  111. </svg>
  112. <strong className="uppy-Dashboard-serviceMsg-title">
  113. {props.i18n('sessionRestored')}
  114. </strong>
  115. <div className="uppy-Dashboard-serviceMsg-text">
  116. {renderRestoredText()}
  117. </div>
  118. </div>
  119. )}
  120. {showFileList ? (
  121. <FileList
  122. {...props}
  123. itemsPerRow={itemsPerRow}
  124. />
  125. ) : (
  126. <AddFiles {...props} isSizeMD={isSizeMD} />
  127. )}
  128. <Slide>
  129. {props.showAddFilesPanel ? <AddFilesPanel key="AddFiles" {...props} isSizeMD={isSizeMD} /> : null}
  130. </Slide>
  131. <Slide>
  132. {props.fileCardFor ? <FileCard key="FileCard" {...props} /> : null}
  133. </Slide>
  134. <Slide>
  135. {props.activePickerPanel ? <PickerPanelContent key="Picker" {...props} /> : null}
  136. </Slide>
  137. <Slide>
  138. {props.showFileEditor ? <EditorPanel key="Editor" {...props} /> : null}
  139. </Slide>
  140. <div className="uppy-Dashboard-progressindicators">
  141. {props.progressindicators.map((target) => {
  142. return props.uppy.getPlugin(target.id).render(props.state)
  143. })}
  144. </div>
  145. </div>
  146. </div>
  147. </div>
  148. )
  149. return (
  150. // Wrap it for RTL language support
  151. <div className={wrapperClassName} dir={props.direction}>
  152. {dashboard}
  153. </div>
  154. )
  155. }