From 6722029b73e7383856fd0777ca58863c7d0faab4 Mon Sep 17 00:00:00 2001
From: Ron Lucke <lucke@elan-ev.de>
Date: Mon, 15 Jan 2024 13:16:21 +0000
Subject: [PATCH] fix #3151

Closes #3151

Merge request studip/studip!2487
---
 .../CoursewareAccordionContainer.vue          |  1 +
 .../CoursewareStructuralElement.vue           | 13 +++--
 resources/vue/mixins/courseware/container.js  | 53 ++++++++++---------
 .../vue/store/courseware/courseware.module.js | 11 ++++
 4 files changed, 48 insertions(+), 30 deletions(-)

diff --git a/resources/vue/components/courseware/containers/CoursewareAccordionContainer.vue b/resources/vue/components/courseware/containers/CoursewareAccordionContainer.vue
index 75db30cdb01..b43c811b6d0 100644
--- a/resources/vue/components/courseware/containers/CoursewareAccordionContainer.vue
+++ b/resources/vue/components/courseware/containers/CoursewareAccordionContainer.vue
@@ -51,6 +51,7 @@
                             handle=".cw-sortable-handle"
                             group="blocks"
                             @start="isDragging = true"
+                            @end="dropBlock"
                             :containerId="container.id"
                             :sectionId="index"
                         >
diff --git a/resources/vue/components/courseware/structural-element/CoursewareStructuralElement.vue b/resources/vue/components/courseware/structural-element/CoursewareStructuralElement.vue
index 34d3145f5d1..3842a36565b 100644
--- a/resources/vue/components/courseware/structural-element/CoursewareStructuralElement.vue
+++ b/resources/vue/components/courseware/structural-element/CoursewareStructuralElement.vue
@@ -680,6 +680,7 @@ import IsoDate from '../layouts/IsoDate.vue';
 import FeedbackDialog from '../../feedback/FeedbackDialog.vue'
 import FeedbackCreateDialog from '../../feedback/FeedbackCreateDialog.vue';
 import StudipFiveStars from '../../feedback/StudipFiveStars.vue';
+import StudipProgressIndicator from '../../StudipProgressIndicator.vue';
 import draggable from 'vuedraggable';
 import containerMixin from '@/vue/mixins/courseware/container.js';
 import { mapActions, mapGetters } from 'vuex';
@@ -712,6 +713,7 @@ export default {
         IsoDate,
         StockImageSelector,
         StudipDialog,
+        StudipProgressIndicator,
         draggable,
     }),
     props: ['canVisit', 'orderedStructuralElements', 'structuralElement'],
@@ -770,7 +772,6 @@ export default {
                 'expire-date': ''
             },
             deletingPreviewImage: false,
-            processing: false,
             keyboardSelected: null,
             assistiveLive: '',
             uploadImageURL: null,
@@ -845,7 +846,8 @@ export default {
             getFeedbackElementById: 'feedback-elements/byId',
             feedbackEntries: 'feedback-entries/all',
 
-            currentUser: 'currentUser'
+            currentUser: 'currentUser',
+            processing: 'processing',
         }),
 
         currentId() {
@@ -1446,6 +1448,7 @@ export default {
             loadRelatedFeedback: 'courseware-structural-element-feedback/loadRelated',
             createFeedback: 'feedback-elements/create',
             loadFeedbackElement: 'feedback-elements/loadById',
+            setProcessing: 'setProcessing',
         }),
 
         initCurrent() {
@@ -1624,7 +1627,7 @@ export default {
         },
 
         async storeSort() {
-            const timeout = setTimeout(() => this.processing = true, 800);
+            const timeout = setTimeout(() => this.setProcessing(true), 800);
             if (this.blockedByAnotherUser) {
                 this.companionInfo({ info: this.$gettext('Diese Seite wird bereits bearbeitet.') });
                 clearTimeout(timeout);
@@ -1641,7 +1644,7 @@ export default {
                 }
 
                 clearTimeout(timeout);
-                this.processing = false;
+                this.setProcessing(false);
                 return false;
             }
 
@@ -1652,7 +1655,7 @@ export default {
             this.$emit('select', this.currentId);
 
             clearTimeout(timeout);
-            this.processing = false;
+            this.setProcessing(false);
         },
 
 
diff --git a/resources/vue/mixins/courseware/container.js b/resources/vue/mixins/courseware/container.js
index db60af2f30b..2eb7549949e 100644
--- a/resources/vue/mixins/courseware/container.js
+++ b/resources/vue/mixins/courseware/container.js
@@ -21,6 +21,7 @@ const containerMixin = {
             updateBlock: 'updateBlock',
             updateContainer: 'updateContainer',
             loadContainer: 'courseware-containers/loadById',
+            loadBlock: 'courseware-blocks/loadById',
             loadStructuralElement: 'loadStructuralElement',
             lockObject: 'lockObject',
             unlockObject: 'unlockObject',
@@ -31,6 +32,8 @@ const containerMixin = {
             companionWarning: 'companionWarning',
             sortContainersInStructualElements: 'sortContainersInStructualElements',
             setAdderStorage: 'coursewareBlockAdder',
+            setProcessing: 'setProcessing',
+            containerUpdate: 'courseware-containers/update'
         }),
         dropBlock(e) {
             this.isDragging = false; // implemented bei echt container type
@@ -52,41 +55,41 @@ const containerMixin = {
             }
         },
         async storeInAnotherContainer(data) {
-            // update block container id
-            let block = this.blockById({id: data.blockId });
-            block.relationships.container.data.id = data.targetContainerId;
-            block.attributes.position = data.newPos;
-            await this.lockObject({ id: data.blockId, type: 'courseware-blocks' });
-            await this.updateBlock({
-                block: block,
-                containerId: data.targetContainerId,
-            });
-            await this.unlockObject({ id: data.blockId, type: 'courseware-blocks' });
-
+            this.setProcessing(true);
             // update origin container
             if (data.originContainerId) {
+                await this.lockObject({ id: data.originContainerId, type: 'courseware-containers' });
+                await this.loadContainer({ id : data.originContainerId });
                 let originContainer = this.containerById({ id: data.originContainerId});
                 originContainer.attributes.payload.sections[data.originSectionId].blocks = data.originSectionBlockList;
-                await this.lockObject({ id: data.originContainerId, type: 'courseware-containers' });
-                await this.updateContainer({
-                    container: originContainer,
-                    structuralElementId: originContainer.relationships['structural-element'].data.id,
-                });
+                await this.containerUpdate(
+                    originContainer,
+                );
                 await this.unlockObject({ id: data.originContainerId, type: 'courseware-containers' });
             }
-
             // update target container
+            await this.lockObject({ id: data.targetContainerId, type: 'courseware-containers' });
+            await this.loadContainer({ id : data.targetContainerId });
             let targetContainer = this.containerById({ id: data.targetContainerId});
             targetContainer.attributes.payload.sections[data.targetSectionId].blocks = data.targetSectionBlockList;
-            await this.lockObject({ id: data.targetContainerId, type: 'courseware-containers' });
-            await this.updateContainer({
-                container: targetContainer,
-                structuralElementId: targetContainer.relationships['structural-element'].data.id,
-            });
+            await this.containerUpdate(
+                targetContainer,
+            );
             await this.unlockObject({ id: data.targetContainerId, type: 'courseware-containers' });
-
-            this.loadContainer({id : data.originContainerId });
-            this.loadContainer({id : data.targetContainerId });
+         
+            // update block container id
+            let block = this.blockById({id: data.blockId });
+            block.relationships.container.data.id = data.targetContainerId;
+            block.attributes.position = data.newPos;
+            await this.lockObject({ id: block.id, type: 'courseware-blocks' });
+            await this.updateBlock({
+                block: block,
+                containerId: data.targetContainerId,
+            });
+            await this.unlockObject({ id: block.id, type: 'courseware-blocks' });
+            await this.loadBlock({ id: block.id });
+            await this.loadContainer({ id : data.originContainerId });
+            this.setProcessing(false);
         },
         checkSimpleArrayEquality(firstSet, secondSet) {
             return Array.isArray(firstSet) && Array.isArray(secondSet) &&
diff --git a/resources/vue/store/courseware/courseware.module.js b/resources/vue/store/courseware/courseware.module.js
index d5915b418d3..8b2f8da0c45 100644
--- a/resources/vue/store/courseware/courseware.module.js
+++ b/resources/vue/store/courseware/courseware.module.js
@@ -68,6 +68,7 @@ const getDefaultState = () => {
 
         toolbarActive: true,
         feedbackSettings: null,
+        processing: false,
     };
 };
 
@@ -287,6 +288,9 @@ const getters = {
     progresses(state) {
         return state.progresses;
     },
+    processing(state) {
+        return state.processing;
+    },
 
     oerCampusEnabled(state, getters, rootState, rootGetters) {
         return rootGetters['studip-properties/byId']({ id: 'oer-campus-enabled'}).attributes?.value;
@@ -1457,6 +1461,10 @@ export const actions = {
         commit('setBookmarkFilter', course);
     },
 
+    setProcessing({ commit }, processing) {
+        commit('setProcessing', processing);
+    },
+
     createLink({ dispatch, rootGetters }, { publicLink }) {
         dispatch('courseware-public-links/create', publicLink, { root: true });
     },
@@ -1748,6 +1756,9 @@ export const mutations = {
     },
     setFeedbackSettings(state, feedbackSettings) {
         state.feedbackSettings = feedbackSettings;
+    },
+    setProcessing(state, processing) {
+        state.processing = processing;
     }
 };
 
-- 
GitLab