Preview refactoring
This commit is contained in:
@@ -41,24 +41,15 @@
|
|||||||
clipboard.btn.btn-sm.btn-default(:value='host + file.url', @change='copied(file, $event)', title='Copy to clipboard', style='margin: 0 5px')
|
clipboard.btn.btn-sm.btn-default(:value='host + file.url', @change='copied(file, $event)', title='Copy to clipboard', style='margin: 0 5px')
|
||||||
a
|
a
|
||||||
i.fa.fa-fw.fa-copy
|
i.fa.fa-fw.fa-copy
|
||||||
a.btn.btn-sm.btn-default(title="Preview", @click.prevent.stop="preview=file", v-if="getPreviewType(file)")
|
a.btn.btn-sm.btn-default(title="Preview", @click.prevent.stop="preview=file", v-if="file.previewType")
|
||||||
i.fa.fa-fw.fa-eye
|
i.fa.fa-fw.fa-eye
|
||||||
p
|
p
|
||||||
strong {{ file.metadata.name }}
|
strong {{ file.metadata.name }}
|
||||||
small(v-if="Number.isFinite(file.size)", style="margin-left:15px") ({{ humanFileSize(file.size) }})
|
small(v-if="Number.isFinite(file.size)", style="margin-left:15px") ({{ humanFileSize(file.size) }})
|
||||||
p {{ file.metadata.comment }}
|
p {{ file.metadata.comment }}
|
||||||
|
|
||||||
modal(v-if="preview", @close="preview=false", :has-header="true")
|
preview-modal(:preview="preview", :files="previewFiles", :max-size="config.maxPreviewSize", @close="preview=false")
|
||||||
h4(slot="header") {{preview.metadata.name}}
|
|
||||||
div(slot="body")
|
|
||||||
div(v-if="getPreviewType(preview) === 'image'", style="text-align:center")
|
|
||||||
img(:src="preview.url", style="max-width: 100%; height:auto")
|
|
||||||
div(v-if="getPreviewType(preview) === 'text'")
|
|
||||||
a.btn.btn-sm(style="position:absolute; right:5px; top:-30px;", title="toggle line wrap", @click="lineWrap = !lineWrap", :class="{active:lineWrap}")
|
|
||||||
i.fa.fa-fw.fa-rotate-left.fa-flip-vertical
|
|
||||||
pre(:style="{'white-space':lineWrap?'pre-wrap':'pre'}") {{ previewText }}
|
|
||||||
p(v-if="getPreviewType(preview) === false", style="text-align:center")
|
|
||||||
strong.text-danger No preview available
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
@@ -70,11 +61,25 @@
|
|||||||
|
|
||||||
import FileIcon from './common/FileIcon.vue';
|
import FileIcon from './common/FileIcon.vue';
|
||||||
import Clipboard from './common/Clipboard.vue';
|
import Clipboard from './common/Clipboard.vue';
|
||||||
import Modal from './common/Modal.vue';
|
import PreviewModal from './Download/PreviewModal.vue';
|
||||||
|
|
||||||
|
function getPreviewType(file, maxSize) {
|
||||||
|
if(!file || !file.metadata) return false;
|
||||||
|
if(file.metadata.retention === 'one-time') return false;
|
||||||
|
// no preview for files size > 2MB
|
||||||
|
if(file.size > maxSize) return false;
|
||||||
|
if(file.metadata.type && file.metadata.type.startsWith('image/')) return 'image';
|
||||||
|
else if(file.metadata.type && file.metadata.type.match(/(text\/|xml|json|javascript|x-sh)/)
|
||||||
|
|| file.metadata.name && file.metadata.name
|
||||||
|
.match(/\.(jsx|vue|sh|pug|less|scss|sass|c|h|conf|log|bat|cmd|lua|class|java|py|php|yml|sql|md)$/)) {
|
||||||
|
return 'text';
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'app',
|
name: 'app',
|
||||||
components: { FileIcon, Clipboard, Modal },
|
components: { FileIcon, Clipboard, PreviewModal },
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
files: [],
|
files: [],
|
||||||
@@ -86,53 +91,21 @@
|
|||||||
error: '',
|
error: '',
|
||||||
host: document.location.protocol + '//' + document.location.host,
|
host: document.location.protocol + '//' + document.location.host,
|
||||||
config: {},
|
config: {},
|
||||||
preview: false,
|
preview: false
|
||||||
previewText: '',
|
|
||||||
lineWrap: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
|
||||||
preview: function(preview, old) {
|
|
||||||
if(this.getPreviewType(preview) !== 'text' || preview === old) return;
|
|
||||||
this.getPreviewText();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
downloadsAvailable: function() {
|
downloadsAvailable: function() {
|
||||||
return this.files.filter(f => !f.downloaded || f.metadata.retention !== 'one-time').length > 0
|
return this.files.filter(f => !f.downloaded || f.metadata.retention !== 'one-time').length > 0
|
||||||
|
},
|
||||||
|
previewFiles: function() {
|
||||||
|
return this.files.filter(f => !!f.previewType);
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
getPreviewType(file) {
|
|
||||||
if(!file || !file.metadata) return false;
|
|
||||||
if(file.metadata.retention === 'one-time') return false;
|
|
||||||
// no preview for files size > 2MB
|
|
||||||
if(file.size > this.config.maxPreviewSize) return false;
|
|
||||||
if(file.metadata.type && file.metadata.type.startsWith('image/')) return 'image';
|
|
||||||
else if(file.metadata.type && file.metadata.type.match(/(text\/|xml|json|javascript|x-sh)/)
|
|
||||||
|| file.metadata.name && file.metadata.name
|
|
||||||
.match(/\.(jsx|vue|sh|pug|less|scss|sass|c|h|conf|log|bat|cmd|lua|class|java|py|php|yml|sql)$/)) {
|
|
||||||
return 'text';
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
getPreviewText() {
|
|
||||||
this.previewText = '';
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('GET', '//' + document.location.host + this.preview.url);
|
|
||||||
xhr.onload = () => {
|
|
||||||
if(xhr.status === 200) {
|
|
||||||
this.previewText = xhr.responseText
|
|
||||||
} else {
|
|
||||||
this.previewText = `${xhr.status} ${xhr.statusText}: ${xhr.responseText}`;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
xhr.send();
|
|
||||||
},
|
|
||||||
|
|
||||||
download(file) {
|
download(file) {
|
||||||
if(file.downloaded && file.metadata.retention === 'one-time') {
|
if(file.downloaded && file.metadata.retention === 'one-time') {
|
||||||
alert('One-Time Download: File is not available anymore.');
|
alert('One-Time Download: File is not available anymore.');
|
||||||
@@ -210,7 +183,10 @@
|
|||||||
this.needsPassword = true;
|
this.needsPassword = true;
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
return Object.assign(f, {downloaded: false});
|
return Object.assign(f, {
|
||||||
|
downloaded: false,
|
||||||
|
previewType: getPreviewType(f, this.config.maxPreviewSize)
|
||||||
|
});
|
||||||
});
|
});
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
this.error = e.toString();
|
this.error = e.toString();
|
||||||
|
|||||||
81
app/src/Download/PreviewModal.vue
Normal file
81
app/src/Download/PreviewModal.vue
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
modal(v-if="current", @close="current=false", :has-header="true", @next="next", @prev="prev")
|
||||||
|
div(slot="header")
|
||||||
|
p
|
||||||
|
strong {{current.metadata.name}}
|
||||||
|
div
|
||||||
|
small {{currentIndex+1}} / {{files.length}}
|
||||||
|
span.btn-group(style="margin-left: 15px")
|
||||||
|
a.btn.btn-sm.btn-default(title="previous", @click="prev", v-show="currentIndex > 0")
|
||||||
|
i.fa.fa-fw.fa-arrow-left
|
||||||
|
a.btn.btn-sm.btn-default(title="next", @click="next", v-show="currentIndex < files.length-1")
|
||||||
|
i.fa.fa-fw.fa-arrow-right
|
||||||
|
a.btn.btn-sm.btn-default(title="toggle line wrap", @click="lineWrap = !lineWrap", :class="{active:lineWrap}", v-show="current.previewType === 'text'")
|
||||||
|
i.fa.fa-fw.fa-rotate-left.fa-flip-vertical
|
||||||
|
div(slot="body")
|
||||||
|
div(v-if="current.previewType === 'image'", style="text-align:center")
|
||||||
|
img(:src="current.url", style="max-width: 100%; height:auto")
|
||||||
|
div(v-if="current.previewType === 'text'")
|
||||||
|
pre(:style="{'white-space':lineWrap?'pre-wrap':'pre'}") {{ previewText }}
|
||||||
|
p(v-if="current.previewType === false", style="text-align:center")
|
||||||
|
strong.text-danger No preview available
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="text/babel">
|
||||||
|
import Modal from '../common/Modal.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { Modal },
|
||||||
|
props: ['preview', 'files', 'maxSize'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
previewText: '',
|
||||||
|
lineWrap: false,
|
||||||
|
current: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
currentIndex: function() {
|
||||||
|
return this.files.indexOf(this.current);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
preview: function(preview) {
|
||||||
|
this.current = preview
|
||||||
|
},
|
||||||
|
current: function(val, old) {
|
||||||
|
if(val === false) this.$emit('close');
|
||||||
|
if(val.previewType === 'text' && val !== old) this.getPreviewText();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
next() {
|
||||||
|
if(this.currentIndex >= this.files.length-1) return;
|
||||||
|
this.current = this.files[this.currentIndex + 1];
|
||||||
|
},
|
||||||
|
|
||||||
|
prev() {
|
||||||
|
if(this.currentIndex <= 0) return;
|
||||||
|
this.current = this.files[this.currentIndex - 1];
|
||||||
|
},
|
||||||
|
|
||||||
|
getPreviewText() {
|
||||||
|
this.previewText = '';
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', '//' + document.location.host + this.current.url);
|
||||||
|
xhr.onload = () => {
|
||||||
|
if(xhr.status === 200) {
|
||||||
|
this.previewText = xhr.responseText
|
||||||
|
} else {
|
||||||
|
this.previewText = `${xhr.status} ${xhr.statusText}: ${xhr.responseText}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
.modal.fade.in.background-darken(ref='modal', style="display:block", tabindex='-1', role='dialog', @click.self='close()', @keyup.esc='close()')
|
.modal.fade.in.background-darken(ref='modal', style="display:block", tabindex='-1', role='dialog', @click.self='close()', @keyup.esc='close()', @keyup.left="$emit('prev')", @keyup.right="$emit('next')")
|
||||||
.modal-dialog.modal-fluid(role='document')
|
.modal-dialog.modal-fluid(role='document')
|
||||||
.modal-content
|
.modal-content
|
||||||
.modal-header(v-if='hasHeader')
|
.modal-header(v-if='hasHeader')
|
||||||
@@ -26,11 +26,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$nextTick(function() {
|
this.$nextTick(function() {
|
||||||
this.$refs.modal.focus();
|
this.$refs.modal.focus();
|
||||||
|
|||||||
Reference in New Issue
Block a user