Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <template>
- <div class="row justify-content-center">
- <div class="col-md-8">
- <div class="card card-body text-center mb-4">
- <p class="m-0">
- <b>Hubble prototype video upload interface.</b>
- <br/>
- If there are any issues, please report them via <a href="mailto:techteam@hackpartners.com">email</a>.
- <br/>
- </p>
- </div>
- <div class="row justify-content-end" v-if="state == 'selecting'">
- <div class="col-md-8">
- <form ref="form">
- <input id="6btooj9o4o" type="file" @change="add_files" accept="video/mp4" multiple :disabled="state == 'uploading'" />
- <label for="6btooj9o4o" class="mb-0 d-inline-block btn btn-secondary btn-block py-2" :class="{'cursor-pointer': state == 'selecting', disabled: state == 'uploading'}">
- Select files to add to this upload session
- </label>
- </form>
- </div>
- <div class="col-md-4">
- <button :disabled="files.length == 0 || state == 'uploading'" class="mb-0 btn btn-primary btn-block py-2" @click="upload">
- Upload session files
- </button>
- </div>
- </div>
- <div class="card card-body bg-light text-center p-2" v-if="state != 'selecting'">
- <p class="text-danger m-0" v-if="state == 'uploading'">
- <small><strong>Uploading session selected files. Do not leave this page!</strong></small>
- </p>
- <p class="text-success m-0" v-if="state == 'finished'">
- <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>
- </p>
- <p class="text-danger m-0" v-if="state == 'aborted'">
- <small><strong>Something went wrong! If this issue persists, please contact us with reference <code>{{ session }}</code></strong></small>
- </p>
- </div>
- <div class="card mt-4" v-if="files.length > 0">
- <table class="card-body table table-sm m-0">
- <tr>
- <th>Filename</th>
- <th>Last Modified</th>
- <th>Size</th>
- <th class="w-50"></th>
- <th></th>
- </tr>
- <tr v-for="(file, index) in files" :key="index">
- <td>{{ file.File.name | truncate(16) }}</td>
- <td>{{ file.File.lastModifiedDate | fromNow }}</td>
- <td>{{ file.File.size | prettyBytes }}</td>
- <td class="w-50 align-middle">
- <div class="progress">
- <div :class="`progress-bar ${file.class}`" role="progressbar" :aria-valuenow="file.width" aria-valuemin="0" aria-valuemax="100" :style="`width: ${file.width}%`">
- <span> {{ file.message }} </span>
- </div>
- </div>
- </td>
- <td v-if="state == 'selecting'">
- <span class="text-danger cursor-pointer">✖</span>
- </td>
- </tr>
- </table>
- </div>
- </div>
- </div>
- </template>
- <script>
- const moment = require('moment')
- const uuidv4 = require('uuid/v4')
- const tus = require("tus-js-client")
- const prettyBytes = require('pretty-bytes');
- export default {
- data () {
- return {
- files: [],
- session: uuidv4(),
- state: "selecting",
- }
- },
- methods: {
- add_files (e) {
- Array.from(e.target.files).forEach(f => {
- // Try to find duplicate file names.
- let filenames = this.files.map(ff => ff.name)
- if (filenames.includes(f.name)) return
- this.files.push({
- id: this.files.length,
- File: f,
- class: "",
- width: 0,
- message: "",
- })
- })
- this.$refs.form.reset()
- },
- upload () {
- this.state = "uploading"
- this.files.forEach(this.create_upload)
- },
- async create_upload (file) {
- const ref = this.files[file.id]
- ref.width = 100
- ref.class = "bg-dark"
- ref.message = "Initialising file upload."
- const response = await axios.post("/api/uploads/", {
- session_uuid: this.session,
- original_filename: ref.File.name,
- });
- this.upload_file(file, response.data)
- },
- upload_file (file, filename) {
- const self = this
- const all_files = this.files
- const ref = this.files[file.id]
- ref.TusUpload = new tus.Upload(ref.File, {
- endpoint: "/tus",
- resume: false,
- chunkSize: 1000000,
- metadata: {
- filename: filename,
- filetype: ref.File.type
- },
- onError: function(error) {
- self.abort_all()
- ref.width = 100
- ref.status = "error"
- ref.class = "bg-danger"
- ref.message = "Something went terribly wrong!"
- console.log("Failed because: " + error)
- },
- onProgress: function(bytesUploaded, bytesTotal) {
- let percentage = (bytesUploaded / bytesTotal * 100).toFixed(2)
- ref.status = "progress"
- ref.width = percentage
- ref.class = "bg-primary"
- ref.message = percentage > 10 ? percentage : ""
- },
- onSuccess: function() {
- ref.done = true
- ref.status = "success"
- ref.class = "bg-success"
- ref.message = "File uploaded."
- let arr = Array.from(all_files)
- const reducer = (acc, cv) => {return acc && cv.done}
- if (arr.reduce(reducer, true))
- self.state = 'finished'
- }
- })
- ref.TusUpload.start()
- },
- abort_all () {
- this.state = "aborted"
- this.files.forEach(f => {
- if (f.status != "error") {
- f.TusUpload.abort();
- f.width = 100
- f.status = "abort"
- f.class = "bg-danger"
- f.message = "Uploading aborted."
- }
- })
- }
- },
- filters: {
- prettyBytes: prettyBytes,
- fromNow (value) {
- return moment(value).fromNow();
- }
- }
- }
- </script>
- <style scoped>
- .cursor-pointer {
- cursor: pointer;
- }
- input[type=file] {
- width: 0.1px;
- height: 0.1px;
- opacity: 0;
- overflow: hidden;
- position: absolute;
- z-index: -1;
- }
- input[type=file]:focus + label {
- outline: 1px dotted #000;
- outline: -webkit-focus-ring-color auto 5px;
- }
- </style>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement