Advertisement
Guest User

Untitled

a guest
Oct 19th, 2019
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.83 KB | None | 0 0
  1. <template>
  2. <div class="row justify-content-center">
  3. <div class="col-md-8">
  4.  
  5. <div class="card card-body text-center mb-4">
  6. <p class="m-0">
  7. <b>Hubble prototype video upload interface.</b>
  8. <br/>
  9. If there are any issues, please report them via <a href="mailto:techteam@hackpartners.com">email</a>.
  10. <br/>
  11. </p>
  12. </div>
  13.  
  14. <div class="row justify-content-end" v-if="state == 'selecting'">
  15. <div class="col-md-8">
  16. <form ref="form">
  17. <input id="6btooj9o4o" type="file" @change="add_files" accept="video/mp4" multiple :disabled="state == 'uploading'" />
  18. <label for="6btooj9o4o" class="mb-0 d-inline-block btn btn-secondary btn-block py-2" :class="{'cursor-pointer': state == 'selecting', disabled: state == 'uploading'}">
  19. Select files to add to this upload session
  20. </label>
  21. </form>
  22. </div>
  23. <div class="col-md-4">
  24. <button :disabled="files.length == 0 || state == 'uploading'" class="mb-0 btn btn-primary btn-block py-2" @click="upload">
  25. Upload session files
  26. </button>
  27. </div>
  28. </div>
  29.  
  30. <div class="card card-body bg-light text-center p-2" v-if="state != 'selecting'">
  31. <p class="text-danger m-0" v-if="state == 'uploading'">
  32. <small><strong>Uploading session selected files. Do not leave this page!</strong></small>
  33. </p>
  34. <p class="text-success m-0" v-if="state == 'finished'">
  35. <small><strong>Successfully uploaded all session files. <a href="#" onClick="window.location.reload();return false;">Reload the page</a> to start a new session.</strong></small>
  36. </p>
  37. <p class="text-danger m-0" v-if="state == 'aborted'">
  38. <small><strong>Something went wrong! If this issue persists, please contact us with reference <code>{{ session }}</code></strong></small>
  39. </p>
  40.  
  41. </div>
  42.  
  43. <div class="card mt-4" v-if="files.length > 0">
  44. <table class="card-body table table-sm m-0">
  45. <tr>
  46. <th>Filename</th>
  47. <th>Last Modified</th>
  48. <th>Size</th>
  49. <th class="w-50"></th>
  50. <th></th>
  51. </tr>
  52. <tr v-for="(file, index) in files" :key="index">
  53. <td>{{ file.File.name | truncate(16) }}</td>
  54. <td>{{ file.File.lastModifiedDate | fromNow }}</td>
  55. <td>{{ file.File.size | prettyBytes }}</td>
  56. <td class="w-50 align-middle">
  57. <div class="progress">
  58. <div :class="`progress-bar ${file.class}`" role="progressbar" :aria-valuenow="file.width" aria-valuemin="0" aria-valuemax="100" :style="`width: ${file.width}%`">
  59. <span> {{ file.message }} </span>
  60. </div>
  61. </div>
  62. </td>
  63. <td v-if="state == 'selecting'">
  64. <span class="text-danger cursor-pointer">✖</span>
  65. </td>
  66. </tr>
  67. </table>
  68. </div>
  69.  
  70. </div>
  71. </div>
  72. </template>
  73.  
  74. <script>
  75. const moment = require('moment')
  76. const uuidv4 = require('uuid/v4')
  77. const tus = require("tus-js-client")
  78. const prettyBytes = require('pretty-bytes');
  79.  
  80. export default {
  81. data () {
  82. return {
  83. files: [],
  84. session: uuidv4(),
  85. state: "selecting",
  86. }
  87. },
  88. methods: {
  89. add_files (e) {
  90. Array.from(e.target.files).forEach(f => {
  91. // Try to find duplicate file names.
  92. let filenames = this.files.map(ff => ff.name)
  93. if (filenames.includes(f.name)) return
  94.  
  95. this.files.push({
  96. id: this.files.length,
  97. File: f,
  98. class: "",
  99. width: 0,
  100. message: "",
  101. })
  102. })
  103. this.$refs.form.reset()
  104. },
  105. upload () {
  106. this.state = "uploading"
  107. this.files.forEach(this.create_upload)
  108. },
  109. async create_upload (file) {
  110. const ref = this.files[file.id]
  111.  
  112. ref.width = 100
  113. ref.class = "bg-dark"
  114. ref.message = "Initialising file upload."
  115.  
  116. const response = await axios.post("/api/uploads/", {
  117. session_uuid: this.session,
  118. original_filename: ref.File.name,
  119. });
  120.  
  121. this.upload_file(file, response.data)
  122. },
  123. upload_file (file, filename) {
  124. const self = this
  125. const all_files = this.files
  126. const ref = this.files[file.id]
  127.  
  128. ref.TusUpload = new tus.Upload(ref.File, {
  129. endpoint: "/tus",
  130. resume: false,
  131. chunkSize: 1000000,
  132. metadata: {
  133. filename: filename,
  134. filetype: ref.File.type
  135. },
  136. onError: function(error) {
  137. self.abort_all()
  138. ref.width = 100
  139. ref.status = "error"
  140. ref.class = "bg-danger"
  141. ref.message = "Something went terribly wrong!"
  142. console.log("Failed because: " + error)
  143. },
  144. onProgress: function(bytesUploaded, bytesTotal) {
  145. let percentage = (bytesUploaded / bytesTotal * 100).toFixed(2)
  146. ref.status = "progress"
  147. ref.width = percentage
  148. ref.class = "bg-primary"
  149. ref.message = percentage > 10 ? percentage : ""
  150. },
  151. onSuccess: function() {
  152. ref.done = true
  153. ref.status = "success"
  154. ref.class = "bg-success"
  155. ref.message = "File uploaded."
  156.  
  157. let arr = Array.from(all_files)
  158. const reducer = (acc, cv) => {return acc && cv.done}
  159. if (arr.reduce(reducer, true))
  160. self.state = 'finished'
  161. }
  162. })
  163. ref.TusUpload.start()
  164.  
  165. },
  166. abort_all () {
  167. this.state = "aborted"
  168. this.files.forEach(f => {
  169. if (f.status != "error") {
  170. f.TusUpload.abort();
  171. f.width = 100
  172. f.status = "abort"
  173. f.class = "bg-danger"
  174. f.message = "Uploading aborted."
  175. }
  176. })
  177. }
  178. },
  179. filters: {
  180. prettyBytes: prettyBytes,
  181. fromNow (value) {
  182. return moment(value).fromNow();
  183. }
  184. }
  185. }
  186. </script>
  187.  
  188. <style scoped>
  189. .cursor-pointer {
  190. cursor: pointer;
  191. }
  192.  
  193. input[type=file] {
  194. width: 0.1px;
  195. height: 0.1px;
  196. opacity: 0;
  197. overflow: hidden;
  198. position: absolute;
  199. z-index: -1;
  200. }
  201.  
  202. input[type=file]:focus + label {
  203. outline: 1px dotted #000;
  204. outline: -webkit-focus-ring-color auto 5px;
  205. }
  206. </style>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement