Files
vuefilemanager/resources/js/components/VueFileManagerComponents/Sidebar.vue
MakingCG 515e8ef5ef V1.1
User Authentication
- Login to user account
- Register new user account
- Reset user password

Functionality
- Added locations to menu
- Added trash for deleted folders & files
- Restore files or folders from trash
- Empty trash function
- Favourites folders
- List of 5 latest uploads
- Profile settings page
- Storage info and upload limits

Design
- Night Mode
- Navigation sidebar
- Quick action buttons in mobile version
- Improved mobile UX
- Other small design improvements

Settings
- Enable/Disable user account registration
- Set storage limitation
- Set storage capacity for all users
2020-03-14 18:56:35 +01:00

432 lines
12 KiB
Vue

<template>
<transition name="sidebar">
<div id="sidebar" v-if="isVisibleSidebar || ! isSmallAppSize">
<!--User Headline-->
<UserHeadline/>
<div v-if="app" class="content-scroller">
<!--Locations-->
<div class="menu-list-wrapper">
<TextLabel>Locations</TextLabel>
<ul class="menu-list">
<li class="menu-list-item" @click="goHome">
<FontAwesomeIcon class="icon" icon="hdd"/>
<span class="label">Home</span>
</li>
<!--<li class="menu-list-item">
<FontAwesomeIcon class="icon" icon="share"/>
<span class="label">Shared</span>
</li>-->
<li class="menu-list-item" @click="getTrash">
<FontAwesomeIcon class="icon" icon="trash-alt"/>
<span class="label">Trash</span>
</li>
</ul>
</div>
<!--Favourites-->
<div class="menu-list-wrapper favourites"
@dragover.prevent="dragEnter"
@dragleave="dragLeave"
@drop="dragFinish($event)"
:class="{ 'is-dragenter': area }"
>
<TextLabel>Favourites</TextLabel>
<transition-group tag="ul" class="menu-list" name="folder-item">
<li class="empty-list" v-if="app.favourites.length == 0" :key="0">Drag here your favourite
folder.
</li>
<li @click.stop="openFolder(folder)" class="menu-list-item" v-for="folder in app.favourites"
:key="folder.unique_id">
<div>
<FontAwesomeIcon class="icon" icon="folder"/>
<span class="label">{{ folder.name }}</span>
</div>
<FontAwesomeIcon @click.stop="removeFavourite(folder)" v-if="! $isMobile()" class="delete-icon" icon="times"/>
</li>
</transition-group>
</div>
<!--Last Uploads-->
<div class="menu-list-wrapper">
<TextLabel>Last Uploads</TextLabel>
<p class="empty-list" v-if="app.latest_uploads.length == 0">You don't have any latest uploads.</p>
<FileListItemThumbnail @dblclick.native="downloadFile(item)" @click.native="showFileDetail(item)" :file="item" v-for="item in app.latest_uploads" :key="item.unique_id"/>
</div>
</div>
<!--Storage Size Info-->
<StorageSize v-if="config.storageLimit"/>
<div v-if="isSmallAppSize" class="log-out-button">
<ButtonBase @click.native="$store.dispatch('logOut')" button-style="danger">Log Out</ButtonBase>
</div>
</div>
</transition>
</template>
<script>
import FileListItemThumbnail from '@/components/VueFileManagerComponents/Sidebar/FileListItemThumbnail'
import UserHeadline from '@/components/VueFileManagerComponents/Sidebar/UserHeadline'
import ButtonBase from '@/components/VueFileManagerComponents/FilesView/ButtonBase'
import StorageSize from '@/components/VueFileManagerComponents/Sidebar/StorageSize'
import TextLabel from '@/components/VueFileManagerComponents/Others/TextLabel'
import {mapGetters} from 'vuex'
import {events} from '@/bus'
export default {
name: 'Sidebar',
components: {
FileListItemThumbnail,
UserHeadline,
StorageSize,
ButtonBase,
TextLabel,
},
computed: {
...mapGetters(['homeDirectory', 'app', 'appSize', 'config']),
isSmallAppSize() {
return this.appSize === 'small'
}
},
data() {
return {
area: false,
draggedItem: undefined,
isVisibleSidebar: false,
}
},
methods: {
getTrash() {
this.$store.dispatch('getTrash')
},
goHome() {
this.$store.commit('FLUSH_BROWSER_HISTORY')
this.$store.dispatch('goToFolder', [this.homeDirectory, true])
},
openFolder(folder) {
// Go to folder
this.$store.dispatch('goToFolder', [folder, false])
},
downloadFile(file) {
this.$downloadFile(file.file_url, file.name + '.' + file.mimetype)
},
showFileDetail(file) {
// Dispatch load file info detail
this.$store.dispatch('getLatestUploadDetail', file)
// Show panel if is not open
this.$store.dispatch('fileInfoToggle', true)
},
dragEnter() {
if (this.draggedItem && this.draggedItem.type !== 'folder') return
this.area = true
},
dragLeave() {
this.area = false
},
dragFinish() {
this.area = false
// Check if draged item is folder
if (this.draggedItem && this.draggedItem.type !== 'folder') return
// Check if folder exist in favourites
if (this.app.favourites.find(folder => folder.unique_id == this.draggedItem.unique_id)) return
// Store favourites folder
this.$store.dispatch('addToFavourites', this.draggedItem)
},
removeFavourite(folder) {
// Remove favourites folder
this.$store.dispatch('removeFromFavourites', folder)
}
},
mounted() {
this.$store.dispatch('getAppData')
// Listen for dragstart folder items
events.$on('dragstart', (item) => this.draggedItem = item)
// Listen for show sidebar
events.$on('show:sidebar', () => {
this.isVisibleSidebar = !this.isVisibleSidebar
})
// Listen for hide sidebar
events.$on('show:content', () => {
if (this.isVisibleSidebar) this.isVisibleSidebar = false
})
}
}
</script>
<style scoped lang="scss">
@import "@assets/app.scss";
#sidebar {
position: relative;
flex: 0 0 295px;
border-right: 1px solid $light_background;
}
.content-scroller {
bottom: 50px;
position: absolute;
top: 75px;
left: 0;
right: 0;
overflow-x: auto;
.menu-list-wrapper:first-of-type {
margin-top: 20px;
}
.text-label {
margin-left: 15px;
}
}
.menu-list-wrapper {
margin-bottom: 25px;
.menu-list {
.menu-list-item {
display: block;
padding: 10px 15px 10px 25px;
@include transition(150ms);
cursor: pointer;
position: relative;
white-space: nowrap;
&:hover {
background: rgba($theme, .1);
//background: $light_background;
.icon {
path {
fill: $theme;
}
}
.label {
color: $theme;
}
.delete-icon {
display: block;
}
}
.icon {
@include font-size(13);
width: 15px;
margin-right: 9px;
vertical-align: middle;
path {
fill: $text;
}
}
.delete-icon {
display: none;
position: absolute;
right: 15px;
top: 50%;
@include transform(translateY(-50%));
@include font-size(12);
path {
fill: $text-muted;
}
}
.label {
@include font-size(15);
font-weight: 700;
vertical-align: middle;
white-space: nowrap;
max-width: 210px;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
}
}
}
&.favourites {
&.is-dragenter {
.menu-list {
border: 2px dashed $theme;
border-radius: 8px;
}
}
.menu-list {
border: 2px dashed transparent;
.menu-list-item {
padding: 10px 13px 10 23px;
.icon {
@include font-size(20);
width: 20px;
path {
fill: $theme;
}
}
}
}
}
.empty-list {
@include font-size(12);
color: $text-muted;
display: block;
padding: 15px;
}
}
.log-out-button {
margin-top: 15px;
padding: 15px;
button {
width: 100%;
}
}
@media only screen and (max-width: 1024px) {
#sidebar {
flex: 0 0 265px;
}
.menu-list-wrapper .menu-list .menu-list-item .label {
max-width: 190px;
}
}
@media only screen and (max-width: 690px) {
.content-scroller {
bottom: initial;
position: relative;
top: initial;
overflow-x: initial;
}
#sidebar {
position: absolute;
overflow-y: auto;
top: 0;
left: 0;
right: 0;
z-index: 99;
bottom: 0;
background: white;
opacity: 1;
}
.menu-list-wrapper {
&.favourites {
.menu-list .menu-list-item {
padding: 10px 26px;
}
}
.menu-list .menu-list-item {
padding: 10px 26px;
.label {
@include font-size(16);
}
}
}
.log-out-button {
margin-top: 0;
}
}
@media (prefers-color-scheme: dark) {
#sidebar {
border-color: $dark_mode_foreground;
background: $dark_mode_foreground;
}
.menu-list-wrapper {
.menu-list .menu-list-item {
.label {
color: $dark_mode_text_primary;
}
&:hover {
background: rgba($theme, .1);
}
}
}
}
@media (prefers-color-scheme: dark) and (max-width: 690px){
#sidebar {
border-color: $dark_mode_background;
background: $dark_mode_background;
}
}
.sidebar-enter-active {
transition: all 300ms ease;
}
.sidebar-enter /* .list-leave-active below version 2.1.8 */
{
opacity: 0;
transform: translateX(-100%);
}
// Transition
.folder-item-move {
transition: transform 300s ease;
}
.folder-item-enter-active {
transition: all 300ms ease;
}
.folder-item-leave-active {
transition: all 300ms;
}
.folder-item-enter, .folder-item-leave-to /* .list-leave-active below version 2.1.8 */
{
opacity: 0;
transform: translateX(30px);
}
.folder-item-leave-active {
position: absolute;
}
</style>