index.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. const { h } = require('preact')
  2. function onPauseResumeCancelRetry (props) {
  3. if (props.isUploaded) return
  4. if (props.error && !props.hideRetryButton) {
  5. props.retryUpload(props.file.id)
  6. return
  7. }
  8. if (props.resumableUploads && !props.hidePauseResumeButton) {
  9. props.pauseUpload(props.file.id)
  10. } else if (props.individualCancellation && !props.hideCancelButton) {
  11. props.cancelUpload(props.file.id)
  12. }
  13. }
  14. function progressIndicatorTitle (props) {
  15. if (props.isUploaded) {
  16. return props.i18n('uploadComplete')
  17. }
  18. if (props.error) {
  19. return props.i18n('retryUpload')
  20. }
  21. if (props.resumableUploads) {
  22. if (props.file.isPaused) {
  23. return props.i18n('resumeUpload')
  24. }
  25. return props.i18n('pauseUpload')
  26. } else if (props.individualCancellation) {
  27. return props.i18n('cancelUpload')
  28. }
  29. return ''
  30. }
  31. function ProgressIndicatorButton (props) {
  32. return (
  33. <div class="uppy-Dashboard-Item-progress">
  34. <button
  35. class="uppy-u-reset uppy-Dashboard-Item-progressIndicator"
  36. type="button"
  37. aria-label={progressIndicatorTitle(props)}
  38. title={progressIndicatorTitle(props)}
  39. onclick={() => onPauseResumeCancelRetry(props)}
  40. >
  41. {props.children}
  42. </button>
  43. </div>
  44. )
  45. }
  46. function ProgressCircleContainer ({ children }) {
  47. return (
  48. <svg
  49. aria-hidden="true"
  50. focusable="false"
  51. width="70"
  52. height="70"
  53. viewBox="0 0 36 36"
  54. class="uppy-c-icon uppy-Dashboard-Item-progressIcon--circle"
  55. >
  56. {children}
  57. </svg>
  58. )
  59. }
  60. function ProgressCircle ({ progress }) {
  61. // circle length equals 2 * PI * R
  62. const circleLength = 2 * Math.PI * 15
  63. return (
  64. <g>
  65. <circle class="uppy-Dashboard-Item-progressIcon--bg" r="15" cx="18" cy="18" stroke-width="2" fill="none" />
  66. <circle
  67. class="uppy-Dashboard-Item-progressIcon--progress" r="15" cx="18" cy="18" transform="rotate(-90, 18, 18)" stroke-width="2" fill="none"
  68. stroke-dasharray={circleLength}
  69. stroke-dashoffset={circleLength - (circleLength / 100 * progress)}
  70. />
  71. </g>
  72. )
  73. }
  74. module.exports = function FileProgress (props) {
  75. // Nothing if upload has not started
  76. if (!props.file.progress.uploadStarted) {
  77. return null
  78. }
  79. // Green checkmark when complete
  80. if (props.isUploaded) {
  81. return (
  82. <div class="uppy-Dashboard-Item-progress">
  83. <div class="uppy-Dashboard-Item-progressIndicator">
  84. <ProgressCircleContainer>
  85. <circle r="15" cx="18" cy="18" fill="#1bb240" />
  86. <polygon class="uppy-Dashboard-Item-progressIcon--check" transform="translate(2, 3)" points="14 22.5 7 15.2457065 8.99985857 13.1732815 14 18.3547104 22.9729883 9 25 11.1005634" />
  87. </ProgressCircleContainer>
  88. </div>
  89. </div>
  90. )
  91. }
  92. // Retry button for error
  93. if (props.error && !props.hideRetryButton) {
  94. return (
  95. <ProgressIndicatorButton {...props}>
  96. <svg aria-hidden="true" focusable="false" class="uppy-c-icon uppy-Dashboard-Item-progressIcon--retry" width="28" height="31" viewBox="0 0 16 19">
  97. <path d="M16 11a8 8 0 1 1-8-8v2a6 6 0 1 0 6 6h2z" />
  98. <path d="M7.9 3H10v2H7.9z" />
  99. <path d="M8.536.5l3.535 3.536-1.414 1.414L7.12 1.914z" />
  100. <path d="M10.657 2.621l1.414 1.415L8.536 7.57 7.12 6.157z" />
  101. </svg>
  102. </ProgressIndicatorButton>
  103. )
  104. }
  105. // Pause/resume button for resumable uploads
  106. if (props.resumableUploads && !props.hidePauseResumeButton) {
  107. return (
  108. <ProgressIndicatorButton {...props}>
  109. <ProgressCircleContainer>
  110. <ProgressCircle progress={props.file.progress.percentage} />
  111. {
  112. props.file.isPaused
  113. ? <polygon class="uppy-Dashboard-Item-progressIcon--play" transform="translate(3, 3)" points="12 20 12 10 20 15" />
  114. : (
  115. <g class="uppy-Dashboard-Item-progressIcon--pause" transform="translate(14.5, 13)">
  116. <rect x="0" y="0" width="2" height="10" rx="0" />
  117. <rect x="5" y="0" width="2" height="10" rx="0" />
  118. </g>
  119. )
  120. }
  121. </ProgressCircleContainer>
  122. </ProgressIndicatorButton>
  123. )
  124. }
  125. // Cancel button for non-resumable uploads if individualCancellation is supported (not bundled)
  126. if (!props.resumableUploads && props.individualCancellation && !props.hideCancelButton) {
  127. return (
  128. <ProgressIndicatorButton {...props}>
  129. <ProgressCircleContainer>
  130. <ProgressCircle progress={props.file.progress.percentage} />
  131. <polygon class="cancel" transform="translate(2, 2)" points="19.8856516 11.0625 16 14.9481516 12.1019737 11.0625 11.0625 12.1143484 14.9481516 16 11.0625 19.8980263 12.1019737 20.9375 16 17.0518484 19.8856516 20.9375 20.9375 19.8980263 17.0518484 16 20.9375 12" />
  132. </ProgressCircleContainer>
  133. </ProgressIndicatorButton>
  134. )
  135. }
  136. // Just progress when buttons are disabled
  137. return (
  138. <div class="uppy-Dashboard-Item-progress">
  139. <div class="uppy-Dashboard-Item-progressIndicator">
  140. <ProgressCircleContainer>
  141. <ProgressCircle progress={props.file.progress.percentage} />
  142. </ProgressCircleContainer>
  143. </div>
  144. </div>
  145. )
  146. }