Add drag n drop to results [SCI-9576]

This commit is contained in:
Anton 2023-10-19 15:51:18 +02:00
parent d6f03c6bcc
commit 3dd36e1dda
4 changed files with 54 additions and 6 deletions

View file

@ -1,6 +1,17 @@
<template> <template>
<div class="result-wrapper bg-white p-4 mb-4 rounded"> <div class="result-wrapper p-4 mb-4 rounded relative"
<div class="result-header flex justify-between "> @drop.prevent="dropFile"
@dragenter.prevent="dragEnter($event)"
@dragover.prevent
:class="{ 'bg-sn-super-light-blue': dragingFile, 'bg-white': !dragingFile }"
>
<div class="text-xl items-center flex text-sn-blue h-full justify-center left-0 absolute top-0 w-full"
v-if="dragingFile"
@dragleave.prevent="dragingFile = false">
{{ i18n.t('my_modules.results.drop_message', { name: result.attributes.name }) }}
<StorageUsage v-if="showStorageUsage()" :parent="result"/>
</div>
<div class="result-header flex justify-between" :class="{ 'opacity-0 pointer-events-none': dragingFile }">
<div class="result-head-left flex items-start flex-grow gap-4"> <div class="result-head-left flex items-start flex-grow gap-4">
<a class="result-collapse-link hover:no-underline focus:no-underline py-0.5 border-0 border-y border-transparent border-solid text-sn-black" <a class="result-collapse-link hover:no-underline focus:no-underline py-0.5 border-0 border-y border-transparent border-solid text-sn-black"
:href="'#resultBody' + result.id" :href="'#resultBody' + result.id"
@ -85,7 +96,7 @@
@reorder="updateElementOrder" @reorder="updateElementOrder"
@close="closeReorderModal" @close="closeReorderModal"
/> />
<div class="collapse in pl-10" :id="'resultBody' + result.id"> <div class="collapse in pl-10" :class="{ 'opacity-0 pointer-events-none': dragingFile }" :id="'resultBody' + result.id">
<div v-for="(element, index) in orderedElements" :key="element.id"> <div v-for="(element, index) in orderedElements" :key="element.id">
<component <component
:is="elements[index].attributes.orderable_type" :is="elements[index].attributes.orderable_type"
@ -130,12 +141,17 @@
import WopiFileModal from '../shared/content/attachments/mixins/wopi_file_modal.js' import WopiFileModal from '../shared/content/attachments/mixins/wopi_file_modal.js'
import OveMixin from '../shared/content/attachments/mixins/ove.js' import OveMixin from '../shared/content/attachments/mixins/ove.js'
import UtilsMixin from '../mixins/utils.js' import UtilsMixin from '../mixins/utils.js'
import StorageUsage from '../shared/content/attachments/storage_usage.vue'
export default { export default {
name: 'Results', name: 'Results',
props: { props: {
result: { type: Object, required: true }, result: { type: Object, required: true },
resultToReload: { type: Number, required: false } resultToReload: { type: Number, required: false },
activeDragResult: {
type: Number,
required: false
}
}, },
data() { data() {
return { return {
@ -144,6 +160,7 @@
attachments: [], attachments: [],
attachmentsReady: false, attachmentsReady: false,
showFileModal: false, showFileModal: false,
dragingFile: false,
wellPlateOptions: [ wellPlateOptions: [
{ text: I18n.t('protocols.steps.insert.well_plate_options.32_x_48'), emit: 'create:table', params: [[32, 48], true] }, { text: I18n.t('protocols.steps.insert.well_plate_options.32_x_48'), emit: 'create:table', params: [[32, 48], true] },
{ text: I18n.t('protocols.steps.insert.well_plate_options.16_x_24'), emit: 'create:table', params: [[16, 24], true] }, { text: I18n.t('protocols.steps.insert.well_plate_options.16_x_24'), emit: 'create:table', params: [[16, 24], true] },
@ -164,7 +181,8 @@
Attachments, Attachments,
InlineEdit, InlineEdit,
MenuDropdown, MenuDropdown,
deleteResultModal deleteResultModal,
StorageUsage
}, },
watch: { watch: {
resultToReload() { resultToReload() {
@ -172,6 +190,11 @@
this.loadElements(); this.loadElements();
this.loadAttachments(); this.loadAttachments();
} }
},
activeDragResult() {
if (this.activeDragResult != this.result.id && this.dragingFile) {
this.dragingFile = false;
}
} }
}, },
computed: { computed: {
@ -277,6 +300,20 @@
this.loadElements(); this.loadElements();
}, },
methods: { methods: {
dragEnter(e) {
if (!this.urls.upload_attachment_url) return;
// Detect if dragged element is a file
// https://stackoverflow.com/a/8494918
let dt = e.dataTransfer;
if (dt.types && (dt.types.indexOf ? dt.types.indexOf('Files') != -1 : dt.types.contains('Files'))) {
this.dragingFile = true;
this.$emit('result:drag_enter', this.result.id);
}
},
showStorageUsage() {
return (this.elements.length || this.attachments.length) && !this.isCollapsed && this.result.attributes.storage_limit;
},
openReorderModal() { openReorderModal() {
this.reordering = true; this.reordering = true;
}, },

View file

@ -20,6 +20,7 @@
<Result v-for="result in results" :key="result.id" <Result v-for="result in results" :key="result.id"
:result="result" :result="result"
:resultToReload="resultToReload" :resultToReload="resultToReload"
:activeDragResult="activeDragResult"
@result:elements:loaded="resultToReload = null" @result:elements:loaded="resultToReload = null"
@result:move_element="reloadResult" @result:move_element="reloadResult"
@result:attachments:loaded="resultToReload = null" @result:attachments:loaded="resultToReload = null"
@ -28,6 +29,7 @@
@result:archived="removeResult" @result:archived="removeResult"
@result:deleted="removeResult" @result:deleted="removeResult"
@result:restored="removeResult" @result:restored="removeResult"
@result:drag_enter="dragEnter"
/> />
</div> </div>
</div> </div>
@ -60,6 +62,7 @@
resultToReload: null, resultToReload: null,
nextPageUrl: null, nextPageUrl: null,
loadingPage: false, loadingPage: false,
activeDragResult: null
} }
}, },
mounted() { mounted() {
@ -130,6 +133,9 @@
}, },
removeResult(result_id) { removeResult(result_id) {
this.results = this.results.filter((r) => r.id != result_id); this.results = this.results.filter((r) => r.id != result_id);
},
dragEnter(id) {
this.activeDragResult = id;
} }
} }
} }

View file

@ -10,7 +10,7 @@ class ResultSerializer < ActiveModel::Serializer
attributes :name, :id, :urls, :updated_at, :created_at_formatted, :updated_at_formatted, :user, attributes :name, :id, :urls, :updated_at, :created_at_formatted, :updated_at_formatted, :user,
:my_module_id, :attachments_manageble, :marvinjs_enabled, :marvinjs_context, :type, :my_module_id, :attachments_manageble, :marvinjs_enabled, :marvinjs_context, :type,
:wopi_enabled, :wopi_context, :created_at, :created_by, :archived, :assets_order, :wopi_enabled, :wopi_context, :created_at, :created_by, :archived, :assets_order,
:open_vector_editor_context, :comments_count, :assets_view_mode :open_vector_editor_context, :comments_count, :assets_view_mode, :storage_limit
def marvinjs_enabled def marvinjs_enabled
MarvinJsService.enabled? MarvinJsService.enabled?
@ -36,6 +36,10 @@ class ResultSerializer < ActiveModel::Serializer
scope scope
end end
def storage_limit
nil
end
def marvinjs_context def marvinjs_context
if marvinjs_enabled if marvinjs_enabled
{ {

View file

@ -1274,6 +1274,7 @@ en:
published_table: "entered a table on %{timestamp}." published_table: "entered a table on %{timestamp}."
published_text: "entered a text on %{timestamp}." published_text: "entered a text on %{timestamp}."
published_asset: "uploaded a file on %{timestamp}." published_asset: "uploaded a file on %{timestamp}."
drop_message: "Drop file to add to result %{name}"
expand_label: "Expand All" expand_label: "Expand All"
collapse_label: "Collapse All" collapse_label: "Collapse All"
empty_name: "Add title" empty_name: "Add title"