mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-18 00:02:15 +00:00
info sidebar refactoring
This commit is contained in:
@@ -1,69 +0,0 @@
|
||||
<template>
|
||||
<div class="empty-message">
|
||||
<div class="message text-center">
|
||||
<eye-off-icon v-if="icon === 'eye-off'" size="36" class="icon" />
|
||||
<p>{{ message }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { EyeOffIcon } from 'vue-feather-icons'
|
||||
|
||||
export default {
|
||||
name: 'EmptyMessage',
|
||||
props: ['icon', 'message'],
|
||||
components: {
|
||||
EyeOffIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '/resources/sass/vuefilemanager/_variables';
|
||||
@import '/resources/sass/vuefilemanager/_mixins';
|
||||
|
||||
.empty-message {
|
||||
text-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
|
||||
.message {
|
||||
margin: 0 auto;
|
||||
|
||||
p {
|
||||
margin-top: 10px;
|
||||
max-width: 130px;
|
||||
@include font-size(13);
|
||||
font-weight: 500;
|
||||
color: $text-muted;
|
||||
}
|
||||
|
||||
.icon {
|
||||
display: inline-block;
|
||||
|
||||
path, line, polyline, rect, circle {
|
||||
stroke: $text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dark {
|
||||
.empty-message {
|
||||
|
||||
.message {
|
||||
.icon {
|
||||
path, line, polyline, rect, circle {
|
||||
stroke: $dark_mode_text_secondary;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
color: $dark_mode_text_secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,46 +1,34 @@
|
||||
<template>
|
||||
<div class="info-wrapper">
|
||||
|
||||
<div class="2xl:w-104 w-96 px-2.5 overflow-y-auto overflow-x-hidden h-screen lg:block hidden">
|
||||
<!--Is empty clipboard-->
|
||||
<EmptyMessage
|
||||
v-if="isEmpty"
|
||||
:message="$t('messages.nothing_to_preview')"
|
||||
icon="eye-off"
|
||||
/>
|
||||
<div v-if="isEmpty" class="flex items-center justify-center h-full">
|
||||
<div class="text-center">
|
||||
<eye-off-icon size="28" class="vue-feather text-gray-400 inline-block mb-3" />
|
||||
<small class="text-sm block text-gray-400">
|
||||
{{ $t('messages.nothing_to_preview') }}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--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>
|
||||
<TitlePreview
|
||||
v-if="! isSingleFile && !isEmpty"
|
||||
class="mb-6"
|
||||
icon="check-square"
|
||||
:title="$t('file_detail.selected_multiple')"
|
||||
:subtitle="this.clipboard.length + ' ' + $tc('file_detail.items', this.clipboard.length)"
|
||||
/>
|
||||
|
||||
<!--Single file preview-->
|
||||
<div v-if="isSingleFile && !isEmpty" class="info-headline">
|
||||
<div v-if="isSingleFile && !isEmpty">
|
||||
<FilePreviewDetail />
|
||||
|
||||
<TitlePreview
|
||||
class="mb-6"
|
||||
:icon="clipboard[0].data.type"
|
||||
:title="clipboard[0].data.attributes.name"
|
||||
:subtitle="clipboard[0].data.attributes.mimetype"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!--File info-->
|
||||
<ListInfo v-if="isSingleFile && !isEmpty">
|
||||
|
||||
<!--Author-->
|
||||
<ListInfoItem
|
||||
v-if="canShowAuthor"
|
||||
:title="$t('Author')"
|
||||
>
|
||||
<div class="flex items-center mt-1">
|
||||
<MemberAvatar :size="32" :member="singleFile.data.relationships.owner" />
|
||||
<span class="ml-2 block">{{ singleFile.data.relationships.owner.data.attributes.name }}</span>
|
||||
</div>
|
||||
</ListInfoItem>
|
||||
|
||||
<!--Filesize-->
|
||||
<ListInfoItem
|
||||
@@ -60,9 +48,11 @@
|
||||
v-if="$checkPermission(['master'])"
|
||||
:title="$t('file_detail.where')"
|
||||
>
|
||||
<div class="action-button" @click="openMoveOptions">
|
||||
<span>{{ singleFile.data.relationships.parent ? singleFile.data.relationships.parent.data.attributes.name : $t('locations.home') }}</span>
|
||||
<edit-2-icon size="10" class="edit-icon" />
|
||||
<div @click="$moveFileOrFolder(singleFile)" class="flex items-center cursor-pointer">
|
||||
<span class="inline-block font-bold text-sm">
|
||||
{{ singleFile.data.relationships.parent ? singleFile.data.relationships.parent.data.attributes.name : $t('locations.home') }}
|
||||
</span>
|
||||
<Edit2Icon size="10" class="ml-2" />
|
||||
</div>
|
||||
</ListInfoItem>
|
||||
|
||||
@@ -73,7 +63,7 @@
|
||||
>
|
||||
<div class="action-button" @click="$updateTeamFolder(singleFile)">
|
||||
<TeamMembersPreview :folder="singleFile" :avatar-size="32" />
|
||||
<edit-2-icon size="10" class="edit-icon" />
|
||||
<Edit2Icon size="10" class="ml-2" />
|
||||
</div>
|
||||
</ListInfoItem>
|
||||
|
||||
@@ -82,14 +72,29 @@
|
||||
v-if="$checkPermission('master') && singleFile.data.relationships.shared"
|
||||
:title="$t('file_detail.shared')"
|
||||
>
|
||||
<div @click="openShareOptions" class="action-button">
|
||||
<span>{{ sharedInfo }}</span>
|
||||
<edit-2-icon size="10" class="edit-icon" />
|
||||
<div @click="$shareFileOrFolder(singleFile)" class="flex items-center cursor-pointer mb-2">
|
||||
<span class="inline-block font-bold text-sm">
|
||||
{{ sharedInfo }}
|
||||
</span>
|
||||
<Edit2Icon size="10" class="ml-2" />
|
||||
</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" />
|
||||
<CopyShareLink :item="singleFile" class="copy-share-link" size="small" />
|
||||
<div class="flex items-center w-full">
|
||||
<lock-icon v-if="isLocked" @click="$shareFileOrFolder(singleFile)" size="17" class="hover-text-theme vue-feather cursor-pointer"/>
|
||||
<unlock-icon v-if="! isLocked" @click="$shareFileOrFolder(singleFile)" size="17" class="hover-text-theme vue-feather cursor-pointer"/>
|
||||
<CopyShareLink :item="singleFile" size="small" class="w-full pl-2.5"/>
|
||||
</div>
|
||||
</ListInfoItem>
|
||||
|
||||
<!--Author-->
|
||||
<ListInfoItem
|
||||
v-if="canShowAuthor"
|
||||
:title="$t('Author')"
|
||||
>
|
||||
<div class="flex items-center mt-1.5">
|
||||
<MemberAvatar :size="32" :member="singleFile.data.relationships.owner" />
|
||||
<span class="ml-3 block font-bold font-sm">
|
||||
{{ singleFile.data.relationships.owner.data.attributes.name }}
|
||||
</span>
|
||||
</div>
|
||||
</ListInfoItem>
|
||||
|
||||
@@ -100,39 +105,35 @@
|
||||
>
|
||||
<ImageMetaData />
|
||||
</ListInfoItem>
|
||||
</ListInfo>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FilePreviewDetail from '/resources/js/components/Others/FilePreviewDetail'
|
||||
import CopyShareLink from '/resources/js/components/Others/Forms/CopyShareLink'
|
||||
import {Edit2Icon, LockIcon, UnlockIcon, EyeOffIcon} from 'vue-feather-icons'
|
||||
import ImageMetaData from '/resources/js/components/FilesView/ImageMetaData'
|
||||
import EmptyMessage from '/resources/js/components/FilesView/EmptyMessage'
|
||||
import TitlePreview from '/resources/js/components/FilesView/TitlePreview'
|
||||
import TeamMembersPreview from "../Teams/Components/TeamMembersPreview"
|
||||
import ListInfoItem from '/resources/js/components/Others/ListInfoItem'
|
||||
import {Edit2Icon, LockIcon, UnlockIcon} from 'vue-feather-icons'
|
||||
import ListInfo from '/resources/js/components/Others/ListInfo'
|
||||
import {events} from '/resources/js/bus'
|
||||
import MemberAvatar from "./MemberAvatar"
|
||||
import {mapGetters} from 'vuex'
|
||||
import MemberAvatar from "./MemberAvatar";
|
||||
|
||||
export default {
|
||||
name: 'InfoSidebar',
|
||||
components: {
|
||||
MemberAvatar,
|
||||
TeamMembersPreview,
|
||||
FilePreviewDetail,
|
||||
ImageMetaData,
|
||||
EmptyMessage,
|
||||
CopyShareLink,
|
||||
MemberAvatar,
|
||||
TitlePreview,
|
||||
ListInfoItem,
|
||||
UnlockIcon,
|
||||
CopyShareLink,
|
||||
EyeOffIcon,
|
||||
Edit2Icon,
|
||||
LockIcon,
|
||||
ListInfo,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
@@ -168,43 +169,5 @@
|
||||
&& this.user.data.id !== this.clipboard[0].data.relationships.owner.data.id
|
||||
},
|
||||
},
|
||||
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: 50px;
|
||||
}
|
||||
|
||||
.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>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
<!--More Actions-->
|
||||
<div class="relative">
|
||||
<div v-if="$checkPermission('master')" @click="showMobileNavigation" class="tap-area absolute right-0 p-4 -mr-2 transform -translate-y-2/4">
|
||||
<div v-if="$checkPermission('master')" @click="showMobileNavigation" class="absolute right-0 p-4 -mr-2 transform -translate-y-2/4">
|
||||
<menu-icon size="17" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -88,22 +88,3 @@
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '/resources/sass/vuefilemanager/_variables';
|
||||
@import '/resources/sass/vuefilemanager/_mixins';
|
||||
|
||||
.dark {
|
||||
|
||||
.directory-name {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
|
||||
.tap-area {
|
||||
|
||||
path, line, polyline, rect, circle {
|
||||
stroke: $dark_mode_text_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,93 +1,45 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<div class="icon-wrapper">
|
||||
<CheckSquareIcon v-if="icon === 'check-square'" class="icon text-theme vue-feather" size="21" />
|
||||
<image-icon v-if="icon === 'image'" class="icon text-theme vue-feather" size="21" />
|
||||
<video-icon v-if="icon === 'video'" class="icon text-theme vue-feather" size="21" />
|
||||
<folder-icon v-if="icon === 'folder'" class="icon text-theme vue-feather" size="21" />
|
||||
<file-icon v-if="icon === 'file'" class="icon text-theme vue-feather" size="21" />
|
||||
<div class="flex items-start">
|
||||
<div class="mr-2">
|
||||
<CheckSquareIcon v-if="icon === 'check-square'" class="text-theme vue-feather" size="19" />
|
||||
<image-icon v-if="icon === 'image'" class="text-theme vue-feather" size="19" />
|
||||
<video-icon v-if="icon === 'video'" class="text-theme vue-feather" size="19" />
|
||||
<folder-icon v-if="icon === 'folder'" class="text-theme vue-feather" size="19" />
|
||||
<file-icon v-if="icon === 'file'" class="text-theme vue-feather" size="19" />
|
||||
</div>
|
||||
<div class="text">
|
||||
<span class="title">{{ title }}</span>
|
||||
<span class="subtitle">{{ subtitle }}</span>
|
||||
<div>
|
||||
<b class="font-bold text-base inline-block whitespace-nowrap 2xl:w-72 w-52 overflow-ellipsis overflow-hidden leading-3">
|
||||
{{ title }}
|
||||
</b>
|
||||
<small class="font-bold text-xs text-gray-400 block">
|
||||
{{ subtitle }}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
CheckSquareIcon,
|
||||
FolderIcon,
|
||||
ImageIcon,
|
||||
VideoIcon,
|
||||
FileIcon,
|
||||
} from "vue-feather-icons"
|
||||
|
||||
export default {
|
||||
name: 'TitlePreview',
|
||||
props: [
|
||||
'subtitle',
|
||||
'title',
|
||||
'icon',
|
||||
],
|
||||
components: {
|
||||
CheckSquareIcon,
|
||||
import {
|
||||
CheckSquareIcon,
|
||||
FolderIcon,
|
||||
ImageIcon,
|
||||
VideoIcon,
|
||||
FileIcon,
|
||||
},
|
||||
}
|
||||
} from "vue-feather-icons"
|
||||
|
||||
export default {
|
||||
name: 'TitlePreview',
|
||||
props: [
|
||||
'subtitle',
|
||||
'title',
|
||||
'icon',
|
||||
],
|
||||
components: {
|
||||
CheckSquareIcon,
|
||||
FolderIcon,
|
||||
ImageIcon,
|
||||
VideoIcon,
|
||||
FileIcon,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '/resources/sass/vuefilemanager/_variables';
|
||||
@import '/resources/sass/vuefilemanager/_mixins';
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
||||
.text {
|
||||
padding-left: 10px;
|
||||
width: 100%;
|
||||
word-break: break-all;
|
||||
|
||||
.title {
|
||||
@include font-size(14);
|
||||
font-weight: 700;
|
||||
line-height: 1.4;
|
||||
display: block;
|
||||
color: $text;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
@include font-size(12);
|
||||
font-weight: 600;
|
||||
color: $text-muted;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-wrapper {
|
||||
|
||||
polyline, path, rect, circle, polyline {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dark {
|
||||
.wrapper {
|
||||
.text {
|
||||
.title {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: $dark_mode_text_secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,66 +1,56 @@
|
||||
<template>
|
||||
<div v-if="canBePreview" class="preview">
|
||||
<img v-if="singleFile.data.type === 'image' && singleFile.data.attributes.thumbnail" :src="singleFile.data.attributes.thumbnail.md" :alt="singleFile.data.attributes.name" />
|
||||
<audio v-else-if="singleFile.data.type === 'audio'" :src="singleFile.data.attributes.file_url" controlsList="nodownload" controls></audio>
|
||||
<video v-else-if="singleFile.data.type === 'video'" controlsList="nodownload" disablePictureInPicture playsinline controls>
|
||||
<div v-if="canBePreview" class="w-full block mb-4">
|
||||
|
||||
<!--Image-->
|
||||
<img
|
||||
v-if="singleFile.data.type === 'image' && singleFile.data.attributes.thumbnail"
|
||||
:src="singleFile.data.attributes.thumbnail.md"
|
||||
:alt="singleFile.data.attributes.name"
|
||||
class="rounded-lg overflow-hidden w-full object-cover shadow-lg"
|
||||
/>
|
||||
|
||||
<!--Audio-->
|
||||
<audio
|
||||
v-else-if="singleFile.data.type === 'audio'"
|
||||
:src="singleFile.data.attributes.file_url"
|
||||
controlsList="nodownload"
|
||||
controls
|
||||
class="w-full"
|
||||
>
|
||||
</audio>
|
||||
|
||||
<!--Video-->
|
||||
<video
|
||||
class="w-full h-auto rounded-sm overflow-hidden"
|
||||
v-else-if="singleFile.data.type === 'video'"
|
||||
controlsList="nodownload"
|
||||
disablePictureInPicture
|
||||
playsinline
|
||||
controls
|
||||
>
|
||||
<source :src="singleFile.data.attributes.file_url" type="video/mp4">
|
||||
</video>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { includes } from 'lodash'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {includes} from 'lodash'
|
||||
|
||||
export default {
|
||||
name: 'FilePreview',
|
||||
computed: {
|
||||
...mapGetters([
|
||||
export default {
|
||||
name: 'FilePreview',
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'clipboard',
|
||||
]),
|
||||
singleFile() {
|
||||
return this.clipboard[0]
|
||||
return this.clipboard[0]
|
||||
},
|
||||
canBePreview() {
|
||||
return this.singleFile && ! includes([
|
||||
'folder', 'file'
|
||||
], this.singleFile.data.type)
|
||||
},
|
||||
}
|
||||
canBePreview() {
|
||||
return this.singleFile && !includes([
|
||||
'folder', 'file'
|
||||
], this.singleFile.data.type)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '/resources/sass/vuefilemanager/_variables';
|
||||
@import '/resources/sass/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>
|
||||
</script>
|
||||
@@ -1,64 +1,22 @@
|
||||
<template>
|
||||
<li class="list-info-item">
|
||||
<b class="text-theme dark-text-theme">{{ title }}</b>
|
||||
<span v-if="content">{{ content }}</span>
|
||||
<slot></slot>
|
||||
</li>
|
||||
<div class="mb-4">
|
||||
<small class="text-theme font-bold text-xs block">
|
||||
{{ title }}
|
||||
</small>
|
||||
<b v-if="content" class="inline-block font-bold text-sm">
|
||||
{{ content }}
|
||||
</b>
|
||||
|
||||
<slot v-if="$slots.default" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ListInfoItem',
|
||||
props: ['title', 'content']
|
||||
props: [
|
||||
'content',
|
||||
'title',
|
||||
]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '/resources/sass/vuefilemanager/_variables';
|
||||
@import '/resources/sass/vuefilemanager/_mixins';
|
||||
|
||||
.list-info-item {
|
||||
display: block;
|
||||
padding-bottom: 20px;
|
||||
|
||||
.action-button {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.edit-icon {
|
||||
display: inline-block;
|
||||
margin-left: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
b {
|
||||
display: block;
|
||||
@include font-size(13);
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
@include font-size(14);
|
||||
font-weight: bold;
|
||||
color: $text;
|
||||
}
|
||||
}
|
||||
|
||||
.dark {
|
||||
.list-info-item {
|
||||
|
||||
span {
|
||||
color: $dark_mode_text_primary
|
||||
}
|
||||
|
||||
.action-button {
|
||||
|
||||
.icon {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user