SHARE
TWEET

Untitled

a guest Oct 19th, 2019 75 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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>
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top