forked from platypush/platypush
Added FileSelector
UI component.
This commit is contained in:
parent
bac06e9e7b
commit
d4f6d174c8
2 changed files with 154 additions and 5 deletions
|
@ -27,7 +27,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row item" v-for="(file, i) in filteredFiles" :key="i" @click="path = file.path">
|
||||
<div class="row item" v-for="(file, i) in filteredFiles" :key="i" @click="onItemSelect(file)">
|
||||
<div class="col-10">
|
||||
<i class="icon fa" :class="{'fa-file': file.type !== 'directory', 'fa-folder': file.type === 'directory'}" />
|
||||
<span class="name">
|
||||
|
@ -35,11 +35,11 @@
|
|||
</span>
|
||||
</div>
|
||||
|
||||
<div class="col-2 actions">
|
||||
<div class="col-2 actions" v-if="fileActions.length">
|
||||
<Dropdown>
|
||||
<DropdownItem icon-class="fa fa-play" text="Play"
|
||||
@click="$emit('play', {type: 'file', url: `file://${file.path}`})"
|
||||
v-if="isMedia && mediaExtensions.has(file.name.split('.').pop()?.toLowerCase())" />
|
||||
v-if="hasPlay && file.type !== 'directory'" />
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -58,7 +58,7 @@ export default {
|
|||
name: "Browser",
|
||||
components: {DropdownItem, Dropdown, Loading},
|
||||
mixins: [Utils, MediaUtils],
|
||||
emits: ['back', 'path-change', 'play'],
|
||||
emits: ['back', 'path-change', 'play', 'input'],
|
||||
|
||||
props: {
|
||||
hasBack: {
|
||||
|
@ -96,6 +96,23 @@ export default {
|
|||
return this.files.filter((file) => (file?.name || '').toLowerCase().indexOf(this.filter.toLowerCase()) >= 0)
|
||||
},
|
||||
|
||||
hasPlay() {
|
||||
return this.isMedia && this.files.some((file) => this.mediaExtensions.has(file.name.split('.').pop()?.toLowerCase()))
|
||||
},
|
||||
|
||||
fileActions() {
|
||||
if (!this.hasPlay)
|
||||
return []
|
||||
|
||||
return [
|
||||
{
|
||||
iconClass: 'fa fa-play',
|
||||
text: 'Play',
|
||||
onClick: (file) => this.$emit('play', {type: 'file', url: `file://${file.path}`}),
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
pathTokens() {
|
||||
if (!this.path?.length)
|
||||
return ['/']
|
||||
|
@ -128,10 +145,26 @@ export default {
|
|||
else
|
||||
this.path = [...this.pathTokens].slice(0, -1).join('/').slice(1)
|
||||
},
|
||||
|
||||
onItemSelect(file) {
|
||||
if (file.type === 'directory')
|
||||
this.path = file.path
|
||||
else
|
||||
this.$emit('input', file.path)
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
initialPath() {
|
||||
this.path = this.initialPath
|
||||
},
|
||||
|
||||
path() {
|
||||
this.refresh()
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$watch(() => this.path, () => this.refresh())
|
||||
this.refresh()
|
||||
},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
<template>
|
||||
<div class="file-selector-container">
|
||||
<div class="input">
|
||||
<input type="text"
|
||||
:value="value"
|
||||
:readonly="strict"
|
||||
@input="$emit('input', $event.target.value)" />
|
||||
|
||||
<button type="button"
|
||||
title="Select a file"
|
||||
@click="$refs.fileSelectorModal.show()">
|
||||
<i class="fa fa-folder-open" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Modal title="Select a file" ref="fileSelectorModal">
|
||||
<Browser :initialPath="path"
|
||||
@input="onValueChange($event)"
|
||||
@path-change="path = $event" />
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from "@/components/Modal";
|
||||
import Browser from "@/components/File/Browser";
|
||||
|
||||
export default {
|
||||
emits: ['input'],
|
||||
components: {
|
||||
Browser,
|
||||
Modal,
|
||||
},
|
||||
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
},
|
||||
|
||||
strict: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
path: '/',
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onValueChange(value) {
|
||||
this.$emit('input', value)
|
||||
},
|
||||
|
||||
onFileSelect(value) {
|
||||
if (value != null && (value.startsWith('/') || value.startsWith('file://')))
|
||||
this.path = value.split('/').slice(0, -1).join('/')
|
||||
else
|
||||
this.path = '/'
|
||||
|
||||
this.$refs.fileSelectorModal.hide()
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
value(value) {
|
||||
this.onFileSelect(value)
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.onFileSelect(this.value)
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.file-selector-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.input {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: stretch;
|
||||
|
||||
input {
|
||||
flex-grow: 1;
|
||||
border-radius: 1em 0 0 1em;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0 1em 1em 0;
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.modal) {
|
||||
.body {
|
||||
width: 80vw;
|
||||
height: 80vh;
|
||||
max-width: 800px;
|
||||
padding: 0;
|
||||
|
||||
.items {
|
||||
.item {
|
||||
padding: 1em 0.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
Reference in a new issue