bulk-operations v0.1 adding Drag & Drop for moving items to navigations folders, add folders to favourites

This commit is contained in:
Milos Holba
2020-11-20 17:54:39 +01:00
parent 9d9e07d0fa
commit a3dd817e7a
19 changed files with 323 additions and 166 deletions

View File

@@ -11,7 +11,7 @@
{{ $t('context_menu.move') }}
</div>
</li>
<li class="menu-option" @click="shareItem">
<li class="menu-option" @click="shareItem" v-if="$checkPermission('master')">
<div class="icon">
<link-icon size="17"></link-icon>
</div>
@@ -158,7 +158,7 @@
$checkPermission('master') && !showFromPreview
" id="menu-list" class="menu-options">
<ul class="menu-option-group" v-if="!$isThisLocation(['participant_uploads', 'latest'])">
<li class="menu-option" @click="addToFavourites" v-if="item && isFolder && multiSelectContextMenu">
<li class="menu-option" @click="addToFavourites" v-if="item && isFolder && multiSelectContextMenu ">
<div class="icon">
<star-icon size="17"></star-icon>
</div>
@@ -338,9 +338,12 @@ export default {
computed: {
...mapGetters(['user', 'fileInfoDetail']),
multiSelectContextMenu() {
if(this.fileInfoDetail.length > 1 && this.fileInfoDetail.includes(this.item)) {
// 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)) {
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)) {
return true
}
@@ -364,7 +367,7 @@ export default {
},
isInFavourites() {
return this.favourites.find((el) => el.unique_id == this.item.unique_id)
}
},
},
data() {
return {
@@ -414,7 +417,15 @@ export default {
this.favourites &&
!this.favourites.find((el) => el.unique_id == this.item.unique_id)
) {
//Add to favourite folder that is not selected
if(!this.fileInfoDetail.includes(this.item)){
this.$store.dispatch('addToFavourites', this.item)
}
//Add to favourites all selected folders
if(this.fileInfoDetail.includes(this.item)) {
this.$store.dispatch('addToFavourites', null)
}
} else {
this.$store.dispatch('removeFromFavourites', this.item)
}
@@ -435,7 +446,14 @@ export default {
},
deleteItem() {
// Dispatch remove item
this.$store.dispatch('deleteItem', this.item)
// If is contet menu open on non selected item delete this single item
if(!this.fileInfoDetail.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)) {
this.$store.dispatch('deleteItem')
}
},
createFolder() {
// Create folder

View File

@@ -149,11 +149,9 @@ export default {
return this.FilePreviewType === "list" ? "th" : "th-list";
},
canCreateFolderInView() {
let location = !this.$isThisLocation(["base", "public"]);
let locations = ["base", "public"];
if(location || this.fileInfoDetail.length >1) {
return true
}
return !this.$isThisLocation(locations) || this.fileInfoDetail.length > 1
},
canDeleteInView() {
return !this.$isThisLocation([
@@ -167,10 +165,9 @@ export default {
]);
},
canUploadInView() {
let location = !this.$isThisLocation(["base", "public"]);
if(location || this.fileInfoDetail.length >1) {
return true
}
let locations = ["base", "public"]
return !this.$isThisLocation(locations) || this.fileInfoDetail.length > 1
},
canMoveInView() {
return !this.$isThisLocation([
@@ -182,16 +179,15 @@ export default {
]);
},
canShareInView() {
let location = !this.$isThisLocation([
let locations = [
"base",
"participant_uploads",
"latest",
"shared",
"public",
]);
if(location || this.fileInfoDetail.length > 1) {
return true
}
]
return !this.$isThisLocation(locations) || this.fileInfoDetail.length > 1
},
},
methods: {

View File

@@ -161,12 +161,23 @@
dragFinish(data, event) {
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)) return
// Move folder to new parent
this.$store.dispatch('moveItem', [this.draggingId, data])
//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 item if is not included in selected items
if(this.fileInfoDetail.length === 0 || !this.fileInfoDetail.includes(this.draggingId)){
this.$store.dispatch('moveItem', {to_item:data ,noSelectedItem:this.draggingId})
}
} else {
@@ -200,6 +211,10 @@
this.mobileMultiSelect = false
})
events.$on('drop', () => {
this.isDragging = false
})
events.$on('fileItem:deselect', () =>
this.$store.commit('CLEAR_FILEINFO_DETAIL')
)

View File

@@ -10,23 +10,23 @@
:draggable="canDrag"
@dragstart="$emit('dragstart')"
@drop="
$emit('drop')
drop()
area = false
"
@dragleave="dragLeave"
@dragover.prevent="dragEnter"
class="file-item"
:class="{'is-clicked' : isClicked , 'no-clicked' : !isClicked, 'is-dragenter': area }"
:class="{'is-clicked' : isClicked , 'no-clicked' : !isClicked && this.$isMobile(), 'is-dragenter': area }"
>
<!--Thumbnail for item-->
<div class="icon-item">
<div :class="{'check-select-folder' : this.data.type === 'folder', 'check-select' : this.data.type !== 'folder'}" v-if="mobileMultiSelect">
<div class="select-box" :class="{'select-box-active' : isClicked } ">
<!-- <p>|</p> -->
<CheckIcon v-if="isClicked" class="icon" size="17"/>
</div>
</div>
<!-- MultiSelecting for the mobile version -->
<div :class="{'check-select-folder' : this.data.type === 'folder', 'check-select' : this.data.type !== 'folder'}" v-if="mobileMultiSelect">
<div class="select-box" :class="{'select-box-active' : isClicked } ">
<CheckIcon v-if="isClicked" class="icon" size="17"/>
</div>
</div>
<!--If is file or image, then link item-->
<span v-if="isFile" class="file-icon-text">
@@ -105,11 +105,7 @@
]),
...mapGetters({allData: 'data'}),
isClicked() {
if(this.fileInfoDetail.some(element => element.unique_id == this.data.unique_id)){
return true
}else {
return false
}
return this.fileInfoDetail.some(element => element.unique_id == this.data.unique_id)
},
isFolder() {
return this.data.type === 'folder'
@@ -160,6 +156,9 @@
}
},
methods: {
drop() {
events.$emit('drop')
},
showItemActions() {
// Load file info detail
this.$store.commit('CLEAR_FILEINFO_DETAIL')
@@ -170,6 +169,8 @@
dragEnter() {
if (this.data.type !== 'folder') return
if(this.fileInfoDetail.includes(this.data)) return
this.area = true
},
dragLeave() {
@@ -334,7 +335,7 @@
box-shadow: 0 3px 15px 2px hsla(220, 36%, 16%, 0.05);
}
.select-box-active {
background-color: $text !important;
background-color: $text ;
.icon {
stroke: white;
}
@@ -584,7 +585,7 @@
background-color: $dark_mode_foreground;
}
.select-box-active {
background-color: $dark_mode_text_primary !important;
background-color: $dark_mode_text_primary ;
.icon {
stroke: $text;
}
@@ -619,7 +620,7 @@
path {
fill: $dark_mode_foreground !important;
stroke: #2F3C54 !important;
stroke: #2F3C54 ;
}
}
.item-name {

View File

@@ -8,13 +8,13 @@
:draggable="canDrag"
@dragstart="$emit('dragstart')"
@drop="
$emit('drop')
drop()
area = false
"
@dragleave="dragLeave"
@dragover.prevent="dragEnter"
class="file-item"
:class="{'is-clicked' : isClicked , 'no-clicked' : !isClicked, 'is-dragenter': area }"
:class="{'is-clicked' : isClicked , 'no-clicked' : !isClicked && this.$isMobile(), 'is-dragenter': area }"
>
<div class="check-select" v-if="mobileMultiSelect">
@@ -94,11 +94,7 @@ export default {
...mapGetters(['FilePreviewType', 'fileInfoDetail' ]),
...mapGetters({allData: 'data'}),
isClicked() {
if(this.fileInfoDetail.some(element => element.unique_id == this.data.unique_id)){
return true
}else {
return false
}
return this.fileInfoDetail.some(element => element.unique_id == this.data.unique_id)
},
isFolder() {
return this.data.type === 'folder'
@@ -152,6 +148,9 @@ export default {
}
},
methods: {
drop() {
events.$emit('drop')
},
showItemActions() {
// Load file info detail
this.$store.commit('CLEAR_FILEINFO_DETAIL')
@@ -162,6 +161,8 @@ export default {
dragEnter() {
if (this.data.type !== 'folder') return
if(this.fileInfoDetail.includes(this.data)) return
this.area = true
},
dragLeave() {
@@ -280,6 +281,7 @@ export default {
events.$on('fileItem:deselect', () => {
// Deselect file
if(this.fileInfoDetail.length > 0)
this.$store.commit('CLEAR_FILEINFO_DETAIL')
})
@@ -309,7 +311,7 @@ export default {
box-shadow: 0 3px 15px 2px hsla(220, 36%, 16%, 0.05);
}
.select-box-active {
background-color: $text !important;
background-color: $text ;
.icon {
stroke: white;
}
@@ -492,17 +494,17 @@ export default {
background: white !important;
.item-name {
.name {
color: $text !important;
color: $text !important ;
}
}
}
&:hover,
&:hover ,
&.is-clicked {
border-radius: 8px;
background: $light_background ;
.item-name .name {
color: $theme;
color: $theme ;
}
}
}
@@ -514,7 +516,7 @@ export default {
background-color: $dark_mode_foreground;
}
.select-box-active {
background-color: $dark_mode_text_primary !important;
background-color: $dark_mode_text_primary ;
.icon {
stroke: $text;
}
@@ -546,7 +548,7 @@ export default {
path {
fill: $dark_mode_foreground !important;
stroke: #2F3C54 !important;
stroke: #2F3C54 ;
}
}
.item-name {
@@ -556,15 +558,19 @@ export default {
}
}
}
&:hover,
&.is-clicked {
background: $dark_mode_foreground;
&:hover,
&.is-clicked {
background: $dark_mode_foreground ;
.file-icon {
path {
fill: $dark_mode_background;
}
.item-name .name {
color: $theme ;
}
.file-icon {
path {
fill: $dark_mode_background ;
}
}
}
}

View File

@@ -7,7 +7,7 @@
{{ previewText }}
</MobileActionButton>
<MobileMultiSelectButton @click.native="mobileMultiSelect = !mobileMultiSelect">
Select
{{ $t('context_menu.select') }}
</MobileMultiSelectButton>
<MobileActionButton @click.native="$store.dispatch('emptyTrash')" icon="trash">
{{ $t('context_menu.empty_trash') }}
@@ -23,7 +23,7 @@
{{ $t('context_menu.upload') }}
</MobileActionButtonUpload>
<MobileMultiSelectButton @click.native="mobileMultiSelect = !mobileMultiSelect">
Select
{{ $t('context_menu.select') }}
</MobileMultiSelectButton>
<MobileActionButton @click.native="switchPreview" :icon="previewIcon">
{{ previewText }}
@@ -79,11 +79,9 @@
if(this.mobileMultiSelect ) {
events.$emit('mobileSelecting-start')
// this.mobileMultiSelect = true
}
if(!this.mobileMultiSelect) {
events.$emit('mobileSelecting-stop')
// this.mobileSelecting = false
}
}
},

View File

@@ -14,7 +14,7 @@
<ToolbarButton
v-if="
!$isThisLocation(['trash', 'trash-root']) &&
$checkPermission('master')
$checkPermission('master') || $checkPermission('editor')
"
source="move"
:action="$t('actions.move')"
@@ -386,11 +386,14 @@ export default {
},
moveItem() {
// Open move item popup
//Move item if is not selected
if(!this.mobileMultiSelect) {
let item = this.fileInfoDetail[0]
this.$store.commit('CLEAR_FILEINFO_DETAIL')
events.$emit('popup:open', { name: 'move', item: [item] })
}
//Move all selected items
if(this.mobileMultiSelect) {
events.$emit('popup:open', { name: 'move', item: [this.fileInfoDetail[0]] })
}
@@ -507,6 +510,9 @@ export default {
.mobile-selected-menu-wrapper {
z-index: 1;
.options {
z-index: 1;
}
}
.mobile-selected-menu {

View File

@@ -4,8 +4,8 @@
<CheckSquareIcon class="icon" size="21"/>
</div>
<div class="text">
<span class="title">Selected Multiple Items</span>
<span class="count">{{this.fileInfoDetail.length}} items</span>
<span class="title">{{ $t('file_detail.selected_multiple') }}</span>
<span class="count">{{this.fileInfoDetail.length}} {{ $tc('file_detail.items', this.fileInfoDetail.length) }}</span>
</div>
</div>
</template>
@@ -108,7 +108,15 @@ import {mapGetters} from 'vuex'
.title {
color: $dark_mode_text_primary;
}
}
.count {
color: $dark_mode_text_secondary;
}
}
.icon-wrapper {
.icon {
stroke: $theme;
}
}
}
.move-item {
.text {