mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-05-25 14:14:42 +00:00
bulk-operations merge with the improvements branch
This commit is contained in:
@@ -96,7 +96,7 @@
|
||||
|
||||
<!--ContextMenu for Base location with MASTER permission-->
|
||||
<div v-if="$isThisLocation(['shared']) && $checkPermission('master') && !showFromPreview" id="menu-list" class="menu-options">
|
||||
<ul class="menu-option-group" v-if="item && isFolder && multiSelectContextMenu">
|
||||
<ul class="menu-option-group" v-if="item && isFolder && multiSelectContextMenu">
|
||||
<li class="menu-option" @click="addToFavourites">
|
||||
<div class="icon">
|
||||
<star-icon size="17"></star-icon>
|
||||
@@ -111,6 +111,14 @@
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="menu-option-group" v-if="item">
|
||||
<li class="menu-option" @click="renameItem">
|
||||
<div class="icon">
|
||||
<edit2-icon size="17"></edit2-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.rename') }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="menu-option" @click="shareItem" v-if="multiSelectContextMenu">
|
||||
<div class="icon">
|
||||
<link-icon size="17"></link-icon>
|
||||
@@ -180,6 +188,14 @@
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="menu-option-group" v-if="item">
|
||||
<li class="menu-option" @click="renameItem">
|
||||
<div class="icon">
|
||||
<edit2-icon size="17"></edit2-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.rename') }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="menu-option" @click="moveItem">
|
||||
<div class="icon">
|
||||
<corner-down-right-icon size="17"></corner-down-right-icon>
|
||||
@@ -242,6 +258,14 @@
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="menu-option-group" v-if="item">
|
||||
<li class="menu-option" @click="renameItem">
|
||||
<div class="icon">
|
||||
<edit2-icon size="17"></edit2-icon>
|
||||
</div>
|
||||
<div class="text-label">
|
||||
{{ $t('context_menu.rename') }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="menu-option" @click="moveItem">
|
||||
<div class="icon">
|
||||
<corner-down-right-icon size="17"></corner-down-right-icon>
|
||||
@@ -381,33 +405,17 @@ export default {
|
||||
|
||||
methods: {
|
||||
renameItem() {
|
||||
let itemName = prompt(this.$t('popup_rename.title'), this.item.name)
|
||||
|
||||
if (itemName && itemName !== '') {
|
||||
let item = {
|
||||
unique_id: this.item.unique_id,
|
||||
type: this.item.type,
|
||||
name: itemName
|
||||
}
|
||||
|
||||
this.$store.dispatch('renameItem', item)
|
||||
|
||||
// Change item name if is mobile device or prompted
|
||||
if (this.$isMobile()) {
|
||||
events.$emit('change:name', item)
|
||||
}
|
||||
}
|
||||
events.$emit('popup:open', { name: 'rename-item', item: this.item })
|
||||
},
|
||||
moveItem() {
|
||||
// Open move item popup
|
||||
events.$emit('popup:open', { name: 'move', item: [this.item] })
|
||||
},
|
||||
shareItem() {
|
||||
if (this.item.shared) {
|
||||
// Open share item popup
|
||||
// Open edit share popup
|
||||
events.$emit('popup:open', { name: 'share-edit', item: this.item })
|
||||
} else {
|
||||
// Open share item popup
|
||||
// Open create share popup
|
||||
events.$emit('popup:open', { name: 'share-create', item: this.item })
|
||||
}
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="name-wrapper">
|
||||
<x-icon @click="closeFullPreview" size="22" class="icon-close"></x-icon>
|
||||
<div class="name-count-wrapper">
|
||||
<p class="title">{{ fileInfoDetail[0].name }}</p>
|
||||
<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" @click="menuOpen" v-if="$checkPermission(['master', 'editor'])">
|
||||
@@ -17,7 +17,7 @@
|
||||
<div class="navigation-icons">
|
||||
<div class="navigation-tool-wrapper">
|
||||
<ToolbarButton source="download" class="mobile-hide" @click.native="downloadItem" :action="$t('actions.download')" />
|
||||
<ToolbarButton source="share" class="mobile-hide" :class="{ 'is-inactive': canShareInView }" :action="$t('actions.share')" @click.native="shareItem" />
|
||||
<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>
|
||||
@@ -54,8 +54,11 @@ export default {
|
||||
})
|
||||
return activeIndex
|
||||
},
|
||||
canShowShareView() {
|
||||
return this.$isThisLocation(['base', 'participant_uploads', 'latest', 'shared'])
|
||||
},
|
||||
canShareInView() {
|
||||
return !this.$isThisLocation(['base', 'participant_uploads', 'latest', 'shared', 'public'])
|
||||
return ! this.$isThisLocation(['base', 'participant_uploads', 'latest', 'shared'])
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
||||
@@ -395,25 +395,7 @@ export default {
|
||||
this.$store.dispatch("deleteItem");
|
||||
},
|
||||
renameItem() {
|
||||
let itemName = prompt(
|
||||
this.$t("popup_rename.title"),
|
||||
this.fileInfoDetail[0].name
|
||||
);
|
||||
|
||||
if (itemName && itemName !== "") {
|
||||
let item = {
|
||||
unique_id: this.fileInfoDetail[0].unique_id,
|
||||
type: this.fileInfoDetail[0].type,
|
||||
name: itemName,
|
||||
};
|
||||
|
||||
this.$store.dispatch("renameItem", item);
|
||||
|
||||
// Change item name if is mobile device or prompted
|
||||
if (this.$isMobile()) {
|
||||
events.$emit("change:name", item);
|
||||
}
|
||||
}
|
||||
events.$emit('popup:open', { name: 'rename-item', item: this.fileInfoDetail[0] })
|
||||
},
|
||||
closeAndResetContextMenu() {
|
||||
//If emit to show menu coming from MediaFullPreview dont reset data
|
||||
|
||||
@@ -13,21 +13,28 @@
|
||||
{{ $t('uploading.progress', {current:uploadingFilesCount.current, total: uploadingFilesCount.total, progress: uploadingFileProgress}) }}
|
||||
</span>
|
||||
</div>
|
||||
<ProgressBar :progress="uploadingFileProgress" />
|
||||
<div class="progress-wrapper">
|
||||
<ProgressBar :progress="uploadingFileProgress" />
|
||||
<span @click="cancelUpload" :title="$t('uploading.cancel')" class="cancel-icon">
|
||||
<x-icon size="16" @click="cancelUpload"></x-icon>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProgressBar from '@/components/FilesView/ProgressBar'
|
||||
import { RefreshCwIcon } from 'vue-feather-icons'
|
||||
import { RefreshCwIcon, XIcon } from 'vue-feather-icons'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'UploadProgress',
|
||||
components: {
|
||||
RefreshCwIcon,
|
||||
ProgressBar,
|
||||
XIcon,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
@@ -35,6 +42,11 @@
|
||||
'uploadingFilesCount',
|
||||
'isProcessingFile',
|
||||
])
|
||||
},
|
||||
methods: {
|
||||
cancelUpload() {
|
||||
events.$emit('cancel-upload')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -78,6 +90,22 @@
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
.progress-wrapper {
|
||||
display: flex;
|
||||
|
||||
.cancel-icon {
|
||||
cursor: pointer;
|
||||
padding: 0 13px;
|
||||
|
||||
&:hover {
|
||||
|
||||
line {
|
||||
stroke: $theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.progress-title {
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
@@ -88,6 +116,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 690px) {
|
||||
|
||||
.upload-progress {
|
||||
|
||||
.progress-wrapper .cancel-icon {
|
||||
padding: 0 9px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.progress-bar {
|
||||
background: $dark_mode_foreground;
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
<template>
|
||||
<div class="dropzone" :class="{ 'is-error': error }">
|
||||
<div v-if="imagePreview" @click="resetImage" class="reset-image">
|
||||
<x-icon size="14" class="close-icon"></x-icon>
|
||||
</div>
|
||||
|
||||
<input
|
||||
ref="file"
|
||||
type="file"
|
||||
@@ -26,7 +30,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ImageIcon from "vue-feather-icons/icons/ImageIcon";
|
||||
import { XIcon, ImageIcon } from 'vue-feather-icons'
|
||||
|
||||
export default {
|
||||
name: 'ImageInput',
|
||||
@@ -35,6 +39,7 @@
|
||||
],
|
||||
components: {
|
||||
ImageIcon,
|
||||
XIcon,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -47,6 +52,10 @@
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
resetImage() {
|
||||
this.imagePreview = undefined
|
||||
this.$emit('input', undefined)
|
||||
},
|
||||
showImagePreview(event) {
|
||||
const imgPath = event.target.files[0].name,
|
||||
extn = imgPath
|
||||
@@ -152,6 +161,30 @@
|
||||
@include font-size(12);
|
||||
}
|
||||
}
|
||||
|
||||
.reset-image {
|
||||
z-index: 2;
|
||||
background: white;
|
||||
border-radius: 50px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
cursor: pointer;
|
||||
@include transform(translateY(-50%) translateX(50%));
|
||||
padding: 0px 4px;
|
||||
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.12);
|
||||
|
||||
.close-icon {
|
||||
vertical-align: middle;
|
||||
|
||||
line {
|
||||
path {
|
||||
fill: $text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<div class="icon">
|
||||
<corner-down-right-icon v-if="icon === 'move'" size="15" class="title-icon"></corner-down-right-icon>
|
||||
<link-icon v-if="icon === 'share'" size="17" class="title-icon"></link-icon>
|
||||
<edit2-icon v-if="icon === 'edit'" size="17" class="title-icon"></edit2-icon>
|
||||
</div>
|
||||
<div class="label">
|
||||
<h1 class="title">{{ title }}</h1>
|
||||
@@ -12,7 +13,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {CornerDownRightIcon, LinkIcon, XIcon} from 'vue-feather-icons'
|
||||
import {CornerDownRightIcon, LinkIcon, XIcon, Edit2Icon} from 'vue-feather-icons'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
@@ -22,6 +23,7 @@
|
||||
],
|
||||
components: {
|
||||
CornerDownRightIcon,
|
||||
Edit2Icon,
|
||||
LinkIcon,
|
||||
XIcon,
|
||||
},
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<PopupWrapper name="rename-item">
|
||||
<!--Title-->
|
||||
<PopupHeader :title="$t('popup_rename.title', {item: itemTypeTitle})" icon="edit" />
|
||||
|
||||
<!--Content-->
|
||||
<PopupContent>
|
||||
|
||||
<!--Item Thumbnail-->
|
||||
<ThumbnailItem class="item-thumbnail" :item="pickedItem" info="metadata"/>
|
||||
|
||||
<!--Form to set sharing-->
|
||||
<ValidationObserver @submit.prevent="changeName" ref="renameForm" v-slot="{ invalid }" tag="form" class="form-wrapper">
|
||||
|
||||
<!--Set password-->
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper password" name="Password" rules="required" v-slot="{ errors }">
|
||||
<label class="input-label">{{ $t('popup_rename.label') }}:</label>
|
||||
<input v-model="pickedItem.name" :class="{'is-error': errors[0]}" type="text" :placeholder="$t('popup_rename.placeholder')">
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</ValidationObserver>
|
||||
</PopupContent>
|
||||
|
||||
<!--Actions-->
|
||||
<PopupActions>
|
||||
<ButtonBase
|
||||
class="popup-button"
|
||||
@click.native="$closePopup()"
|
||||
button-style="secondary"
|
||||
>{{ $t('popup_move_item.cancel') }}
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
class="popup-button"
|
||||
@click.native="changeName"
|
||||
button-style="theme"
|
||||
>{{ $t('popup_share_edit.save') }}
|
||||
</ButtonBase>
|
||||
</PopupActions>
|
||||
</PopupWrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {ValidationProvider, ValidationObserver} from 'vee-validate/dist/vee-validate.full'
|
||||
import PopupWrapper from '@/components/Others/Popup/PopupWrapper'
|
||||
import PopupActions from '@/components/Others/Popup/PopupActions'
|
||||
import PopupContent from '@/components/Others/Popup/PopupContent'
|
||||
import PopupHeader from '@/components/Others/Popup/PopupHeader'
|
||||
import ThumbnailItem from '@/components/Others/ThumbnailItem'
|
||||
import ActionButton from '@/components/Others/ActionButton'
|
||||
import ButtonBase from '@/components/FilesView/ButtonBase'
|
||||
import {required} from 'vee-validate/dist/rules'
|
||||
import {events} from '@/bus'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'RenameItem',
|
||||
components: {
|
||||
ValidationProvider,
|
||||
ValidationObserver,
|
||||
ThumbnailItem,
|
||||
ActionButton,
|
||||
PopupWrapper,
|
||||
PopupActions,
|
||||
PopupContent,
|
||||
PopupHeader,
|
||||
ButtonBase,
|
||||
required,
|
||||
},
|
||||
computed: {
|
||||
itemTypeTitle() {
|
||||
return this.pickedItem && this.pickedItem.type === 'folder' ? this.$t('types.folder') : this.$t('types.file')
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pickedItem: undefined,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeName() {
|
||||
if (this.pickedItem.name && this.pickedItem.name !== '') {
|
||||
|
||||
let item = {
|
||||
unique_id: this.pickedItem.unique_id,
|
||||
type: this.pickedItem.type,
|
||||
name: this.pickedItem.name
|
||||
}
|
||||
|
||||
// Rename item request
|
||||
this.$store.dispatch('renameItem', item)
|
||||
|
||||
// Rename item in view
|
||||
events.$emit('change:name', item)
|
||||
|
||||
this.$closePopup()
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
||||
// Show popup
|
||||
events.$on('popup:open', args => {
|
||||
|
||||
if (args.name !== 'rename-item') return
|
||||
|
||||
// Store picked item
|
||||
this.pickedItem = args.item
|
||||
})
|
||||
|
||||
// Close popup
|
||||
events.$on('popup:close', () => {
|
||||
|
||||
// Restore data
|
||||
setTimeout(() => {
|
||||
//
|
||||
}, 150)
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/vue-file-manager/_inapp-forms.scss";
|
||||
@import '@assets/vue-file-manager/_forms';
|
||||
|
||||
.item-thumbnail {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,25 +1,109 @@
|
||||
<template>
|
||||
<div class="content-group">
|
||||
<TextLabel>{{ title }}</TextLabel>
|
||||
<slot></slot>
|
||||
<div class="content-group" :class="{'is-collapsed': ! isVisible, 'collapsable': canCollapse}">
|
||||
|
||||
<div class="group-title" @click="hideGroup">
|
||||
<TextLabel class="title">{{ title }}</TextLabel>
|
||||
<chevron-up-icon v-if="canCollapseWrapper" size="12" class="icon" />
|
||||
</div>
|
||||
|
||||
<transition name="list">
|
||||
<div class="wrapper" v-show="isVisible">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TextLabel from '@/components/Others/TextLabel'
|
||||
import { ChevronUpIcon } from 'vue-feather-icons'
|
||||
|
||||
export default {
|
||||
name: 'ContentGroup',
|
||||
props: ['title'],
|
||||
props: ['title', 'canCollapse', 'slug'],
|
||||
components: {
|
||||
ChevronUpIcon,
|
||||
TextLabel,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isVisible: true,
|
||||
canCollapseWrapper: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
hideGroup() {
|
||||
if (! this.canCollapseWrapper)
|
||||
return
|
||||
|
||||
this.isVisible = !this.isVisible
|
||||
localStorage.setItem('panel-group-' + this.slug, this.isVisible)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
if (this.canCollapse) {
|
||||
|
||||
let savedVisibility = localStorage.getItem('panel-group-' + this.slug)
|
||||
|
||||
this.isVisible = savedVisibility ? !!JSON.parse(String(savedVisibility).toLowerCase()) : true
|
||||
this.canCollapseWrapper = true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
|
||||
.content-group {
|
||||
margin-bottom: 30px;
|
||||
transition: all 300ms;
|
||||
|
||||
.group-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.title {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-right: 19px;
|
||||
opacity: 0.25;
|
||||
@include transition;
|
||||
}
|
||||
}
|
||||
|
||||
&.collapsable {
|
||||
.group-title {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-collapsed {
|
||||
margin-bottom: 15px;
|
||||
|
||||
.icon {
|
||||
@include transform(rotate(180deg));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.list-enter,
|
||||
.list-leave-to {
|
||||
visibility: hidden;
|
||||
height: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.list-enter-active,
|
||||
.list-leave-active {
|
||||
transition: all 300ms;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -20,19 +20,13 @@
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<router-link :to="{name: 'Trash'}" :title="$t('locations.trash')" class="icon-navigation-item trash">
|
||||
<div class="button-icon">
|
||||
<trash-2-icon size="19"></trash-2-icon>
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<router-link :to="{name: 'Profile'}" :class="{'is-active': isUserProfileRoute}" class="icon-navigation-item settings">
|
||||
<router-link :to="{name: 'Profile'}" :class="{'is-active': isUserProfileRoute}" :title="$t('locations.profile')" class="icon-navigation-item settings">
|
||||
<div class="button-icon">
|
||||
<user-icon size="19"></user-icon>
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<router-link v-if="user.data.attributes.role === 'admin'" :to="{name: 'Dashboard'}" :class="{'is-active': $isThisRoute($route, adminRoutes)}" class="icon-navigation-item users">
|
||||
<router-link v-if="user.data.attributes.role === 'admin'" :to="{name: 'Dashboard'}" :class="{'is-active': $isThisRoute($route, adminRoutes)}" :title="$t('locations.settings')" class="icon-navigation-item users">
|
||||
<div class="button-icon">
|
||||
<settings-icon size="19"></settings-icon>
|
||||
</div>
|
||||
@@ -41,7 +35,7 @@
|
||||
|
||||
<!--User avatar & Logout-->
|
||||
<ul class="icon-navigation logout">
|
||||
<li @click="$store.dispatch('logOut')" class="icon-navigation-item">
|
||||
<li @click="$store.dispatch('logOut')" :title="$t('locations.logout')" class="icon-navigation-item">
|
||||
<div class="button-icon">
|
||||
<power-icon size="19"></power-icon>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user