chore: share view logic responsability

pull/1307/head
Ramires Viana 2021-03-03 17:46:37 +00:00
parent d8306559fd
commit edb9e85efd
12 changed files with 113 additions and 80 deletions

View File

@ -58,7 +58,7 @@ export async function put (url, content = '') {
}
export function download (format, ...files) {
let url = store.getters['isSharing'] ? `${baseURL}/api/public/dl/${store.state.hash}` : `${baseURL}/api/raw`
let url = `${baseURL}/api/raw`
if (files.length === 1) {
url += removePrefix(files[0]) + '?'
@ -74,15 +74,13 @@ export function download (format, ...files) {
url += `/?files=${arg}&`
}
if (format !== null) {
if (format) {
url += `algo=${format}&`
}
if (store.state.jwt !== ''){
if (store.state.jwt){
url += `auth=${store.state.jwt}&`
}
if (store.state.token !== ''){
url += `token=${store.state.token}`
}
window.open(url)
}

View File

@ -2,6 +2,7 @@ import * as files from './files'
import * as share from './share'
import * as users from './users'
import * as settings from './settings'
import * as pub from './pub'
import search from './search'
import commands from './commands'
@ -10,6 +11,7 @@ export {
share,
users,
settings,
pub,
commands,
search
}

37
frontend/src/api/pub.js Normal file
View File

@ -0,0 +1,37 @@
import { fetchJSON, removePrefix } from './utils'
import { baseURL } from '@/utils/constants'
export async function fetch(hash, password = "") {
return fetchJSON(`/api/public/share/${hash}`, {
headers: {'X-SHARE-PASSWORD': password},
})
}
export function download(format, hash, token, ...files) {
let url = `${baseURL}/api/public/dl/${hash}`
const prefix = `/share/${hash}`
if (files.length === 1) {
url += removePrefix(files[0], prefix) + '?'
} else {
let arg = ''
for (let file of files) {
arg += removePrefix(file, prefix) + ','
}
arg = arg.substring(0, arg.length - 1)
arg = encodeURIComponent(arg)
url += `/?files=${arg}&`
}
if (format) {
url += `algo=${format}&`
}
if (token) {
url += `token=${token}&`
}
window.open(url)
}

View File

@ -4,12 +4,6 @@ export async function list() {
return fetchJSON('/api/shares')
}
export async function getHash(hash, password = "") {
return fetchJSON(`/api/public/share/${hash}`, {
headers: {'X-SHARE-PASSWORD': password},
})
}
export async function get(url) {
url = removePrefix(url)
return fetchJSON(`/api/share${url}`)

View File

@ -33,11 +33,11 @@ export async function fetchJSON (url, opts) {
}
}
export function removePrefix (url) {
export function removePrefix (url, prefix) {
if (url.startsWith('/files')) {
url = url.slice(6)
} else if (store.getters['isSharing']) {
url = url.slice(7 + store.state.hash.length)
} else if (prefix) {
url = url.replace(prefix, '')
}
if (url === '') url = '/'

View File

@ -13,7 +13,7 @@
:aria-label="name"
:aria-selected="isSelected">
<div>
<img v-if="type==='image' && isThumbsEnabled && !isSharing" v-lazy="thumbnailUrl">
<img v-if="readOnly == undefined && type==='image' && isThumbsEnabled" v-lazy="thumbnailUrl">
<i v-else class="material-icons">{{ icon }}</i>
</div>
@ -45,13 +45,12 @@ export default {
touches: 0
}
},
props: ['name', 'isDir', 'url', 'type', 'size', 'modified', 'index'],
props: ['name', 'isDir', 'url', 'type', 'size', 'modified', 'index', 'readOnly'],
computed: {
...mapState(['user', 'selected', 'req', 'jwt']),
...mapGetters(['selectedCount', 'isSharing']),
...mapGetters(['selectedCount']),
singleClick () {
if (this.isSharing) return false
return this.user.singleClick
return this.readOnly == undefined && this.user.singleClick
},
isSelected () {
return (this.selected.indexOf(this.index) !== -1)
@ -64,10 +63,10 @@ export default {
return 'insert_drive_file'
},
isDraggable () {
return !this.isSharing && this.user.perm.rename
return this.readOnly == undefined && this.user.perm.rename
},
canDrop () {
if (!this.isDir || this.isSharing) return false
if (!this.isDir || this.readOnly == undefined) return false
for (let i of this.selected) {
if (this.req.items[i].url === this.url) {
@ -139,7 +138,7 @@ export default {
to: this.url + this.req.items[i].name,
name: this.req.items[i].name
})
}
}
let base = el.querySelector('.name').innerHTML + '/'
let path = this.$route.path + base

View File

@ -7,43 +7,29 @@
<div class="card-content">
<p>{{ $t('prompts.downloadMessage') }}</p>
<button class="button button--block" @click="download('zip')" v-focus>zip</button>
<button class="button button--block" @click="download('tar')" v-focus>tar</button>
<button class="button button--block" @click="download('targz')" v-focus>tar.gz</button>
<button class="button button--block" @click="download('tarbz2')" v-focus>tar.bz2</button>
<button class="button button--block" @click="download('tarxz')" v-focus>tar.xz</button>
<button class="button button--block" @click="download('tarlz4')" v-focus>tar.lz4</button>
<button class="button button--block" @click="download('tarsz')" v-focus>tar.sz</button>
<button v-for="(ext, format) in formats" :key="format" class="button button--block" @click="showConfirm(format)" v-focus>{{ ext }}</button>
</div>
</div>
</template>
<script>
import {mapGetters, mapState} from 'vuex'
import { files as api } from '@/api'
import { mapState } from 'vuex'
export default {
name: 'download',
computed: {
...mapState(['selected', 'req']),
...mapGetters(['selectedCount'])
},
methods: {
download: function (format) {
if (this.selectedCount === 0) {
api.download(format, this.$route.path)
} else {
let files = []
for (let i of this.selected) {
files.push(this.req.items[i].url)
}
api.download(format, ...files)
data: function () {
return {
formats: {
zip: 'zip',
tar: 'tar',
targz: 'tar.gz',
tarbz2: 'tar.bz2',
tarxz: 'tar.xz',
tarlz4: 'tar.lz4',
tarsz: 'tar.sz'
}
this.$store.commit('closeHovers')
}
}
},
computed: mapState(['showConfirm'])
}
</script>

View File

@ -2,7 +2,6 @@ const getters = {
isLogged: state => state.user !== null,
isFiles: state => !state.loading && state.route.name === 'Files',
isListing: (state, getters) => getters.isFiles && state.req.isDir,
isSharing: state => !state.loading && state.route.name === 'Share',
selectedCount: state => state.selected.length,
progress : state => {
if (state.upload.progress.length == 0) {

View File

@ -22,10 +22,7 @@ const state = {
multiple: false,
show: null,
showShell: false,
showMessage: null,
showConfirm: null,
hash: '',
token: ''
showConfirm: null
}
export default new Vuex.Store({

View File

@ -4,7 +4,7 @@ import moment from 'moment'
const mutations = {
closeHovers: state => {
state.show = null
state.showMessage = null
state.showConfirm = null
},
toggleShell: (state) => {
state.showShell = !state.showShell
@ -16,16 +16,13 @@ const mutations = {
}
state.show = value.prompt
state.showMessage = value.message
state.showConfirm = value.confirm
},
showError: (state, value) => {
showError: (state) => {
state.show = 'error'
state.showMessage = value
},
showSuccess: (state, value) => {
showSuccess: (state) => {
state.show = 'success'
state.showMessage = value
},
setLoading: (state, value) => { state.loading = value },
setReload: (state, value) => { state.reload = value },
@ -46,12 +43,8 @@ const mutations = {
state.user = value
},
setJWT: (state, value) => (state.jwt = value),
setToken: (state, value ) => (state.token = value),
multiple: (state, value) => (state.multiple = value),
addSelected: (state, value) => (state.selected.push(value)),
addPlugin: (state, value) => {
state.plugins.push(value)
},
removeSelected: (state, value) => {
let i = state.selected.indexOf(value)
if (i === -1) return
@ -84,8 +77,7 @@ const mutations = {
resetClipboard: (state) => {
state.clipboard.key = ''
state.clipboard.items = []
},
setHash: (state, value) => (state.hash = value),
}
}
export default mutations

View File

@ -47,7 +47,8 @@
v-bind:url="item.url"
v-bind:modified="item.modified"
v-bind:type="item.type"
v-bind:size="item.size">
v-bind:size="item.size"
readOnly>
</item>
<div v-if="req.items.length > showLimit" class="item">
<div>
@ -97,7 +98,7 @@
<script>
import {mapState, mapMutations, mapGetters} from 'vuex';
import { files, share as api } from '@/api'
import { pub as api } from '@/api'
import { baseURL } from '@/utils/constants'
import filesize from 'filesize'
import moment from 'moment'
@ -124,14 +125,16 @@ export default {
path: '',
showLimit: 500,
password: '',
attemptedPasswordLogin: false
attemptedPasswordLogin: false,
hash: null,
token: null
}),
watch: {
'$route': 'fetchData'
},
created: async function () {
const hash = this.$route.params.pathMatch.split('/')[0]
this.setHash(hash)
this.hash = hash
await this.fetchData()
},
mounted () {
@ -141,7 +144,7 @@ export default {
window.removeEventListener('keydown', this.keyEvent)
},
computed: {
...mapState(['hash', 'req', 'loading', 'multiple', 'selected']),
...mapState(['req', 'loading', 'multiple', 'selected']),
...mapGetters(['selectedCount', 'selectedCount']),
icon: function () {
if (this.req.isDir) return 'folder'
@ -175,7 +178,7 @@ export default {
}
},
methods: {
...mapMutations([ 'setHash', 'resetSelected', 'updateRequest', 'setLoading' ]),
...mapMutations([ 'resetSelected', 'updateRequest', 'setLoading' ]),
base64: function (name) {
return window.btoa(unescape(encodeURIComponent(name)))
},
@ -194,12 +197,11 @@ export default {
if (this.password !== ''){
this.attemptedPasswordLogin = true
}
let file = await api.getHash(encodeURIComponent(this.$route.params.pathMatch), this.password)
let file = await api.fetch(encodeURIComponent(this.$route.params.pathMatch), this.password)
this.path = file.path
if (this.path.endsWith('/')) this.path = this.path.slice(0, -1)
this.token = file.token || ''
this.$store.commit('setToken', this.token)
if (file.isDir) file.items = file.items.map((item, index) => {
item.index = index
item.url = `/share/${this.hash}${this.path}/${encodeURIComponent(item.name)}`
@ -226,11 +228,24 @@ export default {
},
download () {
if (this.selectedCount === 1 && !this.req.items[this.selected[0]].isDir) {
files.download(null, this.req.items[this.selected[0]].url)
api.download(null, this.hash, this.token, this.req.items[this.selected[0]].url)
return
}
this.$store.commit('showHover', 'download')
this.$store.commit('showHover', {
prompt: 'download',
confirm: (format) => {
this.$store.commit('closeHovers')
let files = []
for (let i of this.selected) {
files.push(this.req.items[i].url)
}
api.download(format, this.hash, this.token, ...files)
}
})
}
}
}

View File

@ -158,7 +158,8 @@ export default {
'selected',
'user',
'show',
'multiple'
'multiple',
'selected'
]),
...mapGetters([
'selectedCount'
@ -580,7 +581,20 @@ export default {
return
}
this.$store.commit('showHover', 'download')
this.$store.commit('showHover', {
prompt: 'download',
confirm: (format) => {
this.$store.commit('closeHovers')
let files = []
for (let i of this.selected) {
files.push(this.req.items[i].url)
}
api.download(format, ...files)
}
})
},
switchView: async function () {
this.$store.commit('closeHovers')