mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-05-25 14:14:42 +00:00
Merge remote-tracking branch 'origin/master' into oasis
# Conflicts: # public/chunks/admin-account.js # public/chunks/admin.js # public/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~8cc7d96f.js # public/chunks/app-language.js # public/chunks/app-settings.js # public/chunks/app-setup.js # public/chunks/billings-detail.js # public/chunks/dashboard.js # public/chunks/database.js # public/chunks/environment-setup.js # public/chunks/files.js # public/chunks/files~chunks/shared-files~chunks/shared/file-browser.js # public/chunks/files~chunks/shared-files~chunks/shared/file-browser~chunks/shared/single-file.js # public/chunks/homepage.js # public/chunks/installation-disclaimer.js # public/chunks/invoices.js # public/chunks/page-edit.js # public/chunks/pages.js # public/chunks/plan-create.js # public/chunks/plan-settings.js # public/chunks/plan-subscribers.js # public/chunks/plan.js # public/chunks/plans.js # public/chunks/platform.js # public/chunks/profile.js # public/chunks/profile~chunks/settings-password.js # public/chunks/purchase-code.js # public/chunks/settings-create-payment-methods.js # public/chunks/settings-invoices.js # public/chunks/settings-payment-methods.js # public/chunks/settings-storage.js # public/chunks/settings-subscription.js # public/chunks/settings.js # public/chunks/shared-files.js # public/chunks/shared.js # public/chunks/shared/file-browser.js # public/chunks/stripe-credentials.js # public/chunks/subscription-plans.js # public/chunks/subscription-service.js # public/chunks/upgrade-billing.js # public/chunks/upgrade-plan.js # public/chunks/user-create.js # public/chunks/user-delete.js # public/chunks/user-detail.js # public/chunks/user-invoices.js # public/chunks/user-storage.js # public/chunks/user-subscription.js # public/chunks/user.js # public/chunks/users.js # public/js/main.js # public/mix-manifest.json # public/vendors~chunks/platform~chunks/shared.js
This commit is contained in:
+24
-20
@@ -5,13 +5,14 @@
|
||||
<Alert />
|
||||
<ToastrWrapper />
|
||||
<CookieDisclaimer />
|
||||
<Vignette />
|
||||
|
||||
<!--Show spinner before translations is loaded-->
|
||||
<Spinner v-if="! isLoadedTranslations"/>
|
||||
<Spinner v-if="! isLoaded"/>
|
||||
|
||||
<!--App view-->
|
||||
<router-view v-if="isLoadedTranslations" />
|
||||
<router-view v-if="isLoaded" />
|
||||
|
||||
<Vignette />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -34,7 +35,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoadedTranslations: false
|
||||
isLoaded: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -44,25 +45,12 @@ export default {
|
||||
},
|
||||
beforeMount() {
|
||||
|
||||
// Get language translations
|
||||
this.$store.dispatch('getLanguageTranslations', this.$root.$data.config.language)
|
||||
.then(() => {
|
||||
this.isLoadedTranslations = true
|
||||
|
||||
// Store config to vuex
|
||||
this.$store.commit('INIT', {
|
||||
config: this.$root.$data.config,
|
||||
rootDirectory: {
|
||||
name: this.$t('locations.home'),
|
||||
location: 'base',
|
||||
id: undefined
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Get installation state
|
||||
let installation = this.$root.$data.config.installation
|
||||
|
||||
if (['setup-disclaimer', 'setup-database'].includes(installation))
|
||||
this.isLoaded = true
|
||||
|
||||
// Redirect to database verify code
|
||||
if (installation === 'setup-database')
|
||||
this.$router.push({name: 'PurchaseCode'})
|
||||
@@ -70,6 +58,22 @@ export default {
|
||||
// Redirect to starting installation process
|
||||
if (installation === 'setup-disclaimer')
|
||||
this.$router.push({name: 'InstallationDisclaimer'})
|
||||
|
||||
if (installation === 'setup-done')
|
||||
this.$store.dispatch('getLanguageTranslations', this.$root.$data.config.language)
|
||||
.then(() => {
|
||||
this.isLoaded = true
|
||||
|
||||
// Store config to vuex
|
||||
this.$store.commit('INIT', {
|
||||
config: this.$root.$data.config,
|
||||
rootDirectory: {
|
||||
name: this.$t('locations.home'),
|
||||
location: 'base',
|
||||
id: undefined
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
mounted() {
|
||||
this.$checkOS()
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<div v-if="isVisible" class="popover-item">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'PopoverItem',
|
||||
props: [
|
||||
'name'
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
isVisible: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
events.$on('popover:open', name => {
|
||||
if (this.name === name) this.isVisible = !this.isVisible
|
||||
})
|
||||
|
||||
events.$on('unClick', () => this.isVisible = false)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/vuefilemanager/_variables";
|
||||
@import "@assets/vuefilemanager/_mixins";
|
||||
|
||||
.popover-item {
|
||||
min-width: 250px;
|
||||
position: absolute;
|
||||
z-index: 9;
|
||||
box-shadow: $shadow;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
right: 0;
|
||||
top: 50px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.popover-item {
|
||||
background: $dark_mode_foreground;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<div class="popover-wrapper">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'PopoverWrapper',
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.popover-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<div class="toolbar-button-wrapper">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ToolbarWrapper',
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.toolbar-button-wrapper {
|
||||
margin-left: 28px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1024px) {
|
||||
|
||||
.toolbar-button-wrapper {
|
||||
margin-left: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<div class="toolbar-tools">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ToolbarWrapper',
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/vuefilemanager/_variables";
|
||||
@import "@assets/vuefilemanager/_mixins";
|
||||
|
||||
.toolbar-tools {
|
||||
text-align: right;
|
||||
display: flex;;
|
||||
}
|
||||
</style>
|
||||
@@ -193,21 +193,21 @@ export default {
|
||||
Option
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['user', 'fileInfoDetail']),
|
||||
...mapGetters(['user', 'clipboard']),
|
||||
hasFolder() {
|
||||
return this.fileInfoDetail.find(item => item.type === 'folder')
|
||||
return this.clipboard.find(item => item.type === 'folder')
|
||||
},
|
||||
hasFile() {
|
||||
return this.fileInfoDetail.find(item => item.type !== 'folder')
|
||||
return this.clipboard.find(item => item.type !== 'folder')
|
||||
},
|
||||
isMultiSelectContextMenu() {
|
||||
|
||||
// If is context Menu open on multi selected items open just options for the multi selected items
|
||||
if (this.fileInfoDetail.length > 1 && this.fileInfoDetail.includes(this.item))
|
||||
if (this.clipboard.length > 1 && this.clipboard.includes(this.item))
|
||||
return false
|
||||
|
||||
// If is context Menu open for the non selected item open options for the single item
|
||||
if (this.fileInfoDetail.length < 2 || !this.fileInfoDetail.includes(this.item))
|
||||
if (this.clipboard.length < 2 || !this.clipboard.includes(this.item))
|
||||
return true
|
||||
},
|
||||
favourites() {
|
||||
@@ -250,11 +250,11 @@ export default {
|
||||
restoreItem() {
|
||||
|
||||
// If is item not in selected items restore just this single item
|
||||
if (!this.fileInfoDetail.includes(this.item))
|
||||
if (!this.clipboard.includes(this.item))
|
||||
this.$store.dispatch('restoreItem', this.item)
|
||||
|
||||
// If is item in selected items restore all items from fileInfoDetail
|
||||
if (this.fileInfoDetail.includes(this.item))
|
||||
// If is item in selected items restore all items from clipboard
|
||||
if (this.clipboard.includes(this.item))
|
||||
this.$store.dispatch('restoreItem', null)
|
||||
},
|
||||
shareCancel() {
|
||||
@@ -267,13 +267,14 @@ export default {
|
||||
events.$emit('popup:open', {name: 'move', item: [this.item]})
|
||||
},
|
||||
shareItem() {
|
||||
if (this.item.shared) {
|
||||
// Open edit share popup
|
||||
events.$emit('popup:open', {name: 'share-edit', item: this.item})
|
||||
} else {
|
||||
// Open create share popup
|
||||
events.$emit('popup:open', {name: 'share-create', item: this.item})
|
||||
}
|
||||
let event = this.item.shared
|
||||
? 'share-edit'
|
||||
: 'share-create'
|
||||
|
||||
events.$emit('popup:open', {
|
||||
name: event,
|
||||
item: this.item
|
||||
})
|
||||
},
|
||||
addToFavourites() {
|
||||
// Check if folder is in favourites and then add/remove from favourites
|
||||
@@ -282,12 +283,12 @@ export default {
|
||||
!this.favourites.find(el => el.id === this.item.id)
|
||||
) {
|
||||
// Add to favourite folder that is not selected
|
||||
if (!this.fileInfoDetail.includes(this.item)) {
|
||||
if (!this.clipboard.includes(this.item)) {
|
||||
this.$store.dispatch('addToFavourites', this.item)
|
||||
}
|
||||
|
||||
// Add to favourites all selected folders
|
||||
if (this.fileInfoDetail.includes(this.item)) {
|
||||
if (this.clipboard.includes(this.item)) {
|
||||
this.$store.dispatch('addToFavourites', null)
|
||||
}
|
||||
} else {
|
||||
@@ -295,7 +296,7 @@ export default {
|
||||
}
|
||||
},
|
||||
downloadItem() {
|
||||
if (this.fileInfoDetail.length > 1)
|
||||
if (this.clipboard.length > 1)
|
||||
this.$store.dispatch('downloadFiles')
|
||||
else {
|
||||
this.$downloadFile(this.item.file_url, this.item.name + '.' + this.item.mimetype)
|
||||
@@ -303,18 +304,18 @@ export default {
|
||||
},
|
||||
ItemDetail() {
|
||||
// Dispatch load file info detail
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
|
||||
|
||||
// Show panel if is not open
|
||||
this.$store.dispatch('fileInfoToggle', true)
|
||||
},
|
||||
deleteItem() {
|
||||
// If is context menu open on non selected item delete this single item
|
||||
if (!this.fileInfoDetail.includes(this.item)) {
|
||||
if (!this.clipboard.includes(this.item)) {
|
||||
this.$store.dispatch('deleteItem', this.item)
|
||||
}
|
||||
// If is context menu open to multi selected items dele this selected items
|
||||
if (this.fileInfoDetail.includes(this.item)) {
|
||||
if (this.clipboard.includes(this.item)) {
|
||||
this.$store.dispatch('deleteItem')
|
||||
}
|
||||
},
|
||||
@@ -385,12 +386,6 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
events.$on('actualShowingImage:ContextMenu', (item) => {
|
||||
this.item = item
|
||||
})
|
||||
},
|
||||
created() {
|
||||
events.$on('showContextMenuPreview:show', (item) => {
|
||||
if (!this.showFromPreview) {
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
<template>
|
||||
<div v-if="isVisible" class="sorting-preview">
|
||||
<SortingAndPreviewMenu />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SortingAndPreviewMenu from '@/components/FilesView/SortingAndPreviewMenu'
|
||||
import { events } from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'DesktopSortingAndPreview',
|
||||
components: {SortingAndPreviewMenu},
|
||||
data () {
|
||||
return {
|
||||
isVisible: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
events.$on('sortingAndPreview', (state) => {
|
||||
this.isVisible = state
|
||||
})
|
||||
|
||||
events.$on('unClick', () => {
|
||||
this.isVisible = false
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/vuefilemanager/_variables";
|
||||
@import "@assets/vuefilemanager/_mixins";
|
||||
|
||||
.sorting-preview {
|
||||
min-width: 250px;
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
box-shadow: $shadow;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
right: 66px;
|
||||
top: 63px;
|
||||
|
||||
&.showed {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.sorting-preview {
|
||||
background: $dark_mode_foreground;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,399 +1,334 @@
|
||||
<template>
|
||||
<div id="desktop-toolbar">
|
||||
<div class="toolbar-wrapper">
|
||||
<!-- Go back-->
|
||||
<div class="toolbar-go-back" v-if="homeDirectory">
|
||||
<div @click="goBack" class="go-back-button">
|
||||
<chevron-left-icon size="17" :class="{ 'is-active': browseHistory.length > 1 }" class="icon-back"></chevron-left-icon>
|
||||
|
||||
<span class="back-directory-title">
|
||||
{{ directoryName }}
|
||||
</span>
|
||||
<div v-if="homeDirectory" @click="goBack" class="location">
|
||||
<chevron-left-icon :class="{'is-active': browseHistory.length > 1 }" class="icon-back" size="17" />
|
||||
|
||||
<span @click.stop="folderActions" v-if="browseHistory.length > 1 && $isThisLocation(['base', 'public'])" class="folder-options group" id="folder-actions">
|
||||
<more-horizontal-icon size="14" class="icon-more group-hover-text-theme" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="location-title">
|
||||
{{ directoryName }}
|
||||
</span>
|
||||
|
||||
<!-- Tools-->
|
||||
<div class="toolbar-tools">
|
||||
<!--Search bar-->
|
||||
<div class="toolbar-button-wrapper">
|
||||
<SearchBar/>
|
||||
</div>
|
||||
<span @click.stop="folderActions" v-if="browseHistory.length > 1 && $isThisLocation(['base', 'public'])" class="location-more group" id="folder-actions">
|
||||
<more-horizontal-icon size="14" class="icon-more group-hover-text-theme" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!--Creating controls-->
|
||||
<div class="toolbar-button-wrapper" v-if="$checkPermission(['master', 'editor'])">
|
||||
<ToolbarButtonUpload :class="{ 'is-inactive': canUploadInView || !hasCapacity }" :action="$t('actions.upload')"/>
|
||||
<ToolbarButton :class="{ 'is-inactive': canCreateFolderInView }" @click.native="createFolder" source="folder-plus" :action="$t('actions.create_folder')"/>
|
||||
</div>
|
||||
<ToolbarWrapper>
|
||||
|
||||
<!--File Controls-->
|
||||
<div class="toolbar-button-wrapper" v-if="$checkPermission(['master', 'editor']) && ! $isMobile()">
|
||||
<ToolbarButton source="move" :class="{ 'is-inactive': canMoveInView }" :action="$t('actions.move')" @click.native="moveItem"/>
|
||||
<ToolbarButton v-if="!$isThisLocation(['public'])" source="share" :class="{ 'is-inactive': canShareInView }" :action="$t('actions.share')" @click.native="shareItem"/>
|
||||
<ToolbarButton source="trash" :class="{ 'is-inactive': canDeleteInView }" :action="$t('actions.delete')" @click.native="deleteItem"/>
|
||||
</div>
|
||||
<!--Search bar-->
|
||||
<ToolbarGroup style="margin-left: 0">
|
||||
<SearchBar v-model="query" @reset-query="query = ''" :placeholder="$t('inputs.placeholder_search_files')" />
|
||||
</ToolbarGroup>
|
||||
|
||||
<!--View Controls-->
|
||||
<div class="toolbar-button-wrapper">
|
||||
<ToolbarButton source="preview-sorting" class="preview-sorting" :action="$t('actions.sorting_view')" :class="{ active: sortingAndPreview }" @click.stop.native="sortingAndPreview = !sortingAndPreview"/>
|
||||
<ToolbarButton :action="$t('actions.info_panel')" :class="{ active: fileInfoVisible }" @click.native="$store.dispatch('fileInfoToggle')" source="info"/>
|
||||
</div>
|
||||
</div>
|
||||
<!--Creating controls-->
|
||||
<ToolbarGroup v-if="$checkPermission(['master', 'editor'])">
|
||||
<ToolbarButtonUpload :class="{'is-inactive': canUploadInView || !hasCapacity }" :action="$t('actions.upload')" />
|
||||
<ToolbarButton @click.native="createFolder" :class="{'is-inactive': canCreateFolderInView }" source="folder-plus" :action="$t('actions.create_folder')" />
|
||||
</ToolbarGroup>
|
||||
|
||||
<!--File Controls-->
|
||||
<ToolbarGroup v-if="$checkPermission(['master', 'editor']) && ! $isMobile()">
|
||||
<ToolbarButton @click.native="moveItem" :class="{'is-inactive': canMoveInView }" source="move" :action="$t('actions.move')" />
|
||||
<ToolbarButton @click.native="shareItem" v-if="!$isThisLocation(['public'])" :class="{'is-inactive': canShareInView }" source="share" :action="$t('actions.share')" />
|
||||
<ToolbarButton @click.native="deleteItem" :class="{'is-inactive': canDeleteInView }" source="trash" :action="$t('actions.delete')" />
|
||||
</ToolbarGroup>
|
||||
|
||||
<!--View Controls-->
|
||||
<ToolbarGroup>
|
||||
<PopoverWrapper>
|
||||
<ToolbarButton @click.stop.native="showSortingMenu" source="preview-sorting" :action="$t('actions.sorting_view')" />
|
||||
<PopoverItem name="desktop-sorting">
|
||||
<FileSortingOptions />
|
||||
</PopoverItem>
|
||||
</PopoverWrapper>
|
||||
<ToolbarButton @click.native="$store.dispatch('fileInfoToggle')" :class="{'active': isVisibleSidebar }" :action="$t('actions.info_panel')" source="info" />
|
||||
</ToolbarGroup>
|
||||
</ToolbarWrapper>
|
||||
</div>
|
||||
<UploadProgress/>
|
||||
|
||||
<UploadProgress />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ToolbarButtonUpload from '@/components/FilesView/ToolbarButtonUpload'
|
||||
import { ChevronLeftIcon, MoreHorizontalIcon } from 'vue-feather-icons'
|
||||
import UploadProgress from '@/components/FilesView/UploadProgress'
|
||||
import ToolbarButton from '@/components/FilesView/ToolbarButton'
|
||||
import SearchBar from '@/components/FilesView/SearchBar'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { events } from '@/bus'
|
||||
import { last } from 'lodash'
|
||||
import ToolbarButtonUpload from '@/components/FilesView/ToolbarButtonUpload'
|
||||
import FileSortingOptions from '@/components/FilesView/FileSortingOptions'
|
||||
import {ChevronLeftIcon, MoreHorizontalIcon} from 'vue-feather-icons'
|
||||
import UploadProgress from '@/components/FilesView/UploadProgress'
|
||||
import PopoverWrapper from '@/components/Desktop/PopoverWrapper'
|
||||
import ToolbarWrapper from '@/components/Desktop/ToolbarWrapper'
|
||||
import ToolbarButton from '@/components/FilesView/ToolbarButton'
|
||||
import ToolbarGroup from '@/components/Desktop/ToolbarGroup'
|
||||
import PopoverItem from '@/components/Desktop/PopoverItem'
|
||||
import SearchBar from '@/components/FilesView/SearchBar'
|
||||
import {debounce, last} from 'lodash'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'ToolBar',
|
||||
components: {
|
||||
ToolbarButtonUpload,
|
||||
MoreHorizontalIcon,
|
||||
ChevronLeftIcon,
|
||||
UploadProgress,
|
||||
ToolbarButton,
|
||||
SearchBar
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'FilePreviewType',
|
||||
'fileInfoVisible',
|
||||
'fileInfoDetail',
|
||||
'currentFolder',
|
||||
'browseHistory',
|
||||
'homeDirectory'
|
||||
]),
|
||||
hasCapacity() {
|
||||
// Check if set storage limitation
|
||||
if (!this.$store.getters.config.storageLimit) return true
|
||||
export default {
|
||||
name: 'ToolBar',
|
||||
components: {
|
||||
ToolbarButtonUpload,
|
||||
FileSortingOptions,
|
||||
MoreHorizontalIcon,
|
||||
ChevronLeftIcon,
|
||||
ToolbarWrapper,
|
||||
UploadProgress,
|
||||
PopoverWrapper,
|
||||
ToolbarButton,
|
||||
ToolbarGroup,
|
||||
PopoverItem,
|
||||
SearchBar,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'isVisibleSidebar',
|
||||
'FilePreviewType',
|
||||
'currentFolder',
|
||||
'browseHistory',
|
||||
'homeDirectory',
|
||||
'clipboard',
|
||||
]),
|
||||
hasCapacity() {
|
||||
// Check if storage limitation is set
|
||||
if (!this.$store.getters.config.storageLimit) return true
|
||||
|
||||
// Check if is loaded user
|
||||
if (!this.$store.getters.user) return true
|
||||
// Check if user is loaded
|
||||
if (!this.$store.getters.user) return true
|
||||
|
||||
// Check if user has storage
|
||||
return this.$store.getters.user.data.attributes.storage.used <= 100
|
||||
},
|
||||
directoryName() {
|
||||
return this.currentFolder
|
||||
? this.currentFolder.name
|
||||
: this.homeDirectory.name
|
||||
},
|
||||
preview() {
|
||||
return this.FilePreviewType === 'list' ? 'th' : 'th-list'
|
||||
},
|
||||
canCreateFolderInView() {
|
||||
return !this.$isThisLocation(['base', 'public'])
|
||||
},
|
||||
canDeleteInView() {
|
||||
let locations = [
|
||||
'trash',
|
||||
'trash-root',
|
||||
'base',
|
||||
'participant_uploads',
|
||||
'latest',
|
||||
'shared',
|
||||
'public'
|
||||
]
|
||||
return !this.$isThisLocation(locations) || this.fileInfoDetail.length === 0
|
||||
},
|
||||
canUploadInView() {
|
||||
return !this.$isThisLocation(['base', 'public'])
|
||||
},
|
||||
canMoveInView() {
|
||||
let locations = [
|
||||
'base',
|
||||
'participant_uploads',
|
||||
'latest',
|
||||
'shared',
|
||||
'public'
|
||||
]
|
||||
return !this.$isThisLocation(locations) || this.fileInfoDetail.length === 0
|
||||
// Check if user has storage
|
||||
return this.$store.getters.user.data.attributes.storage.used <= 100
|
||||
},
|
||||
directoryName() {
|
||||
return this.currentFolder
|
||||
? this.currentFolder.name
|
||||
: this.homeDirectory.name
|
||||
},
|
||||
preview() {
|
||||
return this.FilePreviewType === 'list'
|
||||
? 'th'
|
||||
: 'th-list'
|
||||
},
|
||||
canCreateFolderInView() {
|
||||
return !this.$isThisLocation(['base', 'public'])
|
||||
},
|
||||
canDeleteInView() {
|
||||
let locations = [
|
||||
'participant_uploads',
|
||||
'trash-root',
|
||||
'latest',
|
||||
'shared',
|
||||
'public',
|
||||
'trash',
|
||||
'base',
|
||||
]
|
||||
return !this.$isThisLocation(locations) || this.clipboard.length === 0
|
||||
},
|
||||
canUploadInView() {
|
||||
return !this.$isThisLocation(['base', 'public'])
|
||||
},
|
||||
canMoveInView() {
|
||||
let locations = [
|
||||
'participant_uploads',
|
||||
'latest',
|
||||
'shared',
|
||||
'public',
|
||||
'base',
|
||||
]
|
||||
return !this.$isThisLocation(locations) || this.clipboard.length === 0
|
||||
},
|
||||
canShareInView() {
|
||||
let locations = [
|
||||
'participant_uploads',
|
||||
'latest',
|
||||
'shared',
|
||||
'public',
|
||||
'base',
|
||||
]
|
||||
return !this.$isThisLocation(locations) || this.clipboard.length > 1 || this.clipboard.length === 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
query: '',
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
query(val) {
|
||||
this.$searchFiles(val)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showSortingMenu() {
|
||||
events.$emit('popover:open', 'desktop-sorting')
|
||||
},
|
||||
goBack() {
|
||||
let previousFolder = last(this.browseHistory)
|
||||
|
||||
},
|
||||
canShareInView() {
|
||||
let locations = [
|
||||
'base',
|
||||
'participant_uploads',
|
||||
'latest',
|
||||
'shared',
|
||||
'public'
|
||||
]
|
||||
if (!previousFolder) return
|
||||
|
||||
return !this.$isThisLocation(locations) || this.fileInfoDetail.length > 1 || this.fileInfoDetail.length === 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
sortingAndPreview: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
sortingAndPreview() {
|
||||
if (this.sortingAndPreview) {
|
||||
events.$emit('sortingAndPreview', true)
|
||||
}
|
||||
if (previousFolder.location === 'trash-root') {
|
||||
this.$store.dispatch('getTrash')
|
||||
|
||||
if (!this.sortingAndPreview) {
|
||||
events.$emit('unClick')
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
// Get previous folder
|
||||
let previousFolder = last(this.browseHistory)
|
||||
} else if (previousFolder.location === 'shared') {
|
||||
this.$store.dispatch('getShared')
|
||||
|
||||
if (!previousFolder) return
|
||||
} else {
|
||||
if (this.$isThisLocation('public')) {
|
||||
this.$store.dispatch('browseShared', [
|
||||
{folder: previousFolder, back: true, init: false}
|
||||
])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [
|
||||
{folder: previousFolder, back: true, init: false}
|
||||
])
|
||||
}
|
||||
}
|
||||
},
|
||||
folderActions() {
|
||||
events.$emit('folder:actions', this.currentFolder)
|
||||
},
|
||||
deleteItem() {
|
||||
if (this.clipboard.length > 0)
|
||||
this.$store.dispatch('deleteItem')
|
||||
},
|
||||
createFolder() {
|
||||
this.$store.dispatch('createFolder', {name: this.$t('popup_create_folder.folder_default_name')})
|
||||
},
|
||||
moveItem() {
|
||||
if (this.clipboard.length > 0)
|
||||
events.$emit('popup:open', {name: 'move', item: this.clipboard})
|
||||
},
|
||||
shareItem() {
|
||||
let event = this.clipboard[0].shared
|
||||
? 'share-edit'
|
||||
: 'share-create'
|
||||
|
||||
if (previousFolder.location === 'trash-root') {
|
||||
this.$store.dispatch('getTrash')
|
||||
} else if (previousFolder.location === 'shared') {
|
||||
this.$store.dispatch('getShared')
|
||||
} else {
|
||||
if (this.$isThisLocation('public')) {
|
||||
this.$store.dispatch('browseShared', [
|
||||
{ folder: previousFolder, back: true, init: false }
|
||||
])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [
|
||||
{ folder: previousFolder, back: true, init: false }
|
||||
])
|
||||
}
|
||||
}
|
||||
},
|
||||
folderActions() {
|
||||
events.$emit('folder:actions', this.currentFolder)
|
||||
},
|
||||
deleteItem() {
|
||||
if (this.fileInfoDetail.length > 0)
|
||||
this.$store.dispatch('deleteItem')
|
||||
},
|
||||
createFolder() {
|
||||
this.$store.dispatch('createFolder', {name: this.$t('popup_create_folder.folder_default_name')})
|
||||
},
|
||||
moveItem() {
|
||||
if (this.fileInfoDetail.length > 0)
|
||||
events.$emit('popup:open', { name: 'move', item: this.fileInfoDetail })
|
||||
},
|
||||
shareItem() {
|
||||
if (this.fileInfoDetail[0]) {
|
||||
//ADD BY M
|
||||
if (this.fileInfoDetail[0].shared) {
|
||||
events.$emit('popup:open', {
|
||||
name: 'share-edit',
|
||||
item: this.fileInfoDetail[0]
|
||||
})
|
||||
} else {
|
||||
events.$emit('popup:open', {
|
||||
name: 'share-create',
|
||||
item: this.fileInfoDetail[0]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// events.$on('sortingAndPreview', (state) => {
|
||||
// this.sortingAndPreview = state
|
||||
// })
|
||||
|
||||
events.$on('unClick', () => {
|
||||
this.sortingAndPreview = false
|
||||
})
|
||||
}
|
||||
}
|
||||
events.$emit('popup:open', {
|
||||
name: event,
|
||||
item: this.clipboard[0]
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/vuefilemanager/_variables";
|
||||
@import "@assets/vuefilemanager/_mixins";
|
||||
|
||||
.preview-sorting {
|
||||
/deep/ .label {
|
||||
color: $text !important;
|
||||
}
|
||||
.is-inactive {
|
||||
opacity: 0.25;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.toolbar-wrapper {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
> div {
|
||||
flex-grow: 1;
|
||||
align-self: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.directory-name {
|
||||
vertical-align: middle;
|
||||
@include font-size(17);
|
||||
color: $text;
|
||||
font-weight: 700;
|
||||
max-width: 220px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
}
|
||||
.location {
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
|
||||
.icon-back {
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
margin-right: 6px;
|
||||
opacity: 0.15;
|
||||
pointer-events: none;
|
||||
@include transition(150ms);
|
||||
.icon-back {
|
||||
@include transition(150ms);
|
||||
pointer-events: none;
|
||||
margin-right: 6px;
|
||||
flex-shrink: 0;
|
||||
opacity: 0.15;
|
||||
|
||||
&.is-active {
|
||||
opacity: 1;
|
||||
pointer-events: initial;
|
||||
}
|
||||
}
|
||||
&.is-active {
|
||||
opacity: 1;
|
||||
pointer-events: initial;
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar-go-back {
|
||||
cursor: pointer;
|
||||
.location-title {
|
||||
@include font-size(15);
|
||||
line-height: 1;
|
||||
font-weight: 700;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: $text;
|
||||
}
|
||||
|
||||
.folder-options {
|
||||
vertical-align: middle;
|
||||
margin-left: 6px;
|
||||
padding: 1px 4px;
|
||||
line-height: 0;
|
||||
border-radius: 3px;
|
||||
@include transition(150ms);
|
||||
.location-more {
|
||||
margin-left: 6px;
|
||||
padding: 1px 4px;
|
||||
line-height: 0;
|
||||
border-radius: 3px;
|
||||
@include transition(150ms);
|
||||
|
||||
svg circle {
|
||||
@include transition(150ms);
|
||||
}
|
||||
svg circle {
|
||||
@include transition(150ms);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $light_background;
|
||||
&:hover {
|
||||
background: $light_background;
|
||||
|
||||
svg circle {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-more {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.back-directory-title {
|
||||
@include font-size(15);
|
||||
line-height: 1;
|
||||
font-weight: 700;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
color: $text;
|
||||
}
|
||||
svg circle {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar-position {
|
||||
text-align: center;
|
||||
text-align: center;
|
||||
|
||||
span {
|
||||
@include font-size(17);
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar-tools {
|
||||
text-align: right;
|
||||
|
||||
.toolbar-button-wrapper {
|
||||
margin-left: 28px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
&:first-child {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
margin-left: 5px;
|
||||
|
||||
&.active {
|
||||
|
||||
&.preview-sorting {
|
||||
background: $light_background;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-inactive {
|
||||
opacity: 0.25;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
span {
|
||||
@include font-size(17);
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1024px) {
|
||||
.toolbar-go-back .back-directory-title {
|
||||
max-width: 120px;
|
||||
}
|
||||
.location {
|
||||
|
||||
.toolbar-tools {
|
||||
.button {
|
||||
margin-left: 0;
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
}
|
||||
.location-title {
|
||||
max-width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar-button-wrapper {
|
||||
margin-left: 25px;
|
||||
}
|
||||
}
|
||||
.toolbar-tools {
|
||||
.button {
|
||||
margin-left: 0;
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
#desktop-toolbar {
|
||||
display: none;
|
||||
}
|
||||
#desktop-toolbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.toolbar .directory-name {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
.toolbar .directory-name {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
|
||||
.toolbar-go-back {
|
||||
.back-directory-title {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
.toolbar-go-back {
|
||||
.location-title {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
|
||||
.folder-options {
|
||||
&:hover {
|
||||
background: $dark_mode_foreground;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.active {
|
||||
&.preview-sorting {
|
||||
background: $dark_mode_foreground !important;
|
||||
}
|
||||
}
|
||||
.location-more {
|
||||
&:hover {
|
||||
background: $dark_mode_foreground;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,20 +1,30 @@
|
||||
<template>
|
||||
<MultiSelected :title="title" :subtitle="subtitle" id="multi-select-ui" v-show="isVisible"/>
|
||||
<TitlePreview
|
||||
icon="check-square"
|
||||
:title="title"
|
||||
:subtitle="subtitle"
|
||||
id="drag-ui"
|
||||
v-show="isVisible"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MultiSelected from '@/components/FilesView/MultiSelected'
|
||||
import TitlePreview from '@/components/FilesView/TitlePreview'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { events } from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'DragUI',
|
||||
components: { MultiSelected },
|
||||
components: {
|
||||
TitlePreview
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['fileInfoDetail']),
|
||||
...mapGetters([
|
||||
'clipboard'
|
||||
]),
|
||||
title() {
|
||||
let filesLength = this.fileInfoDetail.length,
|
||||
hasDraggedItem = this.fileInfoDetail.includes(this.draggedItem)
|
||||
let filesLength = this.clipboard.length,
|
||||
hasDraggedItem = this.clipboard.includes(this.draggedItem)
|
||||
|
||||
// Title for multiple selected items
|
||||
if (filesLength > 1 && hasDraggedItem) {
|
||||
@@ -27,8 +37,8 @@ export default {
|
||||
}
|
||||
},
|
||||
subtitle() {
|
||||
let filesLength = this.fileInfoDetail.length,
|
||||
hasDraggedItem = this.fileInfoDetail.includes(this.draggedItem)
|
||||
let filesLength = this.clipboard.length,
|
||||
hasDraggedItem = this.clipboard.includes(this.draggedItem)
|
||||
|
||||
// Subtitle for multiple selected items
|
||||
if (filesLength > 1 && hasDraggedItem) {
|
||||
@@ -56,7 +66,6 @@ export default {
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// Handle Drag & Drop Ghost show
|
||||
events.$on('dragstart', data => {
|
||||
this.draggedItem = data
|
||||
|
||||
@@ -65,9 +74,7 @@ export default {
|
||||
}, 100)
|
||||
})
|
||||
|
||||
events.$on('drop', () => {
|
||||
this.isVisible = false
|
||||
})
|
||||
events.$on('drop', () => this.isVisible = false)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -76,7 +83,7 @@ export default {
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
#multi-select-ui {
|
||||
#drag-ui {
|
||||
max-width: 300px;
|
||||
min-width: 250px;
|
||||
position: fixed;
|
||||
@@ -89,7 +96,7 @@ export default {
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
#multi-select-ui {
|
||||
#drag-ui {
|
||||
background: $dark_mode_foreground;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<div class="empty-page" v-if="isLoading || isEmpty">
|
||||
<div class="empty-state">
|
||||
|
||||
<!--Shared empty message-->
|
||||
<div class="text-content" v-if="$isThisLocation(['shared']) && ! isLoading">
|
||||
<h1 class="title">{{ $t('shared.empty_shared') }}</h1>
|
||||
</div>
|
||||
|
||||
<!--Trash empty message-->
|
||||
<div class="text-content" v-if="$isThisLocation(['trash', 'trash-root']) && ! isLoading">
|
||||
<h1 class="title">{{ $t('empty_page.title') }}</h1>
|
||||
</div>
|
||||
|
||||
<!--Trash empty message-->
|
||||
<div class="text-content" v-if="$isThisLocation(['participant_uploads']) && ! isLoading">
|
||||
<h1 class="title">{{ $t('messages.nothing_from_participants') }}</h1>
|
||||
</div>
|
||||
|
||||
<!--Base file browser empty message-->
|
||||
<div class="text-content" v-if="$isThisLocation(['base', 'public', 'latest']) && !isLoading">
|
||||
<h1 class="title">{{ $t('empty_page.title') }}</h1>
|
||||
<p v-if="$checkPermission(['master', 'editor'])" class="description">{{ $t('empty_page.description') }}</p>
|
||||
<ButtonUpload
|
||||
v-if="$checkPermission(['master', 'editor'])"
|
||||
button-style="theme"
|
||||
>
|
||||
{{ $t('empty_page.call_to_action') }}
|
||||
</ButtonUpload>
|
||||
</div>
|
||||
|
||||
<!--Spinner-->
|
||||
<div class="text-content" v-if="isLoading">
|
||||
<Spinner />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ButtonUpload from '@/components/FilesView/ButtonUpload'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
import {mapGetters} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'EmptyFilePage',
|
||||
props: [
|
||||
'title',
|
||||
'description'
|
||||
],
|
||||
components: {
|
||||
ButtonUpload,
|
||||
Spinner,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'currentFolder',
|
||||
'isLoading',
|
||||
'entries',
|
||||
]),
|
||||
isEmpty() {
|
||||
return this.entries && this.entries.length == 0
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.empty-page {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
margin-top: 85px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.empty-state {
|
||||
margin: 0 auto;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.text-content {
|
||||
text-align: center;
|
||||
margin: 30px 0;
|
||||
|
||||
.title {
|
||||
@include font-size(20);
|
||||
color: $text;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.description {
|
||||
@include font-size(13);
|
||||
color: $text-muted;
|
||||
margin-bottom: 20px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.text-content {
|
||||
|
||||
.title {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
|
||||
.description {
|
||||
color: $dark_mode_text_secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,113 +0,0 @@
|
||||
<template>
|
||||
<div class="empty-page" v-if="isLoading || isEmpty">
|
||||
<div class="empty-state">
|
||||
|
||||
<!--Shared empty message-->
|
||||
<div class="text-content" v-if="$isThisLocation(['shared']) && ! isLoading">
|
||||
<h1 class="title">{{ $t('shared.empty_shared') }}</h1>
|
||||
</div>
|
||||
|
||||
<!--Trash empty message-->
|
||||
<div class="text-content" v-if="$isThisLocation(['trash', 'trash-root']) && ! isLoading">
|
||||
<h1 class="title">{{ $t('empty_page.title') }}</h1>
|
||||
</div>
|
||||
|
||||
<!--Trash empty message-->
|
||||
<div class="text-content" v-if="$isThisLocation(['participant_uploads']) && ! isLoading">
|
||||
<h1 class="title">{{ $t('messages.nothing_from_participants') }}</h1>
|
||||
</div>
|
||||
|
||||
<!--Base file browser empty message-->
|
||||
<div class="text-content" v-if="$isThisLocation(['base', 'public', 'latest']) && !isLoading">
|
||||
<h1 class="title">{{ $t('empty_page.title') }}</h1>
|
||||
<p v-if="$checkPermission(['master', 'editor'])" class="description">{{ $t('empty_page.description') }}</p>
|
||||
<ButtonUpload
|
||||
v-if="$checkPermission(['master', 'editor'])"
|
||||
button-style="theme"
|
||||
>
|
||||
{{ $t('empty_page.call_to_action') }}
|
||||
</ButtonUpload>
|
||||
</div>
|
||||
|
||||
<!--Spinner-->
|
||||
<div class="text-content" v-if="isLoading">
|
||||
<Spinner/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ButtonUpload from '@/components/FilesView/ButtonUpload'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
import {mapGetters} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'EmptyPage',
|
||||
props: ['title', 'description'],
|
||||
components: {
|
||||
ButtonUpload,
|
||||
Spinner
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['data', 'isLoading', 'currentFolder']),
|
||||
isEmpty() {
|
||||
return this.data && this.data.length == 0
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.empty-page {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
margin-top: 85px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.empty-state {
|
||||
margin: 0 auto;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.text-content {
|
||||
text-align: center;
|
||||
margin: 30px 0;
|
||||
|
||||
.title {
|
||||
@include font-size(20);
|
||||
color: $text;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.description {
|
||||
@include font-size(13);
|
||||
color: $text-muted;
|
||||
margin-bottom: 20px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.text-content {
|
||||
|
||||
.title {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
|
||||
.description {
|
||||
color: $dark_mode_text_secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,236 @@
|
||||
<template>
|
||||
<div id="mobile-actions-wrapper">
|
||||
|
||||
<!--Base location-->
|
||||
<div v-if="$isThisLocation(['base']) && $checkPermission(['master', 'editor']) && ! isSelectMode" class="mobile-actions">
|
||||
<MobileActionButton @click.native="showLocations" icon="filter">
|
||||
{{ filterLocationTitle }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="createFolder" icon="folder-plus">
|
||||
{{ $t('context_menu.add_folder') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButtonUpload>
|
||||
{{ $t('context_menu.upload') }}
|
||||
</MobileActionButtonUpload>
|
||||
<MobileActionButton @click.native="enableMultiSelectMode" icon="check-square">
|
||||
{{ $t('context_menu.select') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="showViewOptions" icon="preview-sorting">
|
||||
{{ $t('preview_sorting.preview_sorting_button') }}
|
||||
</MobileActionButton>
|
||||
</div>
|
||||
|
||||
<!--Base location editor-->
|
||||
<div v-if="$isThisLocation('public') && $checkPermission('editor') && ! isSelectMode" class="mobile-actions">
|
||||
<MobileActionButton @click.native="createFolder" icon="folder-plus">
|
||||
{{ $t('context_menu.add_folder') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButtonUpload>
|
||||
{{ $t('context_menu.upload') }}
|
||||
</MobileActionButtonUpload>
|
||||
<MobileActionButton @click.native="enableMultiSelectMode" icon="check-square">
|
||||
{{ $t('context_menu.select') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="showViewOptions" icon="preview-sorting">
|
||||
{{ $t('preview_sorting.preview_sorting_button') }}
|
||||
</MobileActionButton>
|
||||
</div>
|
||||
|
||||
<!--Base location visitor-->
|
||||
<div v-if="$isThisLocation('public') && $checkPermission('visitor') && ! isSelectMode" class="mobile-actions">
|
||||
<MobileActionButton @click.native="enableMultiSelectMode" icon="check-square">
|
||||
{{ $t('context_menu.select') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="showViewOptions" icon="preview-sorting">
|
||||
{{ $t('preview_sorting.preview_sorting_button') }}
|
||||
</MobileActionButton>
|
||||
</div>
|
||||
|
||||
<!--Recent uploads location-->
|
||||
<div v-if="$isThisLocation('latest') && ! isSelectMode" class="mobile-actions">
|
||||
<MobileActionButton @click.native="showLocations" icon="filter">
|
||||
{{ filterLocationTitle }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButtonUpload>
|
||||
{{ $t('context_menu.upload') }}
|
||||
</MobileActionButtonUpload>
|
||||
<MobileActionButton @click.native="enableMultiSelectMode" icon="check-square">
|
||||
{{ $t('context_menu.select') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="showViewOptions" icon="preview-sorting">
|
||||
{{ $t('preview_sorting.preview_sorting_button') }}
|
||||
</MobileActionButton>
|
||||
</div>
|
||||
|
||||
<!--Trash location--->
|
||||
<div v-if="$isThisLocation(['trash', 'trash-root']) && ! isSelectMode" class="mobile-actions">
|
||||
<MobileActionButton @click.native="showLocations" icon="filter">
|
||||
{{ filterLocationTitle }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="$store.dispatch('emptyTrash')" icon="trash">
|
||||
{{ $t('context_menu.empty_trash') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="enableMultiSelectMode" icon="check-square">
|
||||
{{ $t('context_menu.select') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="showViewOptions" icon="preview-sorting">
|
||||
{{ $t('preview_sorting.preview_sorting_button') }}
|
||||
</MobileActionButton>
|
||||
</div>
|
||||
|
||||
<!--Shared location--->
|
||||
<div v-if="$isThisLocation(['shared', 'participant_uploads']) && ! isSelectMode" class="mobile-actions">
|
||||
<MobileActionButton @click.native="showLocations" icon="filter">
|
||||
{{ filterLocationTitle }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="enableMultiSelectMode" icon="check-square">
|
||||
{{ $t('context_menu.select') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="showViewOptions" icon="preview-sorting">
|
||||
{{ $t('preview_sorting.preview_sorting_button') }}
|
||||
</MobileActionButton>
|
||||
</div>
|
||||
|
||||
<!-- Multi select mode -->
|
||||
<div v-if="isSelectMode" class="mobile-actions">
|
||||
<MobileActionButton @click.native="selectAll" icon="check-square">
|
||||
{{ $t('mobile_selecting.select_all') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="deselectAll" icon="x-square">
|
||||
{{ $t('mobile_selecting.deselect_all') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="disableMultiSelectMode" icon="check">
|
||||
{{ $t('mobile_selecting.done') }}
|
||||
</MobileActionButton>
|
||||
</div>
|
||||
|
||||
<!--Upload Progressbar-->
|
||||
<UploadProgress />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MobileActionButtonUpload from '@/components/FilesView/MobileActionButtonUpload'
|
||||
import MobileActionButton from '@/components/FilesView/MobileActionButton'
|
||||
import UploadProgress from '@/components/FilesView/UploadProgress'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
import store from "../../store";
|
||||
|
||||
export default {
|
||||
name: 'FileActionsMobile',
|
||||
components: {
|
||||
MobileActionButtonUpload,
|
||||
MobileActionButton,
|
||||
UploadProgress,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'FilePreviewType'
|
||||
]),
|
||||
previewIcon() {
|
||||
return this.FilePreviewType === 'list'
|
||||
? 'th'
|
||||
: 'th-list'
|
||||
},
|
||||
filterLocationTitle() {
|
||||
return {
|
||||
'base': 'Files',
|
||||
'public': 'Files',
|
||||
'shared': 'Shared',
|
||||
'latest': 'Latest',
|
||||
'trash': 'Trash',
|
||||
'trash-root': 'Trash',
|
||||
'participant_uploads': 'Participants',
|
||||
}[this.$store.getters.currentFolder.location]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isSelectMode: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showLocations() {
|
||||
events.$emit('mobile-menu:show', 'file-filter')
|
||||
},
|
||||
selectAll() {
|
||||
this.$store.commit('ADD_ALL_ITEMS_TO_CLIPBOARD')
|
||||
},
|
||||
deselectAll() {
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
},
|
||||
enableMultiSelectMode() {
|
||||
this.isSelectMode = true
|
||||
|
||||
events.$emit('mobileSelecting:start')
|
||||
},
|
||||
disableMultiSelectMode() {
|
||||
this.isSelectMode = false
|
||||
|
||||
events.$emit('mobileSelecting:stop')
|
||||
},
|
||||
showViewOptions() {
|
||||
events.$emit('mobile-menu:show', 'file-sorting')
|
||||
},
|
||||
createFolder() {
|
||||
events.$emit('popup:open', {name: 'create-folder'})
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
events.$on('mobileSelecting:stop', () => this.isSelectMode = false)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.button-enter-active,
|
||||
.button-leave-active {
|
||||
transition: all 250ms;
|
||||
}
|
||||
|
||||
.button-enter {
|
||||
opacity: 0;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.button-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(50%);
|
||||
}
|
||||
|
||||
.button-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#mobile-actions-wrapper {
|
||||
display: none;
|
||||
background: white;
|
||||
position: sticky;
|
||||
top: 35px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.mobile-actions {
|
||||
white-space: nowrap;
|
||||
overflow-x: auto;
|
||||
margin: 0 -15px;
|
||||
padding: 10px 0 10px 15px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
|
||||
#mobile-actions-wrapper {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
#mobile-actions-wrapper {
|
||||
background: $dark_mode_background;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,442 +1,439 @@
|
||||
<template>
|
||||
<div class="file-content" id="file-content-id" :class="{ 'is-offset': filesInQueueTotal > 0, 'is-dragging': isDragging }"
|
||||
@dragover.prevent
|
||||
@drop.stop.prevent="dropUpload($event)"
|
||||
@dragover="dragEnter"
|
||||
@dragleave="dragLeave"
|
||||
@keydown.delete="deleteItems"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
:class="{'is-offset': filesInQueueTotal > 0, 'is-dragging': isDragging }"
|
||||
class="file-content"
|
||||
id="file-content-id"
|
||||
@drop.stop.prevent="dropUpload($event)"
|
||||
@keydown.delete="deleteItems"
|
||||
@dragover="dragEnter"
|
||||
@dragleave="dragLeave"
|
||||
@dragover.prevent
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="files-container"
|
||||
ref="fileContainer"
|
||||
:class="{'is-fileinfo-visible': fileInfoVisible && !$isMinimalScale() , 'mobile-multi-select' : mobileMultiSelect}"
|
||||
@click.self="filesContainerClick"
|
||||
>
|
||||
<!--MobileToolbar-->
|
||||
:class="{'is-visible': isVisibleSidebar, 'mobile-multi-select': isMultiSelect}"
|
||||
@click.self="filesContainerClick"
|
||||
class="files-container"
|
||||
ref="fileContainer"
|
||||
>
|
||||
<MobileToolbar />
|
||||
|
||||
<!--Searchbar-->
|
||||
<SearchBar class="mobile-search" />
|
||||
<SearchBar v-model="query" @reset-query="query = ''" class="mobile-search" :placeholder="$t('inputs.placeholder_search_files')" />
|
||||
|
||||
<!--Mobile Actions-->
|
||||
<MobileActions />
|
||||
<!--Mobile Actions-->
|
||||
<FileActionsMobile />
|
||||
|
||||
<!--Item previews list-->
|
||||
<!--Item previews list-->
|
||||
<div v-if="isList" class="file-list-wrapper">
|
||||
<transition-group
|
||||
name="file"
|
||||
tag="section"
|
||||
class="file-list"
|
||||
:class="FilePreviewType"
|
||||
>
|
||||
name="file"
|
||||
tag="section"
|
||||
class="file-list"
|
||||
:class="FilePreviewType"
|
||||
>
|
||||
<FileItemList
|
||||
@dragstart="dragStart(item)"
|
||||
@drop.stop.native.prevent="dragFinish(item, $event)"
|
||||
@contextmenu.native.prevent="contextMenu($event, item)"
|
||||
:item="item"
|
||||
v-for="item in data"
|
||||
:key="item.id"
|
||||
class="file-item"
|
||||
:class="draggedItems.includes(item) ? 'dragged' : '' "
|
||||
/>
|
||||
@dragstart="dragStart(item)"
|
||||
@drop.stop.native.prevent="dragFinish(item, $event)"
|
||||
@contextmenu.native.prevent="contextMenu($event, item)"
|
||||
:item="item"
|
||||
v-for="item in entries"
|
||||
:key="item.id"
|
||||
class="file-item"
|
||||
:class="draggedItems.includes(item) ? 'dragged' : '' "
|
||||
/>
|
||||
</transition-group>
|
||||
</div>
|
||||
|
||||
<!--Item previews grid-->
|
||||
<!--Item previews grid-->
|
||||
<div v-if="isGrid" class="file-grid-wrapper">
|
||||
<transition-group
|
||||
name="file"
|
||||
tag="section"
|
||||
class="file-list"
|
||||
:class="FilePreviewType"
|
||||
>
|
||||
name="file"
|
||||
tag="section"
|
||||
class="file-list"
|
||||
:class="FilePreviewType"
|
||||
>
|
||||
<FileItemGrid
|
||||
@dragstart="dragStart(item)"
|
||||
@drop.native.prevent="dragFinish(item, $event)"
|
||||
@contextmenu.native.prevent="contextMenu($event, item)"
|
||||
:item="item"
|
||||
v-for="item in data"
|
||||
:key="item.id"
|
||||
class="file-item"
|
||||
:class="draggedItems.includes(item) ? 'dragged' : '' "
|
||||
/>
|
||||
@dragstart="dragStart(item)"
|
||||
@drop.native.prevent="dragFinish(item, $event)"
|
||||
@contextmenu.native.prevent="contextMenu($event, item)"
|
||||
:item="item"
|
||||
v-for="item in entries"
|
||||
:key="item.id"
|
||||
class="file-item"
|
||||
:class="draggedItems.includes(item) ? 'dragged' : '' "
|
||||
/>
|
||||
</transition-group>
|
||||
</div>
|
||||
|
||||
<!--Show empty page if folder is empty-->
|
||||
<EmptyPage v-if="! isSearching" />
|
||||
<!--Show empty page if folder is empty-->
|
||||
<EmptyFilePage v-if="! isSearching" />
|
||||
|
||||
<!--Show empty page if no search results-->
|
||||
<!--Show empty page if no search results-->
|
||||
<EmptyMessage
|
||||
v-if="isSearching && isEmpty"
|
||||
:message="$t('messages.nothing_was_found')"
|
||||
icon="eye-slash"
|
||||
/>
|
||||
v-if="isSearching && isEmpty"
|
||||
:message="$t('messages.nothing_was_found')"
|
||||
icon="eye-slash"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!--File Info Panel-->
|
||||
<div v-if="! $isMinimalScale()" class="file-info-container" :class="{ 'is-fileinfo-visible': fileInfoVisible }">
|
||||
<!--File info panel-->
|
||||
<FileInfoPanel v-if="fileInfoDetail.length === 1" />
|
||||
|
||||
<MultiSelected v-if="fileInfoDetail.length > 1"
|
||||
:title="$t('file_detail.selected_multiple')"
|
||||
:subtitle="this.fileInfoDetail.length + ' ' + $tc('file_detail.items', this.fileInfoDetail.length)"
|
||||
/>
|
||||
|
||||
<!--If file info panel empty show message-->
|
||||
<EmptyMessage v-if="fileInfoDetail.length === 0" :message="$t('messages.nothing_to_preview')" icon="eye-off" />
|
||||
<!--File Info Panel-->
|
||||
<div :class="{'is-visible': isVisibleSidebar }" class="file-info-container">
|
||||
<InfoSidebar />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MobileToolbar from '@/components/FilesView/MobileToolbar'
|
||||
import MobileActions from '@/components/FilesView/MobileActions'
|
||||
import MultiSelected from '@/components/FilesView/MultiSelected'
|
||||
import FileInfoPanel from '@/components/FilesView/FileInfoPanel'
|
||||
import FileItemList from '@/components/FilesView/FileItemList'
|
||||
import FileItemGrid from '@/components/FilesView/FileItemGrid'
|
||||
import EmptyMessage from '@/components/FilesView/EmptyMessage'
|
||||
import EmptyPage from '@/components/FilesView/EmptyPage'
|
||||
import SearchBar from '@/components/FilesView/SearchBar'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
import FileActionsMobile from '@/components/FilesView/FileActionsMobile'
|
||||
import MobileToolbar from '@/components/FilesView/MobileToolbar'
|
||||
import EmptyFilePage from '@/components/FilesView/EmptyFilePage'
|
||||
import EmptyMessage from '@/components/FilesView/EmptyMessage'
|
||||
import FileItemList from '@/components/FilesView/FileItemList'
|
||||
import FileItemGrid from '@/components/FilesView/FileItemGrid'
|
||||
import InfoSidebar from '@/components/FilesView/InfoSidebar'
|
||||
import SearchBar from '@/components/FilesView/SearchBar'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
import {debounce} from "lodash";
|
||||
|
||||
export default {
|
||||
name: 'FilesContainer',
|
||||
components: {
|
||||
MobileToolbar,
|
||||
MobileActions,
|
||||
MultiSelected,
|
||||
FileInfoPanel,
|
||||
FileItemList,
|
||||
FileItemGrid,
|
||||
EmptyMessage,
|
||||
SearchBar,
|
||||
EmptyPage
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'filesInQueueTotal',
|
||||
'fileInfoVisible',
|
||||
'fileInfoDetail',
|
||||
'currentFolder',
|
||||
'FilePreviewType',
|
||||
'isSearching',
|
||||
'isLoading',
|
||||
'data'
|
||||
]),
|
||||
isGrid() {
|
||||
return this.FilePreviewType === 'grid'
|
||||
},
|
||||
isList() {
|
||||
return this.FilePreviewType === 'list'
|
||||
},
|
||||
isEmpty() {
|
||||
return this.data.length == 0
|
||||
},
|
||||
draggedItems() {
|
||||
//Set opacity for dragged items
|
||||
export default {
|
||||
name: 'FilesContainer',
|
||||
components: {
|
||||
FileActionsMobile,
|
||||
EmptyFilePage,
|
||||
MobileToolbar,
|
||||
FileItemList,
|
||||
FileItemGrid,
|
||||
EmptyMessage,
|
||||
InfoSidebar,
|
||||
SearchBar,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'filesInQueueTotal',
|
||||
'isVisibleSidebar',
|
||||
'FilePreviewType',
|
||||
'currentFolder',
|
||||
'isSearching',
|
||||
'clipboard',
|
||||
'isLoading',
|
||||
'entries'
|
||||
]),
|
||||
isGrid() {
|
||||
return this.FilePreviewType === 'grid'
|
||||
},
|
||||
isList() {
|
||||
return this.FilePreviewType === 'list'
|
||||
},
|
||||
isEmpty() {
|
||||
return this.entries.length == 0
|
||||
},
|
||||
draggedItems() {
|
||||
//Set opacity for dragged items
|
||||
|
||||
if (!this.fileInfoDetail.includes(this.draggingId)) {
|
||||
return [this.draggingId]
|
||||
}
|
||||
if (!this.clipboard.includes(this.draggingId)) {
|
||||
return [this.draggingId]
|
||||
}
|
||||
|
||||
if (this.fileInfoDetail.includes(this.draggingId)) {
|
||||
return this.fileInfoDetail
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
draggingId: undefined,
|
||||
isDragging: false,
|
||||
mobileMultiSelect: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
deleteItems() {
|
||||
if (this.fileInfoDetail.length > 0 && this.$checkPermission('master') || this.$checkPermission('editor')) {
|
||||
this.$store.dispatch('deleteItem')
|
||||
}
|
||||
},
|
||||
dropUpload(event) {
|
||||
// Upload external file
|
||||
this.$uploadExternalFiles(event, this.currentFolder.id)
|
||||
if (this.clipboard.includes(this.draggingId)) {
|
||||
return this.clipboard
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
query(val) {
|
||||
this.$searchFiles(val)
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
draggingId: undefined,
|
||||
isDragging: false,
|
||||
isMultiSelect: false,
|
||||
query: '',
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
deleteItems() {
|
||||
if (this.clipboard.length > 0 && this.$checkPermission('master') || this.$checkPermission('editor')) {
|
||||
this.$store.dispatch('deleteItem')
|
||||
}
|
||||
},
|
||||
dropUpload(event) {
|
||||
// Upload external file
|
||||
this.$uploadExternalFiles(event, this.currentFolder.id)
|
||||
|
||||
this.isDragging = false
|
||||
},
|
||||
dragEnter() {
|
||||
this.isDragging = true
|
||||
},
|
||||
dragLeave() {
|
||||
this.isDragging = false
|
||||
},
|
||||
dragStart(data) {
|
||||
let img = document.createElement('img')
|
||||
img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
|
||||
event.dataTransfer.setDragImage(img, 0, 0)
|
||||
this.isDragging = false
|
||||
},
|
||||
dragEnter() {
|
||||
this.isDragging = true
|
||||
},
|
||||
dragLeave() {
|
||||
this.isDragging = false
|
||||
},
|
||||
dragStart(data) {
|
||||
let img = document.createElement('img')
|
||||
img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
|
||||
event.dataTransfer.setDragImage(img, 0, 0)
|
||||
|
||||
events.$emit('dragstart', data)
|
||||
events.$emit('dragstart', data)
|
||||
|
||||
// Store dragged folder
|
||||
this.draggingId = data
|
||||
},
|
||||
dragFinish(data, event) {
|
||||
// Store dragged folder
|
||||
this.draggingId = data
|
||||
},
|
||||
dragFinish(data, event) {
|
||||
|
||||
if (event.dataTransfer.items.length == 0) {
|
||||
// Prevent to drop on file or image
|
||||
if (data.type !== 'folder' || this.draggingId === data) return
|
||||
if (event.dataTransfer.items.length == 0) {
|
||||
// Prevent to drop on file or image
|
||||
if (data.type !== 'folder' || this.draggingId === data) return
|
||||
|
||||
//Prevent move selected folder to folder if in beteewn selected folders
|
||||
if (this.fileInfoDetail.find(item => item === data && this.fileInfoDetail.length > 1)) return
|
||||
//Prevent move selected folder to folder if in beteewn selected folders
|
||||
if (this.clipboard.find(item => item === data && this.clipboard.length > 1)) return
|
||||
|
||||
// Move folder to new parent
|
||||
// Move folder to new parent
|
||||
|
||||
//Move item if is not included in selected items
|
||||
if (!this.fileInfoDetail.includes(this.draggingId)) {
|
||||
this.$store.dispatch('moveItem', {to_item: data, noSelectedItem: this.draggingId})
|
||||
}
|
||||
//Move item if is not included in selected items
|
||||
if (!this.clipboard.includes(this.draggingId)) {
|
||||
this.$store.dispatch('moveItem', {to_item: data, noSelectedItem: this.draggingId})
|
||||
}
|
||||
|
||||
//Move selected items to folder
|
||||
if (this.fileInfoDetail.length > 0 && this.fileInfoDetail.includes(this.draggingId)) {
|
||||
this.$store.dispatch('moveItem', {to_item: data, noSelectedItem: null})
|
||||
}
|
||||
//Move selected items to folder
|
||||
if (this.clipboard.length > 0 && this.clipboard.includes(this.draggingId)) {
|
||||
this.$store.dispatch('moveItem', {to_item: data, noSelectedItem: null})
|
||||
}
|
||||
|
||||
} else {
|
||||
} else {
|
||||
|
||||
// Get id of current folder
|
||||
const id = data.type !== 'folder' ? this.currentFolder.id : data.id
|
||||
// Get id of current folder
|
||||
const id = data.type !== 'folder' ? this.currentFolder.id : data.id
|
||||
|
||||
// Upload external file
|
||||
this.$uploadExternalFiles(event, id)
|
||||
}
|
||||
// Upload external file
|
||||
this.$uploadExternalFiles(event, id)
|
||||
}
|
||||
|
||||
this.isDragging = false
|
||||
},
|
||||
contextMenu(event, item) {
|
||||
events.$emit('contextMenu:show', event, item)
|
||||
},
|
||||
filesContainerClick() {
|
||||
this.isDragging = false
|
||||
},
|
||||
contextMenu(event, item) {
|
||||
events.$emit('contextMenu:show', event, item)
|
||||
},
|
||||
filesContainerClick() {
|
||||
|
||||
// Deselect items clicked by outside
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
events.$on('mobileSelecting:start', () => {
|
||||
this.mobileMultiSelect = true
|
||||
})
|
||||
// Deselect items clicked by outside
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
events.$on('mobileSelecting:start', () => {
|
||||
this.isMultiSelect = true
|
||||
})
|
||||
|
||||
events.$on('mobileSelecting:stop', () => {
|
||||
this.mobileMultiSelect = false
|
||||
})
|
||||
events.$on('mobileSelecting:stop', () => {
|
||||
this.isMultiSelect = false
|
||||
})
|
||||
|
||||
events.$on('drop', () => {
|
||||
this.isDragging = false
|
||||
events.$on('drop', () => {
|
||||
this.isDragging = false
|
||||
|
||||
setTimeout(() => {
|
||||
this.draggingId = undefined
|
||||
}, 10)
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.draggingId = undefined
|
||||
}, 10)
|
||||
})
|
||||
|
||||
events.$on('fileItem:deselect', () => {
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
})
|
||||
events.$on('fileItem:deselect', () => {
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
})
|
||||
|
||||
events.$on('scrollTop', () => {
|
||||
events.$on('scrollTop', () => {
|
||||
|
||||
// Scroll top
|
||||
var container = document.getElementsByClassName(
|
||||
'files-container'
|
||||
)[0]
|
||||
// Scroll top
|
||||
var container = document.getElementsByClassName(
|
||||
'files-container'
|
||||
)[0]
|
||||
|
||||
if (container)
|
||||
container.scrollTop = 0
|
||||
})
|
||||
}
|
||||
}
|
||||
if (container)
|
||||
container.scrollTop = 0
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.file-list {
|
||||
.dragged {
|
||||
/deep/ .is-dragenter {
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
.file-list {
|
||||
.dragged {
|
||||
/deep/ .is-dragenter {
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dragged {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.dragged {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#multi-selected {
|
||||
position: fixed;
|
||||
pointer-events: none;
|
||||
z-index: 100;
|
||||
#multi-selected {
|
||||
position: fixed;
|
||||
pointer-events: none;
|
||||
z-index: 100;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-multi-select {
|
||||
bottom: 50px !important;
|
||||
top: 0px;
|
||||
}
|
||||
.mobile-multi-select {
|
||||
bottom: 50px !important;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.button-upload {
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.button-upload {
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.mobile-search {
|
||||
display: none;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.mobile-search {
|
||||
display: none;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.file-content {
|
||||
display: flex;
|
||||
.file-content {
|
||||
display: flex;
|
||||
|
||||
&.is-dragging {
|
||||
@include transform(scale(0.99));
|
||||
}
|
||||
}
|
||||
&.is-dragging {
|
||||
@include transform(scale(0.99));
|
||||
}
|
||||
}
|
||||
|
||||
.files-container {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
flex: 0 0 100%;
|
||||
@include transition(150ms);
|
||||
position: relative;
|
||||
scroll-behavior: smooth;
|
||||
.files-container {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
flex: 0 0 100%;
|
||||
@include transition(150ms);
|
||||
position: relative;
|
||||
scroll-behavior: smooth;
|
||||
|
||||
&.is-fileinfo-visible {
|
||||
flex: 0 1 100%;
|
||||
}
|
||||
&.is-visible {
|
||||
flex: 0 1 100%;
|
||||
}
|
||||
|
||||
.file-list {
|
||||
.file-list {
|
||||
|
||||
&.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, 180px);
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, 180px);
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.file-info-container {
|
||||
flex: 0 0 300px;
|
||||
padding-left: 20px;
|
||||
overflow: auto;
|
||||
}
|
||||
.file-info-container {
|
||||
flex: 0 0 300px;
|
||||
padding-left: 20px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
// Transition
|
||||
.file-move {
|
||||
transition: transform 0.6s;
|
||||
}
|
||||
// Transition
|
||||
.file-move {
|
||||
transition: transform 0.6s;
|
||||
}
|
||||
|
||||
.file-enter-active {
|
||||
transition: all 300ms ease;
|
||||
}
|
||||
.file-enter-active {
|
||||
transition: all 300ms ease;
|
||||
}
|
||||
|
||||
.file-leave-active {
|
||||
transition: all 0ms;
|
||||
}
|
||||
.file-leave-active {
|
||||
transition: all 0ms;
|
||||
}
|
||||
|
||||
.file-enter, .file-leave-to /* .list-leave-active below version 2.1.8 */
|
||||
{
|
||||
opacity: 0;
|
||||
transform: translateX(-20px);
|
||||
}
|
||||
.file-enter, .file-leave-to /* .list-leave-active below version 2.1.8 */
|
||||
{
|
||||
opacity: 0;
|
||||
transform: translateX(-20px);
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 960px) {
|
||||
@media only screen and (min-width: 960px) {
|
||||
|
||||
.file-content {
|
||||
position: absolute;
|
||||
top: 72px;
|
||||
left: 15px;
|
||||
right: 15px;
|
||||
bottom: 0;
|
||||
@include transition;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
.file-content {
|
||||
position: absolute;
|
||||
top: 72px;
|
||||
left: 15px;
|
||||
right: 15px;
|
||||
bottom: 0;
|
||||
@include transition;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
&.is-offset {
|
||||
margin-top: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.is-offset {
|
||||
margin-top: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
@media only screen and (max-width: 960px) {
|
||||
|
||||
.file-info-container {
|
||||
display: none;
|
||||
}
|
||||
.file-info-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mobile-search {
|
||||
display: block;
|
||||
}
|
||||
.file-content {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 15px;
|
||||
right: 15px;
|
||||
bottom: 0;
|
||||
@include transition;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
.mobile-search {
|
||||
display: block;
|
||||
}
|
||||
.file-content {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 15px;
|
||||
right: 15px;
|
||||
bottom: 0;
|
||||
@include transition;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
&.is-offset {
|
||||
margin-top: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.is-offset {
|
||||
margin-top: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 690px) {
|
||||
@media only screen and (max-width: 690px) {
|
||||
|
||||
.files-container {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
position: fixed;
|
||||
overflow-y: auto;
|
||||
.files-container {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
position: fixed;
|
||||
overflow-y: auto;
|
||||
|
||||
.file-list {
|
||||
.file-list {
|
||||
|
||||
&.grid {
|
||||
grid-template-columns: repeat(auto-fill, 120px);
|
||||
}
|
||||
}
|
||||
}
|
||||
&.grid {
|
||||
grid-template-columns: repeat(auto-fill, 120px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.file-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0;
|
||||
@include transition;
|
||||
.file-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0;
|
||||
@include transition;
|
||||
|
||||
&.is-offset {
|
||||
margin-top: 50px;
|
||||
}
|
||||
}
|
||||
&.is-offset {
|
||||
margin-top: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-search {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.mobile-search {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.file-info-container {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.file-info-container {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<MenuMobile name="file-filter">
|
||||
<MenuMobileGroup>
|
||||
<OptionGroup>
|
||||
<Option @click.native="goToFiles" :title="$t('menu.files')" icon="hard-drive" :is-active="$isThisLocation('base')" is-hover-disabled="true" />
|
||||
<Option @click.native="goToLatest" :title="$t('menu.latest')" icon="upload-cloud" :is-active="$isThisLocation('latest')" is-hover-disabled="true" />
|
||||
<Option @click.native="goToTrash" :title="$t('menu.trash')" icon="trash" :is-active="$isThisLocation(['trash', 'trash-root'])" is-hover-disabled="true" />
|
||||
</OptionGroup>
|
||||
<OptionGroup>
|
||||
<Option @click.native="goToShared" :title="$t('sidebar.my_shared')" icon="share" :is-active="$isThisLocation('shared')" is-hover-disabled="true" />
|
||||
<Option @click.native="goToParticipantUploads" :title="$t('sidebar.participant_uploads')" icon="users" :is-active="$isThisLocation('participant_uploads')" is-hover-disabled="true" />
|
||||
</OptionGroup>
|
||||
</MenuMobileGroup>
|
||||
</MenuMobile>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MenuMobileGroup from '@/components/Mobile/MenuMobileGroup'
|
||||
import OptionGroup from '@/components/FilesView/OptionGroup'
|
||||
import MenuMobile from '@/components/Mobile/MenuMobile'
|
||||
import Option from '@/components/FilesView/Option'
|
||||
import {mapGetters} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'FileMenuMobile',
|
||||
components: {
|
||||
MenuMobileGroup,
|
||||
OptionGroup,
|
||||
MenuMobile,
|
||||
Option,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'homeDirectory'
|
||||
]),
|
||||
},
|
||||
methods: {
|
||||
flushBrowseHistory() {
|
||||
this.$store.commit('FLUSH_FOLDER_HISTORY')
|
||||
},
|
||||
goToFiles() {
|
||||
this.$store.dispatch('getFolder', [{folder: this.homeDirectory, back: false, init: true}])
|
||||
this.flushBrowseHistory()
|
||||
},
|
||||
goToLatest() {
|
||||
this.$store.dispatch('getLatest')
|
||||
this.flushBrowseHistory()
|
||||
},
|
||||
goToTrash() {
|
||||
this.$store.dispatch('getTrash')
|
||||
this.flushBrowseHistory()
|
||||
},
|
||||
goToShared() {
|
||||
this.$store.dispatch('getShared', [{back: false, init: false}])
|
||||
this.flushBrowseHistory()
|
||||
},
|
||||
goToParticipantUploads() {
|
||||
this.$store.dispatch('getParticipantUploads')
|
||||
this.flushBrowseHistory()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,96 +0,0 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="showFullPreview"
|
||||
class="file-full-preview-wrapper"
|
||||
id="fileFullPreview"
|
||||
ref="filePreview"
|
||||
tabindex="-1"
|
||||
@click="closeContextMenu"
|
||||
@keydown.esc=";(showFullPreview = false), hideContextMenu()"
|
||||
@keydown.right="next"
|
||||
@keydown.left="prev"
|
||||
>
|
||||
<FilePreviewNavigationPanel />
|
||||
<MediaFullPreview />
|
||||
<FilePreviewActions />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { events } from '@/bus'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
import MediaFullPreview from '@/components/FilesView/MediaFullPreview'
|
||||
import FilePreviewActions from '@/components/FilesView/FilePreviewActions'
|
||||
import FilePreviewNavigationPanel from '@/components/FilesView/FilePreviewNavigationPanel'
|
||||
|
||||
export default {
|
||||
name: 'FileFullPreview',
|
||||
components: {
|
||||
MediaFullPreview,
|
||||
FilePreviewNavigationPanel,
|
||||
FilePreviewActions
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['fileInfoDetail', 'data'])
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showFullPreview: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
closeContextMenu(event) {
|
||||
if ((event.target.parentElement.id || event.target.id) === 'fast-preview-menu') {
|
||||
return
|
||||
} else {
|
||||
events.$emit('showContextMenuPreview:hide')
|
||||
}
|
||||
},
|
||||
next: function() {
|
||||
events.$emit('filePreviewAction:next')
|
||||
},
|
||||
prev: function() {
|
||||
events.$emit('filePreviewAction:prev')
|
||||
},
|
||||
hideContextMenu() {
|
||||
events.$emit('showContextMenuPreview:hide')
|
||||
}
|
||||
},
|
||||
|
||||
updated() {
|
||||
//Focus file preview for key binding
|
||||
if (this.showFullPreview) {
|
||||
this.$refs.filePreview.focus()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
events.$on('fileFullPreview:show', () => {
|
||||
this.showFullPreview = true
|
||||
})
|
||||
events.$on('fileFullPreview:hide', () => {
|
||||
this.showFullPreview = false
|
||||
|
||||
events.$emit('hide:mobile-navigation')
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
|
||||
.file-full-preview-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
z-index: 7;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.file-full-preview-wrapper {
|
||||
background-color: $dark_mode_background;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,218 +0,0 @@
|
||||
<template>
|
||||
<div class="file-info-content" v-if="fileInfoDetail.length === 1">
|
||||
<div class="file-headline" spellcheck="false">
|
||||
<FilePreview/>
|
||||
|
||||
<!--File info-->
|
||||
<div class="flex">
|
||||
<div class="icon">
|
||||
<div class="icon-preview">
|
||||
<image-icon v-if="fileType === 'image'" size="21"></image-icon>
|
||||
<video-icon v-if="fileType === 'video'" size="21"></video-icon>
|
||||
<folder-icon v-if="fileType === 'folder'" size="21"></folder-icon>
|
||||
<file-icon v-if="fileType === 'file'" size="21"></file-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="file-info">
|
||||
<span ref="name" class="name">{{ fileInfoDetail[0].name }}</span>
|
||||
<span class="mimetype text-theme" v-if="fileInfoDetail[0].mimetype">.{{ fileInfoDetail[0].mimetype }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Info list-->
|
||||
<ListInfo>
|
||||
<ListInfoItem v-if="fileInfoDetail[0].filesize"
|
||||
:title="$t('file_detail.size')"
|
||||
:content="fileInfoDetail[0].filesize">
|
||||
</ListInfoItem>
|
||||
|
||||
<ListInfoItem v-if="$checkPermission(['master']) && fileInfoDetail[0].author !== 'user'"
|
||||
:title="$t('file_detail.author')"
|
||||
:content="$t('file_detail.author_participant')">
|
||||
</ListInfoItem>
|
||||
|
||||
<ListInfoItem
|
||||
:title="$t('file_detail.created_at')"
|
||||
:content="fileInfoDetail[0].created_at">
|
||||
</ListInfoItem>
|
||||
|
||||
<ListInfoItem v-if="$checkPermission(['master'])"
|
||||
:title="$t('file_detail.where')">
|
||||
<div class="action-button" @click="moveItem">
|
||||
<span>{{ fileInfoDetail[0].parent ? fileInfoDetail[0].parent.name : $t('locations.home') }}</span>
|
||||
<edit-2-icon size="10" class="edit-icon"></edit-2-icon>
|
||||
</div>
|
||||
</ListInfoItem>
|
||||
<ListInfoItem v-if="$checkPermission('master') && fileInfoDetail[0].shared"
|
||||
:title="$t('file_detail.shared')">
|
||||
<div class="action-button" @click="shareItemOptions">
|
||||
<span>{{ sharedInfo }}</span>
|
||||
<edit-2-icon size="10" class="edit-icon"></edit-2-icon>
|
||||
</div>
|
||||
<div class="sharelink">
|
||||
<lock-icon v-if="isLocked" @click="shareItemOptions" class="lock-icon" size="17"></lock-icon>
|
||||
<unlock-icon v-if="! isLocked" @click="shareItemOptions" class="lock-icon" size="17"></unlock-icon>
|
||||
<CopyInput class="copy-sharelink" size="small" :item="fileInfoDetail[0]"/>
|
||||
</div>
|
||||
</ListInfoItem>
|
||||
|
||||
<ListInfoItem v-if="canShowMetaData" :title="$t('file_detail_meta.meta_data')">
|
||||
<ImageMetaData />
|
||||
</ListInfoItem>
|
||||
</ListInfo>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {Edit2Icon, LockIcon, UnlockIcon, ImageIcon, VideoIcon, FolderIcon, FileIcon} from 'vue-feather-icons'
|
||||
import ImageMetaData from '@/components/FilesView/ImageMetaData'
|
||||
import FilePreview from '@/components/FilesView/FilePreview'
|
||||
import CopyInput from '@/components/Others/Forms/CopyInput'
|
||||
import ListInfoItem from '@/components/Others/ListInfoItem'
|
||||
import ListInfo from '@/components/Others/ListInfo'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from "@/bus"
|
||||
|
||||
export default {
|
||||
name: 'FileInfoPanel',
|
||||
components: {
|
||||
ImageMetaData,
|
||||
ListInfoItem,
|
||||
ListInfo,
|
||||
FilePreview,
|
||||
FolderIcon,
|
||||
UnlockIcon,
|
||||
VideoIcon,
|
||||
CopyInput,
|
||||
ImageIcon,
|
||||
FileIcon,
|
||||
Edit2Icon,
|
||||
LockIcon,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['fileInfoDetail', 'permissionOptions']),
|
||||
fileType() {
|
||||
return this.fileInfoDetail[0].type
|
||||
},
|
||||
canShowMetaData() {
|
||||
return this.fileInfoDetail[0].metadata && this.fileInfoDetail[0].metadata.ExifImageWidth
|
||||
},
|
||||
sharedInfo() {
|
||||
// Get permission title
|
||||
let title = this.permissionOptions.find(option => {
|
||||
return option.value === this.fileInfoDetail[0].shared.permission
|
||||
})
|
||||
|
||||
return title ? this.$t(title.label) : this.$t('shared.can_download')
|
||||
},
|
||||
sharedIcon() {
|
||||
switch (this.fileInfoDetail[0].shared.permission) {
|
||||
case 'editor':
|
||||
return 'user-edit'
|
||||
break
|
||||
case 'visitor':
|
||||
return 'user'
|
||||
break
|
||||
default:
|
||||
return 'download'
|
||||
}
|
||||
},
|
||||
isLocked() {
|
||||
return this.fileInfoDetail[0].shared.is_protected
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
shareItemOptions() {
|
||||
// Open share item popup
|
||||
events.$emit('popup:open', {name: 'share-edit', item: this.fileInfoDetail[0]})
|
||||
},
|
||||
moveItem() {
|
||||
// Move item fire popup
|
||||
events.$emit("popup:open", { name: "move", item: this.fileInfoDetail});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.file-info-content {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.file-headline {
|
||||
margin-bottom: 20px;
|
||||
border-radius: 8px;
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.icon-preview {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
outline: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.file-info {
|
||||
padding-left: 10px;
|
||||
width: 100%;
|
||||
word-break: break-all;
|
||||
|
||||
.name {
|
||||
@include font-size(14);
|
||||
font-weight: 700;
|
||||
line-height: 1.4;
|
||||
display: block;
|
||||
color: $text;
|
||||
}
|
||||
|
||||
.mimetype {
|
||||
@include font-size(12);
|
||||
font-weight: 600;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sharelink {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
|
||||
.lock-icon {
|
||||
display: inline-block;
|
||||
width: 15px;
|
||||
margin-right: 9px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.copy-sharelink {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.file-headline {
|
||||
|
||||
.file-info {
|
||||
|
||||
.name {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<div class="file-wrapper" @click.stop="clickedItem" @dblclick="goToItem" spellcheck="false">
|
||||
<!--Grid preview-->
|
||||
<div class="file-wrapper" @mouseup.stop="clickedItem" @dblclick="goToItem" spellcheck="false">
|
||||
<div :draggable="canDrag" @dragstart="$emit('dragstart')" @drop="
|
||||
drop()
|
||||
area = false" @dragleave="dragLeave" @dragover.prevent="dragEnter" class="file-item" :class="{'is-clicked' : isClicked , 'no-clicked' : !isClicked && this.$isMobile(), 'is-dragenter': area }">
|
||||
@@ -8,7 +7,7 @@
|
||||
<div class="icon-item">
|
||||
|
||||
<!-- MultiSelecting for the mobile version -->
|
||||
<div :class="{'check-select-folder' : this.item.type === 'folder', 'check-select' : this.item.type !== 'folder'}" v-if="multiSelectMode">
|
||||
<div :class="{'check-select-folder' : this.item.type === 'folder', 'check-select' : this.item.type !== 'folder'}" v-if="mobileMultiSelect">
|
||||
<div class="select-box" :class="{'select-box-active' : isClicked } ">
|
||||
<CheckIcon v-if="isClicked" class="icon" size="17" />
|
||||
</div>
|
||||
@@ -58,8 +57,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span @click.stop="showItemActions" class="show-actions" v-if="$isMobile() && ! multiSelectMode && canShowMobileOptions">
|
||||
<MoreHorizontalIcon icon="ellipsis-h" size="16" class="icon-action text-theme"/>
|
||||
<span @mousedown.stop="showItemActions" class="show-actions" v-if="$isMobile() && ! mobileMultiSelect && canShowMobileOptions">
|
||||
<MoreHorizontalIcon icon="ellipsis-h" size="16" class="icon-action text-theme" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -84,7 +83,7 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'FilePreviewType', 'sharedDetail', 'fileInfoDetail', 'data'
|
||||
'FilePreviewType', 'sharedDetail', 'clipboard', 'entries'
|
||||
]),
|
||||
folderEmojiOrColor() {
|
||||
|
||||
@@ -102,7 +101,7 @@ export default {
|
||||
|
||||
},
|
||||
isClicked() {
|
||||
return this.fileInfoDetail.some(element => element.id === this.item.id)
|
||||
return this.clipboard.some(element => element.id === this.item.id)
|
||||
},
|
||||
isFolder() {
|
||||
return this.item.type === 'folder'
|
||||
@@ -149,7 +148,7 @@ export default {
|
||||
return {
|
||||
area: false,
|
||||
itemName: undefined,
|
||||
multiSelectMode: false
|
||||
mobileMultiSelect: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -158,10 +157,10 @@ export default {
|
||||
},
|
||||
showItemActions() {
|
||||
// Load file info detail
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
|
||||
|
||||
events.$emit('mobileMenu:show')
|
||||
events.$emit('mobile-menu:show', 'file-menu')
|
||||
},
|
||||
dragEnter() {
|
||||
if (this.item.type !== 'folder') return
|
||||
@@ -181,77 +180,79 @@ export default {
|
||||
|
||||
if (e.ctrlKey || e.metaKey && !e.shiftKey) {
|
||||
// Click + Ctrl
|
||||
if (this.fileInfoDetail.some(item => item.id === this.item.id)) {
|
||||
this.$store.commit('REMOVE_ITEM_FILEINFO_DETAIL', this.item)
|
||||
if (this.clipboard.some(item => item.id === this.item.id)) {
|
||||
this.$store.commit('REMOVE_ITEM_FROM_CLIPBOARD', this.item)
|
||||
} else {
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
|
||||
}
|
||||
} else if (e.shiftKey) {
|
||||
// Click + Shift
|
||||
let lastItem = this.data.indexOf(this.fileInfoDetail[this.fileInfoDetail.length - 1])
|
||||
let clickedItem = this.data.indexOf(this.item)
|
||||
let lastItem = this.entries.indexOf(this.clipboard[this.clipboard.length - 1])
|
||||
let clickedItem = this.entries.indexOf(this.item)
|
||||
|
||||
// If Click + Shift + Ctrl dont remove already selected items
|
||||
if (!e.ctrlKey && !e.metaKey) {
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
}
|
||||
|
||||
//Shift selecting from top to bottom
|
||||
if (lastItem < clickedItem) {
|
||||
for (let i = lastItem; i <= clickedItem; i++) {
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.data[i])
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.entries[i])
|
||||
}
|
||||
//Shift selecting from bottom to top
|
||||
} else {
|
||||
for (let i = lastItem; i >= clickedItem; i--) {
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.data[i])
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.entries[i])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Click
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.multiSelectMode && this.$isMobile()) {
|
||||
// Open in mobile version on first click
|
||||
if (this.$isMobile() && this.isFolder) {
|
||||
// Go to folder
|
||||
if (!this.mobileMultiSelect && this.$isMobile()) {
|
||||
|
||||
if (this.isFolder) {
|
||||
|
||||
if (this.$isThisLocation('public')) {
|
||||
this.$store.dispatch('browseShared', [{folder: this.item, back: false, init: false}])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [{folder: this.item, back: false, init: false}])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if (this.$isMobile()) {
|
||||
if (this.isImage || this.isVideo || this.isAudio) {
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
|
||||
events.$emit('fileFullPreview:show')
|
||||
if (this.isImage || this.isVideo || this.isAudio || this.isPdf) {
|
||||
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
|
||||
|
||||
events.$emit('file-preview:show')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.multiSelectMode && this.$isMobile()) {
|
||||
if (this.fileInfoDetail.some(item => item.id === this.item.id)) {
|
||||
this.$store.commit('REMOVE_ITEM_FILEINFO_DETAIL', this.item)
|
||||
if (this.mobileMultiSelect && this.$isMobile()) {
|
||||
if (this.clipboard.some(item => item.id === this.item.id)) {
|
||||
this.$store.commit('REMOVE_ITEM_FROM_CLIPBOARD', this.item)
|
||||
} else {
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
|
||||
}
|
||||
}
|
||||
},
|
||||
goToItem() {
|
||||
if (this.isImage || this.isVideo || this.isAudio) {
|
||||
events.$emit('fileFullPreview:show')
|
||||
if (this.isImage || this.isVideo || this.isAudio || this.isPdf) {
|
||||
events.$emit('file-preview:show')
|
||||
|
||||
} else if (this.isFile || !this.isFolder && !this.isPdf && !this.isVideo && !this.isAudio && !this.isImage) {
|
||||
} else if (this.isFile || !this.isFolder && !this.isVideo && !this.isAudio && !this.isImage) {
|
||||
this.$downloadFile(this.item.file_url, this.item.name + '.' + this.item.mimetype)
|
||||
|
||||
} else if (this.isFolder) {
|
||||
|
||||
//Clear selected data after open another folder
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
|
||||
if (this.$isThisLocation('public')) {
|
||||
this.$store.dispatch('browseShared', [{folder: this.item, back: false, init: false}])
|
||||
@@ -284,13 +285,13 @@ export default {
|
||||
})
|
||||
|
||||
events.$on('mobileSelecting:start', () => {
|
||||
this.multiSelectMode = true
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
this.mobileMultiSelect = true
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
})
|
||||
|
||||
events.$on('mobileSelecting:stop', () => {
|
||||
this.multiSelectMode = false
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
this.mobileMultiSelect = false
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
})
|
||||
// Change item name
|
||||
events.$on('change:name', (item) => {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<div class="file-wrapper" @click.stop="clickedItem" @dblclick="goToItem" spellcheck="false">
|
||||
<!--List preview-->
|
||||
<div class="file-wrapper" @mouseup.stop="clickedItem" @dblclick="goToItem" spellcheck="false">
|
||||
<div
|
||||
:draggable="canDrag"
|
||||
@dragstart="$emit('dragstart')"
|
||||
@@ -13,7 +12,7 @@
|
||||
<transition name="slide-from-left">
|
||||
<div class="check-select" v-if="mobileMultiSelect">
|
||||
<div class="select-box" :class="{'select-box-active' : isClicked } ">
|
||||
<CheckIcon v-if="isClicked" class="icon" size="17"/>
|
||||
<CheckIcon v-if="isClicked" class="icon" size="17" />
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
@@ -26,12 +25,12 @@
|
||||
</span>
|
||||
|
||||
<!--Folder thumbnail-->
|
||||
<FontAwesomeIcon v-if="isFile || (isImage && !item.thumbnail)" class="file-icon" icon="file"/>
|
||||
<FontAwesomeIcon v-if="isFile || (isImage && !item.thumbnail)" class="file-icon" icon="file" />
|
||||
|
||||
<!--Image thumbnail-->
|
||||
<img loading="lazy" v-if="isImage && item.thumbnail" class="image" :src="item.thumbnail" :alt="item.name"/>
|
||||
<img loading="lazy" v-if="isImage && item.thumbnail" class="image" :src="item.thumbnail" :alt="item.name" />
|
||||
|
||||
<!--Else show only folder icon-->
|
||||
<!--Else show only folder icon-->
|
||||
<FolderIcon v-if="isFolder" :item="item" location="file-item-list" class="folder svg-color-theme" />
|
||||
</div>
|
||||
|
||||
@@ -63,7 +62,7 @@
|
||||
<!--Show item actions-->
|
||||
<transition name="slide-from-right">
|
||||
<div class="actions" v-if="$isMobile() && ! mobileMultiSelect">
|
||||
<span @click.stop="showItemActions" class="show-actions">
|
||||
<span @mousedown.stop="showItemActions" class="show-actions">
|
||||
<MoreVerticalIcon size="16" class="icon-action text-theme" />
|
||||
</span>
|
||||
</div>
|
||||
@@ -73,26 +72,32 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { LinkIcon, UserPlusIcon, CheckIcon, MoreVerticalIcon } from 'vue-feather-icons'
|
||||
import {LinkIcon, UserPlusIcon, CheckIcon, MoreVerticalIcon} from 'vue-feather-icons'
|
||||
import FolderIcon from '@/components/FilesView/FolderIcon'
|
||||
import { debounce } from 'lodash'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { events } from '@/bus'
|
||||
import {debounce} from 'lodash'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'FileItemList',
|
||||
props: ['item'],
|
||||
props: [
|
||||
'item'
|
||||
],
|
||||
components: {
|
||||
MoreVerticalIcon,
|
||||
UserPlusIcon,
|
||||
LinkIcon,
|
||||
FolderIcon,
|
||||
CheckIcon,
|
||||
LinkIcon,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['FilePreviewType', 'fileInfoDetail', 'data']),
|
||||
...mapGetters([
|
||||
'FilePreviewType',
|
||||
'clipboard',
|
||||
'entries'
|
||||
]),
|
||||
isClicked() {
|
||||
return this.fileInfoDetail.some(element => element.id === this.item.id)
|
||||
return this.clipboard.some(element => element.id === this.item.id)
|
||||
},
|
||||
isFolder() {
|
||||
return this.item.type === 'folder'
|
||||
@@ -120,7 +125,7 @@ export default {
|
||||
return !this.isDeleted && this.$checkPermission(['master', 'editor'])
|
||||
},
|
||||
timeStamp() {
|
||||
return this.item.deleted_at ? this.$t('item_thumbnail.deleted_at', { time: this.item.deleted_at }) : this.item.created_at
|
||||
return this.item.deleted_at ? this.$t('item_thumbnail.deleted_at', {time: this.item.deleted_at}) : this.item.created_at
|
||||
},
|
||||
folderItems() {
|
||||
return this.item.deleted_at ? this.item.trashed_items : this.item.items
|
||||
@@ -151,11 +156,10 @@ export default {
|
||||
events.$emit('drop')
|
||||
},
|
||||
showItemActions() {
|
||||
// Load file info detail
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
|
||||
|
||||
events.$emit('mobileMenu:show')
|
||||
events.$emit('mobile-menu:show', 'file-menu')
|
||||
},
|
||||
dragEnter() {
|
||||
if (this.item.type !== 'folder') return
|
||||
@@ -174,89 +178,92 @@ export default {
|
||||
document.getSelection().removeAllRanges();
|
||||
|
||||
if ((e.ctrlKey || e.metaKey) && !e.shiftKey) {
|
||||
// Click + Ctrl
|
||||
|
||||
if (this.fileInfoDetail.some(item => item.id === this.item.id)) {
|
||||
this.$store.commit('REMOVE_ITEM_FILEINFO_DETAIL', this.item)
|
||||
// Click + Ctrl
|
||||
if (this.clipboard.some(item => item.id === this.item.id)) {
|
||||
this.$store.commit('REMOVE_ITEM_FROM_CLIPBOARD', this.item)
|
||||
} else {
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
|
||||
}
|
||||
} else if (e.shiftKey) {
|
||||
// Click + Shift
|
||||
let lastItem = this.data.indexOf(this.fileInfoDetail[this.fileInfoDetail.length - 1])
|
||||
let clickedItem = this.data.indexOf(this.item)
|
||||
|
||||
// Click + Shift
|
||||
let lastItem = this.entries.indexOf(this.clipboard[this.clipboard.length - 1])
|
||||
let clickedItem = this.entries.indexOf(this.item)
|
||||
|
||||
// If Click + Shift + Ctrl dont remove already selected items
|
||||
if (!e.ctrlKey && !e.metaKey) {
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
}
|
||||
|
||||
//Shift selecting from top to bottom
|
||||
if (lastItem < clickedItem) {
|
||||
for (let i = lastItem; i <= clickedItem; i++) {
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.data[i])
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.entries[i])
|
||||
}
|
||||
//Shift selecting from bottom to top
|
||||
} else {
|
||||
for (let i = lastItem; i >= clickedItem; i--) {
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.data[i])
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.entries[i])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Click
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
|
||||
|
||||
// Click
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.mobileMultiSelect && this.$isMobile()) {
|
||||
|
||||
// Open in mobile version on first click
|
||||
if (this.$isMobile() && this.isFolder) {
|
||||
// Go to folder
|
||||
if (this.$isThisLocation('public')) {
|
||||
this.$store.dispatch('browseShared', [{ folder: this.item, back: false, init: false }])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [{ folder: this.item, back: false, init: false }])
|
||||
}
|
||||
}
|
||||
if (this.isFolder) {
|
||||
|
||||
if (this.$isMobile()) {
|
||||
if (this.isImage || this.isVideo || this.isAudio) {
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
|
||||
events.$emit('fileFullPreview:show')
|
||||
if (this.$isThisLocation('public')) {
|
||||
this.$store.dispatch('browseShared', [{folder: this.item, back: false, init: false}])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [{folder: this.item, back: false, init: false}])
|
||||
}
|
||||
} else {
|
||||
|
||||
if (this.isImage || this.isVideo || this.isAudio || this.isPdf) {
|
||||
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
|
||||
|
||||
events.$emit('file-preview:show')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.mobileMultiSelect && this.$isMobile()) {
|
||||
if (this.fileInfoDetail.some(item => item.id === this.item.id)) {
|
||||
this.$store.commit('REMOVE_ITEM_FILEINFO_DETAIL', this.item)
|
||||
if (this.clipboard.some(item => item.id === this.item.id)) {
|
||||
this.$store.commit('REMOVE_ITEM_FROM_CLIPBOARD', this.item)
|
||||
} else {
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
|
||||
}
|
||||
}
|
||||
},
|
||||
goToItem() {
|
||||
if (this.isImage || this.isVideo || this.isAudio) {
|
||||
events.$emit('fileFullPreview:show')
|
||||
if (this.isImage || this.isVideo || this.isAudio || this.isPdf) {
|
||||
events.$emit('file-preview:show')
|
||||
|
||||
} else if (this.isFile || !this.isFolder && !this.isPdf && !this.isVideo && !this.isAudio && !this.isImage) {
|
||||
} else if (this.isFile || !this.isFolder && !this.isVideo && !this.isAudio && !this.isImage) {
|
||||
this.$downloadFile(this.item.file_url, this.item.name + '.' + this.item.mimetype)
|
||||
|
||||
} else if (this.isFolder) {
|
||||
|
||||
// Clear selected items after open another folder
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
|
||||
if (this.$isThisLocation('public')) {
|
||||
this.$store.dispatch('browseShared', [{ folder: this.item, back: false, init: false }])
|
||||
this.$store.dispatch('browseShared', [{folder: this.item, back: false, init: false}])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [{ folder: this.item, back: false, init: false }])
|
||||
this.$store.dispatch('getFolder', [{folder: this.item, back: false, init: false}])
|
||||
}
|
||||
}
|
||||
},
|
||||
renameItem: debounce(function(e) {
|
||||
renameItem: debounce(function (e) {
|
||||
// Prevent submit empty string
|
||||
if (e.target.innerText.trim() === '') return
|
||||
|
||||
@@ -273,7 +280,7 @@ export default {
|
||||
|
||||
events.$on('newFolder:focus', (id) => {
|
||||
|
||||
if(this.item.id === id && !this.$isMobile()) {
|
||||
if (this.item.id === id && !this.$isMobile()) {
|
||||
this.$refs[id].focus()
|
||||
document.execCommand('selectAll')
|
||||
}
|
||||
@@ -281,12 +288,12 @@ export default {
|
||||
|
||||
events.$on('mobileSelecting:start', () => {
|
||||
this.mobileMultiSelect = true
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
})
|
||||
|
||||
events.$on('mobileSelecting:stop', () => {
|
||||
this.mobileMultiSelect = false
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
})
|
||||
|
||||
// Change item name
|
||||
@@ -454,7 +461,7 @@ export default {
|
||||
flex: 0 0 50px;
|
||||
line-height: 0;
|
||||
margin-right: 20px;
|
||||
|
||||
|
||||
.folder {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
<template>
|
||||
<MenuMobile name="file-menu">
|
||||
<ThumbnailItem class="item-thumbnail" :item="clipboard[0]" info="metadata" />
|
||||
|
||||
<!--Trash location-->
|
||||
<MenuMobileGroup v-if="$isThisLocation(['trash', 'trash-root']) && $checkPermission('master')">
|
||||
<OptionGroup v-if="clipboard[0]">
|
||||
<Option @click.native="restoreItem" :title="$t('context_menu.restore')" icon="restore" />
|
||||
<Option @click.native="deleteItem" :title="$t('context_menu.delete')" icon="delete" />
|
||||
</OptionGroup>
|
||||
|
||||
<OptionGroup>
|
||||
<Option v-if="!isFolder" @click.native="downloadItem" :title="$t('context_menu.download')" icon="download" />
|
||||
<Option v-if="isFolder" @click.native="downloadFolder" :title="$t('context_menu.zip_folder')" icon="zip-folder" />
|
||||
</OptionGroup>
|
||||
</MenuMobileGroup>
|
||||
|
||||
<!--Shared location-->
|
||||
<MenuMobileGroup v-if="$isThisLocation(['shared']) && $checkPermission('master')">
|
||||
<OptionGroup v-if="clipboard[0] && isFolder">
|
||||
<Option @click.native="addToFavourites" :title="favouritesTitle" icon="star" />
|
||||
</OptionGroup>
|
||||
|
||||
<OptionGroup v-if="clipboard[0]">
|
||||
<Option @click.native="renameItem" :title="$t('context_menu.rename')" icon="rename" />
|
||||
<Option @click.native="shareItem" :title="clipboard[0].shared ? $t('context_menu.share_edit') : $t('context_menu.share')" icon="share" />
|
||||
<Option @click.native="deleteItem" :title="$t('context_menu.delete')" icon="trash" />
|
||||
</OptionGroup>
|
||||
|
||||
<OptionGroup>
|
||||
<Option v-if="!isFolder" @click.native="downloadItem" :title="$t('context_menu.download')" icon="download" />
|
||||
<Option v-if="isFolder" @click.native="downloadFolder" :title="$t('context_menu.zip_folder')" icon="zip-folder" />
|
||||
</OptionGroup>
|
||||
</MenuMobileGroup>
|
||||
|
||||
<!--Base location for user-->
|
||||
<MenuMobileGroup v-if="$isThisLocation(['base', 'participant_uploads', 'latest']) && $checkPermission('master')">
|
||||
<OptionGroup v-if="clipboard[0] && isFolder">
|
||||
<Option @click.native="addToFavourites" :title="favouritesTitle" icon="star" />
|
||||
</OptionGroup>
|
||||
|
||||
<OptionGroup v-if="clipboard[0]">
|
||||
<Option @click.native="renameItem" :title="$t('context_menu.rename')" icon="rename" />
|
||||
<Option @click.native="moveItem" :title="$t('context_menu.move')" icon="move-item" />
|
||||
<Option @click.native="shareItem" :title="clipboard[0].shared ? $t('context_menu.share_edit') : $t('context_menu.share')" icon="share" />
|
||||
<Option @click.native="deleteItem" :title="$t('context_menu.delete')" icon="trash" />
|
||||
</OptionGroup>
|
||||
|
||||
<OptionGroup>
|
||||
<Option v-if="!isFolder" @click.native="downloadItem" :title="$t('context_menu.download')" icon="download" />
|
||||
<Option v-if="isFolder" @click.native="downloadFolder" :title="$t('context_menu.zip_folder')" icon="zip-folder" />
|
||||
</OptionGroup>
|
||||
</MenuMobileGroup>
|
||||
|
||||
<!--Base location for guest-->
|
||||
<MenuMobileGroup v-if="$isThisLocation(['base', 'public']) && $checkPermission('editor')">
|
||||
<OptionGroup>
|
||||
<Option v-if="clipboard[0]" @click.native="renameItem" :title="$t('context_menu.rename')" icon="rename" />
|
||||
<Option v-if="clipboard[0]" @click.native="moveItem" :title="$t('context_menu.move')" icon="move-item" />
|
||||
<Option @click.native="deleteItem" :title="$t('context_menu.delete')" icon="trash" />
|
||||
</OptionGroup>
|
||||
|
||||
<OptionGroup>
|
||||
<Option v-if="!isFolder" @click.native="downloadItem" :title="$t('context_menu.download')" icon="download" />
|
||||
<Option v-if="isFolder" @click.native="downloadFolder" :title="$t('context_menu.zip_folder')" icon="zip-folder" />
|
||||
</OptionGroup>
|
||||
</MenuMobileGroup>
|
||||
|
||||
<!--Base location for guest with visit permission-->
|
||||
<MenuMobileGroup v-if="$isThisLocation(['base', 'public']) && $checkPermission('visitor')">
|
||||
<OptionGroup>
|
||||
<Option v-if="!isFolder" @click.native="downloadItem" :title="$t('context_menu.download')" icon="download" />
|
||||
<Option v-if="isFolder" @click.native="downloadFolder" :title="$t('context_menu.zip_folder')" icon="zip-folder" />
|
||||
</OptionGroup>
|
||||
</MenuMobileGroup>
|
||||
</MenuMobile>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MenuMobileGroup from '@/components/Mobile/MenuMobileGroup'
|
||||
import MenuMobile from '@/components/Mobile/MenuMobile'
|
||||
import ThumbnailItem from '@/components/Others/ThumbnailItem'
|
||||
import OptionGroup from '@/components/FilesView/OptionGroup'
|
||||
import Option from '@/components/FilesView/Option'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'FileMenuMobile',
|
||||
components: {
|
||||
MenuMobileGroup,
|
||||
MenuMobile,
|
||||
ThumbnailItem,
|
||||
OptionGroup,
|
||||
Option,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'clipboard',
|
||||
'user',
|
||||
]),
|
||||
favourites() {
|
||||
return this.user.data.relationships.favourites.data.attributes.folders
|
||||
},
|
||||
favouritesTitle() {
|
||||
return this.isInFavourites
|
||||
? this.$t('context_menu.remove_from_favourites')
|
||||
: this.$t('context_menu.add_to_favourites')
|
||||
},
|
||||
isInFavourites() {
|
||||
return this.favourites.find(el => el.id === this.clipboard[0].id)
|
||||
},
|
||||
isFile() {
|
||||
return !this.isImage && !this.isFolder
|
||||
},
|
||||
isImage() {
|
||||
return this.clipboard[0] && this.clipboard[0].type === 'image'
|
||||
},
|
||||
isFolder() {
|
||||
return this.clipboard[0] && this.clipboard[0].type === 'folder'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isVisible: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
downloadFolder() {
|
||||
this.$store.dispatch('downloadFolder', this.clipboard[0])
|
||||
},
|
||||
moveItem() {
|
||||
events.$emit('popup:open', {name: 'move', item: [this.clipboard[0]]})
|
||||
},
|
||||
shareItem() {
|
||||
let event = this.clipboard[0].shared
|
||||
? 'share-edit'
|
||||
: 'share-create'
|
||||
|
||||
events.$emit('popup:open', {
|
||||
name: event,
|
||||
item: this.clipboard[0]
|
||||
})
|
||||
},
|
||||
addToFavourites() {
|
||||
if (this.favourites && !this.favourites.find(el => el.id === this.clipboard[0].id)) {
|
||||
this.$store.dispatch('addToFavourites', this.clipboard[0])
|
||||
} else {
|
||||
this.$store.dispatch('removeFromFavourites', this.clipboard[0])
|
||||
}
|
||||
},
|
||||
downloadItem() {
|
||||
this.$downloadFile(
|
||||
this.clipboard[0].file_url,
|
||||
this.clipboard[0].name + '.' + this.clipboard[0].mimetype
|
||||
)
|
||||
},
|
||||
deleteItem() {
|
||||
this.$store.dispatch('deleteItem')
|
||||
},
|
||||
restoreItem() {
|
||||
this.$store.dispatch('restoreItem', this.clipboard[0])
|
||||
},
|
||||
renameItem() {
|
||||
events.$emit('popup:open', {name: 'rename-item', item: this.clipboard[0]})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/vuefilemanager/_variables";
|
||||
@import "@assets/vuefilemanager/_mixins";
|
||||
|
||||
.item-thumbnail {
|
||||
padding: 20px 20px 10px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -1,61 +1,77 @@
|
||||
<template>
|
||||
<div v-if="canBePreview" class="preview">
|
||||
<img v-if="fileInfoDetail[0].type == 'image' && fileInfoDetail[0].thumbnail" :src="fileInfoDetail[0].thumbnail" :alt="fileInfoDetail[0].name" />
|
||||
<audio v-else-if="fileInfoDetail[0].type == 'audio'" :src="fileInfoDetail[0].file_url" controlsList="nodownload" controls></audio>
|
||||
<video v-else-if="fileInfoDetail[0].type == 'video'" controlsList="nodownload" disablePictureInPicture playsinline controls>
|
||||
<source :src="fileInfoDetail[0].file_url" type="video/mp4">
|
||||
</video>
|
||||
</div>
|
||||
<div
|
||||
v-if="isFullPreview"
|
||||
class="file-preview"
|
||||
ref="filePreview"
|
||||
tabindex="-1"
|
||||
@keydown.esc="closeFilePreview"
|
||||
@keydown.right="next"
|
||||
@keydown.left="prev"
|
||||
>
|
||||
<FilePreviewToolbar />
|
||||
<FilePreviewMedia />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { includes } from 'lodash'
|
||||
import FilePreviewToolbar from '@/components/FilesView/FilePreviewToolbar'
|
||||
import FilePreviewMedia from '@/components/FilesView/FilePreviewMedia'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'FilePreview',
|
||||
computed: {
|
||||
...mapGetters(['fileInfoDetail']),
|
||||
canBePreview() {
|
||||
return this.fileInfoDetail[0] && ! includes([
|
||||
'folder', 'file'
|
||||
], this.fileInfoDetail[0].type)
|
||||
components: {
|
||||
FilePreviewToolbar,
|
||||
FilePreviewMedia,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isFullPreview: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
closeFilePreview() {
|
||||
this.isFullPreview = false
|
||||
|
||||
events.$emit('showContextMenuPreview:hide')
|
||||
},
|
||||
next() {
|
||||
events.$emit('file-preview:next')
|
||||
},
|
||||
prev() {
|
||||
events.$emit('file-preview:prev')
|
||||
}
|
||||
},
|
||||
updated() {
|
||||
if (this.isFullPreview) {
|
||||
this.$refs.filePreview.focus()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
events.$on('file-preview:show', () => {
|
||||
this.isFullPreview = true
|
||||
})
|
||||
events.$on('file-preview:hide', () => {
|
||||
this.isFullPreview = false
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.preview {
|
||||
.file-preview {
|
||||
width: 100%;
|
||||
display: block;
|
||||
margin-bottom: 7px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
z-index: 7;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
audio {
|
||||
width: 100%;
|
||||
&::-webkit-media-controls-panel {
|
||||
background-color: $light_background;
|
||||
}
|
||||
|
||||
&::-webkit-media-controls-play-button {
|
||||
color: $theme;
|
||||
}
|
||||
}
|
||||
|
||||
video {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 3px;
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.file-preview {
|
||||
background-color: $dark_mode_background;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,78 +0,0 @@
|
||||
<template>
|
||||
<div v-if="filteredFiles.length > 1">
|
||||
<div @click.prevent="prev" class="prev">
|
||||
<chevron-left-icon size="17"></chevron-left-icon>
|
||||
</div>
|
||||
|
||||
<div @click.prevent="next" class="next">
|
||||
<chevron-right-icon size="17"></chevron-right-icon>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { events } from '@/bus'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { ChevronLeftIcon, ChevronRightIcon } from 'vue-feather-icons'
|
||||
export default {
|
||||
name: 'FilePreviewActions',
|
||||
components: {
|
||||
ChevronLeftIcon,
|
||||
ChevronRightIcon
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['fileInfoDetail', 'data']),
|
||||
|
||||
filteredFiles() {
|
||||
let filteredData = []
|
||||
this.data.filter((element) => {
|
||||
if (element.type == this.fileInfoDetail[0].type) {
|
||||
filteredData.push(element)
|
||||
}
|
||||
})
|
||||
return filteredData
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
next: function() {
|
||||
events.$emit('filePreviewAction:next')
|
||||
},
|
||||
prev: function() {
|
||||
events.$emit('filePreviewAction:prev')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
.prev,
|
||||
.next {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 53.5%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
color: $text;
|
||||
border-radius: 50%;
|
||||
text-decoration: none;
|
||||
user-select: none;
|
||||
filter: drop-shadow(0px 1px 0 rgba(255, 255, 255, 1));
|
||||
padding: 10px;
|
||||
}
|
||||
.next {
|
||||
right: 0;
|
||||
}
|
||||
.prev {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.prev,
|
||||
.next {
|
||||
color: $light-text;
|
||||
filter: drop-shadow(0px 1px 0 rgba(17, 19, 20, 1));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,368 @@
|
||||
<template>
|
||||
<div class="media-full-preview" id="mediaPreview" v-if="clipboard[0]">
|
||||
|
||||
<!--Arrow navigation-->
|
||||
<div v-if="files.length > 1" class="navigation-arrows">
|
||||
<div @click.prevent="prev" class="prev">
|
||||
<chevron-left-icon size="17" />
|
||||
</div>
|
||||
|
||||
<div @click.prevent="next" class="next">
|
||||
<chevron-right-icon size="17" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--File preview-->
|
||||
<div class="file-wrapper-preview">
|
||||
|
||||
<!--Show PDF-->
|
||||
<div v-if="isPDF" id="pdf-wrapper" :style="{width: documentSize + '%'}">
|
||||
<pdf :src="pdfdata" v-for="i in numPages" :key="i" :resize="true" :page="i" scale="page-width" style="width:100%; margin:20px auto;" id="printable-file">
|
||||
<template slot="loading">
|
||||
<h1>loading content...</h1>
|
||||
</template>
|
||||
</pdf>
|
||||
</div>
|
||||
|
||||
<!--Show Audio, Video and Image-->
|
||||
<div v-if="!isPDF" class="file-wrapper">
|
||||
|
||||
<audio
|
||||
v-if="isAudio"
|
||||
:class="{ 'file-shadow': !$isMobile() }"
|
||||
class="file audio"
|
||||
:src="currentFile.file_url"
|
||||
controls>
|
||||
</audio>
|
||||
|
||||
<img
|
||||
id="printable-file"
|
||||
v-if="isImage"
|
||||
class="file"
|
||||
:class="{'file-shadow': !$isMobile() }"
|
||||
:src="currentFile.file_url"
|
||||
/>
|
||||
|
||||
<div class="video-wrapper" v-if="isVideo">
|
||||
<video
|
||||
:src="currentFile.file_url"
|
||||
class="video"
|
||||
:class="{'file-shadow': !$isMobile() }"
|
||||
controlsList="nodownload"
|
||||
disablePictureInPicture
|
||||
playsinline
|
||||
controls
|
||||
autoplay
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {ChevronLeftIcon, ChevronRightIcon} from 'vue-feather-icons'
|
||||
import ToolbarButton from '@/components/FilesView/ToolbarButton'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
import pdf from 'pdfvuer'
|
||||
|
||||
export default {
|
||||
name: 'MediaFullPreview',
|
||||
components: {
|
||||
ChevronRightIcon,
|
||||
ChevronLeftIcon,
|
||||
ToolbarButton,
|
||||
Spinner,
|
||||
pdf,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'clipboard',
|
||||
'entries',
|
||||
]),
|
||||
currentFile() {
|
||||
return this.files[Math.abs(this.currentIndex) % this.files.length]
|
||||
},
|
||||
isPDF() {
|
||||
return this.clipboard[0].mimetype === 'pdf'
|
||||
},
|
||||
isVideo() {
|
||||
return this.clipboard[0].type === 'video'
|
||||
},
|
||||
isAudio() {
|
||||
return this.clipboard[0].type === 'audio'
|
||||
},
|
||||
isImage() {
|
||||
return this.clipboard[0].type === 'image'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pdfdata: undefined,
|
||||
numPages: 0,
|
||||
currentIndex: 0,
|
||||
files: [],
|
||||
documentSize: 50,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
files() {
|
||||
if (this.files.length === 0)
|
||||
events.$emit('file-preview:hide')
|
||||
},
|
||||
currentFile() {
|
||||
if (this.clipboard[0]) {
|
||||
this.$store.commit('CLIPBOARD_CLEAR')
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.currentFile)
|
||||
|
||||
// Init pdf instance
|
||||
if (this.clipboard[0].mimetype === 'pdf') {
|
||||
this.getPdf()
|
||||
}
|
||||
}
|
||||
},
|
||||
clipboard() {
|
||||
if (!this.clipboard[0]) {
|
||||
this.currentIndex -= 1
|
||||
|
||||
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.currentFile)
|
||||
|
||||
this.files = []
|
||||
}
|
||||
},
|
||||
data(newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
this.files = []
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
next() {
|
||||
if (!this.files.length > 1) return
|
||||
|
||||
this.pdfdata = undefined
|
||||
|
||||
this.currentIndex += 1
|
||||
|
||||
if (this.currentIndex > this.files.length - 1) {
|
||||
this.currentIndex = 0
|
||||
}
|
||||
},
|
||||
prev() {
|
||||
if (!this.files.length > 1) return
|
||||
|
||||
this.pdfdata = undefined
|
||||
|
||||
this.currentIndex -= 1
|
||||
|
||||
if (this.currentIndex < 0) {
|
||||
this.currentIndex = this.files.length - 1
|
||||
}
|
||||
},
|
||||
getPdf() {
|
||||
this.pdfdata = undefined
|
||||
this.numPages = 0
|
||||
|
||||
let self = this;
|
||||
|
||||
self.pdfdata = pdf.createLoadingTask(this.currentFile.file_url);
|
||||
|
||||
self.pdfdata.then(pdf => self.numPages = pdf.numPages);
|
||||
},
|
||||
getFilesForView() {
|
||||
let requestedFile = this.clipboard[0]
|
||||
|
||||
this.entries.map(element => {
|
||||
|
||||
if (requestedFile.mimetype === 'pdf') {
|
||||
|
||||
if (element.mimetype === 'pdf')
|
||||
this.files.push(element)
|
||||
|
||||
} else {
|
||||
|
||||
if (element.type === requestedFile.type)
|
||||
this.files.push(element)
|
||||
}
|
||||
})
|
||||
|
||||
this.files.forEach((element, index) => {
|
||||
if (element.id === this.clipboard[0].id) {
|
||||
this.currentIndex = index
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
created() {
|
||||
|
||||
// Set zoom size
|
||||
this.documentSize = window.innerWidth < 960 ? 100 : 50
|
||||
|
||||
events.$on('file-preview:next', () => this.next())
|
||||
events.$on('file-preview:prev', () => this.prev())
|
||||
|
||||
events.$on('document-zoom:in', () => {
|
||||
if (this.documentSize < 100)
|
||||
this.documentSize += 10
|
||||
})
|
||||
|
||||
events.$on('document-zoom:out', () => {
|
||||
if (this.documentSize > 40)
|
||||
this.documentSize -= 10
|
||||
})
|
||||
|
||||
this.getFilesForView()
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style src="pdfvuer/dist/pdfvuer.css" lang="css"></style>
|
||||
<style lang="scss">
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.navigation-arrows {
|
||||
|
||||
.prev, .next {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 45%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
color: $text;
|
||||
border-radius: 50%;
|
||||
text-decoration: none;
|
||||
user-select: none;
|
||||
filter: drop-shadow(0px 1px 0 rgba(255, 255, 255, 1));
|
||||
padding: 10px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.next {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.prev {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#pdf-wrapper {
|
||||
overflow-y: scroll;
|
||||
margin: 0 auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.media-full-preview {
|
||||
height: calc(100% - 72px);
|
||||
top: 72px;
|
||||
position: relative;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.file-wrapper-preview {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 30px 0px;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: white;
|
||||
|
||||
.file-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.file-shadow {
|
||||
box-shadow: 0 8px 40px rgba(17, 26, 52, 0.05);
|
||||
}
|
||||
|
||||
.file {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.audio {
|
||||
border-radius: 28px;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.video-wrapper {
|
||||
max-width: 1080px;
|
||||
max-height: 100%;
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
& {
|
||||
max-width: 800px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1920px) and (max-width: 2560px) {
|
||||
& {
|
||||
max-width: 1080px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 2560px) and (max-width: 3840px) {
|
||||
& {
|
||||
max-width: 1440px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 3840px) {
|
||||
& {
|
||||
max-width: 2160px;
|
||||
}
|
||||
}
|
||||
|
||||
.video {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
|
||||
.media-full-preview {
|
||||
top: 53px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.navigation-arrows {
|
||||
.prev, .next {
|
||||
color: $light-text;
|
||||
filter: drop-shadow(0px 1px 0 rgba(17, 19, 20, 1));
|
||||
}
|
||||
}
|
||||
|
||||
.file-wrapper-preview {
|
||||
background-color: $dark_mode_background;
|
||||
|
||||
.file-wrapper {
|
||||
.file-shadow {
|
||||
box-shadow: 0 8px 40px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,319 +0,0 @@
|
||||
<template>
|
||||
<div class="navigation-panel" v-if="fileInfoDetail[0]">
|
||||
<div class="name-wrapper">
|
||||
<x-icon @click="closeFullPreview" size="22" class="icon-close hover-text-theme" />
|
||||
<div class="name-count-wrapper">
|
||||
<p class="title">{{ fileInfoDetail[0].name }}</p>
|
||||
<span class="file-count"> ({{ showingImageIndex + ' ' + $t('pronouns.of') + ' ' + filteredFiles.length }}) </span>
|
||||
</div>
|
||||
<span id="fast-preview-menu" class="fast-menu-icon group" @click.stop="menuOpen" v-if="$checkPermission(['master', 'editor', 'visitor'])">
|
||||
<more-horizontal-icon class="more-icon group-hover-text-theme" size="14" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="created-at-wrapper">
|
||||
<p>{{ fileInfoDetail[0].filesize }}, {{ fileInfoDetail[0].created_at }}</p>
|
||||
</div>
|
||||
<div class="navigation-icons">
|
||||
<div class="navigation-tool-wrapper">
|
||||
<ToolbarButton source="download" class="mobile-hide" @click.native="downloadItem" :action="$t('actions.download')" />
|
||||
<ToolbarButton v-if="canShowShareView" :class="{ 'is-inactive': canShareInView }" @click.native="shareItem" source="share" class="mobile-hide" :action="$t('actions.share')" />
|
||||
<ToolbarButton v-if="this.fileInfoDetail[0].type === 'image'" source="print" :action="$t('actions.print')" @click.native="printMethod()" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { events } from '@/bus'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { XIcon, MoreHorizontalIcon } from 'vue-feather-icons'
|
||||
|
||||
import ToolbarButton from '@/components/FilesView/ToolbarButton'
|
||||
|
||||
export default {
|
||||
name: 'FilePreviewNavigationPanel',
|
||||
components: { ToolbarButton, XIcon, MoreHorizontalIcon },
|
||||
computed: {
|
||||
...mapGetters(['fileInfoDetail', 'data']),
|
||||
filteredFiles() {
|
||||
let files = []
|
||||
this.data.filter((element) => {
|
||||
if (element.type == this.fileInfoDetail[0].type) {
|
||||
files.push(element)
|
||||
}
|
||||
})
|
||||
return files
|
||||
},
|
||||
showingImageIndex() {
|
||||
let activeIndex = ''
|
||||
this.filteredFiles.filter((element, index) => {
|
||||
if (element.id === this.fileInfoDetail[0].id) {
|
||||
activeIndex = index + 1
|
||||
}
|
||||
})
|
||||
return activeIndex
|
||||
},
|
||||
canShowShareView() {
|
||||
return this.$isThisLocation(['base', 'participant_uploads', 'latest', 'shared'])
|
||||
},
|
||||
canShareInView() {
|
||||
return ! this.$isThisLocation(['base', 'participant_uploads', 'latest', 'shared'])
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showContextMenu: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
printMethod() {
|
||||
var tab = document.getElementById('image')
|
||||
var win = window.open('', '', 'height=700,width=700')
|
||||
win.document.write(tab.outerHTML)
|
||||
win.document.close()
|
||||
win.print()
|
||||
},
|
||||
downloadItem() {
|
||||
// Download file
|
||||
this.$downloadFile(this.fileInfoDetail[0].file_url, this.fileInfoDetail[0].name + '.' + this.fileInfoDetail[0].mimetype)
|
||||
},
|
||||
shareItem() {
|
||||
if (this.fileInfoDetail[0].shared) {
|
||||
events.$emit('popup:open', {
|
||||
name: 'share-edit',
|
||||
item: this.fileInfoDetail[0]
|
||||
})
|
||||
} else {
|
||||
events.$emit('popup:open', {
|
||||
name: 'share-create',
|
||||
item: this.fileInfoDetail[0]
|
||||
})
|
||||
}
|
||||
},
|
||||
menuOpen() {
|
||||
if (this.$isMobile()) {
|
||||
events.$emit('mobileMenu:show', 'showFromMediaPreview')
|
||||
} else {
|
||||
events.$emit('showContextMenuPreview:show', this.fileInfoDetail[0])
|
||||
}
|
||||
},
|
||||
closeFullPreview() {
|
||||
events.$emit('fileFullPreview:hide')
|
||||
events.$emit('showContextMenuPreview:hide')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.name-wrapper {
|
||||
width: 33%;
|
||||
height: 22px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
align-self: center;
|
||||
white-space: nowrap;
|
||||
|
||||
.name-count-wrapper {
|
||||
margin-left: 6px;
|
||||
margin-right: 6px;
|
||||
|
||||
.file-count {
|
||||
@include font-size(15);
|
||||
line-height: 1;
|
||||
font-weight: 700;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
align-self: center;
|
||||
color: $text;
|
||||
}
|
||||
.title {
|
||||
@include font-size(15);
|
||||
max-width: 250px;
|
||||
line-height: 1;
|
||||
font-weight: 700;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
color: $text;
|
||||
}
|
||||
@media (max-width: 570px) {
|
||||
.title{
|
||||
max-width: 180px;
|
||||
@include font-size(17);
|
||||
}
|
||||
.file-count {
|
||||
@include font-size(17);
|
||||
}
|
||||
}
|
||||
}
|
||||
.icon-close {
|
||||
min-width: 22px;
|
||||
padding: 1px 4px;
|
||||
border-radius: 6px;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
@include transition(150ms);
|
||||
|
||||
&:hover {
|
||||
background: $light_background;
|
||||
|
||||
line {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
.fast-menu-icon {
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
vertical-align: middle;
|
||||
padding: 1px 4px;
|
||||
line-height: 0;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
@include transition(150ms);
|
||||
|
||||
svg circle {
|
||||
@include transition(150ms);
|
||||
}
|
||||
&:hover {
|
||||
background: $light_background;
|
||||
|
||||
svg circle {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
.more-icon {
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
.context-menu {
|
||||
min-width: 250px;
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
box-shadow: $shadow;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
top: 29px;
|
||||
|
||||
&.showed {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.created-at-wrapper {
|
||||
width: 33%;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
|
||||
p {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@include font-size(11);
|
||||
}
|
||||
}
|
||||
|
||||
.navigation-icons {
|
||||
width: 33%;
|
||||
text-align: right;
|
||||
|
||||
.navigation-tool-wrapper {
|
||||
margin-left: 28px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.button {
|
||||
margin-left: 5px;
|
||||
&:hover {
|
||||
background: $light_background;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.navigation-panel {
|
||||
height: 63px;
|
||||
width: 100%;
|
||||
padding: 10px 15px;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
z-index: 8;
|
||||
align-items: center;
|
||||
background-color: white;
|
||||
color: $text;
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
|
||||
.context-menu {
|
||||
|
||||
.name-wrapper {
|
||||
width: 67%;
|
||||
}
|
||||
}
|
||||
|
||||
.navigation-icons {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navigation-panel {
|
||||
height: 53px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.created-at-wrapper {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.name-wrapper {
|
||||
justify-content: space-between;
|
||||
flex-direction: row-reverse;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.navigation-panel {
|
||||
background-color: $dark_mode_background;
|
||||
color: $dark_mode_text_primary;
|
||||
|
||||
.icon-close {
|
||||
color: $dark_mode_text_primary;
|
||||
&:hover {
|
||||
background-color: $dark_mode_background;
|
||||
}
|
||||
}
|
||||
|
||||
.fast-menu-icon:hover {
|
||||
background: $dark_mode_background;
|
||||
}
|
||||
}
|
||||
|
||||
.name-wrapper {
|
||||
.title,
|
||||
.file-count {
|
||||
color: $dark_mode_text_primary !important;
|
||||
}
|
||||
}
|
||||
|
||||
.navigation-icons {
|
||||
.button:hover {
|
||||
background: $dark_mode_background;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,357 @@
|
||||
<template>
|
||||
<div class="navigation-panel" v-if="clipboard[0]">
|
||||
<div class="name-wrapper">
|
||||
<x-icon @click="closeFullPreview" size="22" class="icon-close hover-text-theme" />
|
||||
<div class="name-count-wrapper">
|
||||
<p class="title">{{ clipboard[0].name }}</p>
|
||||
<span class="file-count"> ({{ showingImageIndex + ' ' + $t('pronouns.of') + ' ' + files.length }}) </span>
|
||||
</div>
|
||||
<span @click.stop="menuOpen" id="fast-preview-menu" class="fast-menu-icon group">
|
||||
<more-horizontal-icon class="more-icon group-hover-text-theme" size="14" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="created-at-wrapper">
|
||||
<p>{{ clipboard[0].filesize }}, {{ clipboard[0].created_at }}</p>
|
||||
</div>
|
||||
|
||||
<div class="navigation-icons">
|
||||
<div v-if="isPdf" class="navigation-tool-wrapper">
|
||||
<ToolbarButton @click.native="increaseSizeOfPDF" source="zoom-in" :action="$t('pdf_zoom_in')" />
|
||||
<ToolbarButton @click.native="decreaseSizeOfPDF" source="zoom-out" :action="$t('pdf_zoom_out')" />
|
||||
</div>
|
||||
<div class="navigation-tool-wrapper">
|
||||
<ToolbarButton @click.native="downloadItem" class="mobile-hide" source="download" :action="$t('actions.download')" />
|
||||
<ToolbarButton v-if="canShareItem" @click.native="shareItem" class="mobile-hide" :class="{ 'is-inactive': !canShareItem }" source="share" :action="$t('actions.share')" />
|
||||
<ToolbarButton v-if="isImage" @click.native="printMethod()" source="print" :action="$t('actions.print')" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ToolbarButton from '@/components/FilesView/ToolbarButton'
|
||||
import {XIcon, MoreHorizontalIcon} from 'vue-feather-icons'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'FilePreviewToolbar',
|
||||
components: {
|
||||
MoreHorizontalIcon,
|
||||
ToolbarButton,
|
||||
XIcon,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'clipboard',
|
||||
'entries'
|
||||
]),
|
||||
isImage() {
|
||||
return this.clipboard[0].type === 'image'
|
||||
},
|
||||
isPdf() {
|
||||
return this.clipboard[0].mimetype === 'pdf'
|
||||
},
|
||||
files() {
|
||||
let files = []
|
||||
|
||||
this.entries.map(element => {
|
||||
|
||||
if (this.clipboard[0].mimetype === 'pdf') {
|
||||
|
||||
if (element.mimetype === 'pdf')
|
||||
files.push(element)
|
||||
|
||||
} else {
|
||||
|
||||
if (element.type === this.clipboard[0].type)
|
||||
files.push(element)
|
||||
}
|
||||
})
|
||||
|
||||
return files
|
||||
},
|
||||
showingImageIndex() {
|
||||
let activeIndex = undefined
|
||||
|
||||
this.files.forEach((element, index) => {
|
||||
if (element.id === this.clipboard[0].id) {
|
||||
activeIndex = index + 1
|
||||
}
|
||||
})
|
||||
|
||||
return activeIndex
|
||||
},
|
||||
canShareItem() {
|
||||
return this.$isThisLocation([
|
||||
'base', 'participant_uploads', 'latest', 'shared'
|
||||
])
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
increaseSizeOfPDF() {
|
||||
events.$emit('document-zoom:in')
|
||||
},
|
||||
decreaseSizeOfPDF() {
|
||||
events.$emit('document-zoom:out')
|
||||
},
|
||||
printMethod() {
|
||||
let tab = document.getElementById('printable-file')
|
||||
let win = window.open('', '', 'height=700,width=700')
|
||||
|
||||
win.document.write(tab.outerHTML)
|
||||
win.document.close()
|
||||
win.print()
|
||||
},
|
||||
downloadItem() {
|
||||
this.$downloadFile(
|
||||
this.clipboard[0].file_url,
|
||||
this.clipboard[0].name + '.' + this.clipboard[0].mimetype
|
||||
)
|
||||
},
|
||||
shareItem() {
|
||||
let event = this.clipboard[0].shared
|
||||
? 'share-edit'
|
||||
: 'share-create'
|
||||
|
||||
events.$emit('popup:open', {
|
||||
name: event,
|
||||
item: this.clipboard[0]
|
||||
})
|
||||
},
|
||||
menuOpen() {
|
||||
if (this.$isMobile()) {
|
||||
events.$emit('mobile-menu:show', 'file-menu')
|
||||
} else {
|
||||
events.$emit('showContextMenuPreview:show', this.clipboard[0])
|
||||
}
|
||||
},
|
||||
closeFullPreview() {
|
||||
events.$emit('file-preview:hide')
|
||||
events.$emit('showContextMenuPreview:hide')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.name-wrapper {
|
||||
width: 33%;
|
||||
height: 22px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
align-self: center;
|
||||
white-space: nowrap;
|
||||
|
||||
.name-count-wrapper {
|
||||
margin-left: 6px;
|
||||
margin-right: 6px;
|
||||
|
||||
.file-count {
|
||||
@include font-size(15);
|
||||
line-height: 1;
|
||||
font-weight: 700;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
align-self: center;
|
||||
color: $text;
|
||||
}
|
||||
|
||||
.title {
|
||||
@include font-size(15);
|
||||
max-width: 250px;
|
||||
line-height: 1;
|
||||
font-weight: 700;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
color: $text;
|
||||
}
|
||||
|
||||
@media (max-width: 570px) {
|
||||
.title {
|
||||
max-width: 180px;
|
||||
@include font-size(17);
|
||||
}
|
||||
.file-count {
|
||||
@include font-size(17);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon-close {
|
||||
min-width: 22px;
|
||||
padding: 1px 4px;
|
||||
border-radius: 6px;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
@include transition(150ms);
|
||||
|
||||
&:hover {
|
||||
background: $light_background;
|
||||
|
||||
line {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fast-menu-icon {
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
vertical-align: middle;
|
||||
padding: 1px 4px;
|
||||
line-height: 0;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
@include transition(150ms);
|
||||
|
||||
svg circle {
|
||||
@include transition(150ms);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $light_background;
|
||||
|
||||
svg circle {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.more-icon {
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.context-menu {
|
||||
min-width: 250px;
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
box-shadow: $shadow;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
top: 29px;
|
||||
|
||||
&.showed {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.created-at-wrapper {
|
||||
width: 33%;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
|
||||
p {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@include font-size(11);
|
||||
}
|
||||
}
|
||||
|
||||
.navigation-icons {
|
||||
width: 33%;
|
||||
text-align: right;
|
||||
|
||||
.navigation-tool-wrapper {
|
||||
margin-left: 28px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.button {
|
||||
margin-left: 5px;
|
||||
|
||||
&:hover {
|
||||
background: $light_background;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.navigation-panel {
|
||||
height: 63px;
|
||||
width: 100%;
|
||||
padding: 10px 15px;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
z-index: 8;
|
||||
align-items: center;
|
||||
background-color: white;
|
||||
color: $text;
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
|
||||
.context-menu {
|
||||
|
||||
.name-wrapper {
|
||||
width: 67%;
|
||||
}
|
||||
}
|
||||
|
||||
.navigation-icons {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navigation-panel {
|
||||
height: 53px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.created-at-wrapper {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.name-wrapper {
|
||||
justify-content: space-between;
|
||||
flex-direction: row-reverse;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.navigation-panel {
|
||||
background-color: $dark_mode_background;
|
||||
color: $dark_mode_text_primary;
|
||||
|
||||
.icon-close {
|
||||
color: $dark_mode_text_primary;
|
||||
|
||||
&:hover {
|
||||
background-color: $dark_mode_background;
|
||||
}
|
||||
}
|
||||
|
||||
.fast-menu-icon:hover {
|
||||
background: $dark_mode_background;
|
||||
}
|
||||
}
|
||||
|
||||
.name-wrapper {
|
||||
.title,
|
||||
.file-count {
|
||||
color: $dark_mode_text_primary !important;
|
||||
}
|
||||
}
|
||||
|
||||
.navigation-icons {
|
||||
.button:hover {
|
||||
background: $dark_mode_background;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<MenuMobile name="file-sorting">
|
||||
<MenuMobileGroup>
|
||||
<FileSortingOptions />
|
||||
</MenuMobileGroup>
|
||||
</MenuMobile>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FileSortingOptions from '@/components/FilesView/FileSortingOptions'
|
||||
import MenuMobileGroup from '@/components/Mobile/MenuMobileGroup'
|
||||
import MenuMobile from '@/components/Mobile/MenuMobile'
|
||||
|
||||
export default {
|
||||
name: 'FilterSortingMobile',
|
||||
components: {
|
||||
FileSortingOptions,
|
||||
MenuMobileGroup,
|
||||
MenuMobile,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
+9
-107
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div class="menu-options" id="menu-list">
|
||||
<OptionGroup class="menu-option-group">
|
||||
<div>
|
||||
<OptionGroup>
|
||||
<Option v-if="isList" @click.native="changePreview('grid')" :title="$t('preview_sorting.grid_view')" icon="grid" />
|
||||
<Option v-if="isGrid" @click.native="changePreview('list')" :title="$t('preview_sorting.list_view')" icon="list" />
|
||||
</OptionGroup>
|
||||
<OptionGroup class="menu-option-group">
|
||||
<OptionGroup>
|
||||
<Option @click.native.stop="sort('created_at')" :title="$t('preview_sorting.sort_date')" icon="calendar" />
|
||||
<Option @click.native.stop="sort('name')" :title="$t('preview_sorting.sort_alphabet')" icon="alphabet" />
|
||||
</OptionGroup>
|
||||
@@ -19,25 +19,20 @@
|
||||
|
||||
import OptionGroup from '@/components/FilesView/OptionGroup'
|
||||
import Option from '@/components/FilesView/Option'
|
||||
import { CalendarIcon, ListIcon, GridIcon, ArrowUpIcon, CheckIcon } from 'vue-feather-icons'
|
||||
import AlphabetIcon from '@/components/FilesView/Icons/AlphabetIcon'
|
||||
import { ArrowUpIcon } from 'vue-feather-icons'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { events } from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'SortingAndPreviewMenu',
|
||||
name: 'FileSortingOptions',
|
||||
components: {
|
||||
OptionGroup,
|
||||
Option,
|
||||
CalendarIcon,
|
||||
AlphabetIcon,
|
||||
ArrowUpIcon,
|
||||
CheckIcon,
|
||||
ListIcon,
|
||||
GridIcon
|
||||
Option,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['FilePreviewType']),
|
||||
...mapGetters([
|
||||
'FilePreviewType'
|
||||
]),
|
||||
isGrid() {
|
||||
return this.FilePreviewType === 'grid'
|
||||
},
|
||||
@@ -55,7 +50,6 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
sort(field) {
|
||||
|
||||
this.filter.field = field
|
||||
|
||||
// Set sorting direction
|
||||
@@ -74,16 +68,10 @@ export default {
|
||||
this.$getDataByLocation()
|
||||
},
|
||||
changePreview(previewType) {
|
||||
|
||||
this.$store.dispatch('changePreviewType', previewType)
|
||||
|
||||
if (this.$isMobile())
|
||||
events.$emit('mobileSortingAndPreview', false)
|
||||
events.$emit('mobileSortingAndPreviewVignette', this.mobileSortingAndPreview)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
let sorting = JSON.parse(localStorage.getItem('sorting'))
|
||||
|
||||
// Set default sorting if in not setup in LocalStorage
|
||||
@@ -92,89 +80,3 @@ export default {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/vuefilemanager/_variables";
|
||||
@import "@assets/vuefilemanager/_mixins";
|
||||
|
||||
.show-icon {
|
||||
margin-left: auto;
|
||||
max-height: 19px;
|
||||
|
||||
.arrow-down {
|
||||
@include transform(rotate(180deg));
|
||||
}
|
||||
}
|
||||
|
||||
.menu-option {
|
||||
display: flex;
|
||||
|
||||
.icon {
|
||||
margin-right: 20px;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
.text-label {
|
||||
@include font-size(16);
|
||||
}
|
||||
}
|
||||
|
||||
.sorting-preview {
|
||||
min-width: 250px;
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
box-shadow: $shadow;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
right: 66px;
|
||||
top: 63px;
|
||||
|
||||
&.showed {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-options {
|
||||
list-style: none;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
.menu-option-group {
|
||||
padding: 5px 0;
|
||||
border-bottom: 1px solid $light_mode_border;
|
||||
|
||||
&:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-bottom: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-option {
|
||||
white-space: nowrap;
|
||||
font-weight: 700;
|
||||
@include font-size(14);
|
||||
padding: 15px 20px;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
color: $text;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.menu-options {
|
||||
.menu-option-group {
|
||||
border-color: $dark_mode_border_color;
|
||||
}
|
||||
|
||||
.menu-option {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<svg class="preview-list-icon" fill="none" stroke="currentColor" stroke-width="1.5" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" width="15px" height="15px" viewBox="0 0 20 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg class="preview-list-icon" fill="none" stroke="currentColor" stroke-width="1.5" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" width="20px" height="20px" viewBox="0 0 20 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<rect x="9.77777778" y="0" width="6.22222222" height="6.22222222"></rect>
|
||||
<rect x="9.77777778" y="9.77777778" width="6.22222222" height="6.22222222"></rect>
|
||||
<line x1="0" y1="2" x2="6" y2="2"></line>
|
||||
@@ -1,108 +1,109 @@
|
||||
<template>
|
||||
<div>
|
||||
<ul class="meta-data-list">
|
||||
<li v-if="fileInfoDetail.metadata.DateTimeOriginal">
|
||||
<li v-if="clipboard.metadata.DateTimeOriginal">
|
||||
<span>{{ $t('file_detail_meta.time_data') }}</span>
|
||||
<b>{{ fileInfoDetail.metadata.DateTimeOriginal }}</b>
|
||||
<b>{{ clipboard.metadata.DateTimeOriginal }}</b>
|
||||
</li>
|
||||
|
||||
<li v-if="fileInfoDetail.metadata.Artist">
|
||||
<li v-if="clipboard.metadata.Artist">
|
||||
<span>{{ $t('file_detail_meta.author') }}</span>
|
||||
<b>{{ fileInfoDetail.metadata.Artist }}</b>
|
||||
<b>{{ clipboard.metadata.Artist }}</b>
|
||||
</li>
|
||||
|
||||
<li v-if="fileInfoDetail.metadata.ExifImageWidth && fileInfoDetail.metadata.ExifImageLength">
|
||||
<li v-if="clipboard.metadata.ExifImageWidth && clipboard.metadata.ExifImageLength">
|
||||
<span>{{ $t('file_detail_meta.dimension') }}</span>
|
||||
<b>{{ fileInfoDetail.metadata.ExifImageWidth }}x{{ fileInfoDetail.metadata.ExifImageLength }}</b>
|
||||
<b>{{ clipboard.metadata.ExifImageWidth }}x{{ clipboard.metadata.ExifImageLength }}</b>
|
||||
</li>
|
||||
|
||||
<li v-if="fileInfoDetail.metadata.XResolution && fileInfoDetail.metadata.YResolution">
|
||||
<li v-if="clipboard.metadata.XResolution && clipboard.metadata.YResolution">
|
||||
<span>{{ $t('file_detail_meta.resolution') }}</span>
|
||||
<b>{{ fileInfoDetail.metadata.XResolution }}x{{ fileInfoDetail.metadata.YResolution }}</b>
|
||||
<b>{{ clipboard.metadata.XResolution }}x{{ clipboard.metadata.YResolution }}</b>
|
||||
</li>
|
||||
|
||||
<li v-if="fileInfoDetail.metadata.ColorSpace">
|
||||
<li v-if="clipboard.metadata.ColorSpace">
|
||||
<span> {{ $t('file_detail_meta.color_space') }}</span>
|
||||
<b>{{ fileInfoDetail.metadata.ColorSpace}}</b>
|
||||
<b>{{ clipboard.metadata.ColorSpace }}</b>
|
||||
</li>
|
||||
|
||||
<!--TODO: Colour profile:sRGB IEC61966-2.1-->
|
||||
<!--TODO: Colour profile:sRGB IEC61966-2.1-->
|
||||
|
||||
<li v-if="fileInfoDetail.metadata.Make">
|
||||
<li v-if="clipboard.metadata.Make">
|
||||
<span>{{ $t('file_detail_meta.make') }}</span>
|
||||
<b>{{ fileInfoDetail.metadata.Make }}</b>
|
||||
<b>{{ clipboard.metadata.Make }}</b>
|
||||
</li>
|
||||
|
||||
<li v-if="fileInfoDetail.metadata.Model">
|
||||
<li v-if="clipboard.metadata.Model">
|
||||
<span>{{ $t('file_detail_meta.model') }}</span>
|
||||
<b>{{ fileInfoDetail.metadata.Model }}</b>
|
||||
<b>{{ clipboard.metadata.Model }}</b>
|
||||
</li>
|
||||
|
||||
<li v-if="fileInfoDetail.metadata.ApertureValue">
|
||||
<li v-if="clipboard.metadata.ApertureValue">
|
||||
<span>{{ $t('file_detail_meta.aperture_value') }}</span>
|
||||
<b v-html="parseInt(fileInfoDetail.metadata.ApertureValue) / 100"></b>
|
||||
<b v-html="parseInt(clipboard.metadata.ApertureValue) / 100"></b>
|
||||
</li>
|
||||
|
||||
<li v-if="fileInfoDetail.metadata.ExposureTime">
|
||||
<li v-if="clipboard.metadata.ExposureTime">
|
||||
<span>{{ $t('file_detail_meta.exposure') }}</span>
|
||||
<b>{{ fileInfoDetail.metadata.ExposureTime }}</b>
|
||||
<b>{{ clipboard.metadata.ExposureTime }}</b>
|
||||
</li>
|
||||
|
||||
<li v-if="fileInfoDetail.metadata.FocalLength">
|
||||
<li v-if="clipboard.metadata.FocalLength">
|
||||
<span>{{ $t('file_detail_meta.focal') }}</span>
|
||||
<b>{{ fileInfoDetail.metadata.FocalLength }}</b>
|
||||
<b>{{ clipboard.metadata.FocalLength }}</b>
|
||||
</li>
|
||||
|
||||
<li v-if="fileInfoDetail.metadata.ISOSpeedRatings">
|
||||
<li v-if="clipboard.metadata.ISOSpeedRatings">
|
||||
<span>{{ $t('file_detail_meta.iso') }}</span>
|
||||
<b>{{ fileInfoDetail.metadata.ISOSpeedRatings }}</b>
|
||||
<b>{{ clipboard.metadata.ISOSpeedRatings }}</b>
|
||||
</li>
|
||||
|
||||
<li v-if="fileInfoDetail.metadata.COMPUTED.ApertureFNumber">
|
||||
<li v-if="clipboard.metadata.COMPUTED.ApertureFNumber">
|
||||
<span>{{ $t('file_detail_meta.aperature') }}</span>
|
||||
<b>{{ fileInfoDetail.metadata.COMPUTED.ApertureFNumber }}</b>
|
||||
<b>{{ clipboard.metadata.COMPUTED.ApertureFNumber }}</b>
|
||||
</li>
|
||||
|
||||
<li v-if="fileInfoDetail.metadata.COMPUTED.CCDWidth">
|
||||
<li v-if="clipboard.metadata.COMPUTED.CCDWidth">
|
||||
<span>{{ $t('file_detail_meta.camera_lens') }}</span>
|
||||
<b>{{ fileInfoDetail.metadata.COMPUTED.CCDWidth }}</b>
|
||||
<b>{{ clipboard.metadata.COMPUTED.CCDWidth }}</b>
|
||||
</li>
|
||||
|
||||
<li v-if="fileInfoDetail.metadata.GPSLongitude">
|
||||
<li v-if="clipboard.metadata.GPSLongitude">
|
||||
<span>{{ $t('file_detail_meta.longitude') }}</span>
|
||||
<b>{{ formatGps(fileInfoDetail.metadata.GPSLongitude,fileInfoDetail.metadata.GPSLongitudeRef) }}</b>
|
||||
</li>
|
||||
|
||||
<li v-if="fileInfoDetail.metadata.GPSLatitude">
|
||||
<span>{{ $t('file_detail_meta.latitude') }}</span>
|
||||
<b>{{ formatGps(fileInfoDetail.metadata.GPSLatitude, fileInfoDetail.metadata.GPSLatitudeRef) }}</b>
|
||||
<b>{{ formatGps(clipboard.metadata.GPSLongitude, clipboard.metadata.GPSLongitudeRef) }}</b>
|
||||
</li>
|
||||
|
||||
<li v-if="clipboard.metadata.GPSLatitude">
|
||||
<span>{{ $t('file_detail_meta.latitude') }}</span>
|
||||
<b>{{ formatGps(clipboard.metadata.GPSLatitude, clipboard.metadata.GPSLatitudeRef) }}</b>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {split} from 'lodash'
|
||||
|
||||
export default {
|
||||
name: 'ImageMetaData',
|
||||
computed: {
|
||||
fileInfoDetail() {
|
||||
return this.$store.getters.fileInfoDetail[0]
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
formatGps(location, ref) {
|
||||
let data = []
|
||||
location.forEach(location => {
|
||||
data.push(split(location , '/' , 2)[0])
|
||||
})
|
||||
return `${data[0]}° ${data[1]}' ${data[2].substr(0,4) / 100}" ${ref} `
|
||||
}
|
||||
},
|
||||
|
||||
name: 'ImageMetaData',
|
||||
computed: {
|
||||
clipboard() {
|
||||
return this.$store.getters.clipboard[0]
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
formatGps(location, ref) {
|
||||
let data = []
|
||||
|
||||
location.forEach(location => {
|
||||
data.push(split(location, '/', 2)[0])
|
||||
})
|
||||
|
||||
return `${data[0]}° ${data[1]}' ${data[2].substr(0, 4) / 100}" ${ref} `
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -111,33 +112,33 @@ export default {
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.meta-data-list {
|
||||
list-style: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
list-style: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 9px 0;
|
||||
border-bottom: 1px solid $light_mode_border;
|
||||
li {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 9px 0;
|
||||
border-bottom: 1px solid $light_mode_border;
|
||||
|
||||
b, span {
|
||||
@include font-size(14);
|
||||
color: $text;
|
||||
}
|
||||
}
|
||||
b, span {
|
||||
@include font-size(14);
|
||||
color: $text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.meta-data-list {
|
||||
li {
|
||||
border-color: $dark_mode_border_color;
|
||||
.meta-data-list {
|
||||
li {
|
||||
border-color: $dark_mode_border_color;
|
||||
|
||||
b, span {
|
||||
color: $dark_mode_text_primary !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
b, span {
|
||||
color: $dark_mode_text_primary !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,186 @@
|
||||
<template>
|
||||
<div class="info-wrapper">
|
||||
|
||||
<!--Is empty clipboard-->
|
||||
<EmptyMessage
|
||||
v-if="isEmpty"
|
||||
:message="$t('messages.nothing_to_preview')"
|
||||
icon="eye-off"
|
||||
/>
|
||||
|
||||
<!--Multiple item selection-->
|
||||
<div v-if="! isSingleFile && !isEmpty" class="info-headline">
|
||||
<TitlePreview
|
||||
icon="check-square"
|
||||
:title="$t('file_detail.selected_multiple')"
|
||||
:subtitle="this.clipboard.length + ' ' + $tc('file_detail.items', this.clipboard.length)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!--Single file preview-->
|
||||
<div v-if="isSingleFile && !isEmpty" class="info-headline">
|
||||
<FilePreviewDetail />
|
||||
|
||||
<TitlePreview
|
||||
:icon="clipboard[0].type"
|
||||
:title="clipboard[0].name"
|
||||
:subtitle="clipboard[0].mimetype"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!--File info-->
|
||||
<ListInfo v-if="isSingleFile && !isEmpty">
|
||||
|
||||
<!--Filesize-->
|
||||
<ListInfoItem
|
||||
v-if="singleFile.filesize"
|
||||
:title="$t('file_detail.size')"
|
||||
:content="singleFile.filesize"
|
||||
/>
|
||||
|
||||
<!--Participant-->
|
||||
<ListInfoItem
|
||||
v-if="$checkPermission(['master']) && singleFile.author !== 'user'"
|
||||
:title="$t('file_detail.author')"
|
||||
:content="$t('file_detail.author_participant')"
|
||||
/>
|
||||
|
||||
<!--Created At-->
|
||||
<ListInfoItem
|
||||
:title="$t('file_detail.created_at')"
|
||||
:content="singleFile.created_at"
|
||||
/>
|
||||
|
||||
<!--Location-->
|
||||
<ListInfoItem
|
||||
v-if="$checkPermission(['master'])"
|
||||
:title="$t('file_detail.where')"
|
||||
>
|
||||
<div class="action-button" @click="openMoveOptions">
|
||||
<span>{{ singleFile.parent ? singleFile.parent.name : $t('locations.home') }}</span>
|
||||
<edit-2-icon size="10" class="edit-icon" />
|
||||
</div>
|
||||
</ListInfoItem>
|
||||
|
||||
<!--Shared-->
|
||||
<ListInfoItem
|
||||
v-if="$checkPermission('master') && singleFile.shared"
|
||||
:title="$t('file_detail.shared')"
|
||||
>
|
||||
<div @click="openShareOptions" class="action-button">
|
||||
<span>{{ sharedInfo }}</span>
|
||||
<edit-2-icon size="10" class="edit-icon" />
|
||||
</div>
|
||||
<div class="share-link">
|
||||
<lock-icon v-if="isLocked" @click="openShareOptions" class="lock-icon" size="17" />
|
||||
<unlock-icon v-if="! isLocked" @click="openShareOptions" class="lock-icon" size="17" />
|
||||
<CopyInput :item="singleFile" class="copy-share-link" size="small" />
|
||||
</div>
|
||||
</ListInfoItem>
|
||||
|
||||
<!--Metadata-->
|
||||
<ListInfoItem
|
||||
v-if="canShowMetaData"
|
||||
:title="$t('file_detail_meta.meta_data')"
|
||||
>
|
||||
<ImageMetaData />
|
||||
</ListInfoItem>
|
||||
</ListInfo>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FilePreviewDetail from '@/components/Others/FilePreviewDetail'
|
||||
import {Edit2Icon, LockIcon, UnlockIcon} from 'vue-feather-icons'
|
||||
import ImageMetaData from '@/components/FilesView/ImageMetaData'
|
||||
import EmptyMessage from '@/components/FilesView/EmptyMessage'
|
||||
import TitlePreview from '@/components/FilesView/TitlePreview'
|
||||
import CopyInput from '@/components/Others/Forms/CopyInput'
|
||||
import ListInfoItem from '@/components/Others/ListInfoItem'
|
||||
import ListInfo from '@/components/Others/ListInfo'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from "@/bus"
|
||||
|
||||
export default {
|
||||
name: 'InfoSidebar',
|
||||
components: {
|
||||
FilePreviewDetail,
|
||||
ImageMetaData,
|
||||
EmptyMessage,
|
||||
TitlePreview,
|
||||
ListInfoItem,
|
||||
UnlockIcon,
|
||||
CopyInput,
|
||||
Edit2Icon,
|
||||
LockIcon,
|
||||
ListInfo,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'permissionOptions',
|
||||
'clipboard',
|
||||
]),
|
||||
isEmpty() {
|
||||
return this.clipboard.length === 0
|
||||
},
|
||||
isSingleFile() {
|
||||
return this.clipboard.length === 1
|
||||
},
|
||||
singleFile() {
|
||||
return this.clipboard[0]
|
||||
},
|
||||
canShowMetaData() {
|
||||
return this.clipboard[0].metadata && this.clipboard[0].metadata.ExifImageWidth
|
||||
},
|
||||
isLocked() {
|
||||
return this.clipboard[0].shared.is_protected
|
||||
},
|
||||
sharedInfo() {
|
||||
let title = this.permissionOptions.find(option => {
|
||||
return option.value === this.clipboard[0].shared.permission
|
||||
})
|
||||
|
||||
return title ? this.$t(title.label) : this.$t('shared.can_download')
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
openShareOptions() {
|
||||
events.$emit('popup:open', {name: 'share-edit', item: this.clipboard[0]})
|
||||
},
|
||||
openMoveOptions() {
|
||||
events.$emit("popup:open", {name: "move", item: this.clipboard});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.info-wrapper {
|
||||
padding-bottom: 20px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.info-headline {
|
||||
margin-bottom: 20px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.share-link {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
|
||||
.lock-icon {
|
||||
display: inline-block;
|
||||
width: 15px;
|
||||
margin-right: 9px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.copy-share-link {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,236 +0,0 @@
|
||||
<template>
|
||||
<div class="media-full-preview" id="mediaPreview" v-if="this.isMedia && fileInfoDetail[0]">
|
||||
<div class="file-wrapper-preview" v-for="i in [currentIndex]" :key="i">
|
||||
<div class="file-wrapper">
|
||||
<audio class="file audio" :class="{ 'file-shadow': !isMobileDevice }" v-if="fileInfoDetail[0].type == 'audio'" :src="currentFile.file_url" controlsList="nodownload" controls></audio>
|
||||
<img v-if="fileInfoDetail[0].type === 'image' && currentFile.thumbnail" class="file" :class="{ 'file-shadow': !isMobileDevice }" id="image" :src="currentFile.file_url" />
|
||||
<div class="video-wrapper" v-if="fileInfoDetail[0].type === 'video' && currentFile.file_url">
|
||||
<video :src="currentFile.file_url" class="video" :class="{ 'file-shadow': !isMobileDevice }" controlsList="nodownload" disablePictureInPicture playsinline controls autoplay />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { events } from '@/bus'
|
||||
import { mapGetters } from 'vuex'
|
||||
import ToolbarButton from '@/components/FilesView/ToolbarButton'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
|
||||
export default {
|
||||
name: 'MediaFullPreview',
|
||||
components: { ToolbarButton, Spinner },
|
||||
computed: {
|
||||
...mapGetters(['fileInfoDetail', 'data']),
|
||||
|
||||
isMobileDevice() {
|
||||
return this.$isMobile()
|
||||
},
|
||||
|
||||
currentFile: function() {
|
||||
return this.sliderFile[Math.abs(this.currentIndex) % this.sliderFile.length]
|
||||
},
|
||||
isMedia() {
|
||||
return this.fileInfoDetail[0] === 'image' || 'video' || 'audio'
|
||||
},
|
||||
|
||||
canShareInView() {
|
||||
return !this.$isThisLocation(['base', 'participant_uploads', 'latest', 'shared', 'public'])
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentIndex: 1,
|
||||
sliderFile: []
|
||||
// loaded: false
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
sliderFile() {
|
||||
//Close file preview after delete all items
|
||||
if (this.sliderFile.length == 0) {
|
||||
events.$emit('fileFullPreview:hide')
|
||||
}
|
||||
},
|
||||
currentFile() {
|
||||
//Handle actual view image in fileInfoDetail
|
||||
if (this.fileInfoDetail[0]) {
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.currentFile)
|
||||
events.$emit('actualShowingImage:ContextMenu', this.currentFile)
|
||||
// this.loaded = false
|
||||
}
|
||||
},
|
||||
fileInfoDetail() {
|
||||
//File delete handling - show next image after delete one
|
||||
if (!this.fileInfoDetail[0]) {
|
||||
this.currentIndex = this.currentIndex - 1
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.currentFile)
|
||||
this.sliderFile = []
|
||||
this.filteredFiles()
|
||||
}
|
||||
},
|
||||
data(newValue, oldValue) {
|
||||
//Move item handling
|
||||
if (newValue != oldValue) {
|
||||
this.sliderFile = []
|
||||
this.filteredFiles()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
filteredFiles() {
|
||||
this.data.filter((element) => {
|
||||
if (element.type == this.fileInfoDetail[0].type) {
|
||||
this.sliderFile.push(element)
|
||||
}
|
||||
})
|
||||
this.choseActiveFile()
|
||||
},
|
||||
choseActiveFile() {
|
||||
this.sliderFile.forEach((element, index) => {
|
||||
if (element.id == this.fileInfoDetail[0].id) {
|
||||
this.currentIndex = index
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.sliderFile.length > 1) {
|
||||
events.$on('filePreviewAction:next', () => {
|
||||
this.currentIndex += 1
|
||||
this.slideType = 'next'
|
||||
if (this.currentIndex > this.sliderFile.length - 1) {
|
||||
this.currentIndex = 0
|
||||
}
|
||||
})
|
||||
events.$on('filePreviewAction:prev', () => {
|
||||
this.slideType = 'prev'
|
||||
this.currentIndex -= 1
|
||||
if (this.currentIndex < 0) {
|
||||
this.currentIndex = this.sliderFile.length - 1
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.filteredFiles()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.media-full-preview {
|
||||
height: calc(100% - 72px);
|
||||
top: 72px;
|
||||
position: relative;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.navigation-panel {
|
||||
width: 100%;
|
||||
height: 7%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
justify-content: space-between;
|
||||
background-color: $light-background;
|
||||
color: $text;
|
||||
.icon-close {
|
||||
color: $text;
|
||||
@include font-size(21);
|
||||
&:hover {
|
||||
color: $theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.file-wrapper-preview {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 30px 0px;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: white;
|
||||
|
||||
.file-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.file-shadow {
|
||||
box-shadow: 0 8px 40px rgba(17, 26, 52, 0.05);
|
||||
}
|
||||
|
||||
.file {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.audio {
|
||||
border-radius: 28px;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.video-wrapper {
|
||||
max-width: 1080px;
|
||||
max-height: 100%;
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
& {
|
||||
max-width: 800px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1920px) and (max-width: 2560px) {
|
||||
& {
|
||||
max-width: 1080px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 2560px) and (max-width: 3840px) {
|
||||
& {
|
||||
max-width: 1440px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 3840px) {
|
||||
& {
|
||||
max-width: 2160px;
|
||||
}
|
||||
}
|
||||
.video {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.file-wrapper-preview {
|
||||
background-color: $dark_mode_background;
|
||||
.file-wrapper {
|
||||
.file-shadow {
|
||||
box-shadow: 0 8px 40px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<button class="mobile-action-button">
|
||||
<div class="flex">
|
||||
<filter-icon v-if="icon === 'filter'" size="15" class="icon dark-text-theme" />
|
||||
<credit-card-icon v-if="icon === 'credit-card'" size="15" class="icon dark-text-theme" />
|
||||
<folder-plus-icon v-if="icon === 'folder-plus'" size="15" class="icon dark-text-theme" />
|
||||
<list-icon v-if="icon === 'th-list'" size="15" class="icon dark-text-theme" />
|
||||
@@ -12,7 +13,7 @@
|
||||
<x-square-icon v-if="icon === 'x-square'" size="15" class="icon dark-text-theme" />
|
||||
<check-icon v-if="icon === 'check'" size="15" class="icon dark-text-theme" />
|
||||
<dollar-sign-icon v-if="icon === 'dollar-sign'" size="15" class="icon dark-text-theme" />
|
||||
<sorting-and-preview-icon v-if="icon === 'preview-sorting'" size="15" class="icon dark-text-theme preview-sorting" />
|
||||
<sorting-icon v-if="icon === 'preview-sorting'" class="icon dark-text-theme preview-sorting" />
|
||||
<span class="label">
|
||||
<slot></slot>
|
||||
</span>
|
||||
@@ -21,8 +22,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { DollarSignIcon, CheckIcon, XSquareIcon, CheckSquareIcon, FolderPlusIcon, ListIcon, GridIcon, TrashIcon, UserPlusIcon, PlusIcon, CreditCardIcon } from 'vue-feather-icons'
|
||||
import SortingAndPreviewIcon from '@/components/FilesView/Icons/SortingAndPreviewIcon'
|
||||
import { FilterIcon, DollarSignIcon, CheckIcon, XSquareIcon, CheckSquareIcon, FolderPlusIcon, ListIcon, GridIcon, TrashIcon, UserPlusIcon, PlusIcon, CreditCardIcon } from 'vue-feather-icons'
|
||||
import SortingIcon from '@/components/FilesView/Icons/SortingIcon'
|
||||
|
||||
export default {
|
||||
name: 'MobileActionButton',
|
||||
@@ -30,13 +31,14 @@
|
||||
'icon'
|
||||
],
|
||||
components: {
|
||||
SortingAndPreviewIcon,
|
||||
SortingIcon,
|
||||
CheckSquareIcon,
|
||||
DollarSignIcon,
|
||||
CreditCardIcon,
|
||||
FolderPlusIcon,
|
||||
UserPlusIcon,
|
||||
XSquareIcon,
|
||||
FilterIcon,
|
||||
CheckIcon,
|
||||
TrashIcon,
|
||||
PlusIcon,
|
||||
@@ -52,9 +54,9 @@
|
||||
|
||||
.mobile-action-button {
|
||||
background: $light_background;
|
||||
margin-right: 15px;
|
||||
margin-right: 8px;
|
||||
border-radius: 8px;
|
||||
padding: 7px 10px;
|
||||
padding: 7px 14px;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
@include transition(150ms);
|
||||
@@ -68,7 +70,7 @@
|
||||
margin-right: 10px;
|
||||
@include font-size(14);
|
||||
|
||||
path, line, polyline, rect, circle {
|
||||
path, line, polyline, rect, circle, polygon {
|
||||
@include transition(150ms);
|
||||
}
|
||||
}
|
||||
@@ -89,7 +91,7 @@
|
||||
.mobile-action-button {
|
||||
background: $dark_mode_foreground;
|
||||
|
||||
path, line, polyline, rect, circle {
|
||||
path, line, polyline, rect, circle, polygon {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,9 +39,9 @@
|
||||
|
||||
.mobile-action-button {
|
||||
background: $light_background;
|
||||
margin-right: 15px;
|
||||
margin-right: 8px;
|
||||
border-radius: 8px;
|
||||
padding: 7px 10px;
|
||||
padding: 7px 14px;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
|
||||
|
||||
@@ -1,192 +0,0 @@
|
||||
<template>
|
||||
<div id="mobile-actions-wrapper">
|
||||
|
||||
<!--Actions for trash location with MASTER permission--->
|
||||
<div v-if="trashLocationMenu && ! multiSelectMode" class="mobile-actions">
|
||||
<MobileActionButton @click.native="$store.dispatch('emptyTrash')" icon="trash">
|
||||
{{ $t('context_menu.empty_trash') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="enableMultiSelectMode" icon="check-square">
|
||||
{{ $t('context_menu.select') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton class="preview-sorting" @click.native="showViewOptions" icon="preview-sorting">
|
||||
{{$t('preview_sorting.preview_sorting_button')}}
|
||||
</MobileActionButton>
|
||||
</div>
|
||||
|
||||
<!--ContextMenu for Base location with MASTER permission-->
|
||||
<transition name="button">
|
||||
<div v-if="baseLocationMasterMenu && ! multiSelectMode" class="mobile-actions">
|
||||
<MobileActionButton @click.native="createFolder" icon="folder-plus" :class="{'is-inactive' : multiSelectMode}">
|
||||
{{ $t('context_menu.add_folder') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButtonUpload :class="{'is-inactive' : multiSelectMode}">
|
||||
{{ $t('context_menu.upload') }}
|
||||
</MobileActionButtonUpload>
|
||||
<MobileActionButton @click.native="enableMultiSelectMode" icon="check-square">
|
||||
{{ $t('context_menu.select') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton class="preview-sorting" @click.native="showViewOptions" icon="preview-sorting">
|
||||
{{$t('preview_sorting.preview_sorting_button')}}
|
||||
</MobileActionButton>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<!-- Selecting buttons -->
|
||||
<transition name="button">
|
||||
<div v-if="multiSelectMode" class="mobile-actions">
|
||||
<MobileActionButton @click.native="selectAll" icon="check-square">
|
||||
{{$t('mobile_selecting.select_all')}}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="deselectAll" icon="x-square">
|
||||
{{$t('mobile_selecting.deselect_all')}}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="disableMultiSelectMode" icon="check">
|
||||
{{$t('mobile_selecting.done')}}
|
||||
</MobileActionButton>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<!--ContextMenu for Base location with VISITOR permission-->
|
||||
<div v-if="baseLocationVisitorMenu && ! multiSelectMode" class="mobile-actions">
|
||||
<MobileActionButton @click.native="enableMultiSelectMode" icon="check-square">
|
||||
{{ $t('context_menu.select') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton class="preview-sorting" @click.native="showViewOptions" icon="preview-sorting">
|
||||
{{$t('preview_sorting.preview_sorting_button')}}
|
||||
</MobileActionButton>
|
||||
</div>
|
||||
|
||||
<!--Upload Progressbar-->
|
||||
<UploadProgress />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MobileActionButtonUpload from '@/components/FilesView/MobileActionButtonUpload'
|
||||
import MobileActionButton from '@/components/FilesView/MobileActionButton'
|
||||
import UploadProgress from '@/components/FilesView/UploadProgress'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'MobileActions',
|
||||
components: {
|
||||
MobileActionButtonUpload,
|
||||
MobileActionButton,
|
||||
UploadProgress,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['FilePreviewType']),
|
||||
previewIcon() {
|
||||
return this.FilePreviewType === 'list' ? 'th' : 'th-list'
|
||||
},
|
||||
trashLocationMenu() {
|
||||
return this.$isThisLocation(['trash', 'trash-root']) && this.$checkPermission('master')
|
||||
},
|
||||
baseLocationMasterMenu() {
|
||||
return this.$isThisLocation(['base', 'public']) && this.$checkPermission(['master', 'editor'])
|
||||
},
|
||||
baseLocationVisitorMenu() {
|
||||
return (this.$isThisLocation(['base', 'shared', 'public']) && this.$checkPermission('visitor')) || (this.$isThisLocation(['latest', 'shared']) && this.$checkPermission('master'))
|
||||
},
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
multiSelectMode: false,
|
||||
mobileSortingAndPreview: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selectAll() {
|
||||
this.$store.commit('SELECT_ALL_FILES')
|
||||
},
|
||||
deselectAll() {
|
||||
this.$store.commit('CLEAR_FILEINFO_DETAIL')
|
||||
},
|
||||
enableMultiSelectMode() {
|
||||
this.multiSelectMode = true
|
||||
|
||||
events.$emit('mobileSelecting:start')
|
||||
},
|
||||
disableMultiSelectMode() {
|
||||
this.multiSelectMode = false
|
||||
|
||||
events.$emit('mobileSelecting:stop')
|
||||
},
|
||||
showViewOptions() {
|
||||
this.mobileSortingAndPreview = ! this.mobileSortingAndPreview
|
||||
|
||||
// Toggle mobile sorting
|
||||
events.$emit('mobileSortingAndPreview', this.mobileSortingAndPreview)
|
||||
events.$emit('mobileSortingAndPreviewVignette', this.mobileSortingAndPreview)
|
||||
},
|
||||
createFolder() {
|
||||
events.$emit('popup:open', {name: 'create-folder'})
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
events.$on('mobileSelecting:stop', () => this.multiSelectMode = false)
|
||||
events.$on('mobileSortingAndPreview', state => this.mobileSortingAndPreview = state)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.button-enter-active,
|
||||
.button-leave-active {
|
||||
transition: all 250ms;
|
||||
}
|
||||
|
||||
.button-enter {
|
||||
opacity: 0;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.button-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(50%);
|
||||
}
|
||||
|
||||
.button-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#mobile-actions-wrapper {
|
||||
display: none;
|
||||
background: white;
|
||||
position: sticky;
|
||||
top: 35px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.mobile-action-button {
|
||||
&.is-inactive {
|
||||
opacity: 0.25;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-actions {
|
||||
white-space: nowrap;
|
||||
overflow-x: auto;
|
||||
margin: 0 -15px;
|
||||
padding: 10px 0 10px 15px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
|
||||
#mobile-actions-wrapper {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
#mobile-actions-wrapper {
|
||||
background: $dark_mode_background;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,560 +0,0 @@
|
||||
<template>
|
||||
<div class="options-wrapper">
|
||||
<transition name="context-menu">
|
||||
<div v-if="isVisible" ref="contextmenu" class="options" @click="closeAndResetContextMenu">
|
||||
|
||||
<div class="menu-wrapper">
|
||||
|
||||
<!--Item Thumbnail-->
|
||||
<ThumbnailItem class="item-thumbnail" :item="fileInfoDetail[0]" info="metadata"/>
|
||||
|
||||
<!--Mobile for trash location-->
|
||||
<div v-if="$isThisLocation(['trash', 'trash-root']) && $checkPermission('master')" class="menu-options">
|
||||
<ul class="menu-option-group">
|
||||
<li class="menu-option" @click="$store.dispatch('restoreItem', fileInfoDetail[0])" v-if="fileInfoDetail[0]">
|
||||
<div class="icon">
|
||||
<life-buoy-icon size="17"></life-buoy-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.restore') }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="menu-option delete" @click="deleteItem" v-if="fileInfoDetail[0]">
|
||||
<div class="icon">
|
||||
<trash-2-icon size="17"></trash-2-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.delete') }}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="menu-option-group" >
|
||||
<li class="menu-option" @click="downloadItem" v-if="!isFolder">
|
||||
<div class="icon">
|
||||
<download-cloud-icon size="17"></download-cloud-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.download') }}
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="menu-option" @click="downloadFolder" v-if="isFolder">
|
||||
<div class="icon">
|
||||
<paperclip-icon size="17"></paperclip-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.zip_folder') }}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!--Mobile for Base location-->
|
||||
<div v-if="$isThisLocation(['shared']) && $checkPermission('master')" class="menu-options">
|
||||
<ul class="menu-option-group">
|
||||
<li class="menu-option" @click="addToFavourites" v-if="fileInfoDetail[0] && isFolder">
|
||||
<div class="icon">
|
||||
<star-icon size="17"></star-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{
|
||||
isInFavourites
|
||||
? $t('context_menu.remove_from_favourites')
|
||||
: $t('context_menu.add_to_favourites')
|
||||
}}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="menu-option-group">
|
||||
<li class="menu-option" @click="renameItem" v-if="fileInfoDetail[0]">
|
||||
<div class="icon">
|
||||
<edit-2-icon size="17"></edit-2-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.rename') }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="menu-option" @click="shareItem" v-if="fileInfoDetail[0]">
|
||||
<div class="icon">
|
||||
<link-icon size="17"></link-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{
|
||||
fileInfoDetail[0].shared
|
||||
? $t('context_menu.share_edit')
|
||||
: $t('context_menu.share')
|
||||
}}
|
||||
</div>
|
||||
</li>
|
||||
<li class="menu-option delete" @click="deleteItem" v-if="fileInfoDetail[0]">
|
||||
<div class="icon">
|
||||
<trash-2-icon size="17"></trash-2-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.delete') }}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="menu-option-group">
|
||||
<li class="menu-option" @click="downloadItem" v-if="!isFolder">
|
||||
<div class="icon">
|
||||
<download-cloud-icon size="17"></download-cloud-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.download') }}
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="menu-option" @click="downloadFolder" v-if="isFolder">
|
||||
<div class="icon">
|
||||
<paperclip-icon size="17"></paperclip-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.zip_folder') }}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!--Mobile for Base location-->
|
||||
<div v-if="$isThisLocation(['base', 'participant_uploads', 'latest']) && $checkPermission('master')" class="menu-options">
|
||||
<ul class="menu-option-group" v-if="fileInfoDetail[0] && isFolder">
|
||||
<li class="menu-option" @click="addToFavourites">
|
||||
<div class="icon">
|
||||
<star-icon size="17"></star-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{
|
||||
isInFavourites
|
||||
? $t('context_menu.remove_from_favourites')
|
||||
: $t('context_menu.add_to_favourites')
|
||||
}}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="menu-option-group">
|
||||
<li class="menu-option" @click="renameItem" v-if="fileInfoDetail[0]">
|
||||
<div class="icon">
|
||||
<edit-2-icon size="17"></edit-2-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.rename') }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="menu-option" @click="moveItem" v-if="fileInfoDetail[0]">
|
||||
<div class="icon">
|
||||
<corner-down-right-icon size="17"></corner-down-right-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.move') }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="menu-option" @click="shareItem" v-if="fileInfoDetail[0]">
|
||||
<div class="icon">
|
||||
<link-icon size="17"></link-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{
|
||||
fileInfoDetail[0].shared
|
||||
? $t('context_menu.share_edit')
|
||||
: $t('context_menu.share')
|
||||
}}
|
||||
</div>
|
||||
</li>
|
||||
<li class="menu-option delete" @click="deleteItem" v-if="fileInfoDetail[0]">
|
||||
<div class="icon">
|
||||
<trash-2-icon size="17"></trash-2-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.delete') }}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="menu-option-group">
|
||||
<li class="menu-option" @click="downloadItem" v-if="!isFolder">
|
||||
<div class="icon">
|
||||
<download-cloud-icon size="17"></download-cloud-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.download') }}
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="menu-option" @click="downloadFolder" v-if="isFolder">
|
||||
<div class="icon">
|
||||
<paperclip-icon size="17"></paperclip-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.zip_folder') }}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!--Mobile for Base location with EDITOR permission-->
|
||||
<div v-if="$isThisLocation(['base', 'public']) && $checkPermission('editor')" class="menu-options">
|
||||
<ul class="menu-option-group">
|
||||
<li class="menu-option" @click="renameItem" v-if="fileInfoDetail[0]">
|
||||
<div class="icon">
|
||||
<edit-2-icon size="17"></edit-2-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.rename') }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="menu-option" @click="moveItem" v-if="fileInfoDetail[0]">
|
||||
<div class="icon">
|
||||
<corner-down-right-icon size="17"></corner-down-right-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.move') }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="menu-option" @click="deleteItem">
|
||||
<div class="icon">
|
||||
<trash-2-icon size="17"></trash-2-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.delete') }}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="menu-option-group">
|
||||
<li class="menu-option" @click="downloadItem" v-if="!isFolder">
|
||||
<div class="icon">
|
||||
<download-cloud-icon size="17"></download-cloud-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.download') }}
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="menu-option" @click="downloadFolder" v-if="isFolder">
|
||||
<div class="icon">
|
||||
<paperclip-icon size="17"></paperclip-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.zip_folder') }}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!--Mobile for Base location with VISITOR permission-->
|
||||
<div v-if="$isThisLocation(['base', 'public']) && $checkPermission('visitor')" class="menu-options">
|
||||
<ul class="menu-option-group">
|
||||
<li class="menu-option" @click="downloadItem" v-if="!isFolder">
|
||||
<div class="icon">
|
||||
<download-cloud-icon size="17"></download-cloud-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.download') }}
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="menu-option" @click="downloadFolder" v-if="isFolder">
|
||||
<div class="icon">
|
||||
<paperclip-icon size="17"></paperclip-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.zip_folder') }}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<transition name="fade">
|
||||
<div v-show="isVisible" class="vignette" @click="closeAndResetContextMenu"></div>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ThumbnailItem from '@/components/Others/ThumbnailItem'
|
||||
|
||||
import {
|
||||
CornerDownRightIcon,
|
||||
DownloadCloudIcon,
|
||||
FolderPlusIcon,
|
||||
PaperclipIcon,
|
||||
LifeBuoyIcon,
|
||||
Trash2Icon,
|
||||
Edit2Icon,
|
||||
TrashIcon,
|
||||
StarIcon,
|
||||
LinkIcon,
|
||||
EyeIcon
|
||||
} from 'vue-feather-icons'
|
||||
import { events } from '@/bus'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'MobileMenu',
|
||||
components: {
|
||||
CornerDownRightIcon,
|
||||
DownloadCloudIcon,
|
||||
FolderPlusIcon,
|
||||
PaperclipIcon,
|
||||
ThumbnailItem,
|
||||
LifeBuoyIcon,
|
||||
Trash2Icon,
|
||||
Edit2Icon,
|
||||
TrashIcon,
|
||||
LinkIcon,
|
||||
StarIcon,
|
||||
EyeIcon
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['fileInfoDetail', 'user']),
|
||||
favourites() {
|
||||
return this.user.data.relationships.favourites.data.attributes.folders
|
||||
},
|
||||
isInFavourites() {
|
||||
return this.favourites.find(
|
||||
(el) => el.id == this.fileInfoDetail[0].id
|
||||
)
|
||||
},
|
||||
isFile() {
|
||||
return (
|
||||
this.fileInfoDetail[0] &&
|
||||
this.fileInfoDetail[0].type !== 'folder' &&
|
||||
this.fileInfoDetail[0] &&
|
||||
this.fileInfoDetail[0].type !== 'image'
|
||||
)
|
||||
},
|
||||
isImage() {
|
||||
return this.fileInfoDetail[0] && this.fileInfoDetail[0].type === 'image'
|
||||
},
|
||||
isFolder() {
|
||||
return this.fileInfoDetail[0] && this.fileInfoDetail[0].type === 'folder'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isVisible: false,
|
||||
showFromMediaPreview: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
downloadFolder(){
|
||||
this.$store.dispatch( 'downloadFolder' , this.fileInfoDetail[0] )
|
||||
},
|
||||
moveItem() {
|
||||
events.$emit('popup:open', { name: 'move', item: [this.fileInfoDetail[0]] })
|
||||
},
|
||||
shareItem() {
|
||||
if (this.fileInfoDetail[0].shared) {
|
||||
// Open share item popup
|
||||
events.$emit('popup:open', {
|
||||
name: 'share-edit',
|
||||
item: this.fileInfoDetail[0]
|
||||
})
|
||||
} else {
|
||||
// Open share item popup
|
||||
events.$emit('popup:open', {
|
||||
name: 'share-create',
|
||||
item: this.fileInfoDetail[0]
|
||||
})
|
||||
}
|
||||
},
|
||||
addToFavourites() {
|
||||
if (
|
||||
this.favourites &&
|
||||
!this.favourites.find(
|
||||
(el) => el.id == this.fileInfoDetail[0].id
|
||||
)
|
||||
) {
|
||||
this.$store.dispatch('addToFavourites', this.fileInfoDetail[0])
|
||||
} else {
|
||||
this.$store.dispatch('removeFromFavourites', this.fileInfoDetail[0])
|
||||
}
|
||||
},
|
||||
downloadItem() {
|
||||
this.$downloadFile(
|
||||
this.fileInfoDetail[0].file_url,
|
||||
this.fileInfoDetail[0].name + '.' + this.fileInfoDetail[0].mimetype
|
||||
)
|
||||
},
|
||||
deleteItem() {
|
||||
this.$store.dispatch('deleteItem')
|
||||
},
|
||||
renameItem() {
|
||||
events.$emit('popup:open', { name: 'rename-item', item: this.fileInfoDetail[0] })
|
||||
},
|
||||
closeAndResetContextMenu() {
|
||||
//If emit to show menu coming from MediaFullPreview dont reset data
|
||||
this.isVisible = false
|
||||
this.showFromMediaPreview = false
|
||||
events.$emit('hide:mobile-navigation')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
events.$on('mobileMenu:show', showFromMedia => {
|
||||
// If emit come from MediaFullPreview
|
||||
if (showFromMedia) {
|
||||
this.isVisible = true
|
||||
this.showFromMediaPreview = true
|
||||
} else {
|
||||
this.isVisible = !this.isVisible
|
||||
}
|
||||
})
|
||||
|
||||
// Hide mobile menu
|
||||
events.$on('mobileMenu:hide', () => {
|
||||
this.isVisible = false
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/vuefilemanager/_variables";
|
||||
@import "@assets/vuefilemanager/_mixins";
|
||||
|
||||
.mobile-selected-menu {
|
||||
display: flex;
|
||||
margin-left: 15px;
|
||||
margin-right: 15px;
|
||||
|
||||
.close-icon {
|
||||
margin-left: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.icon {
|
||||
margin-right: 20px;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
.text-label {
|
||||
@include font-size(16);
|
||||
}
|
||||
}
|
||||
|
||||
.vignette {
|
||||
background: rgba(0, 0, 0, 0.35);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 9;
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.options {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 99;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
border-top-left-radius: 12px;
|
||||
border-top-right-radius: 12px;
|
||||
|
||||
&.showed {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.item-thumbnail {
|
||||
padding: 20px 20px 10px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.menu-options {
|
||||
margin-top: 10px;
|
||||
list-style: none;
|
||||
width: 100%;
|
||||
|
||||
.menu-option-group {
|
||||
padding: 5px 0;
|
||||
border-bottom: 1px solid $light_mode_border;
|
||||
|
||||
&:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-bottom: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-option {
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.15px;
|
||||
@include font-size(14);
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
padding: 17px 20px;
|
||||
text-align: center;
|
||||
|
||||
&:last-child {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.vignette {
|
||||
background: $dark_mode_vignette;
|
||||
}
|
||||
|
||||
.options {
|
||||
background: $dark_mode_foreground;
|
||||
|
||||
.menu-options {
|
||||
background: $dark_mode_foreground;
|
||||
|
||||
.menu-option-group {
|
||||
border-color: $dark_mode_border_color;
|
||||
}
|
||||
|
||||
.menu-option {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Transition
|
||||
.context-menu-enter-active,
|
||||
.fade-enter-active {
|
||||
transition: all 200ms;
|
||||
}
|
||||
|
||||
.context-menu-leave-active,
|
||||
.fade-leave-active {
|
||||
transition: all 200ms;
|
||||
}
|
||||
|
||||
.fade-enter,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.context-menu-enter,
|
||||
.context-menu-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.context-menu-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
</style>
|
||||
@@ -1,76 +0,0 @@
|
||||
<template>
|
||||
<transition v-if="isVisible" name="preview-menu" >
|
||||
<SortingAndPreviewMenu class="options"/>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SortingAndPreviewMenu from '@/components/FilesView/SortingAndPreviewMenu'
|
||||
import { events } from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'MobileSortingAndPreview',
|
||||
components: {SortingAndPreviewMenu},
|
||||
data () {
|
||||
return {
|
||||
isVisible: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
events.$on('mobileSortingAndPreview', (state) => {
|
||||
this.isVisible = state
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/vuefilemanager/_variables";
|
||||
@import "@assets/vuefilemanager/_mixins";
|
||||
|
||||
.options {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 99;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
border-top-left-radius: 12px;
|
||||
border-top-right-radius: 12px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.options {
|
||||
background: $dark_mode_foreground;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Transition
|
||||
.preview-menu-enter-active,
|
||||
.fade-enter-active {
|
||||
transition: all 200ms;
|
||||
}
|
||||
|
||||
.preview-menu-leave-active,
|
||||
.fade-leave-active {
|
||||
transition: all 200ms;
|
||||
}
|
||||
|
||||
.fade-enter,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.preview-menu-enter,
|
||||
.preview-menu-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.preview-menu-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -3,16 +3,18 @@
|
||||
|
||||
<!-- Go back-->
|
||||
<div @click="goBack" class="go-back-button">
|
||||
<chevron-left-icon size="17" :class="{'is-visible': browseHistory.length > 1}" class="icon-back"></chevron-left-icon>
|
||||
<chevron-left-icon :class="{'is-visible': browseHistory.length > 1}" size="17" class="icon-back" />
|
||||
</div>
|
||||
|
||||
<!--Folder Title-->
|
||||
<div class="directory-name">{{ directoryName }}</div>
|
||||
<div class="directory-name">
|
||||
{{ directoryName }}
|
||||
</div>
|
||||
|
||||
<!--More Actions-->
|
||||
<div class="more-actions-button">
|
||||
<div class="tap-area" @click="showMobileNavigation" v-if="$checkPermission('master')">
|
||||
<menu-icon size="17"></menu-icon>
|
||||
<div v-if="$checkPermission('master')" @click="showMobileNavigation" class="tap-area">
|
||||
<menu-icon size="17" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -38,9 +40,8 @@
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'fileInfoVisible',
|
||||
'isVisibleSidebar',
|
||||
'FilePreviewType',
|
||||
'fileInfoDetail',
|
||||
'currentFolder',
|
||||
'browseHistory',
|
||||
'homeDirectory',
|
||||
@@ -51,11 +52,10 @@
|
||||
},
|
||||
methods: {
|
||||
showMobileNavigation() {
|
||||
events.$emit('show:mobile-navigation')
|
||||
events.$emit('mobile-menu:show', 'user-navigation')
|
||||
events.$emit('mobileSelecting:stop')
|
||||
},
|
||||
goBack() {
|
||||
|
||||
let previousFolder = last(this.browseHistory)
|
||||
|
||||
if (previousFolder.location === 'trash-root') {
|
||||
|
||||
+40
-40
@@ -1,31 +1,31 @@
|
||||
<template>
|
||||
<transition name="context-menu">
|
||||
<div class="multiselect-actions" v-if="mobileMultiSelect">
|
||||
<ToolbarButton class="action-btn" v-if="!$isThisLocation(['trash', 'trash-root' , 'shared', 'latest']) && $checkPermission('master') || $checkPermission('editor')" source="move" :action="$t('actions.move')" :class="{'is-inactive' : fileInfoDetail.length < 1}" @click.native="moveItem"/>
|
||||
<ToolbarButton class="action-btn" v-if="!$isThisLocation(['trash', 'trash-root' , 'shared', 'latest']) && $checkPermission('master') || $checkPermission('editor')" source="move" :action="$t('actions.move')" :class="{'is-inactive' : clipboard.length < 1}" @click.native="moveItem" />
|
||||
|
||||
<ToolbarButton class="action-btn" v-if="!$isThisLocation(['shared']) && $checkPermission('master') || $checkPermission('editor')" source="trash" :class="{'is-inactive' : fileInfoDetail.length < 1}" :action="$t('actions.delete')" @click.native="deleteItem"/>
|
||||
<ToolbarButton class="action-btn" v-if="!$isThisLocation(['shared']) && $checkPermission('master') || $checkPermission('editor')" source="trash" :class="{'is-inactive' : clipboard.length < 1}" :action="$t('actions.delete')" @click.native="deleteItem" />
|
||||
|
||||
<ToolbarButton class="action-btn" v-if="!$isThisLocation(['shared'])" source="download" :class="{'is-inactive': canDownloadItems}" :action="$t('actions.delete')" @click.native="downloadItem"/>
|
||||
<ToolbarButton class="action-btn" v-if="!$isThisLocation(['shared'])" source="download" :class="{'is-inactive': canDownloadItems}" :action="$t('actions.delete')" @click.native="downloadItem" />
|
||||
|
||||
<ToolbarButton class="action-btn" source="shared-off" @click.native="shareCancel" v-if="$isThisLocation(['shared'])"/>
|
||||
<ToolbarButton class="action-btn" source="shared-off" @click.native="shareCancel" v-if="$isThisLocation(['shared'])" />
|
||||
|
||||
<ToolbarButton class="action-btn close-icon" source="close" :action="$t('actions.close')" @click.native="closeSelecting"/>
|
||||
<ToolbarButton class="action-btn close-icon" source="close" :action="$t('actions.close')" @click.native="closeSelecting" />
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ToolbarButton from '@/components/FilesView/ToolbarButton'
|
||||
import { events } from '@/bus'
|
||||
import { mapGetters } from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
import {mapGetters} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'MobileMultiSelectMenu',
|
||||
components: { ToolbarButton },
|
||||
name: 'MultiSelectToolbarMobile',
|
||||
components: {ToolbarButton},
|
||||
computed: {
|
||||
...mapGetters(['fileInfoDetail']),
|
||||
...mapGetters(['clipboard']),
|
||||
canDownloadItems() {
|
||||
return this.fileInfoDetail.filter(item => item.type === 'folder').length !== 0
|
||||
return this.clipboard.filter(item => item.type === 'folder').length !== 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -34,7 +34,7 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
shareCancel() {
|
||||
shareCancel() {
|
||||
this.$store.dispatch('shareCancel')
|
||||
this.closeSelecting()
|
||||
},
|
||||
@@ -42,16 +42,16 @@ export default {
|
||||
events.$emit('mobileSelecting:stop')
|
||||
},
|
||||
downloadItem() {
|
||||
if (this.fileInfoDetail.length > 1)
|
||||
if (this.clipboard.length > 1)
|
||||
this.$store.dispatch('downloadFiles')
|
||||
else {
|
||||
this.$downloadFile(this.fileInfoDetail[0].file_url, this.fileInfoDetail[0].name + '.' + this.fileInfoDetail[0].mimetype)
|
||||
this.$downloadFile(this.clipboard[0].file_url, this.clipboard[0].name + '.' + this.clipboard[0].mimetype)
|
||||
}
|
||||
this.closeSelecting()
|
||||
},
|
||||
moveItem() {
|
||||
// Open move item popup
|
||||
events.$emit('popup:open', { name: 'move', item: [this.fileInfoDetail[0]] })
|
||||
events.$emit('popup:open', {name: 'move', item: [this.clipboard[0]]})
|
||||
},
|
||||
deleteItem() {
|
||||
//Delete items
|
||||
@@ -120,37 +120,37 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.multiselect-actions {
|
||||
background: $dark_mode_foreground;
|
||||
}
|
||||
.multiselect-actions {
|
||||
background: $dark_mode_foreground;
|
||||
}
|
||||
}
|
||||
|
||||
// Transition
|
||||
.context-menu-enter-active,
|
||||
.fade-enter-active {
|
||||
transition: all 200ms;
|
||||
}
|
||||
// Transition
|
||||
.context-menu-enter-active,
|
||||
.fade-enter-active {
|
||||
transition: all 200ms;
|
||||
}
|
||||
|
||||
.context-menu-leave-active,
|
||||
.fade-leave-active {
|
||||
transition: all 200ms;
|
||||
}
|
||||
.context-menu-leave-active,
|
||||
.fade-leave-active {
|
||||
transition: all 200ms;
|
||||
}
|
||||
|
||||
.fade-enter,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
.fade-enter,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.context-menu-enter,
|
||||
.context-menu-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
.context-menu-enter,
|
||||
.context-menu-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.context-menu-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
.context-menu-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,32 +1,64 @@
|
||||
<template>
|
||||
<li class="menu-option group">
|
||||
<div class="icon group-hover-text-theme">
|
||||
<calendar-icon v-if="icon === 'calendar'" size="17" class="group-hover-text-theme"/>
|
||||
<grid-icon v-if="icon === 'grid'" size="17" class="group-hover-text-theme"/>
|
||||
<list-icon v-if="icon === 'list'" size="17" class="group-hover-text-theme"/>
|
||||
<trash-2-icon v-if="icon === 'trash'" size="17" class="group-hover-text-theme"/>
|
||||
<life-buoy-icon v-if="icon === 'restore'" size="17" class="group-hover-text-theme"/>
|
||||
<trash-icon v-if="icon === 'empty-trash'" size="17" class="group-hover-text-theme"/>
|
||||
<eye-icon v-if="icon ==='detail'" size="17" class="group-hover-text-theme"/>
|
||||
<download-cloud-icon v-if="icon === 'download'" size="17" class="group-hover-text-theme"/>
|
||||
<edit2-icon v-if="icon === 'rename'" size="17" class="group-hover-text-theme"/>
|
||||
<corner-down-right-icon v-if="icon === 'move-item'" size="17" class="group-hover-text-theme"/>
|
||||
<link-icon v-if="icon === 'share'" size="17" class="group-hover-text-theme"/>
|
||||
<star-icon v-if="icon === 'favourites'" size="17" class="group-hover-text-theme"/>
|
||||
<folder-plus-icon v-if="icon === 'create-folder'" size="17" class="group-hover-text-theme"/>
|
||||
<smile-icon v-if="icon === 'no-options'" size="17" class="group-hover-text-theme"/>
|
||||
<paperclip-icon v-if="icon === 'zip-folder'" size="17" class="group-hover-text-theme"/>
|
||||
<alphabet-icon v-if="icon === 'alphabet'" size="17" class="group-hover-text-theme"/>
|
||||
<li class="menu-option group" :class="{'hover-disabled': isHoverDisabled}">
|
||||
<div class="icon-left group-hover-text-theme">
|
||||
<calendar-icon v-if="icon === 'calendar'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<grid-icon v-if="icon === 'grid'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<list-icon v-if="icon === 'list'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<trash-2-icon v-if="icon === 'trash'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<life-buoy-icon v-if="icon === 'restore'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<trash-icon v-if="icon === 'empty-trash'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<eye-icon v-if="icon ==='detail'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<download-cloud-icon v-if="icon === 'download'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<edit2-icon v-if="icon === 'rename'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<corner-down-right-icon v-if="icon === 'move-item'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<link-icon v-if="icon === 'share'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<star-icon v-if="icon === 'favourites'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<folder-plus-icon v-if="icon === 'create-folder'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<smile-icon v-if="icon === 'no-options'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<paperclip-icon v-if="icon === 'zip-folder'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<alphabet-icon v-if="icon === 'alphabet'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<star-icon v-if="icon === 'star'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<hard-drive-icon v-if="icon === 'hard-drive'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<upload-cloud-icon v-if="icon === 'upload-cloud'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<users-icon v-if="icon === 'users'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<user-icon v-if="icon === 'user'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<settings-icon v-if="icon === 'settings'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<power-icon v-if="icon === 'power'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<lock-icon v-if="icon === 'lock'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<cloud-icon v-if="icon === 'cloud'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<credit-card-icon v-if="icon === 'credit-card'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<file-text-icon v-if="icon === 'file-text'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<database-icon v-if="icon === 'database'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<globe-icon v-if="icon === 'globe'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<monitor-icon v-if="icon === 'monitor'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
<box-icon v-if="icon === 'box'" size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
</div>
|
||||
<div class="text-label group-hover-text-theme">
|
||||
<div class="text-label group-hover-text-theme" :class="{'text-theme': isActive}">
|
||||
{{ title }}
|
||||
</div>
|
||||
<div v-if="isArrowRight" class="icon-right group-hover-text-theme">
|
||||
<chevron-right-icon size="17" class="group-hover-text-theme" :class="{'text-theme': isActive}"/>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AlphabetIcon from '@/components/FilesView/Icons/AlphabetIcon'
|
||||
import {
|
||||
ChevronRightIcon,
|
||||
BoxIcon,
|
||||
MonitorIcon,
|
||||
GlobeIcon,
|
||||
FileTextIcon,
|
||||
CreditCardIcon,
|
||||
CloudIcon,
|
||||
LockIcon,
|
||||
PowerIcon,
|
||||
SettingsIcon,
|
||||
UsersIcon,
|
||||
UserIcon,
|
||||
UploadCloudIcon,
|
||||
HardDriveIcon,
|
||||
CornerDownRightIcon,
|
||||
DownloadCloudIcon,
|
||||
FolderPlusIcon,
|
||||
@@ -42,28 +74,50 @@ import {
|
||||
GridIcon,
|
||||
ListIcon,
|
||||
CalendarIcon,
|
||||
DatabaseIcon,
|
||||
} from 'vue-feather-icons'
|
||||
|
||||
export default {
|
||||
name: 'Option',
|
||||
props:['title' , 'icon'],
|
||||
props:[
|
||||
'isHoverDisabled',
|
||||
'isArrowRight',
|
||||
'isActive',
|
||||
'title',
|
||||
'icon'
|
||||
],
|
||||
components: {
|
||||
BoxIcon,
|
||||
MonitorIcon,
|
||||
GlobeIcon,
|
||||
DatabaseIcon,
|
||||
ChevronRightIcon,
|
||||
FileTextIcon,
|
||||
CreditCardIcon,
|
||||
CloudIcon,
|
||||
LockIcon,
|
||||
CornerDownRightIcon,
|
||||
DownloadCloudIcon,
|
||||
UploadCloudIcon,
|
||||
FolderPlusIcon,
|
||||
HardDriveIcon,
|
||||
PaperclipIcon,
|
||||
SettingsIcon,
|
||||
LifeBuoyIcon,
|
||||
CalendarIcon,
|
||||
AlphabetIcon,
|
||||
Trash2Icon,
|
||||
SmileIcon,
|
||||
PowerIcon,
|
||||
UsersIcon,
|
||||
Edit2Icon,
|
||||
TrashIcon,
|
||||
LinkIcon,
|
||||
StarIcon,
|
||||
EyeIcon,
|
||||
GridIcon,
|
||||
ListIcon,
|
||||
CalendarIcon,
|
||||
UserIcon,
|
||||
EyeIcon,
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -83,7 +137,21 @@ import {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.icon {
|
||||
.icon-right {
|
||||
vertical-align: middle;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
|
||||
svg {
|
||||
@include transform(translateY(3px));
|
||||
}
|
||||
|
||||
polyline {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-left {
|
||||
margin-right: 20px;
|
||||
line-height: 0;
|
||||
|
||||
@@ -101,16 +169,17 @@ import {
|
||||
@include font-size(16);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:hover:not(.hover-disabled) {
|
||||
background: $light_background;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.menu-option {
|
||||
color: $dark_mode_text_primary;
|
||||
|
||||
&:hover {
|
||||
&:hover:not(.hover-disabled) {
|
||||
background: lighten($dark_mode_foreground, 2%);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,29 +7,29 @@
|
||||
<x-icon class="pointer" size="19" />
|
||||
</div>
|
||||
<input
|
||||
v-model="query"
|
||||
class="query focus-border-theme"
|
||||
type="text"
|
||||
name="query"
|
||||
:placeholder="$t('inputs.placeholder_search_files')"
|
||||
v-model="query"
|
||||
@input="$emit('input', query)"
|
||||
class="query focus-border-theme"
|
||||
type="text"
|
||||
:placeholder="placeholder"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { SearchIcon, XIcon } from 'vue-feather-icons'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {debounce} from 'lodash'
|
||||
import {SearchIcon, XIcon} from 'vue-feather-icons'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'SearchBar',
|
||||
name: 'DesktopSearchBar',
|
||||
props: [
|
||||
'placeholder'
|
||||
],
|
||||
components: {
|
||||
SearchIcon,
|
||||
XIcon,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['currentFolder']),
|
||||
isQuery() {
|
||||
return this.query !== '' && typeof this.query !== 'undefined'
|
||||
}
|
||||
@@ -39,36 +39,14 @@
|
||||
query: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
query(val) {
|
||||
return this.getResult(val)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetQuery() {
|
||||
this.query = ''
|
||||
},
|
||||
getResult: debounce(function (value) {
|
||||
if (this.isQuery) {
|
||||
// Get search result if query is not empty
|
||||
this.$store.dispatch('getSearchResult', value)
|
||||
} else if (typeof value !== 'undefined') {
|
||||
if (this.currentFolder) {
|
||||
|
||||
// Get back after delete query to previosly folder
|
||||
if ( this.$isThisLocation('public') ) {
|
||||
this.$store.dispatch('browseShared', [{folder: this.currentFolder, back: true, init: false}])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [{folder: this.currentFolder, back: true, init: false}])
|
||||
}
|
||||
}
|
||||
|
||||
this.$store.commit('CHANGE_SEARCHING_STATE', false)
|
||||
}
|
||||
}, 300)
|
||||
this.$emit('reset-query')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
events.$on('clear-query', () => (this.query = undefined))
|
||||
events.$on('clear-query', () => this.query = undefined)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
+26
-20
@@ -1,26 +1,41 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<div class="icon-wrapper">
|
||||
<CheckSquareIcon class="icon text-theme" size="21" />
|
||||
<div class="icon-wrapper">
|
||||
<CheckSquareIcon v-if="icon === 'check-square'" class="icon text-theme" size="21" />
|
||||
<image-icon v-if="icon === 'image'" class="icon text-theme" size="21" />
|
||||
<video-icon v-if="icon === 'video'" class="icon text-theme" size="21" />
|
||||
<folder-icon v-if="icon === 'folder'" class="icon text-theme" size="21" />
|
||||
<file-icon v-if="icon === 'file'" class="icon text-theme" size="21" />
|
||||
</div>
|
||||
<div class="text">
|
||||
<span class="title">{{ title }}</span>
|
||||
<span class="count">{{ subtitle }}</span>
|
||||
<span class="subtitle">{{ subtitle }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {CheckSquareIcon} from "vue-feather-icons"
|
||||
import {
|
||||
CheckSquareIcon,
|
||||
FolderIcon,
|
||||
ImageIcon,
|
||||
VideoIcon,
|
||||
FileIcon,
|
||||
} from "vue-feather-icons"
|
||||
|
||||
export default {
|
||||
name: 'MultiSelected',
|
||||
name: 'TitlePreview',
|
||||
props: [
|
||||
'subtitle',
|
||||
'title',
|
||||
'subtitle'
|
||||
'icon',
|
||||
],
|
||||
components: {
|
||||
CheckSquareIcon
|
||||
CheckSquareIcon,
|
||||
FolderIcon,
|
||||
ImageIcon,
|
||||
VideoIcon,
|
||||
FileIcon,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -31,7 +46,7 @@ export default {
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
|
||||
.text {
|
||||
padding-left: 10px;
|
||||
@@ -46,7 +61,7 @@ export default {
|
||||
color: $text;
|
||||
}
|
||||
|
||||
.count {
|
||||
.subtitle {
|
||||
@include font-size(12);
|
||||
font-weight: 600;
|
||||
color: $text-muted;
|
||||
@@ -55,17 +70,8 @@ export default {
|
||||
}
|
||||
|
||||
.icon-wrapper {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
outline: none;
|
||||
border: none;
|
||||
|
||||
polyline, path {
|
||||
polyline, path, rect, circle, polyline {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
@@ -78,7 +84,7 @@ export default {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
|
||||
.count {
|
||||
.subtitle {
|
||||
color: $dark_mode_text_secondary;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,10 @@
|
||||
<template>
|
||||
<button class="button hover-text-theme hover-svg-stroke-theme" :title="action">
|
||||
<corner-down-right-icon
|
||||
v-if="source === 'move'"
|
||||
size="19"
|
||||
class="hover-text-theme"
|
||||
/>
|
||||
<download-cloud-icon
|
||||
v-if="source === 'download'"
|
||||
size="19"
|
||||
class="hover-text-theme"
|
||||
/>
|
||||
<folder-plus-icon
|
||||
v-if="source === 'folder-plus'"
|
||||
size="19"
|
||||
class="hover-text-theme"
|
||||
/>
|
||||
<corner-down-right-icon v-if="source === 'move'" size="19" class="hover-text-theme" />
|
||||
<download-cloud-icon v-if="source === 'download'" size="19" class="hover-text-theme" />
|
||||
<folder-plus-icon v-if="source === 'folder-plus'" size="19" class="hover-text-theme" />
|
||||
<zoom-in-icon v-if="source === 'zoom-in'" size="19" />
|
||||
<zoom-out-icon v-if="source === 'zoom-out'" size="19" />
|
||||
<edit-2-icon v-if="source === 'rename'" size="19" />
|
||||
<printer-icon v-if="source === 'print'" size="19" />
|
||||
<trash-2-icon v-if="source === 'trash'" size="19" />
|
||||
@@ -24,46 +14,53 @@
|
||||
<link-icon v-if="source === 'share'" size="19" />
|
||||
<x-icon v-if="source === 'close'" size="19" />
|
||||
<cloud-off-icon v-if="source === 'shared-off'" size="19" />
|
||||
<sorting-and-preview-icon v-if="source === 'preview-sorting'" size="19" class="preview-sorting"/>
|
||||
<sorting-icon v-if="source === 'preview-sorting'" class="preview-sorting"/>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
FolderPlusIcon,
|
||||
Trash2Icon,
|
||||
GridIcon,
|
||||
ListIcon,
|
||||
Edit2Icon,
|
||||
InfoIcon,
|
||||
CornerDownRightIcon,
|
||||
LinkIcon,
|
||||
DownloadCloudIcon,
|
||||
XIcon,
|
||||
PrinterIcon,
|
||||
CloudOffIcon,
|
||||
} from "vue-feather-icons";
|
||||
import SortingAndPreviewIcon from '@/components/FilesView/Icons/SortingAndPreviewIcon'
|
||||
|
||||
export default {
|
||||
name: "ToolbarButton",
|
||||
props: ["source", "action"],
|
||||
components: {
|
||||
SortingAndPreviewIcon,
|
||||
import SortingIcon from '@/components/FilesView/Icons/SortingIcon'
|
||||
import {
|
||||
CornerDownRightIcon,
|
||||
DownloadCloudIcon,
|
||||
FolderPlusIcon,
|
||||
CloudOffIcon,
|
||||
PrinterIcon,
|
||||
ZoomOutIcon,
|
||||
ZoomInIcon,
|
||||
Trash2Icon,
|
||||
Edit2Icon,
|
||||
ListIcon,
|
||||
XIcon,
|
||||
GridIcon,
|
||||
ListIcon,
|
||||
InfoIcon,
|
||||
LinkIcon,
|
||||
},
|
||||
};
|
||||
XIcon,
|
||||
} from "vue-feather-icons";
|
||||
|
||||
export default {
|
||||
name: "ToolbarButton",
|
||||
props: [
|
||||
'source',
|
||||
'action'
|
||||
],
|
||||
components: {
|
||||
SortingIcon,
|
||||
CornerDownRightIcon,
|
||||
DownloadCloudIcon,
|
||||
FolderPlusIcon,
|
||||
CloudOffIcon,
|
||||
PrinterIcon,
|
||||
ZoomOutIcon,
|
||||
ZoomInIcon,
|
||||
Trash2Icon,
|
||||
Edit2Icon,
|
||||
ListIcon,
|
||||
GridIcon,
|
||||
InfoIcon,
|
||||
LinkIcon,
|
||||
XIcon,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
<template>
|
||||
<ul class="link-group">
|
||||
<router-link :to="{name: link.routeName}" v-for="(link, i) in navigation" :key="i" v-if="link.isVisible" :class="link.icon" class="link-item" @click.native="$emit('menu', link.icon)">
|
||||
<div class="menu-icon">
|
||||
<hard-drive-icon v-if="link.icon === 'hard-drive'" size="17"></hard-drive-icon>
|
||||
<share-icon v-if="link.icon === 'share'" size="17"></share-icon>
|
||||
<trash2-icon v-if="link.icon === 'trash'" size="17"></trash2-icon>
|
||||
<power-icon v-if="link.icon === 'power'" size="17"></power-icon>
|
||||
<settings-icon v-if="link.icon === 'settings'" size="17"></settings-icon>
|
||||
<upload-cloud-icon v-if="link.icon === 'latest'" size="17"></upload-cloud-icon>
|
||||
<user-icon v-if="link.icon === 'user'" size="17"></user-icon>
|
||||
<users-icon v-if="link.icon === 'users'" size="17"></users-icon>
|
||||
<lock-icon v-if="link.icon === 'lock'" size="17"></lock-icon>
|
||||
<file-text-icon v-if="link.icon === 'file-text'" size="17"></file-text-icon>
|
||||
<database-icon v-if="link.icon === 'database'" size="17"></database-icon>
|
||||
<credit-card-icon v-if="link.icon === 'credit-card'" size="17"></credit-card-icon>
|
||||
<cloud-icon v-if="link.icon === 'cloud'" size="17"></cloud-icon>
|
||||
<monitor-icon v-if="link.icon === 'monitor'" size="17"></monitor-icon>
|
||||
<box-icon v-if="link.icon === 'box'" size="17"></box-icon>
|
||||
<globe-icon v-if="link.icon === 'language'" size="17"></globe-icon>
|
||||
</div>
|
||||
<b class="menu-link">
|
||||
<span>{{ link.title }}</span>
|
||||
<chevron-right-icon size="15" class="arrow-right"></chevron-right-icon>
|
||||
</b>
|
||||
</router-link>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
ChevronRightIcon,
|
||||
UploadCloudIcon,
|
||||
CreditCardIcon,
|
||||
HardDriveIcon,
|
||||
FileTextIcon,
|
||||
SettingsIcon,
|
||||
DatabaseIcon,
|
||||
MonitorIcon,
|
||||
Trash2Icon,
|
||||
CloudIcon,
|
||||
PowerIcon,
|
||||
GlobeIcon,
|
||||
ShareIcon,
|
||||
UsersIcon,
|
||||
UserIcon,
|
||||
LockIcon,
|
||||
BoxIcon,
|
||||
} from 'vue-feather-icons'
|
||||
|
||||
export default {
|
||||
name: 'MenuBar',
|
||||
components: {
|
||||
BoxIcon,
|
||||
MonitorIcon,
|
||||
ChevronRightIcon,
|
||||
UploadCloudIcon,
|
||||
CreditCardIcon,
|
||||
HardDriveIcon,
|
||||
DatabaseIcon,
|
||||
FileTextIcon,
|
||||
SettingsIcon,
|
||||
Trash2Icon,
|
||||
CloudIcon,
|
||||
PowerIcon,
|
||||
GlobeIcon,
|
||||
UsersIcon,
|
||||
ShareIcon,
|
||||
LockIcon,
|
||||
UserIcon,
|
||||
},
|
||||
props: [
|
||||
'navigation'
|
||||
],
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.link-item {
|
||||
display: flex;
|
||||
text-decoration: none;
|
||||
padding: 17px 0;
|
||||
width: 100%;
|
||||
|
||||
&.power {
|
||||
|
||||
.menu-icon {
|
||||
|
||||
path, line, polyline, rect, circle, ellipse {
|
||||
stroke: $red;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-link {
|
||||
color: $red;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
display: block;
|
||||
margin-right: 20px;
|
||||
|
||||
svg {
|
||||
margin-top: -1px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
path, line, polyline, rect, circle, ellipse {
|
||||
stroke: $text;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-link {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: $text;
|
||||
|
||||
span {
|
||||
@include font-size(14);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.link-item {
|
||||
|
||||
.menu-icon {
|
||||
|
||||
path, line, polyline, rect, circle, ellipse {
|
||||
stroke: $dark_mode_text_primary;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-link {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<transition name="context-menu">
|
||||
<div v-if="isVisible" @click="closeMenu" class="options">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'MenuMobile',
|
||||
props: [
|
||||
'name'
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
isVisible: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
closeMenu() {
|
||||
this.isVisible = false
|
||||
|
||||
events.$emit('mobile-menu:hide')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
events.$on('mobile-menu:show', name => {
|
||||
if (name === this.name)
|
||||
this.isVisible = !this.isVisible
|
||||
})
|
||||
|
||||
events.$on('mobile-menu:hide', () => this.isVisible = false)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/vuefilemanager/_variables";
|
||||
@import "@assets/vuefilemanager/_mixins";
|
||||
|
||||
.options {
|
||||
position: absolute;
|
||||
padding-bottom: 12px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 99;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
border-top-left-radius: 12px;
|
||||
border-top-right-radius: 12px;
|
||||
|
||||
&.showed {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
// Transition
|
||||
.context-menu-enter-active,
|
||||
.fade-enter-active {
|
||||
transition: all 300ms;
|
||||
}
|
||||
|
||||
.context-menu-leave-active,
|
||||
.fade-leave-active {
|
||||
transition: all 300ms;
|
||||
}
|
||||
|
||||
.fade-enter,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.context-menu-enter,
|
||||
.context-menu-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.context-menu-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.options {
|
||||
background: $dark_mode_foreground;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div class="menu-options">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'MenuMobileGroup',
|
||||
components: {
|
||||
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['config']),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/vuefilemanager/_variables";
|
||||
@import "@assets/vuefilemanager/_mixins";
|
||||
|
||||
.menu-options {
|
||||
margin-top: 10px;
|
||||
list-style: none;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<!-- Go back-->
|
||||
<div @click="goBack" class="go-back">
|
||||
<chevron-left-icon size="17" class="icon"></chevron-left-icon>
|
||||
<chevron-left-icon size="17" class="icon" />
|
||||
</div>
|
||||
|
||||
<!--Folder Title-->
|
||||
@@ -25,7 +25,7 @@
|
||||
} from 'vue-feather-icons'
|
||||
|
||||
export default {
|
||||
name: 'MenuBar',
|
||||
name: 'MobileHeader',
|
||||
props: [
|
||||
'title'
|
||||
],
|
||||
@@ -35,7 +35,7 @@
|
||||
},
|
||||
methods: {
|
||||
showMobileNavigation() {
|
||||
events.$emit('show:mobile-navigation')
|
||||
events.$emit('mobile-menu:show', 'user-navigation')
|
||||
},
|
||||
goBack() {
|
||||
this.$router.back();
|
||||
|
||||
@@ -1,32 +1,24 @@
|
||||
<template>
|
||||
<div @contextmenu.prevent.capture="contextMenu($event, undefined)"
|
||||
id="files-view">
|
||||
<ContextMenu/>
|
||||
<DesktopSortingAndPreview/>
|
||||
<DesktopToolbar/>
|
||||
<div @contextmenu.prevent.capture="contextMenu($event, undefined)" id="files-view">
|
||||
<DesktopToolbar/>
|
||||
<ContextMenu />
|
||||
<FileBrowser/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DesktopSortingAndPreview from '@/components/FilesView/DesktopSortingAndPreview'
|
||||
import DesktopToolbar from '@/components/FilesView/DesktopToolbar'
|
||||
import FileBrowser from '@/components/FilesView/FileBrowser'
|
||||
import ContextMenu from '@/components/FilesView/ContextMenu'
|
||||
import {mapGetters} from 'vuex'
|
||||
import ContextMenu from '@/components/FilesView/ContextMenu'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'FilesView',
|
||||
components: {
|
||||
DesktopSortingAndPreview,
|
||||
DesktopToolbar,
|
||||
FileBrowser,
|
||||
ContextMenu,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['config']),
|
||||
},
|
||||
methods: {
|
||||
contextMenu(event, item) {
|
||||
events.$emit('contextMenu:show', event, item)
|
||||
@@ -36,8 +28,6 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
#files-view {
|
||||
font-family: 'Nunito', sans-serif;
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'CreateFolder',
|
||||
name: 'CreateFolderPopup',
|
||||
components: {
|
||||
ValidationProvider,
|
||||
ValidationObserver,
|
||||
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<div v-if="canBePreview" class="preview">
|
||||
<img v-if="clipboard[0].type == 'image' && clipboard[0].thumbnail" :src="clipboard[0].thumbnail" :alt="clipboard[0].name" />
|
||||
<audio v-else-if="clipboard[0].type == 'audio'" :src="clipboard[0].file_url" controlsList="nodownload" controls></audio>
|
||||
<video v-else-if="clipboard[0].type == 'video'" controlsList="nodownload" disablePictureInPicture playsinline controls>
|
||||
<source :src="clipboard[0].file_url" type="video/mp4">
|
||||
</video>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { includes } from 'lodash'
|
||||
|
||||
export default {
|
||||
name: 'FilePreview',
|
||||
computed: {
|
||||
...mapGetters(['clipboard']),
|
||||
canBePreview() {
|
||||
return this.clipboard[0] && ! includes([
|
||||
'folder', 'file'
|
||||
], this.clipboard[0].type)
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.preview {
|
||||
width: 100%;
|
||||
display: block;
|
||||
margin-bottom: 7px;
|
||||
|
||||
img {
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
audio {
|
||||
width: 100%;
|
||||
&::-webkit-media-controls-panel {
|
||||
background-color: $light_background;
|
||||
}
|
||||
|
||||
&::-webkit-media-controls-play-button {
|
||||
color: $theme;
|
||||
}
|
||||
}
|
||||
|
||||
video {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -175,12 +175,12 @@ export default {
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.input-wrapper {
|
||||
background: $dark_mode_foreground;
|
||||
background: lighten($dark_mode_foreground, 3%);
|
||||
|
||||
.email-list {
|
||||
|
||||
.email-input {
|
||||
background: $dark_mode_foreground;
|
||||
background: lighten($dark_mode_foreground, 3%);
|
||||
color: $dark_mode_text_primary;
|
||||
|
||||
&::placeholder {
|
||||
@@ -190,6 +190,4 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
|
||||
.box-item {
|
||||
border-color: $dark_mode_border_color;
|
||||
background: $dark_mode_foreground;
|
||||
background: lighten($dark_mode_foreground, 3%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
<!--If is selected-->
|
||||
<div class="selected" v-if="selected">
|
||||
<div class="option-icon" v-if="selected.icon">
|
||||
<user-icon v-if="selected.icon === 'user'" size="14"></user-icon>
|
||||
<edit2-icon v-if="selected.icon === 'user-edit'" size="14"></edit2-icon>
|
||||
<user-icon v-if="selected.icon === 'user'" size="14" />
|
||||
<edit2-icon v-if="selected.icon === 'user-edit'" size="14" />
|
||||
</div>
|
||||
<span class="option-value">{{ selected.label }}</span>
|
||||
</div>
|
||||
@@ -23,34 +23,64 @@
|
||||
|
||||
<!--Options-->
|
||||
<transition name="slide-in">
|
||||
<ul class="input-options" v-if="isOpen">
|
||||
<li class="option-item" @click="selectOption(option)" v-for="(option, i) in options" :key="i">
|
||||
<div class="option-icon" v-if="option.icon">
|
||||
<user-icon v-if="option.icon === 'user'" size="14"></user-icon>
|
||||
<edit2-icon v-if="option.icon === 'user-edit'" size="14"></edit2-icon>
|
||||
</div>
|
||||
<span class="option-value">{{ option.label }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="input-options" v-if="isOpen">
|
||||
<div v-if="options.length > 5" class="select-search">
|
||||
<input v-model="query" ref="search" type="text" :placeholder="$t('select_search_placeholder')" class="search-input focus-border-theme">
|
||||
</div>
|
||||
<ul class="option-list">
|
||||
<li class="option-item" @click="selectOption(option)" v-for="(option, i) in optionList" :key="i">
|
||||
<div class="option-icon" v-if="option.icon">
|
||||
<user-icon v-if="option.icon === 'user'" size="14" />
|
||||
<edit2-icon v-if="option.icon === 'user-edit'" size="14" />
|
||||
</div>
|
||||
<span class="option-value">{{ option.label }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ChevronDownIcon, Edit2Icon, UserIcon } from 'vue-feather-icons'
|
||||
import {debounce, omitBy} from "lodash"
|
||||
|
||||
export default {
|
||||
name:'SelectInput',
|
||||
props: ['options', 'isError', 'default', 'placeholder'],
|
||||
props: [
|
||||
'placeholder',
|
||||
'options',
|
||||
'isError',
|
||||
'default',
|
||||
],
|
||||
components: {
|
||||
Edit2Icon,
|
||||
UserIcon,
|
||||
ChevronDownIcon
|
||||
},
|
||||
watch: {
|
||||
query: debounce(function (val) {
|
||||
this.searchedResults = omitBy(this.options, string => {
|
||||
return !string.label.toLowerCase().includes(val.toLowerCase())
|
||||
})
|
||||
}, 200),
|
||||
},
|
||||
computed: {
|
||||
isSearching() {
|
||||
return this.searchedResults && this.query !== ''
|
||||
},
|
||||
optionList() {
|
||||
return this.isSearching
|
||||
? this.searchedResults
|
||||
: this.options
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
searchedResults: undefined,
|
||||
selected: undefined,
|
||||
isOpen: false,
|
||||
query: '',
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -67,10 +97,13 @@
|
||||
},
|
||||
openMenu() {
|
||||
this.isOpen = ! this.isOpen
|
||||
|
||||
if (this.isOpen) {
|
||||
this.$nextTick(() => this.$refs.search.focus());
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
|
||||
if (this.default)
|
||||
this.selected = this.options.find(option => option.value === this.default)
|
||||
}
|
||||
@@ -87,6 +120,26 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.select-search {
|
||||
background: white;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
padding: 13px;
|
||||
|
||||
.search-input {
|
||||
border: 1px solid transparent;
|
||||
background: $light_background;
|
||||
@include transition(150ms);
|
||||
@include font-size(14);
|
||||
border-radius: 8px;
|
||||
padding: 13px 20px;
|
||||
appearance: none;
|
||||
font-weight: 700;
|
||||
outline: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.input-options {
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.12);
|
||||
background: white;
|
||||
@@ -184,6 +237,14 @@
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.select-search {
|
||||
background: $dark_mode_foreground;
|
||||
|
||||
.search-input {
|
||||
background: $dark_mode_background;
|
||||
}
|
||||
}
|
||||
|
||||
.input-area {
|
||||
background: $dark_mode_foreground;
|
||||
border-color: $dark_mode_foreground;
|
||||
|
||||
@@ -1,199 +1,141 @@
|
||||
<template>
|
||||
<div class="mobile-main-navigation" v-if="user">
|
||||
<transition name="context-menu">
|
||||
<nav v-if="isVisible" class="mobile-navigation">
|
||||
<MenuMobile name="user-navigation">
|
||||
|
||||
<!--User Info-->
|
||||
<div class="user-info">
|
||||
<UserAvatar size="large"/>
|
||||
<UserHeadline/>
|
||||
</div>
|
||||
<!--User avatar-->
|
||||
<UserHeadline v-if="!clickedSubmenu" class="user-info" />
|
||||
|
||||
<!--Navigation-->
|
||||
<MenuItemList :navigation="navigation" @menu="action"/>
|
||||
</nav>
|
||||
</transition>
|
||||
<transition name="fade">
|
||||
<div v-show="isVisible" class="vignette" @click="closeAndResetContextMenu"></div>
|
||||
</transition>
|
||||
</div>
|
||||
<!--Go back button-->
|
||||
<div v-if="clickedSubmenu" @click.stop="showSubmenu(undefined)" class="go-back">
|
||||
<chevron-left-icon size="19" class="text-theme" />
|
||||
<span class="title text-theme">{{ backTitle }}</span>
|
||||
</div>
|
||||
|
||||
<!--Menu links-->
|
||||
<MenuMobileGroup>
|
||||
|
||||
<!--Main navigation-->
|
||||
<OptionGroup v-if="!clickedSubmenu">
|
||||
<Option @click.native="goToFiles" :title="$t('menu.files')" icon="hard-drive" is-hover-disabled="true"/>
|
||||
<Option @click.native.stop="showSubmenu('settings')" :title="$t('menu.settings')" icon="user" :is-arrow-right="true" is-hover-disabled="true"/>
|
||||
<Option v-if="isAdmin" @click.native.stop="showSubmenu('admin')" :title="$t('menu.admin')" icon="settings" :is-arrow-right="true" is-hover-disabled="true"/>
|
||||
</OptionGroup>
|
||||
<OptionGroup v-if="!clickedSubmenu">
|
||||
<Option @click.native="logOut" :title="$t('menu.logout')" icon="power" is-hover-disabled="true" />
|
||||
</OptionGroup>
|
||||
|
||||
<!--Submenu: User settings-->
|
||||
<OptionGroup v-if="clickedSubmenu === 'settings'">
|
||||
<Option @click.native="goToRoute('Profile')" :title="$t('menu.profile')" icon="user" is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('Storage')" :title="$t('menu.storage')" icon="hard-drive" is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('Password')" :title="$t('menu.password')" icon="lock" is-hover-disabled="true" />
|
||||
</OptionGroup>
|
||||
<OptionGroup v-if="clickedSubmenu === 'settings' && config.isSaaS">
|
||||
<Option v-if="" @click.native="goToRoute('Subscription')" :title="$t('menu.subscription')" icon="cloud" is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('PaymentMethods')" :title="$t('menu.payment_cards')" icon="credit-card" is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('Invoice')" :title="$t('menu.invoices')" icon="file-text" is-hover-disabled="true" />
|
||||
</OptionGroup>
|
||||
|
||||
<!--Submenu: Admin settings-->
|
||||
<OptionGroup v-if="clickedSubmenu === 'admin'">
|
||||
<Option @click.native="goToRoute('Dashboard')" :title="$t('admin_menu.dashboard')" icon="box" is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('Users')" :title="$t('admin_menu.users')" icon="users" is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('AppOthers')" :title="$t('admin_menu.settings')" icon="settings" is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('Pages')" :title="$t('admin_menu.pages')" icon="monitor" is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('Language')" :title="$t('languages')" icon="globe" is-hover-disabled="true" />
|
||||
</OptionGroup>
|
||||
<OptionGroup v-if="clickedSubmenu === 'admin' && config.isSaaS">
|
||||
<Option v-if="" @click.native="goToRoute('Plans')" :title="$t('admin_menu.plans')" icon="database" is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('Invoices')" :title="$t('admin_menu.invoices')" icon="file-text" is-hover-disabled="true" />
|
||||
</OptionGroup>
|
||||
</MenuMobileGroup>
|
||||
</MenuMobile>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MenuMobileGroup from '@/components/Mobile/MenuMobileGroup'
|
||||
import OptionGroup from '@/components/FilesView/OptionGroup'
|
||||
import UserHeadline from '@/components/Sidebar/UserHeadline'
|
||||
import MenuItemList from '@/components/Mobile/MenuItemList'
|
||||
import UserAvatar from '@/components/Others/UserAvatar'
|
||||
import MenuMobile from '@/components/Mobile/MenuMobile'
|
||||
import Option from '@/components/FilesView/Option'
|
||||
import {ChevronLeftIcon} from 'vue-feather-icons'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'UserMobileNavigation',
|
||||
name: 'MobileNavigation',
|
||||
components: {
|
||||
MenuItemList,
|
||||
ChevronLeftIcon,
|
||||
MenuMobileGroup,
|
||||
UserHeadline,
|
||||
UserAvatar,
|
||||
OptionGroup,
|
||||
MenuMobile,
|
||||
Option,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['user', 'homeDirectory']),
|
||||
navigation() {
|
||||
return [
|
||||
{
|
||||
icon: 'hard-drive',
|
||||
title: this.$t('menu.files'),
|
||||
routeName: 'Files',
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
icon: 'latest',
|
||||
title: this.$t('menu.latest'),
|
||||
routeName: 'Files',
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
icon: 'share',
|
||||
title: this.$t('menu.shared'),
|
||||
routeName: 'SharedFiles',
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
icon: 'trash',
|
||||
title: this.$t('menu.trash'),
|
||||
routeName: 'Files',
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
icon: 'user',
|
||||
title: this.$t('menu.settings'),
|
||||
routeName: 'UserProfileMobileMenu',
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
icon: 'settings',
|
||||
title: this.$t('menu.admin'),
|
||||
routeName: 'AdminMobileMenu',
|
||||
isVisible: this.user.data.attributes.role === 'admin',
|
||||
},
|
||||
{
|
||||
icon: 'power',
|
||||
title: this.$t('menu.logout'),
|
||||
routeName: 'LogOut',
|
||||
isVisible: true,
|
||||
},
|
||||
]
|
||||
...mapGetters([
|
||||
'homeDirectory',
|
||||
'config',
|
||||
'user',
|
||||
]),
|
||||
isAdmin() {
|
||||
return this.user && this.user.data.attributes.role === 'admin'
|
||||
},
|
||||
backTitle() {
|
||||
let location = {
|
||||
'settings': this.$t('menu.settings'),
|
||||
'admin': this.$t('menu.admin')
|
||||
}
|
||||
|
||||
return 'Go back from ' + location[this.clickedSubmenu]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isVisible: false,
|
||||
clickedSubmenu: undefined,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
action(name) {
|
||||
|
||||
if (name === 'latest') {
|
||||
this.$store.dispatch('getLatest')
|
||||
}
|
||||
|
||||
if (name === 'trash') {
|
||||
this.$store.dispatch('getTrash')
|
||||
}
|
||||
|
||||
if (name === 'hard-drive') {
|
||||
this.$store.dispatch('getFolder', [{folder: this.homeDirectory, back: false, init: true}])
|
||||
}
|
||||
|
||||
if (name === 'power') {
|
||||
this.$store.dispatch('logOut')
|
||||
}
|
||||
|
||||
this.closeAndResetContextMenu()
|
||||
goToRoute(route) {
|
||||
this.$router.push({name: route})
|
||||
this.clickedSubmenu = undefined
|
||||
},
|
||||
closeAndResetContextMenu() {
|
||||
this.isVisible = false
|
||||
showSubmenu(name) {
|
||||
this.clickedSubmenu = name
|
||||
},
|
||||
goToFiles() {
|
||||
if (this.$route.name !== 'Files')
|
||||
this.$router.push({name: 'Files'})
|
||||
|
||||
events.$emit('hide:mobile-navigation')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
events.$on('show:mobile-navigation', () => {
|
||||
this.isVisible = true
|
||||
})
|
||||
this.$store.dispatch('getFolder', [{folder: this.homeDirectory, back: false, init: true}])
|
||||
},
|
||||
logOut() {
|
||||
this.$store.dispatch('logOut')
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.mobile-navigation {
|
||||
padding: 20px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 99;
|
||||
background: white;
|
||||
border-top-left-radius: 12px;
|
||||
border-top-right-radius: 12px;
|
||||
min-height: 440px;
|
||||
max-height: 80%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.vignette {
|
||||
background: rgba(0, 0, 0, 0.35);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 9;
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
}
|
||||
@import "@assets/vuefilemanager/_variables";
|
||||
@import "@assets/vuefilemanager/_mixins";
|
||||
|
||||
.user-info {
|
||||
padding: 20px 20px 10px;
|
||||
}
|
||||
|
||||
.go-back {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
padding: 30px 20px 10px;
|
||||
cursor: pointer;
|
||||
|
||||
@media only screen and (max-width: 690px) {
|
||||
.title {
|
||||
@include font-size(14);
|
||||
font-weight: 700;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.mobile-navigation {
|
||||
background: $dark_mode_background;
|
||||
polyline {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
// Transition
|
||||
.context-menu-enter-active,
|
||||
.fade-enter-active {
|
||||
transition: all 200ms;
|
||||
}
|
||||
|
||||
.context-menu-leave-active,
|
||||
.fade-leave-active {
|
||||
transition: all 200ms;
|
||||
}
|
||||
|
||||
.fade-enter,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.context-menu-enter,
|
||||
.context-menu-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.context-menu-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
+20
-47
@@ -11,12 +11,12 @@
|
||||
|
||||
<!--Folder tree-->
|
||||
<div v-if="! isLoadingTree && navigation">
|
||||
<ThumbnailItem v-if="fileInfoDetail.length < 2 || isSelectedItem" class="item-thumbnail" :item="pickedItem" info="location" />
|
||||
<ThumbnailItem v-if="clipboard.length < 2 || isSelectedItem" class="item-thumbnail" :item="pickedItem" info="location" />
|
||||
|
||||
<MultiSelected class="multiple-selected"
|
||||
<TitlePreview class="multiple-selected"
|
||||
:title="$t('file_detail.selected_multiple')"
|
||||
:subtitle="this.fileInfoDetail.length + ' ' + $tc('file_detail.items', this.fileInfoDetail.length)"
|
||||
v-if="fileInfoDetail.length > 1 && !isSelectedItem" />
|
||||
:subtitle="this.clipboard.length + ' ' + $tc('file_detail.items', this.clipboard.length)"
|
||||
v-if="clipboard.length > 1 && !isSelectedItem" />
|
||||
|
||||
<TreeMenu :disabled-by-id="pickedItem" :depth="1" :nodes="items" v-for="items in navigation" :key="items.id" />
|
||||
</div>
|
||||
@@ -43,22 +43,23 @@
|
||||
<script>
|
||||
import PopupWrapper from '@/components/Others/Popup/PopupWrapper'
|
||||
import PopupActions from '@/components/Others/Popup/PopupActions'
|
||||
import MultiSelected from '@/components/FilesView/MultiSelected'
|
||||
import TitlePreview from '@/components/FilesView/TitlePreview'
|
||||
import PopupContent from '@/components/Others/Popup/PopupContent'
|
||||
import PopupHeader from '@/components/Others/Popup/PopupHeader'
|
||||
import ThumbnailItem from '@/components/Others/ThumbnailItem'
|
||||
import ButtonBase from '@/components/FilesView/ButtonBase'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
import TreeMenu from '@/components/Others/TreeMenu'
|
||||
import {isArray, isNull} from 'lodash'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'MoveItem',
|
||||
name: 'MoveItemPopup',
|
||||
components: {
|
||||
ThumbnailItem,
|
||||
TitlePreview,
|
||||
PopupWrapper,
|
||||
MultiSelected,
|
||||
PopupActions,
|
||||
PopupContent,
|
||||
PopupHeader,
|
||||
@@ -67,7 +68,10 @@
|
||||
Spinner,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['navigation', 'fileInfoDetail']),
|
||||
...mapGetters([
|
||||
'clipboard',
|
||||
'navigation',
|
||||
]),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -83,7 +87,7 @@
|
||||
if (!this.selectedFolder) return
|
||||
|
||||
// Prevent to move items to the same parent
|
||||
if (this.fileInfoDetail.find(item => item.parent_id === this.selectedFolder.id)) return
|
||||
if ( isArray(this.selectedFolder) && this.clipboard.find(item => item.parent_id === this.selectedFolder.id)) return
|
||||
|
||||
// Move item
|
||||
if (!this.isSelectedItem) {
|
||||
@@ -94,9 +98,6 @@
|
||||
this.$store.dispatch('moveItem', {to_item: this.selectedFolder, isSelectedItem: this.pickedItem})
|
||||
}
|
||||
|
||||
console.log('to item:', this.selectedFolder);
|
||||
console.log('isSelectedItem:', this.pickedItem);
|
||||
|
||||
// Close popup
|
||||
events.$emit('popup:close')
|
||||
|
||||
@@ -106,12 +107,14 @@
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
||||
// Select folder in tree
|
||||
events.$on('pick-folder', folder => {
|
||||
|
||||
if (folder.id === this.pickedItem.id) {
|
||||
this.selectedFolder = undefined
|
||||
|
||||
} else if ( ! folder.id && folder.location === 'base') {
|
||||
this.selectedFolder = 'base'
|
||||
|
||||
} else {
|
||||
this.selectedFolder = folder
|
||||
}
|
||||
@@ -131,13 +134,13 @@
|
||||
})
|
||||
|
||||
// Store picked item
|
||||
if (!this.fileInfoDetail.includes(args.item[0])) {
|
||||
if (!this.clipboard.includes(args.item[0])) {
|
||||
this.pickedItem = args.item[0]
|
||||
this.isSelectedItem = true
|
||||
}
|
||||
|
||||
if (this.fileInfoDetail.includes(args.item[0])) {
|
||||
this.pickedItem = this.fileInfoDetail[0]
|
||||
if (this.clipboard.includes(args.item[0])) {
|
||||
this.pickedItem = this.clipboard[0]
|
||||
this.isSelectedItem = false
|
||||
}
|
||||
})
|
||||
@@ -165,35 +168,5 @@
|
||||
.multiple-selected {
|
||||
padding: 0 20px;;
|
||||
margin-bottom: 20px;
|
||||
|
||||
/deep/ .text {
|
||||
.title {
|
||||
color: $text;
|
||||
}
|
||||
|
||||
.count {
|
||||
color: $text-muted;
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .icon-wrapper {
|
||||
.icon {
|
||||
stroke: $theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.multiple-selected {
|
||||
/deep/ .text {
|
||||
.title {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
|
||||
.count {
|
||||
color: $dark_mode_text_secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<PopupWrapper>
|
||||
|
||||
<div class="popup-image">
|
||||
<span class="emoji">{{ emoji }}</span>
|
||||
</div>
|
||||
+1
-1
@@ -59,7 +59,7 @@ import {required} from 'vee-validate/dist/rules'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'RenameItem',
|
||||
name: 'RenameItemPopup',
|
||||
components: {
|
||||
ValidationProvider,
|
||||
ValidationObserver,
|
||||
+1
-1
@@ -112,7 +112,7 @@ import {events} from '@/bus'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'ShareCreate',
|
||||
name: 'ShareCreatePopup',
|
||||
components: {
|
||||
ValidationProvider,
|
||||
ValidationObserver,
|
||||
+1
-1
@@ -115,7 +115,7 @@
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'ShareEdit',
|
||||
name: 'ShareEditPopup',
|
||||
components: {
|
||||
ValidationProvider,
|
||||
ValidationObserver,
|
||||
@@ -121,7 +121,6 @@
|
||||
<script>
|
||||
import {ChevronUpIcon, ChevronLeftIcon, ChevronRightIcon} from 'vue-feather-icons'
|
||||
import DatatableCell from '@/components/Others/Tables/DatatableCell'
|
||||
import {chunk, sortBy} from 'lodash'
|
||||
import axios from "axios";
|
||||
|
||||
export default {
|
||||
|
||||
@@ -31,14 +31,14 @@
|
||||
TreeMenu,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['fileInfoDetail']),
|
||||
...mapGetters(['clipboard']),
|
||||
indent() {
|
||||
return { paddingLeft: this.depth * 20 + 'px' }
|
||||
},
|
||||
disableId() {
|
||||
let canBeShow = true
|
||||
if(this.fileInfoDetail.includes(this.disabledById)){
|
||||
this.fileInfoDetail.map(item => {
|
||||
if(this.clipboard.includes(this.disabledById)){
|
||||
this.clipboard.map(item => {
|
||||
if(item.id === this.nodes.id) {
|
||||
canBeShow = false
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
FolderIcon,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['fileInfoDetail']),
|
||||
...mapGetters(['clipboard']),
|
||||
|
||||
disabledFolder() {
|
||||
let disableFolder = false
|
||||
@@ -84,12 +84,12 @@
|
||||
methods: {
|
||||
dragFinish() {
|
||||
// Move no selected item
|
||||
if(!this.fileInfoDetail.includes(this.draggedItem[0])) {
|
||||
if(!this.clipboard.includes(this.draggedItem[0])) {
|
||||
this.$store.dispatch('moveItem', {to_item: this.nodes ,noSelectedItem:this.draggedItem[0]})
|
||||
}
|
||||
|
||||
// Move all selected items
|
||||
if(this.fileInfoDetail.includes(this.draggedItem[0])) {
|
||||
if(this.clipboard.includes(this.draggedItem[0])) {
|
||||
this.$store.dispatch('moveItem', {to_item: this.nodes ,noSelectedItem:null})
|
||||
}
|
||||
|
||||
@@ -127,12 +127,12 @@
|
||||
//Get dragged item
|
||||
events.$on('dragstart' , (data) => {
|
||||
//If is dragged item not selected
|
||||
if(!this.fileInfoDetail.includes(data)) {
|
||||
if(!this.clipboard.includes(data)) {
|
||||
this.draggedItem = [data]
|
||||
}
|
||||
//If are the dragged items selected
|
||||
if(this.fileInfoDetail.includes(data)) {
|
||||
this.draggedItem = this.fileInfoDetail
|
||||
if(this.clipboard.includes(data)) {
|
||||
this.draggedItem = this.clipboard
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -26,22 +26,20 @@
|
||||
methods: {
|
||||
closePopup() {
|
||||
events.$emit('popup:close')
|
||||
events.$emit('mobileMenu:hide')
|
||||
events.$emit('mobileSortingAndPreview', false)
|
||||
events.$emit('mobile-menu:hide')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
// Hide vignette
|
||||
events.$on('popup:close', () => this.isVisibleVignette = false)
|
||||
|
||||
// Show vignette
|
||||
events.$on('popup:open', () => this.isVisibleVignette = true)
|
||||
events.$on('mobile-menu:show', () => this.isVisibleVignette = true)
|
||||
events.$on('alert:open', () => this.isVisibleVignette = true)
|
||||
events.$on('success:open', () => this.isVisibleVignette = true)
|
||||
events.$on('confirm:open', () => this.isVisibleVignette = true)
|
||||
events.$on('mobileSortingAndPreviewVignette', (state) => this.isVisibleVignette = state)
|
||||
|
||||
// Hide vignette
|
||||
events.$on('mobile-menu:hide', () => this.isVisibleVignette = false)
|
||||
events.$on('popup:close', () => this.isVisibleVignette = false)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@
|
||||
} from 'vue-feather-icons'
|
||||
|
||||
export default {
|
||||
name: 'MenuBar',
|
||||
name: 'SidebarNavigation',
|
||||
components: {
|
||||
HardDriveIcon,
|
||||
SettingsIcon,
|
||||
@@ -1,18 +1,26 @@
|
||||
<template>
|
||||
<div class="user-meta" v-if="user">
|
||||
<b class="name">{{ user.data.relationships.settings.data.attributes.name }}</b>
|
||||
<span class="email text-theme">{{ user.data.attributes.email }}</span>
|
||||
<div class="user-headline">
|
||||
<UserAvatar size="large"/>
|
||||
<div class="user-meta">
|
||||
<b class="name">{{ user.data.relationships.settings.data.attributes.name }}</b>
|
||||
<span class="email text-theme">{{ user.data.attributes.email }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UserAvatar from '@/components/Others/UserAvatar'
|
||||
import { mapGetters } from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'UserHeadline',
|
||||
components: {
|
||||
UserAvatar,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['user']),
|
||||
...mapGetters([
|
||||
'user'
|
||||
]),
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -21,6 +29,11 @@
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.user-headline {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.user-meta {
|
||||
padding-left: 20px;
|
||||
|
||||
@@ -35,12 +48,4 @@
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 690px) {
|
||||
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
Vendored
+23
-20
@@ -7,6 +7,28 @@ import axios from 'axios'
|
||||
const Helpers = {
|
||||
install(Vue) {
|
||||
|
||||
Vue.prototype.$searchFiles = debounce(function (value) {
|
||||
|
||||
if (value !== '' && typeof value !== 'undefined') {
|
||||
|
||||
this.$store.dispatch('getSearchResult', value)
|
||||
|
||||
} else if (typeof value !== 'undefined') {
|
||||
|
||||
if (this.$store.getters.currentFolder) {
|
||||
|
||||
// Get back after delete query to previously folder
|
||||
if (this.$isThisLocation('public')) {
|
||||
this.$store.dispatch('browseShared', [{folder: this.$store.getters.currentFolder, back: true, init: false}])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [{folder: this.$store.getters.currentFolder, back: true, init: false}])
|
||||
}
|
||||
}
|
||||
|
||||
this.$store.commit('CHANGE_SEARCHING_STATE', false)
|
||||
}
|
||||
}, 300)
|
||||
|
||||
Vue.prototype.$updateText = debounce(function (route, name, value) {
|
||||
|
||||
let enableEmptyInput = ['mimetypes_blacklist', 'google_analytics', 'upload_limit', 'description']
|
||||
@@ -253,24 +275,6 @@ const Helpers = {
|
||||
})
|
||||
}
|
||||
|
||||
Vue.prototype.$isMinimalScale = function () {
|
||||
let sizeType = store.getters.filesViewWidth
|
||||
|
||||
return sizeType === 'minimal-scale'
|
||||
}
|
||||
|
||||
Vue.prototype.$isCompactScale = function () {
|
||||
let sizeType = store.getters.filesViewWidth
|
||||
|
||||
return sizeType === 'compact-scale'
|
||||
}
|
||||
|
||||
Vue.prototype.$isFullScale = function () {
|
||||
let sizeType = store.getters.filesViewWidth
|
||||
|
||||
return sizeType === 'full-scale'
|
||||
}
|
||||
|
||||
Vue.prototype.$isSomethingWrong = function () {
|
||||
events.$emit('alert:open', {
|
||||
title: i18n.t('popup_error.title'),
|
||||
@@ -346,8 +350,7 @@ const Helpers = {
|
||||
// Detect windows
|
||||
Vue.prototype.$checkOS = function () {
|
||||
if (navigator.userAgent.indexOf('Windows') != -1) {
|
||||
let body = document.body
|
||||
body.classList.add('windows')
|
||||
document.body.classList.add('windows')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -91,7 +91,7 @@ Vue.config.productionTip = false;
|
||||
|
||||
// Handle position of Drag & Drop Ghost
|
||||
document.addEventListener('drag', event => {
|
||||
let multiSelect = document.getElementById('multi-select-ui')
|
||||
let multiSelect = document.getElementById('drag-ui')
|
||||
|
||||
multiSelect.style.top = event.clientY + 20 + 'px'
|
||||
multiSelect.style.left = event.clientX + 'px'
|
||||
|
||||
Vendored
-22
@@ -1,11 +1,7 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import i18n from '@/i18n/index'
|
||||
import store from './store/index'
|
||||
|
||||
import AdminMobileMenu from './views/Mobile/AdminMobileMenu'
|
||||
import UserProfileMobileMenu from './views/Mobile/UserProfileMobileMenu'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
const routesOasis = [
|
||||
@@ -417,24 +413,6 @@ const routesAdmin = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'AdminMobileMenu',
|
||||
path: '/admin-menu',
|
||||
component: AdminMobileMenu,
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
title: 'routes_title.settings_mobile'
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'UserProfileMobileMenu',
|
||||
path: '/user-menu',
|
||||
component: UserProfileMobileMenu,
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
title: 'routes_title.profile_settings'
|
||||
},
|
||||
},
|
||||
]
|
||||
const routesShared = [
|
||||
{
|
||||
|
||||
Vendored
+4
-4
@@ -3,7 +3,7 @@ import axios from "axios";
|
||||
import Vue from "vue";
|
||||
|
||||
const defaultState = {
|
||||
fileInfoPanelVisible: localStorage.getItem('file_info_visibility') === 'true' || false,
|
||||
isVisibleSidebar: localStorage.getItem('file_info_visibility') === 'true' || false,
|
||||
FilePreviewType: localStorage.getItem('preview_type') || 'list',
|
||||
config: undefined,
|
||||
index: undefined,
|
||||
@@ -982,7 +982,7 @@ const actions = {
|
||||
},
|
||||
fileInfoToggle: (context, visibility = undefined) => {
|
||||
if (!visibility) {
|
||||
if (context.state.fileInfoPanelVisible) {
|
||||
if (context.state.isVisibleSidebar) {
|
||||
context.commit('FILE_INFO_TOGGLE', false)
|
||||
} else {
|
||||
context.commit('FILE_INFO_TOGGLE', true)
|
||||
@@ -1025,7 +1025,7 @@ const mutations = {
|
||||
state.config.stripe_public_key = data
|
||||
},
|
||||
FILE_INFO_TOGGLE(state, isVisible) {
|
||||
state.fileInfoPanelVisible = isVisible
|
||||
state.isVisibleSidebar = isVisible
|
||||
|
||||
localStorage.setItem('file_info_visibility', isVisible)
|
||||
},
|
||||
@@ -1044,7 +1044,7 @@ const mutations = {
|
||||
}
|
||||
|
||||
const getters = {
|
||||
fileInfoVisible: state => state.fileInfoPanelVisible,
|
||||
isVisibleSidebar: state => state.isVisibleSidebar,
|
||||
FilePreviewType: state => state.FilePreviewType,
|
||||
expirationList: state => state.expirationList,
|
||||
homeDirectory: state => state.homeDirectory,
|
||||
|
||||
+41
-42
@@ -5,13 +5,15 @@ import router from '@/router'
|
||||
import i18n from '@/i18n/index'
|
||||
|
||||
const defaultState = {
|
||||
fileInfoDetail: [],
|
||||
currentFolder: undefined,
|
||||
navigation: undefined,
|
||||
|
||||
isSearching: false,
|
||||
browseHistory: [],
|
||||
isLoading: true,
|
||||
data: [],
|
||||
|
||||
browseHistory: [],
|
||||
clipboard: [],
|
||||
entries: [],
|
||||
}
|
||||
|
||||
const actions = {
|
||||
@@ -30,7 +32,7 @@ const actions = {
|
||||
// Set folder location
|
||||
payload.folder.location = payload.folder.deleted_at || payload.folder.location === 'trash' ? 'trash' : 'base'
|
||||
|
||||
if (! payload.back && !payload.sorting)
|
||||
if (!payload.back && !payload.sorting)
|
||||
commit('STORE_PREVIOUS_FOLDER', getters.currentFolder)
|
||||
|
||||
let url = payload.folder.location === 'trash'
|
||||
@@ -77,7 +79,7 @@ const actions = {
|
||||
})
|
||||
|
||||
axios
|
||||
.get(getters.api + '/browse/latest' )
|
||||
.get(getters.api + '/browse/latest')
|
||||
.then(response => {
|
||||
commit('LOADING_STATE', {loading: false, data: response.data})
|
||||
events.$emit('scrollTop')
|
||||
@@ -175,7 +177,6 @@ const actions = {
|
||||
.catch(() => Vue.prototype.$isSomethingWrong())
|
||||
},
|
||||
getFolderTree: ({commit, getters}) => {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
// Get route
|
||||
@@ -204,19 +205,19 @@ const actions = {
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
LOADING_STATE(state, payload) {
|
||||
state.clipboard = []
|
||||
state.entries = payload.data
|
||||
state.isLoading = payload.loading
|
||||
},
|
||||
UPDATE_FOLDER_TREE(state, tree) {
|
||||
state.navigation = tree
|
||||
},
|
||||
LOADING_STATE(state, payload) {
|
||||
state.fileInfoDetail= []
|
||||
state.data = payload.data
|
||||
state.isLoading = payload.loading
|
||||
},
|
||||
FLUSH_FOLDER_HISTORY(state) {
|
||||
state.browseHistory = []
|
||||
},
|
||||
FLUSH_SHARED(state, id) {
|
||||
state.data.find(item => {
|
||||
state.entries.find(item => {
|
||||
if (item.id === id) item.shared = undefined
|
||||
})
|
||||
},
|
||||
@@ -227,13 +228,14 @@ const mutations = {
|
||||
state.browseHistory.pop()
|
||||
},
|
||||
CHANGE_ITEM_NAME(state, updatedFile) {
|
||||
// Rename filename in file info detail
|
||||
if (state.fileInfoDetail && state.fileInfoDetail.id === updatedFile.id) {
|
||||
state.fileInfoDetail = updatedFile
|
||||
|
||||
// Rename filename in clipboard
|
||||
if (state.clipboard && state.clipboard.id === updatedFile.id) {
|
||||
state.clipboard = updatedFile
|
||||
}
|
||||
|
||||
// Rename item name in data view
|
||||
state.data.find(item => {
|
||||
state.entries.find(item => {
|
||||
if (item.id === updatedFile.id) {
|
||||
item.name = updatedFile.name
|
||||
item.color = updatedFile.color ? updatedFile.color : null
|
||||
@@ -241,60 +243,57 @@ const mutations = {
|
||||
}
|
||||
})
|
||||
},
|
||||
REMOVE_ITEM_FILEINFO_DETAIL(state,item) {
|
||||
state.fileInfoDetail = state.fileInfoDetail.filter(element => element.id !== item.id)
|
||||
},
|
||||
CLEAR_FILEINFO_DETAIL(state) {
|
||||
state.fileInfoDetail = []
|
||||
},
|
||||
LOAD_FILEINFO_DETAIL(state, item) {
|
||||
state.fileInfoDetail = []
|
||||
state.fileInfoDetail.push(item)
|
||||
},
|
||||
GET_FILEINFO_DETAIL(state, item) {
|
||||
let checkData = state.data.find(el => el.id === item.id)
|
||||
if(state.fileInfoDetail.includes(checkData)) return
|
||||
|
||||
state.fileInfoDetail.push(checkData ? checkData : state.currentFolder)
|
||||
},
|
||||
SELECT_ALL_FILES(state){
|
||||
state.fileInfoDetail = state.data
|
||||
},
|
||||
CHANGE_SEARCHING_STATE(state, searchState) {
|
||||
state.isSearching = searchState
|
||||
},
|
||||
UPDATE_SHARED_ITEM(state, data) {
|
||||
state.data.find(item => {
|
||||
state.entries.find(item => {
|
||||
if (item.id === data.item_id) item.shared = data
|
||||
})
|
||||
},
|
||||
ADD_NEW_FOLDER(state, folder) {
|
||||
state.data.unshift(folder)
|
||||
state.entries.unshift(folder)
|
||||
},
|
||||
ADD_NEW_ITEMS(state, items) {
|
||||
state.data = state.data.concat(items)
|
||||
state.entries = state.entries.concat(items)
|
||||
},
|
||||
REMOVE_ITEM(state, id) {
|
||||
state.data = state.data.filter(el => el.id !== id)
|
||||
state.entries = state.entries.filter(el => el.id !== id)
|
||||
},
|
||||
INCREASE_FOLDER_ITEM(state, id) {
|
||||
state.data.map(el => {
|
||||
state.entries.map(el => {
|
||||
if (el.id && el.id === id) el.items++
|
||||
})
|
||||
},
|
||||
STORE_CURRENT_FOLDER(state, folder) {
|
||||
state.currentFolder = folder
|
||||
},
|
||||
REMOVE_ITEM_FROM_CLIPBOARD(state, item) {
|
||||
state.clipboard = state.clipboard.filter(element => element.id !== item.id)
|
||||
},
|
||||
ADD_ALL_ITEMS_TO_CLIPBOARD(state) {
|
||||
state.clipboard = state.entries
|
||||
},
|
||||
ADD_ITEM_TO_CLIPBOARD(state, item) {
|
||||
let selectedItem = state.entries.find(el => el.id === item.id)
|
||||
|
||||
if (state.clipboard.includes(selectedItem)) return
|
||||
|
||||
state.clipboard.push(selectedItem ? selectedItem : state.currentFolder)
|
||||
},
|
||||
CLIPBOARD_CLEAR(state) {
|
||||
state.clipboard = []
|
||||
},
|
||||
}
|
||||
|
||||
const getters = {
|
||||
fileInfoDetail: state => state.fileInfoDetail,
|
||||
clipboard: state => state.clipboard,
|
||||
currentFolder: state => state.currentFolder,
|
||||
browseHistory: state => state.browseHistory,
|
||||
isSearching: state => state.isSearching,
|
||||
navigation: state => state.navigation,
|
||||
isLoading: state => state.isLoading,
|
||||
data: state => state.data,
|
||||
entries: state => state.entries,
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
+11
-13
@@ -41,7 +41,7 @@ const actions = {
|
||||
let files = []
|
||||
|
||||
// get ids of selected files
|
||||
getters.fileInfoDetail.forEach(file => files.push(file.id))
|
||||
getters.clipboard.forEach(file => files.push(file.id))
|
||||
|
||||
// Get route
|
||||
let route = getters.sharedDetail
|
||||
@@ -71,9 +71,9 @@ const actions = {
|
||||
let itemsToMove = []
|
||||
let items = [noSelectedItem]
|
||||
|
||||
// If coming no selected item dont get items to move from fileInfoDetail
|
||||
// If coming no selected item dont get items to move from clipboard
|
||||
if (!noSelectedItem)
|
||||
items = getters.fileInfoDetail
|
||||
items = getters.clipboard
|
||||
|
||||
items.forEach(data => itemsToMove.push({
|
||||
'id': data.id,
|
||||
@@ -82,15 +82,13 @@ const actions = {
|
||||
|
||||
// Remove file preview
|
||||
if (!noSelectedItem)
|
||||
commit('CLEAR_FILEINFO_DETAIL')
|
||||
commit('CLIPBOARD_CLEAR')
|
||||
|
||||
// Get route
|
||||
let route = getters.sharedDetail
|
||||
? `/api/editor/move/${router.currentRoute.params.token}`
|
||||
: '/api/move'
|
||||
|
||||
console.log(to_item);
|
||||
|
||||
axios
|
||||
.post(route, {
|
||||
to_id: to_item.id ? to_item.id : null,
|
||||
@@ -269,9 +267,9 @@ const actions = {
|
||||
let items = [item]
|
||||
let restoreToHome = false
|
||||
|
||||
// If coming no selected item dont get items to restore from fileInfoDetail
|
||||
// If coming no selected item dont get items to restore from clipboard
|
||||
if (!item)
|
||||
items = getters.fileInfoDetail
|
||||
items = getters.clipboard
|
||||
|
||||
// Check if file can be restored to home directory
|
||||
if (getters.currentFolder.location === 'trash')
|
||||
@@ -283,7 +281,7 @@ const actions = {
|
||||
}))
|
||||
|
||||
// Remove file preview
|
||||
commit('CLEAR_FILEINFO_DETAIL')
|
||||
commit('CLIPBOARD_CLEAR')
|
||||
|
||||
axios
|
||||
.post(getters.api + '/trash/restore', {
|
||||
@@ -301,9 +299,9 @@ const actions = {
|
||||
let itemsToDelete = []
|
||||
let items = [noSelectedItem]
|
||||
|
||||
// If coming no selected item dont get items to move from fileInfoDetail
|
||||
// If coming no selected item dont get items to move from clipboard
|
||||
if (!noSelectedItem)
|
||||
items = getters.fileInfoDetail
|
||||
items = getters.clipboard
|
||||
|
||||
items.forEach(data => {
|
||||
itemsToDelete.push({
|
||||
@@ -335,7 +333,7 @@ const actions = {
|
||||
|
||||
// Remove file preview
|
||||
if (!noSelectedItem) {
|
||||
commit('CLEAR_FILEINFO_DETAIL')
|
||||
commit('CLIPBOARD_CLEAR')
|
||||
}
|
||||
|
||||
// Get route
|
||||
@@ -387,7 +385,7 @@ const actions = {
|
||||
commit('LOADING_STATE', {loading: false, data: []})
|
||||
events.$emit('scrollTop')
|
||||
|
||||
commit('CLEAR_FILEINFO_DETAIL')
|
||||
commit('CLIPBOARD_CLEAR')
|
||||
})
|
||||
.catch(() => Vue.prototype.$isSomethingWrong())
|
||||
}
|
||||
|
||||
+2
-2
@@ -95,7 +95,7 @@ const actions = {
|
||||
let items = [singleItem]
|
||||
|
||||
if(!singleItem) {
|
||||
items = getters.fileInfoDetail
|
||||
items = getters.clipboard
|
||||
}
|
||||
|
||||
items.forEach(data => {
|
||||
@@ -119,7 +119,7 @@ const actions = {
|
||||
// Flush shared data
|
||||
commit('FLUSH_SHARED', item.id)
|
||||
|
||||
commit('CLEAR_FILEINFO_DETAIL')
|
||||
commit('CLIPBOARD_CLEAR')
|
||||
})
|
||||
resolve(true)
|
||||
|
||||
|
||||
+4
-4
@@ -56,9 +56,9 @@ const actions = {
|
||||
let addFavourites = []
|
||||
let items = [folder]
|
||||
|
||||
// If dont coming single folder get folders to add to favourites from fileInfoDetail
|
||||
// If dont coming single folder get folders to add to favourites from clipboard
|
||||
if (!folder)
|
||||
items = context.getters.fileInfoDetail
|
||||
items = context.getters.clipboard
|
||||
|
||||
items.forEach((data) => {
|
||||
if (data.type === 'folder') {
|
||||
@@ -71,9 +71,9 @@ const actions = {
|
||||
}
|
||||
})
|
||||
|
||||
// If dont coming single folder clear the selected folders in fileInfoDetail
|
||||
// If dont coming single folder clear the selected folders in clipboard
|
||||
if (!folder) {
|
||||
context.commit('CLEAR_FILEINFO_DETAIL')
|
||||
context.commit('CLIPBOARD_CLEAR')
|
||||
}
|
||||
|
||||
let pushToFavorites = []
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
<!--Mobile Navigation-->
|
||||
<MobileNavigation />
|
||||
|
||||
<!--Confirm Popup-->
|
||||
<Confirm />
|
||||
<!--ConfirmPopup Popup-->
|
||||
<ConfirmPopup />
|
||||
|
||||
<!-- Create language popup -->
|
||||
<CreateLanguage/>
|
||||
|
||||
<!--Navigation Sidebar-->
|
||||
<MenuBar/>
|
||||
<SidebarNavigation/>
|
||||
|
||||
<ContentSidebar>
|
||||
|
||||
@@ -90,12 +90,12 @@
|
||||
|
||||
<script>
|
||||
import { UsersIcon, SettingsIcon, FileTextIcon, CreditCardIcon, DatabaseIcon, BoxIcon, MonitorIcon, GlobeIcon } from 'vue-feather-icons'
|
||||
import SidebarNavigation from '@/components/Sidebar/SidebarNavigation'
|
||||
import MobileNavigation from '@/components/Others/MobileNavigation'
|
||||
import ContentSidebar from '@/components/Sidebar/ContentSidebar'
|
||||
import CreateLanguage from '@/components/Others/CreateLanguage'
|
||||
import ContentGroup from '@/components/Sidebar/ContentGroup'
|
||||
import Confirm from '@/components/Others/Popup/Confirm'
|
||||
import MenuBar from '@/components/Sidebar/MenuBar'
|
||||
import ConfirmPopup from '@/components/Others/Popup/ConfirmPopup'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
@@ -104,6 +104,7 @@
|
||||
...mapGetters(['config']),
|
||||
},
|
||||
components: {
|
||||
SidebarNavigation,
|
||||
MobileNavigation,
|
||||
CreateLanguage,
|
||||
ContentSidebar,
|
||||
@@ -115,8 +116,7 @@
|
||||
MonitorIcon,
|
||||
UsersIcon,
|
||||
GlobeIcon,
|
||||
Confirm,
|
||||
MenuBar,
|
||||
ConfirmPopup,
|
||||
BoxIcon,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -321,8 +321,6 @@ export default {
|
||||
get_started_description: response.data.get_started_description,
|
||||
footer_content: response.data.footer_content
|
||||
}
|
||||
|
||||
console.log(this.app);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false
|
||||
|
||||
@@ -386,7 +386,7 @@
|
||||
}
|
||||
|
||||
.languages-wrapper {
|
||||
margin-top: 0px;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -430,7 +430,7 @@
|
||||
@media only screen and (max-width: 1024px) {
|
||||
|
||||
.search-bar-wrapper {
|
||||
top: 15px;
|
||||
top: 58px;
|
||||
z-index: 7;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<p>{{ $t('user_box_delete.description') }}</p>
|
||||
</InfoBox>
|
||||
<ValidationObserver ref="deleteUser" @submit.prevent="deleteUser" v-slot="{ invalid }" tag="form" class="form block-form">
|
||||
<ValidationProvider tag="div" class="block-wrapper" v-slot="{ errors }" mode="passive" name="User name" :rules="'required|is:' + user.data.relationships.settings.data.attributes.name">
|
||||
<ValidationProvider tag="div" class="block-wrapper" v-slot="{ errors }" mode="passive" name="User name" rules="required">
|
||||
<label>{{ $t('admin_page_user.label_delete_user', {user: user.data.relationships.settings.data.attributes.name}) }}:</label>
|
||||
<div class="single-line-form">
|
||||
<input v-model="userName"
|
||||
@@ -71,6 +71,15 @@
|
||||
|
||||
if (!isValid) return;
|
||||
|
||||
if (this.userName !== this.user.data.relationships.settings.data.attributes.name) {
|
||||
|
||||
this.$refs.deleteUser.setErrors({
|
||||
'User name': 'The user name is not the same.'
|
||||
});
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
this.isSendingRequest = true
|
||||
|
||||
axios
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<span class="empty-note navigator" v-if="tree.length == 0">
|
||||
{{ $t('sidebar.folders_empty') }}
|
||||
</span>
|
||||
<TreeMenuNavigator class="folder-tree" :depth="0" :nodes="items" v-for="items in tree" :key="items.id"/>
|
||||
<TreeMenuNavigator class="folder-tree" :depth="0" :nodes="folder" v-for="folder in tree" :key="folder.id"/>
|
||||
</ContentGroup>
|
||||
|
||||
<!--Favourites-->
|
||||
@@ -74,7 +74,7 @@
|
||||
<script>
|
||||
import UpgradeSidebarBanner from '@/components/Others/UpgradeSidebarBanner'
|
||||
import TreeMenuNavigator from '@/components/Others/TreeMenuNavigator'
|
||||
import MultiSelected from '@/components/FilesView/MultiSelected'
|
||||
import TitlePreview from '@/components/FilesView/TitlePreview'
|
||||
import ContentFileView from '@/components/Others/ContentFileView'
|
||||
import ContentSidebar from '@/components/Sidebar/ContentSidebar'
|
||||
import ContentGroup from '@/components/Sidebar/ContentGroup'
|
||||
@@ -94,7 +94,7 @@ export default {
|
||||
UpgradeSidebarBanner,
|
||||
TreeMenuNavigator,
|
||||
ContentFileView,
|
||||
MultiSelected,
|
||||
TitlePreview,
|
||||
ContentSidebar,
|
||||
UploadCloudIcon,
|
||||
ContentGroup,
|
||||
@@ -104,7 +104,7 @@ export default {
|
||||
XIcon
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['user', 'homeDirectory', 'currentFolder', 'config', 'fileInfoDetail']),
|
||||
...mapGetters(['user', 'homeDirectory', 'currentFolder', 'config', 'clipboard']),
|
||||
favourites() {
|
||||
return this.user.data.relationships.favourites.data.attributes.folders
|
||||
},
|
||||
@@ -137,7 +137,7 @@ export default {
|
||||
dragEnter() {
|
||||
if (this.draggedItem && this.draggedItem.type !== 'folder') return
|
||||
|
||||
if (this.fileInfoDetail.length > 0 && this.fileInfoDetail.find(item => item.type !== 'folder')) return
|
||||
if (this.clipboard.length > 0 && this.clipboard.find(item => item.type !== 'folder')) return
|
||||
|
||||
this.area = true
|
||||
},
|
||||
@@ -156,17 +156,17 @@ export default {
|
||||
if (this.favourites.find(folder => folder.id == this.draggedItem.id)) return
|
||||
|
||||
// Prevent to move folders to self
|
||||
if (this.fileInfoDetail.length > 0 && this.fileInfoDetail.find(item => item.type !== 'folder')) return
|
||||
if (this.clipboard.length > 0 && this.clipboard.find(item => item.type !== 'folder')) return
|
||||
|
||||
// Store favourites folder
|
||||
|
||||
//Add to favourites non selected folder
|
||||
if (!this.fileInfoDetail.includes(this.draggedItem)) {
|
||||
if (!this.clipboard.includes(this.draggedItem)) {
|
||||
this.$store.dispatch('addToFavourites', this.draggedItem)
|
||||
}
|
||||
|
||||
//Add to favourites selected folders
|
||||
if (this.fileInfoDetail.includes(this.draggedItem)) {
|
||||
if (this.clipboard.includes(this.draggedItem)) {
|
||||
this.$store.dispatch('addToFavourites', null)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<!--Navigator-->
|
||||
<ContentGroup :title="$t('sidebar.locations_title')">
|
||||
<div class="menu-list-wrapper vertical">
|
||||
<li class="menu-list-item link" :class="{'is-active': $isThisLocation(['shared'])}" @click="getShared()">
|
||||
<li class="menu-list-item link" :class="{'is-active': $isThisLocation(['shared'])}" @click="getShared">
|
||||
<div class="icon text-theme">
|
||||
<link-icon size="17"></link-icon>
|
||||
</div>
|
||||
@@ -14,7 +14,7 @@
|
||||
{{ $t('sidebar.my_shared') }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="menu-list-item link" :class="{'is-active': $isThisLocation(['participant_uploads'])}" @click="getParticipantUploads()">
|
||||
<li class="menu-list-item link" :class="{'is-active': $isThisLocation(['participant_uploads'])}" @click="getParticipantUploads">
|
||||
<div class="icon text-theme">
|
||||
<users-icon size="17"></users-icon>
|
||||
</div>
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
<template>
|
||||
<div id="single-page">
|
||||
<div id="page-content">
|
||||
|
||||
<!--Header-->
|
||||
<MobileHeader :title="$t($router.currentRoute.meta.title)"/>
|
||||
|
||||
<!--Content-->
|
||||
<div class="content-page">
|
||||
<nav class="mobile-navigation">
|
||||
|
||||
<!--Admin menu-->
|
||||
<b class="mobile-menu-label">{{ $t('global.admin') }}</b>
|
||||
<MenuItemList :navigation="AdminNavigation" />
|
||||
|
||||
<!--SaaS menu-->
|
||||
<b v-if="config.isSaaS" class="mobile-menu-label">{{ $t('global.saas') }}</b>
|
||||
<MenuItemList v-if="config.isSaaS" :navigation="SassNavigation" />
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MenuItemList from '@/components/Mobile/MenuItemList'
|
||||
import MobileHeader from '@/components/Mobile/MobileHeader'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'AdminMobileMenu',
|
||||
components: {
|
||||
MenuItemList,
|
||||
MobileHeader,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['config']),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
AdminNavigation: [
|
||||
{
|
||||
icon: 'box',
|
||||
title: this.$t('admin_menu.dashboard'),
|
||||
routeName: 'Dashboard',
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
icon: 'users',
|
||||
title: this.$t('admin_menu.users'),
|
||||
routeName: 'Users',
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
icon: 'settings',
|
||||
title: this.$t('admin_menu.settings'),
|
||||
routeName: 'AppOthers',
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
icon: 'monitor',
|
||||
title: this.$t('admin_menu.pages'),
|
||||
routeName: 'Pages',
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
icon: 'language',
|
||||
title: this.$t('languages'),
|
||||
routeName: 'Language',
|
||||
isVisible: true,
|
||||
|
||||
}
|
||||
],
|
||||
SassNavigation: [
|
||||
{
|
||||
icon: 'database',
|
||||
title: this.$t('admin_menu.plans'),
|
||||
routeName: 'Plans',
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
icon: 'file-text',
|
||||
title: this.$t('admin_menu.invoices'),
|
||||
routeName: 'Invoices',
|
||||
isVisible: true,
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.mobile-navigation {
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 99;
|
||||
|
||||
.mobile-menu-label {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 5px;
|
||||
@include font-size(11);
|
||||
color: $text-muted;
|
||||
display: block;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.mobile-navigation {
|
||||
|
||||
.mobile-menu-label {
|
||||
color: $dark_mode_text_secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,114 +0,0 @@
|
||||
<template>
|
||||
<div id="single-page">
|
||||
<div id="page-content">
|
||||
|
||||
<!--Header-->
|
||||
<MobileHeader :title="$t($router.currentRoute.meta.title)"/>
|
||||
|
||||
<!--Content-->
|
||||
<div class="content-page">
|
||||
<nav class="mobile-navigation">
|
||||
|
||||
<!--Admin menu-->
|
||||
<b class="mobile-menu-label">{{ $t('global.menu') }}</b>
|
||||
<MenuItemList :navigation="ProfileNavigation" />
|
||||
|
||||
<!--SaaS menu-->
|
||||
<b class="mobile-menu-label">{{ $t('global.subscription') }}</b>
|
||||
<MenuItemList :navigation="SubscriptionNavigation" />
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MenuItemList from '@/components/Mobile/MenuItemList'
|
||||
import MobileHeader from '@/components/Mobile/MobileHeader'
|
||||
|
||||
export default {
|
||||
name: 'UserProfileMobileMenu',
|
||||
components: {
|
||||
MenuItemList,
|
||||
MobileHeader,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
ProfileNavigation: [
|
||||
{
|
||||
icon: 'user',
|
||||
title: this.$t('menu.profile'),
|
||||
routeName: 'Profile',
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
icon: 'hard-drive',
|
||||
title: this.$t('menu.storage'),
|
||||
routeName: 'Storage',
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
icon: 'lock',
|
||||
title: this.$t('menu.password'),
|
||||
routeName: 'Password',
|
||||
isVisible: true,
|
||||
},
|
||||
],
|
||||
SubscriptionNavigation: [
|
||||
{
|
||||
icon: 'cloud',
|
||||
title: this.$t('menu.subscription'),
|
||||
routeName: 'Subscription',
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
icon: 'credit-card',
|
||||
title: this.$t('menu.payment_cards'),
|
||||
routeName: 'PaymentMethods',
|
||||
isVisible: true,
|
||||
},
|
||||
{
|
||||
icon: 'file-text',
|
||||
title: this.$t('menu.invoices'),
|
||||
routeName: 'Invoice',
|
||||
isVisible: true,
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
.mobile-navigation {
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 99;
|
||||
|
||||
.mobile-menu-label {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 5px;
|
||||
@include font-size(11);
|
||||
color: $text-muted;
|
||||
display: block;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.mobile-navigation {
|
||||
|
||||
.mobile-menu-label {
|
||||
color: $dark_mode_text_secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,118 +1,103 @@
|
||||
<template>
|
||||
<div id="application-wrapper">
|
||||
|
||||
<!--Full File Preview-->
|
||||
<FileFullPreview />
|
||||
<!--File preview window-->
|
||||
<FilePreview />
|
||||
|
||||
<!--Mobile Navigation-->
|
||||
<MobileNavigation />
|
||||
|
||||
<!--Processing popup-->
|
||||
<!--Popups-->
|
||||
<ProcessingPopup />
|
||||
<ConfirmPopup />
|
||||
|
||||
<!--Confirm Popup-->
|
||||
<Confirm />
|
||||
<ShareCreatePopup />
|
||||
<ShareEditPopup />
|
||||
|
||||
<!--Share Item popup-->
|
||||
<ShareCreate />
|
||||
<ShareEdit />
|
||||
<CreateFolderPopup />
|
||||
<RenameItemPopup />
|
||||
|
||||
<!--Rename folder/file item-->
|
||||
<RenameItem />
|
||||
<MoveItemPopup />
|
||||
|
||||
<!--Create folder mobile UI-->
|
||||
<CreateFolder />
|
||||
<!--Mobile components-->
|
||||
<FileSortingMobile />
|
||||
<FileFilterMobile />
|
||||
<FileMenuMobile />
|
||||
|
||||
<!--Move item popup-->
|
||||
<MoveItem />
|
||||
<MultiSelectToolbarMobile />
|
||||
|
||||
<!-- Mobile Menu for Multi selected items -->
|
||||
<MobileMultiSelectMenu />
|
||||
<!--Navigations-->
|
||||
<MobileNavigation />
|
||||
<SidebarNavigation />
|
||||
|
||||
<!--Drag UI-->
|
||||
<!--Others-->
|
||||
<DragUI />
|
||||
|
||||
<!--Mobile menu for selecting view and sorting-->
|
||||
<MobileSortingAndPreview />
|
||||
|
||||
<!--Mobile Menu-->
|
||||
<MobileMenu />
|
||||
|
||||
<!--Navigation Sidebar-->
|
||||
<MenuBar />
|
||||
|
||||
<!--File page-->
|
||||
<keep-alive :include="['Admin', 'Users']">
|
||||
<router-view :class="{'is-scaled-down': isScaledDown}" />
|
||||
</keep-alive>
|
||||
<router-view :class="{'is-scaled-down': isScaledDown}" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MobileSortingAndPreview from '@/components/FilesView/MobileSortingAndPreview'
|
||||
import MobileMultiSelectMenu from '@/components/FilesView/MobileMultiSelectMenu'
|
||||
import ProcessingPopup from '@/components/FilesView/ProcessingPopup'
|
||||
import FileFullPreview from '@/components/FilesView/FileFullPreview'
|
||||
import MobileNavigation from '@/components/Others/MobileNavigation'
|
||||
import CreateFolder from '@/components/Others/CreateFolder'
|
||||
import MobileMenu from '@/components/FilesView/MobileMenu'
|
||||
import ShareCreate from '@/components/Others/ShareCreate'
|
||||
import Confirm from '@/components/Others/Popup/Confirm'
|
||||
import RenameItem from '@/components/Others/RenameItem'
|
||||
import ShareEdit from '@/components/Others/ShareEdit'
|
||||
import MoveItem from '@/components/Others/MoveItem'
|
||||
import DragUI from '@/components/FilesView/DragUI'
|
||||
import MenuBar from '@/components/Sidebar/MenuBar'
|
||||
import {includes} from 'lodash'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
import MultiSelectToolbarMobile from '@/components/FilesView/MultiSelectToolbarMobile'
|
||||
import FileSortingMobile from '@/components/FilesView/FileSortingMobile'
|
||||
import SidebarNavigation from '@/components/Sidebar/SidebarNavigation'
|
||||
import FileFilterMobile from '@/components/FilesView/FileFilterMobile'
|
||||
import CreateFolderPopup from '@/components/Others/CreateFolderPopup'
|
||||
import ProcessingPopup from '@/components/FilesView/ProcessingPopup'
|
||||
import MobileNavigation from '@/components/Others/MobileNavigation'
|
||||
import ShareCreatePopup from '@/components/Others/ShareCreatePopup'
|
||||
import FileMenuMobile from '@/components/FilesView/FileMenuMobile'
|
||||
import ConfirmPopup from '@/components/Others/Popup/ConfirmPopup'
|
||||
import RenameItemPopup from '@/components/Others/RenameItemPopup'
|
||||
import ShareEditPopup from '@/components/Others/ShareEditPopup'
|
||||
import MoveItemPopup from '@/components/Others/MoveItemPopup'
|
||||
import FilePreview from '@/components/FilesView/FilePreview'
|
||||
import DragUI from '@/components/FilesView/DragUI'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'Platform',
|
||||
components: {
|
||||
MobileSortingAndPreview,
|
||||
MobileMultiSelectMenu,
|
||||
MobileNavigation,
|
||||
FileFullPreview,
|
||||
ProcessingPopup,
|
||||
CreateFolder,
|
||||
ShareCreate,
|
||||
MobileMenu,
|
||||
RenameItem,
|
||||
ShareEdit,
|
||||
MoveItem,
|
||||
Confirm,
|
||||
MenuBar,
|
||||
DragUI,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'config'
|
||||
]),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isScaledDown: false
|
||||
export default {
|
||||
name: 'Platform',
|
||||
components: {
|
||||
MultiSelectToolbarMobile,
|
||||
CreateFolderPopup,
|
||||
FileSortingMobile,
|
||||
SidebarNavigation,
|
||||
FileFilterMobile,
|
||||
MobileNavigation,
|
||||
ShareCreatePopup,
|
||||
ProcessingPopup,
|
||||
RenameItemPopup,
|
||||
ShareEditPopup,
|
||||
FileMenuMobile,
|
||||
MoveItemPopup,
|
||||
ConfirmPopup,
|
||||
FilePreview,
|
||||
DragUI,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'config'
|
||||
]),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isScaledDown: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
events.$on('mobile-menu:show', () => this.isScaledDown = true)
|
||||
|
||||
events.$on('fileItem:deselect', () => this.isScaledDown = false)
|
||||
events.$on('mobile-menu:hide', () => this.isScaledDown = false)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
events.$on('show:mobile-navigation', () => this.isScaledDown = true)
|
||||
events.$on('hide:mobile-navigation', () => this.isScaledDown = false)
|
||||
events.$on('mobileMenu:show', () => this.isScaledDown = true)
|
||||
events.$on('fileItem:deselect', () => this.isScaledDown = false)
|
||||
events.$on('mobileSortingAndPreview', state => this.isScaledDown = state)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '@assets/vuefilemanager/_variables';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
@media only screen and (max-width: 690px) {
|
||||
@media only screen and (max-width: 690px) {
|
||||
|
||||
.is-scaled-down {
|
||||
@include transform(scale(0.95));
|
||||
.is-scaled-down {
|
||||
@include transform(scale(0.95));
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,108 +1,112 @@
|
||||
<template>
|
||||
<div id="application-wrapper">
|
||||
|
||||
<!--Full File Preview-->
|
||||
<FileFullPreview />
|
||||
|
||||
<!--Loading Spinner-->
|
||||
<Spinner v-if="isLoading" />
|
||||
|
||||
<!--Move item popup-->
|
||||
<MoveItem />
|
||||
<!--File preview window-->
|
||||
<FilePreview />
|
||||
|
||||
<!-- Processing popup for zip -->
|
||||
<!--Popups-->
|
||||
<ProcessingPopup />
|
||||
|
||||
<!-- Mobile Menu for Multi selected items -->
|
||||
<MobileMultiSelectMenu />
|
||||
<CreateFolderPopup />
|
||||
<RenameItemPopup />
|
||||
|
||||
<!--Rename folder/file item-->
|
||||
<RenameItem />
|
||||
<MoveItemPopup />
|
||||
|
||||
<!--Create folder mobile UI-->
|
||||
<CreateFolder />
|
||||
<!-- Mobile components -->
|
||||
<FileSortingMobile />
|
||||
<FileMenuMobile />
|
||||
|
||||
<!--Drag UI-->
|
||||
<MultiSelectToolbarMobile />
|
||||
|
||||
<!--Others-->
|
||||
<Vignette />
|
||||
<DragUI />
|
||||
|
||||
<!--Mobile Menu-->
|
||||
<MobileMenu />
|
||||
|
||||
<!--Mobile menu for selecting view and sorting-->
|
||||
<MobileSortingAndPreview />
|
||||
|
||||
<!--System alerts-->
|
||||
<Alert />
|
||||
|
||||
<!--Background vignette-->
|
||||
<Vignette />
|
||||
|
||||
<!--Pages-->
|
||||
<router-view />
|
||||
<router-view :class="{'is-scaled-down': isScaledDown}" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MobileSortingAndPreview from '@/components/FilesView/MobileSortingAndPreview'
|
||||
import MobileMultiSelectMenu from '@/components/FilesView/MobileMultiSelectMenu'
|
||||
import ProcessingPopup from '@/components/FilesView/ProcessingPopup'
|
||||
import FileFullPreview from '@/components/FilesView/FileFullPreview'
|
||||
import CreateFolder from '@/components/Others/CreateFolder'
|
||||
import MobileMenu from '@/components/FilesView/MobileMenu'
|
||||
import RenameItem from '@/components/Others/RenameItem'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
import MoveItem from '@/components/Others/MoveItem'
|
||||
import Vignette from '@/components/Others/Vignette'
|
||||
import DragUI from '@/components/FilesView/DragUI'
|
||||
import Alert from '@/components/FilesView/Alert'
|
||||
import {mapGetters} from 'vuex'
|
||||
import MultiSelectToolbarMobile from '@/components/FilesView/MultiSelectToolbarMobile'
|
||||
import FileSortingMobile from '@/components/FilesView/FileSortingMobile'
|
||||
import CreateFolderPopup from '@/components/Others/CreateFolderPopup'
|
||||
import ProcessingPopup from '@/components/FilesView/ProcessingPopup'
|
||||
import FileMenuMobile from '@/components/FilesView/FileMenuMobile'
|
||||
import RenameItemPopup from '@/components/Others/RenameItemPopup'
|
||||
import MoveItemPopup from '@/components/Others/MoveItemPopup'
|
||||
import FilePreview from '@/components/FilesView/FilePreview'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
import Vignette from '@/components/Others/Vignette'
|
||||
import DragUI from '@/components/FilesView/DragUI'
|
||||
import Alert from '@/components/FilesView/Alert'
|
||||
import {events} from '@/bus'
|
||||
import {mapGetters} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'Platform',
|
||||
components: {
|
||||
MobileSortingAndPreview,
|
||||
MobileMultiSelectMenu,
|
||||
FileFullPreview,
|
||||
ProcessingPopup,
|
||||
CreateFolder,
|
||||
MobileMenu,
|
||||
RenameItem,
|
||||
MoveItem,
|
||||
Vignette,
|
||||
Spinner,
|
||||
DragUI,
|
||||
Alert,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'config'
|
||||
]),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
export default {
|
||||
name: 'Platform',
|
||||
components: {
|
||||
MultiSelectToolbarMobile,
|
||||
CreateFolderPopup,
|
||||
FileSortingMobile,
|
||||
ProcessingPopup,
|
||||
RenameItemPopup,
|
||||
FileMenuMobile,
|
||||
MoveItemPopup,
|
||||
FilePreview,
|
||||
Vignette,
|
||||
Spinner,
|
||||
DragUI,
|
||||
Alert,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'config'
|
||||
]),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
isScaledDown: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
events.$on('mobile-menu:show', () => this.isScaledDown = true)
|
||||
events.$on('fileItem:deselect', () => this.isScaledDown = false)
|
||||
|
||||
this.$store.dispatch('getShareDetail', this.$route.params.token)
|
||||
.then(response => {
|
||||
this.isLoading = false
|
||||
|
||||
// Show public file browser
|
||||
if (response.data.data.attributes.type === 'folder' && !response.data.data.attributes.is_protected && this.$router.currentRoute.name !== 'SharedFileBrowser') {
|
||||
this.$router.push({name: 'SharedFileBrowser'})
|
||||
}
|
||||
|
||||
// Show public single file
|
||||
if (response.data.data.attributes.type !== 'folder' && !response.data.data.attributes.is_protected && this.$router.currentRoute.name !== 'SharedSingleFile') {
|
||||
this.$router.push({name: 'SharedSingleFile'})
|
||||
}
|
||||
|
||||
// Show authentication page
|
||||
if (response.data.data.attributes.is_protected && this.$router.currentRoute.name !== 'SharedAuthentication') {
|
||||
this.$router.push({name: 'SharedAuthentication'})
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('getShareDetail', this.$route.params.token)
|
||||
.then(response => {
|
||||
this.isLoading = false
|
||||
|
||||
// Show public file browser
|
||||
if (response.data.data.attributes.type === 'folder' && !response.data.data.attributes.is_protected && this.$router.currentRoute.name !== 'SharedFileBrowser') {
|
||||
this.$router.push({name: 'SharedFileBrowser'})
|
||||
}
|
||||
|
||||
// Show public single file
|
||||
if (response.data.data.attributes.type !== 'folder' && !response.data.data.attributes.is_protected && this.$router.currentRoute.name !== 'SharedSingleFile') {
|
||||
this.$router.push({name: 'SharedSingleFile'})
|
||||
}
|
||||
|
||||
// Show authentication page
|
||||
if (response.data.data.attributes.is_protected && this.$router.currentRoute.name !== 'SharedAuthentication') {
|
||||
this.$router.push({name: 'SharedAuthentication'})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '@assets/vuefilemanager/_mixins';
|
||||
|
||||
@media only screen and (max-width: 690px) {
|
||||
|
||||
.is-scaled-down {
|
||||
@include transform(scale(0.95));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<div class="menu-list-wrapper vertical">
|
||||
<a class="menu-list-item link" @click="goHome">
|
||||
<div class="icon">
|
||||
<home-icon size="17"></home-icon>
|
||||
<home-icon size="17"/>
|
||||
</div>
|
||||
<div class="label">
|
||||
{{ $t('sidebar.home') }}
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
<!--Navigator-->
|
||||
<ContentGroup :title="$t('sidebar.navigator_title')" class="navigator">
|
||||
<TreeMenuNavigator class="folder-tree" :depth="0" :nodes="items" v-for="items in navigationTree" :key="items.id" />
|
||||
<TreeMenuNavigator class="folder-tree" :depth="0" :nodes="folder" v-for="folder in navigationTree" :key="folder.id" />
|
||||
</ContentGroup>
|
||||
</ContentSidebar>
|
||||
|
||||
@@ -28,14 +28,11 @@
|
||||
<DesktopToolbar />
|
||||
|
||||
<FileBrowser />
|
||||
|
||||
<DesktopSortingAndPreview />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DesktopSortingAndPreview from '@/components/FilesView/DesktopSortingAndPreview'
|
||||
import TreeMenuNavigator from '@/components/Others/TreeMenuNavigator'
|
||||
import DesktopToolbar from '@/components/FilesView/DesktopToolbar'
|
||||
import ContentSidebar from '@/components/Sidebar/ContentSidebar'
|
||||
@@ -49,7 +46,6 @@
|
||||
export default {
|
||||
name: 'SharedFileBrowser',
|
||||
components: {
|
||||
DesktopSortingAndPreview,
|
||||
TreeMenuNavigator,
|
||||
ContentSidebar,
|
||||
DesktopToolbar,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
@endphp
|
||||
|
||||
{{-- Group options --}}
|
||||
.group:hover .group-hover-text-theme {color: {{ $color }} !important;}
|
||||
.group:hover:not(.hover-disabled) .group-hover-text-theme {color: {{ $color }} !important;}
|
||||
|
||||
|
||||
{{-- Single option --}}
|
||||
@@ -50,7 +50,7 @@
|
||||
{{-- Emoji Picker --}}
|
||||
.active-menu.focus-border-theme {border-color: {{ $color }} !important;}
|
||||
|
||||
{{-- Menubar --}}
|
||||
{{-- Sidebar Navigation --}}
|
||||
.router-link-active.home .button-icon {background: {{ $color }}10}
|
||||
|
||||
{{-- Content Panel --}}
|
||||
|
||||
Reference in New Issue
Block a user