diff --git a/lib/classes/JsonApi/Routes/Courseware/Authority.php b/lib/classes/JsonApi/Routes/Courseware/Authority.php
index 04f955e52a34990125c70503ded8565f17ec2981..320648be8a487471bf4a628d41d6ffa877a3d161 100755
--- a/lib/classes/JsonApi/Routes/Courseware/Authority.php
+++ b/lib/classes/JsonApi/Routes/Courseware/Authority.php
@@ -56,7 +56,13 @@ class Authority
     public static function canUpdateBlock(User $user, Block $resource)
     {
         if ($resource->isBlocked()) {
-            return $resource->getBlockerUserId() == $user->id;
+            $perm = $GLOBALS['perm']->have_studip_perm(
+                $resource->container->structural_element->course->config->COURSEWARE_EDITING_PERMISSION,
+                $resource->container->structural_element->course->id,
+                $user->id
+            );
+
+            return $resource->getBlockerUserId() == $user->id || $perm;
         }
 
         return self::canUpdateContainer($user, $resource->container);
@@ -68,8 +74,29 @@ class Authority
     }
 
     public static function canUpdateEditBlocker(User $user, $resource)
-    {
-        return $resource->edit_blocker_id == '' || $resource->edit_blocker_id === $user->id;
+    { 
+        $structural_element = null;
+        if ($resource instanceof Block) {
+            $structural_element = $resource->container->structural_element;
+        }
+        if ($resource instanceof Container) {
+            $structural_element = $resource->structural_element;
+        }
+        if ($resource instanceof StructuralElement) {
+            $structural_element = $resource;
+        }
+
+        if ($structural_element === null) {
+            return false;
+        }
+
+        $perm = $GLOBALS['perm']->have_studip_perm(
+            $structural_element->course->config->COURSEWARE_EDITING_PERMISSION,
+            $structural_element->course->id,
+            $user->id
+        );
+
+        return $resource->edit_blocker_id == '' || $resource->edit_blocker_id === $user->id || $perm;
     }
 
     public static function canShowContainer(User $user, Container $resource)
diff --git a/resources/assets/stylesheets/scss/courseware.scss b/resources/assets/stylesheets/scss/courseware.scss
index eda8513c6042d79aadb6dea7d43e1c8953d4f318..1f04e4c82bccf9c5757ee27352ed500306806eed 100755
--- a/resources/assets/stylesheets/scss/courseware.scss
+++ b/resources/assets/stylesheets/scss/courseware.scss
@@ -746,6 +746,14 @@ ribbon end
             font-weight: 700;
             line-height: 2em;
             font-size: 1.1em;
+
+            &.cw-default-container-blocker-warning {
+                font-weight: 400;
+            }
+        }
+
+        img {
+            vertical-align: text-bottom;
         }
 
         .cw-container-actions {
@@ -842,12 +850,6 @@ form.cw-container-dialog-edit-form {
 .cw-default-block {
     display: flex;
     flex-flow: row;
-    .cw-default-block-invisible-info {
-        img {
-            vertical-align: text-bottom;
-        }
-    }
-
 }
 .cw-content-wrapper {
     display: flex;
@@ -882,10 +884,19 @@ form.cw-container-dialog-edit-form {
     padding: 4px 10px;
 
     span {
+        font-size: 1.1em;
         color: $base-color;
         font-weight: 700;
         line-height: 2em;
-        font-size: 1.1em;
+
+        &.cw-default-block-invisible-info,
+        &.cw-default-block-blocker-warning {
+            font-weight: 400;
+        }
+    }
+
+    img {
+        vertical-align: text-bottom;
     }
 
     .cw-block-actions {
@@ -898,6 +909,12 @@ form.cw-container-dialog-edit-form {
     }
 }
 
+.cw-block-edit-warning {
+    font-style: italic;
+    color: $dark-gray-color;
+    margin: 1em 0 0.5em 0;
+}
+
 .cw-discuss-wrapper,
 .cw-block-features {
 
@@ -3046,23 +3063,31 @@ a u d i o  b l o c k
             padding-top: 106px;
         }
     }
-    .cw-audio-empty {
-        @include background-icon(file, info, 96);
-        border: solid thin $content-color-40;
-        background-position: center 1em;
-        background-repeat: no-repeat;
-        min-height: 140px;
-        padding: 1em;
-        p {
-            text-align: center;
-            padding-top: 106px;
-        }
-    }
 }
 /* * * * * * * * * * * * * *
 a u d i o  b l o c k  e n d
 * * * * * * * * * * * * * */
 
+/* * * * * * * * * * * * * * * * * * * *
+f o r  m u l t i m e d i a  b l o c k s
+* * * * * * * * * * * * * * * * * * * */
+.cw-file-empty {
+    @include background-icon(file, info, 96);
+    border: solid thin $content-color-40;
+    background-position: center 1em;
+    background-repeat: no-repeat;
+    min-height: 140px;
+    padding: 1em;
+    p {
+        text-align: center;
+        padding-top: 106px;
+    }
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * 
+f o r  m u l t i m e d i a  b l o c k s  e n d
+* * * * * * * * * * * * * * * * * * * * * * * */
+
 /* * * * * * * * * *
 v i d e o  b l o c k
 * * * * * * * * * * */
diff --git a/resources/vue/components/courseware/CoursewareAccordionContainer.vue b/resources/vue/components/courseware/CoursewareAccordionContainer.vue
index 5f58dc46ee8d5a83acb33270d9a17e98055863db..924a92b0745ec3666961588139382a6a342fb8a8 100755
--- a/resources/vue/components/courseware/CoursewareAccordionContainer.vue
+++ b/resources/vue/components/courseware/CoursewareAccordionContainer.vue
@@ -4,9 +4,10 @@
         containerClass="cw-container-accordion"
         :canEdit="canEdit"
         :isTeacher="isTeacher"
-        @storeContainer="storeContainer"
         @closeEdit="initCurrentData"
+        @showEdit="setShowEdit"
         @sortBlocks="enableSort"
+        @storeContainer="storeContainer"
     >
         <template v-slot:containerContent>
             <courseware-collapsible-box
@@ -114,6 +115,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentContainer: {},
             currentSections: [],
             sortMode: false,
@@ -164,6 +166,9 @@ export default {
 
             this.currentSections = sections;
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         addSection() {
             this.currentContainer.attributes.payload.sections.push({ name: '', icon: '', blocks: [] });
         },
@@ -225,7 +230,9 @@ export default {
     },
     watch: {
         blocks() {
-            this.initCurrentData();
+            if (!this.showEdit) {
+                this.initCurrentData();
+            }
         }
     }
 };
diff --git a/resources/vue/components/courseware/CoursewareActionWidget.vue b/resources/vue/components/courseware/CoursewareActionWidget.vue
index fcac6864b2433b84177edcaf26f7c000115146b8..d95b32bdcda23a6150f0378aa46837240ed0fac7 100644
--- a/resources/vue/components/courseware/CoursewareActionWidget.vue
+++ b/resources/vue/components/courseware/CoursewareActionWidget.vue
@@ -78,10 +78,10 @@ export default {
             return this.structuralElement?.id;
         },
         blocked() {
-            return this.structuralElement?.relationships['edit-blocker'].data !== null;
+            return this.structuralElement?.relationships?.['edit-blocker']?.data !== null;
         },
         blockerId() {
-            return this.blocked ? this.structuralElement?.relationships['edit-blocker'].data?.id : null;
+            return this.blocked ? this.structuralElement?.relationships?.['edit-blocker']?.data?.id : null;
         },
         blockedByThisUser() {
             return this.blocked && this.userId === this.blockerId;
diff --git a/resources/vue/components/courseware/CoursewareAudioBlock.vue b/resources/vue/components/courseware/CoursewareAudioBlock.vue
index fd860cdbaa1a92138cb88d721a2464a94e8f5ad8..5adb790e87b63d5762d10e466641d419e7c567ff 100755
--- a/resources/vue/components/courseware/CoursewareAudioBlock.vue
+++ b/resources/vue/components/courseware/CoursewareAudioBlock.vue
@@ -5,8 +5,9 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <div v-if="currentTitle !== ''" class="cw-block-title">{{ currentTitle }}</div>
@@ -56,7 +57,7 @@
                             {{ file.name }}
                         </li>
                     </ul>
-                    <div v-if="emptyAudio" class="cw-audio-empty">
+                    <div v-if="emptyAudio" class="cw-file-empty">
                         <p><translate>Es ist keine Audio-Datei verfügbar</translate></p>
                     </div>
                     <div v-if="showRecorder && canGetMediaDevices" class="cw-audio-playlist-recorder">
@@ -175,6 +176,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentTitle: '',
             currentSource: '',
             currentFileId: '',
@@ -341,6 +343,9 @@ export default {
             this.currentFolderId = this.folderId;
             this.currentRecorderEnabled = this.recorderEnabled;
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         updateCurrentFile(file) {
             this.currentFile = file;
             this.currentFileId = file.id;
@@ -593,6 +598,39 @@ export default {
         currentFolderId() {
             this.getFolderFiles();
         },
+        title() {
+            if (!this.showEdit) {
+                this.currentTitle = this.title;
+            }
+        },
+        source() {
+            if (!this.showEdit) {
+                this.currentSource = this.source;
+            }
+        },
+        fileId() {
+            if (!this.showEdit) {
+                this.currentFileId = this.fileId;
+                if (this.currentFileId !== '') {
+                    this.loadFile();
+                }
+            }
+        },
+        webUrl() {
+            if (!this.showEdit) {
+                this.currentWebUrl = this.webUrl;
+            }
+        },
+        folderId() {
+            if (!this.showEdit) {
+                this.currentFolderId = this.folderId;
+            }
+        },
+        recorderEnabled() {
+            if (!this.showEdit) {
+                this.currentRecorderEnabled = this.recorderEnabled;
+            }
+        },
     },
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareBeforeAfterBlock.vue b/resources/vue/components/courseware/CoursewareBeforeAfterBlock.vue
index 2c68473b9cd45792d24318a78ead9d7415d50df5..95f4fb4c462b82c3f7a284812c5b592c6c0aada6 100755
--- a/resources/vue/components/courseware/CoursewareBeforeAfterBlock.vue
+++ b/resources/vue/components/courseware/CoursewareBeforeAfterBlock.vue
@@ -5,11 +5,12 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
-                <TwentyTwenty :before="currentBeforeUrl" :after="currentAfterUrl" />
+                <TwentyTwenty v-if="!isEmpty" :before="currentBeforeUrl" :after="currentAfterUrl" />
             </template>
             <template v-if="canEdit" #edit>
                 <form class="default" @submit.prevent="">
@@ -79,6 +80,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentBeforeSource: '',
             currentBeforeFileId: '',
             currentBeforeFile: {},
@@ -111,40 +113,42 @@ export default {
             return this.block?.attributes?.payload?.after_web_url;
         },
         currentBeforeUrl() {
-            if (this.currentBeforeSource === 'studip'&& this.currentBeforeFile?.meta) {
-                return this.currentBeforeFile.meta['download-url'];
-            } else if (this.currentBeforeSource === 'web') {
+            if (this.currentBeforeSource === 'studip' ) {
+                if (this.currentBeforeFile?.meta) {
+                    return this.currentBeforeFile.meta['download-url'];
+                }
+                if (this.currentBeforeFile?.['download_url']) {
+                    return this.currentBeforeFile['download_url']
+                }
+            }
+
+            if (this.currentBeforeSource === 'web') {
                 return this.currentBeforeWebUrl;
-            } else {
-                return '';
             }
+
+            return '';
         },
         currentAfterUrl() {
-            if (this.currentAfterSource === 'studip'&& this.currentAfterFile?.meta) {
-                return this.currentAfterFile.meta['download-url'];
-            } else if (this.currentAfterSource === 'web') {
+            if (this.currentAfterSource === 'studip') {
+                if (this.currentAfterFile?.meta) {
+                    return this.currentAfterFile.meta['download-url'];
+                }
+                if (this.currentAfterFile?.['download_url']) {
+                    return this.currentAfterFile['download_url']
+                }
+            } 
+            if (this.currentAfterSource === 'web') {
                 return this.currentAfterWebUrl;
-            } else {
-                return '';
             }
+
+            return '';
         },
+        isEmpty() {
+            return !this.currentAfterUrl || !this.currentBeforeUrl;
+        }
     },
     mounted() {
-        this.loadFileRefs(this.block.id).then((response) => {
-            for (let i = 0; i < response.length; i++) {
-                if (response[i].id === this.beforeFileId) {
-                    this.beforeFile = response[i];
-                }
-
-                if (response[i].id === this.afterFileId) {
-                    this.afterFile = response[i];
-                }
-            }
-
-            this.currentBeforeFile = this.beforeFile;
-            this.currentAfterFile  = this.afterFile;
-        });
-
+        this.loadImages();
         this.initCurrentData();
     },
     methods: {
@@ -153,6 +157,22 @@ export default {
             loadFileRefs: 'loadFileRefs',
             companionWarning: 'companionWarning',
         }),
+        loadImages() {
+            this.loadFileRefs(this.block.id).then((response) => {
+                for (let i = 0; i < response.length; i++) {
+                    if (response[i].id === this.beforeFileId) {
+                        this.beforeFile = response[i];
+                    }
+
+                    if (response[i].id === this.afterFileId) {
+                        this.afterFile = response[i];
+                    }
+                }
+
+                this.currentBeforeFile = this.beforeFile;
+                this.currentAfterFile  = this.afterFile;
+            });
+        },
         initCurrentData() {
             this.currentBeforeSource = this.beforeSource;
             this.currentBeforeFileId = this.beforeFileId;
@@ -161,6 +181,9 @@ export default {
             this.currentAfterFileId = this.afterFileId;
             this.currentAfterWebUrl = this.afterWebUrl;
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         updateCurrentBeforeFile(file) {
             this.currentBeforeFile = file;
             this.currentBeforeFileId = file.id;
@@ -227,5 +250,39 @@ export default {
             }
         },
     },
+    watch: {
+        beforeSource() {
+            if (!this.showEdit) {
+                this.currentBeforeSource = this.beforeSource;
+            }
+        },
+        beforeFileId() {
+            if (!this.showEdit) {
+                this.currentBeforeFileId = this.beforeFileId;
+                this.loadImages();
+            }
+        },
+        beforeWebUrl() {
+            if (!this.showEdit) {
+                this.currentBeforeWebUrl = this.beforeWebUrl;
+            }
+        },
+        afterSource() {
+            if (!this.showEdit) {
+                this.currentAfterSource = this.afterSource;
+            }
+        },
+        afterFileId() {
+            if (!this.showEdit) {
+                this.currentAfterFileId = this.afterFileId;
+                this.loadImages();
+            }
+        },
+        afterWebUrl() {
+            if (!this.showEdit) {
+                this.currentAfterWebUrl = this.afterWebUrl;
+            }
+        },
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareBlockActions.vue b/resources/vue/components/courseware/CoursewareBlockActions.vue
index bb2177edc0f8fb63a2f89a88c0707bb14ddcad3f..e5af4249507a5295e70bc45468483ef41e9f0092 100755
--- a/resources/vue/components/courseware/CoursewareBlockActions.vue
+++ b/resources/vue/components/courseware/CoursewareBlockActions.vue
@@ -2,10 +2,12 @@
     <div class="cw-block-actions">
         <studip-action-menu 
             :items="menuItems"
+            collapseAt="2"
             @editBlock="editBlock"
             @setVisibility="setVisibility"
             @showInfo="showInfo"
             @deleteBlock="deleteBlock"
+            @removeLock="removeLock"
         />
     </div>
 </template>
@@ -27,57 +29,68 @@ export default {
         },
         block: Object,
     },
-    data() {
-        return {
-            menuItems: [],
-        };
-    },
     computed: {
         ...mapGetters({
             userId: 'userId',
+            userIsTeacher: 'userIsTeacher',
         }),
         blocked() {
-            return this.block?.relationships['edit-blocker'].data !== null;
+            return this.block?.relationships?.['edit-blocker']?.data !== null;
         },
         blockerId() {
-            return this.blocked ? this.block?.relationships['edit-blocker'].data?.id : null;
+            return this.blocked ? this.block?.relationships?.['edit-blocker']?.data?.id : null;
         },
-    },
-    mounted() {
-        if (this.canEdit) {
-            if (!this.deleteOnly) {
-                this.menuItems.push({
-                    id: 1,
-                    label: this.$gettext('Block bearbeiten'),
-                    icon: 'edit',
-                    emit: 'editBlock',
-                });
-                this.menuItems.push({
-                    id: 2,
-                    label: this.block.attributes.visible
-                        ? this.$gettext('unsichtbar setzen')
-                        : this.$gettext('sichtbar setzen'),
-                    icon: this.block.attributes.visible ? 'visibility-visible' : 'visibility-invisible', // do we change the icons ?
-                    emit: 'setVisibility',
-                });
-                this.menuItems.push({
-                    id: 7,
-                    label: this.$gettext('Informationen zum Block'),
-                    icon: 'info',
-                    emit: 'showInfo',
-                });
+        blockedByThisUser() {
+            return this.blocked && this.userId === this.blockerId;
+        },
+        blockedByAnotherUser() {
+            return this.blocked && this.userId !== this.blockerId;
+        },
+        menuItems() {
+            let menuItems = [];
+            if (this.canEdit) {
+                if (!this.deleteOnly) {
+                    if (!this.blocked) {
+                        menuItems.push({ id: 1, label: this.$gettext('Block bearbeiten'), icon: 'edit', emit: 'editBlock' });
+                        menuItems.push({
+                            id: 2,
+                            label: this.block.attributes.visible
+                                ? this.$gettext('unsichtbar setzen')
+                                : this.$gettext('sichtbar setzen'),
+                            icon: this.block.attributes.visible ? 'visibility-visible' : 'visibility-invisible', // do we change the icons ?
+                            emit: 'setVisibility',
+                        });
+                    }
+                    if (this.blocked && this.blockedByAnotherUser && this.userIsTeacher) {
+                        menuItems.push({
+                            id: 8,
+                            label: this.$gettext('Sperre aufheben'),
+                            icon: 'lock-unlocked',
+                            emit: 'removeLock',
+                        });
+                    }
+                    if (!this.blocked || this.blockedByThisUser) {
+                        menuItems.push({
+                            id: 9,
+                            label: this.$gettext('Block löschen'), 
+                            icon: 'trash',
+                            emit: 'deleteBlock' 
+                        });
+                    }
+                    menuItems.push({
+                        id: 7,
+                        label: this.$gettext('Informationen zum Block'),
+                        icon: 'info',
+                        emit: 'showInfo',
+                    });
+                }
             }
-            this.menuItems.push({
-                id: 9,
-                label: this.$gettext('Block löschen'), 
-                icon: 'trash',
-                emit: 'deleteBlock',
+
+            menuItems.sort((a, b) => {
+                return a.id > b.id ? 1 : b.id > a.id ? -1 : 0;
             });
+            return menuItems;
         }
-
-        this.menuItems.sort((a, b) => {
-            return a.id > b.id ? 1 : b.id > a.id ? -1 : 0;
-        });
     },
     methods: {
         ...mapActions({
@@ -116,12 +129,12 @@ export default {
 
             await this.unlockObject({ id: this.block.id, type: 'courseware-blocks' });
         },
-        copyToClipboard() {
-            // use JSONAPI to copy to clipboard
-        },
         deleteBlock() {
             this.$emit('deleteBlock');
         },
+        removeLock() {
+            this.$emit('removeLock');
+        }
     },
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareCanvasBlock.vue b/resources/vue/components/courseware/CoursewareCanvasBlock.vue
index 42e252de8b80eb2be4c62f49b0a797b2562ba141..6aed6daaad0a546f22a8299ab6aabb0fe5bd0dbd 100755
--- a/resources/vue/components/courseware/CoursewareCanvasBlock.vue
+++ b/resources/vue/components/courseware/CoursewareCanvasBlock.vue
@@ -5,8 +5,9 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <div v-if="currentTitle" class="cw-block-title">
@@ -163,6 +164,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentTitle: '',
             currentImage: '',
             currentFileId: '',
@@ -254,12 +256,7 @@ export default {
         },
     },
     mounted() {
-        this.loadFileRefs(this.block.id).then((response) => {
-            this.file = response[0];
-            this.currentFile = this.file;
-            this.initCurrentData();
-            this.buildCanvas();
-        });
+        this.loadImageFile();
     },
     methods: {
         ...mapActions({
@@ -285,6 +282,17 @@ export default {
                 this.Text = JSON.parse(this.canvasDraw.Text);
             }
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
+        loadImageFile() {
+            this.loadFileRefs(this.block.id).then((response) => {
+                this.file = response[0];
+                this.currentFile = this.file;
+                this.initCurrentData();
+                this.buildCanvas();
+            });
+        },
         updateCurrentFile(file) {
             this.currentFile = file;
             this.currentFileId = file.id;
@@ -595,5 +603,34 @@ export default {
             }
         },
     },
+    watch: {
+        title() {
+            if (!this.showEdit) {
+                this.currentTitle = this.title;
+            }
+        },
+        image() {
+            if (!this.showEdit) {
+                this.currentImage = this.image;
+                this.buildCanvas();
+            }
+        },
+        fileId() {
+            if (!this.showEdit) {
+                this.currentFileId = this.fileId;
+                this.loadImageFile();
+            }
+        },
+        uploadFolderId() {
+            if (!this.showEdit) {
+                this.currentUploadFolderId = this.uploadFolderId;
+            }
+        },
+        showUsersData() {
+            if (!this.showEdit) {
+                this.currentShowUserData = this.showUsersData;
+            }
+        },
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareChartBlock.vue b/resources/vue/components/courseware/CoursewareChartBlock.vue
index 8dd58ec2433dd07e3eb00ce62c09d4b69a076bb0..0c5de9719be2580ee7cc1b705f51f75ecb9ab0b3 100755
--- a/resources/vue/components/courseware/CoursewareChartBlock.vue
+++ b/resources/vue/components/courseware/CoursewareChartBlock.vue
@@ -5,8 +5,9 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <canvas class="cw-chart-block-canvas" ref="chartCanvas" />
@@ -87,9 +88,11 @@ import CoursewareDefaultBlock from './CoursewareDefaultBlock.vue';
 import Chart from 'chart.js';
 import { mapActions } from 'vuex';
 import StudipIcon from '../StudipIcon.vue';
+import { blockMixin } from './block-mixin.js';
 
 export default {
     name: 'courseware-chart-block',
+    mixins: [blockMixin],
     components: {
         CoursewareDefaultBlock,
         StudipIcon,
@@ -101,6 +104,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             chart: null,
             currentContent: [],
             currentLabel: '',
@@ -146,6 +150,9 @@ export default {
             this.currentLabel = this.label;
             this.currentType = this.type;
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         storeBlock() {
             let attributes = {};
             attributes.payload = {};
@@ -281,12 +288,29 @@ export default {
                     });
                     break;
             }
-        },
+        }
     },
     watch: {
         currentType() {
             this.buildChart();
         },
+        content() {
+            if (!this.showEdit && !this.contentsEqual(this.currentContent,this.content)) {
+                this.currentContent = this.content;
+                this.buildChart();
+            }
+        },
+        label() {
+            if (!this.showEdit) {
+                this.currentLabel = this.label;
+                this.buildChart();
+            }
+        },
+        type() {
+            if (!this.showEdit) {
+                this.currentType = this.type;
+            }
+        },
     },
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareCodeBlock.vue b/resources/vue/components/courseware/CoursewareCodeBlock.vue
index 275a77f5e876a04d6eae33520d1024f9f51dafa6..c5492452a63e34355ab9f1f999285e7d5b15f138 100755
--- a/resources/vue/components/courseware/CoursewareCodeBlock.vue
+++ b/resources/vue/components/courseware/CoursewareCodeBlock.vue
@@ -5,8 +5,9 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <pre v-show="currentContent !== ''"  v-highlightjs="currentContent"><code ref="code" :class="[currentLang]"></code></pre>
@@ -51,6 +52,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentLang: '',
             currentContent: '',
         };
@@ -97,6 +99,9 @@ export default {
             this.currentLang = this.lang;
             this.currentContent = this.content;
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         storeBlock() {
             let attributes = {};
             attributes.payload = {};
@@ -110,5 +115,17 @@ export default {
             });
         },
     },
+    watch: {
+        lang() {
+            if (!this.showEdit) {
+                this.currentLang = this.lang;
+            }
+        },
+        content() {
+            if (!this.showEdit) {
+                this.currentContent = this.content;
+            }
+        }
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareConfirmBlock.vue b/resources/vue/components/courseware/CoursewareConfirmBlock.vue
index 4e602f82e1f94eb854ac174a31fea3e67a72df0e..e420bda4820178a7cf0c12323c60a1bf7d937e48 100755
--- a/resources/vue/components/courseware/CoursewareConfirmBlock.vue
+++ b/resources/vue/components/courseware/CoursewareConfirmBlock.vue
@@ -6,8 +6,9 @@
             :isTeacher="isTeacher"
             :preview="true"
             :defaultGrade="false"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <div class="cw-block-title">
@@ -56,6 +57,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentText: '',
             confirm: false,
         };
@@ -85,6 +87,9 @@ export default {
                 this.confirm = this.userData.attributes.payload.confirm;
             }
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         async setConfirm() {
             let data = {};
             data.type = 'courseware-user-data-fields';
@@ -114,5 +119,12 @@ export default {
             });
         },
     },
+    watch: {
+        text() {
+            if (!this.showEdit) {
+                this.currentText = this.text;
+            }
+        }
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareContainerActions.vue b/resources/vue/components/courseware/CoursewareContainerActions.vue
index e1da988467652f68abf2eaf458cc8df9dc2708e5..1c9cbf8ce96d29e5570212c023e11878f2a9772e 100755
--- a/resources/vue/components/courseware/CoursewareContainerActions.vue
+++ b/resources/vue/components/courseware/CoursewareContainerActions.vue
@@ -1,15 +1,18 @@
 <template>
     <div v-if="canEdit" class="cw-container-actions">
         <studip-action-menu 
-            :items="menuItems" 
+            :items="menuItems"
             @editContainer="editContainer"
             @deleteContainer="deleteContainer"
             @sortBlocks="sortBlocks"
+            @removeLock="removeLock"
         />
     </div>
 </template>
 
 <script>
+import { mapGetters } from 'vuex';
+
 export default {
     name: 'courseware-container-actions',
     props: {
@@ -17,19 +20,45 @@ export default {
         container: Object,
     },
     computed: {
+        ...mapGetters({
+            userId: 'userId',
+            userIsTeacher: 'userIsTeacher',
+        }),
+        blocked() {
+            return this.container?.relationships?.['edit-blocker']?.data !== null;
+        },
+        blockerId() {
+            return this.blocked ? this.container?.relationships?.['edit-blocker']?.data?.id : null;
+        },
+        blockedByThisUser() {
+            return this.blocked && this.userId === this.blockerId;
+        },
+        blockedByAnotherUser() {
+            return this.blocked && this.userId !== this.blockerId;
+        },
         menuItems() {
-            if (this.container.attributes["container-type"] === 'list') {
-                return [
-                    { id: 1, label: this.$gettext('Blöcke sortieren'), icon: 'arr_1sort', emit: 'sortBlocks' },
-                    { id: 2, label: this.$gettext('Abschnitt löschen'), icon: 'trash', emit: 'deleteContainer' }
-                ];
-            } else {
-                return [
-                    { id: 1, label: this.$gettext('Abschnitt bearbeiten'), icon: 'edit', emit: 'editContainer' },
-                    { id: 2, label: this.$gettext('Blöcke sortieren'), icon: 'arr_1sort', emit: 'sortBlocks' },
-                    { id: 3, label: this.$gettext('Abschnitt löschen'), icon: 'trash', emit: 'deleteContainer' },
-                ];
+            let menuItems = [];
+            if (!this.blockedByAnotherUser) {
+                if (this.container.attributes["container-type"] !== 'list') {
+                    menuItems.push({ id: 1, label: this.$gettext('Abschnitt bearbeiten'), icon: 'edit', emit: 'editContainer' });
+                }
+                menuItems.push({ id: 2, label: this.$gettext('Blöcke sortieren'), icon: 'arr_1sort', emit: 'sortBlocks' });
+                menuItems.push({ id: 3, label: this.$gettext('Abschnitt löschen'), icon: 'trash', emit: 'deleteContainer' });
             }
+
+            if (this.blocked && this.blockedByAnotherUser && this.userIsTeacher) {
+                menuItems.push({
+                    id: 4,
+                    label: this.$gettext('Sperre aufheben'),
+                    icon: 'lock-unlocked',
+                    emit: 'removeLock',
+                });
+            }
+
+            menuItems.sort((a, b) => {
+                return a.id > b.id ? 1 : b.id > a.id ? -1 : 0;
+            });
+            return menuItems;
         },
     },
     methods: {
@@ -44,6 +73,9 @@ export default {
         },
         sortBlocks() {
             this.$emit('sortBlocks');
+        },
+        removeLock() {
+            this.$emit('removeLock');
         }
     },
 };
diff --git a/resources/vue/components/courseware/CoursewareDateBlock.vue b/resources/vue/components/courseware/CoursewareDateBlock.vue
index da119891f81464a56f8cd175655e94679acd8765..49a1aea523c29a94b77d40db7b3b5b133a85b13d 100755
--- a/resources/vue/components/courseware/CoursewareDateBlock.vue
+++ b/resources/vue/components/courseware/CoursewareDateBlock.vue
@@ -5,8 +5,9 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <div v-if="currentStyle === 'countdown'" class="cw-date-countdown">
@@ -69,7 +70,7 @@
                     </label>
                     <label>
                         <translate>Layout</translate>
-                        <select v-model="currentStyle">
+                        <select v-model="currentStyle" @change="computeTimestamp">
                             <option value="countdown"><translate>Countdown</translate></option>
                             <option value="date"><translate>Datum</translate></option>
                         </select>
@@ -97,6 +98,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentTitle: '',
             currentTimestamp: 0,
             currentStyle: '',
@@ -138,20 +140,29 @@ export default {
         initCurrentData() {
             this.currentTitle = this.title;
             this.currentTimestamp = this.timestamp;
+            this.setCurrentDate();
+            this.setCurrentDeDate();
+            this.currentTime = ('0' + this.date.getHours()).slice(-2) + ':' + ('0' + this.date.getMinutes()).slice(-2);
+            this.currentStyle = this.style;
+        },
+        setCurrentDate() {
             this.currentDate =
                 this.date.getFullYear() +
                 '-' +
                 ('0' + (this.date.getMonth() + 1)).slice(-2) +
                 '-' +
                 ('0' + this.date.getDate()).slice(-2);
+        },
+        setCurrentDeDate() {
             this.currentDeDate =
                 ('0' + this.date.getDate()).slice(-2) +
                 '.' +
                 ('0' + (this.date.getMonth() + 1)).slice(-2) +
                 '.' +
                 this.date.getFullYear();
-            this.currentTime = ('0' + this.date.getHours()).slice(-2) + ':' + ('0' + this.date.getMinutes()).slice(-2);
-            this.currentStyle = this.style;
+        },
+        setShowEdit(state) {
+            this.showEdit = state;
         },
         countdown() {
             let view = this;
@@ -171,6 +182,11 @@ export default {
         },
         computeTimestamp() {
             this.currentTimestamp = new Date(this.currentDate + ' ' + this.currentTime).getTime();
+            this.setCurrentDate();
+            this.setCurrentDeDate();
+            if (this.currentStyle === 'countdown') {
+                this.countdown();
+            }
         },
         storeBlock() {
             let cmpInfo = false;
@@ -196,9 +212,24 @@ export default {
                     containerId: this.block.relationships.container.data.id,
                 });
             }
-
-
         },
     },
+    watch: {
+        title() {
+            if (!this.showEdit) {
+                this.currentTitle = this.title;
+            }
+        },
+        timestamp() {
+            if (!this.showEdit) {
+                this.initCurrentData();
+            }
+        },
+        style() {
+            if (!this.showEdit) {
+                this.currentStyle = this.style;
+            }
+        },
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareDefaultBlock.vue b/resources/vue/components/courseware/CoursewareDefaultBlock.vue
index 458739901c61ef5c76654c3495f21bc086ba8710..123643aea14bd68faa9210ee9138fc487cf7f7c6 100755
--- a/resources/vue/components/courseware/CoursewareDefaultBlock.vue
+++ b/resources/vue/components/courseware/CoursewareDefaultBlock.vue
@@ -3,12 +3,14 @@
         <div class="cw-content-wrapper" :class="[showEditMode ? 'cw-content-wrapper-active' : '']">
             <header v-if="showEditMode" class="cw-block-header">
                 <span class="cw-sortable-handle"></span>
-                <span v-if="!block.attributes.visible" class="cw-default-block-invisible-info">
-                    <studip-icon shape="visibility-invisible" />
-                </span>
+                <studip-icon v-if="!block.attributes.visible" shape="visibility-invisible" />
+                <studip-icon v-if="blockedByAnotherUser" shape="lock-locked" />
                 <span>{{ blockTitle }}</span>
+                <span v-if="blockedByAnotherUser" class="cw-default-block-blocker-warning">
+                    | {{ $gettextInterpolate('wird im Moment von %{ userName } bearbeitet', { userName: this.blockingUserName }) }}
+                </span>
                 <span v-if="!block.attributes.visible" class="cw-default-block-invisible-info">
-                    (<translate>unsichtbar für Nutzende ohne Schreibrecht</translate>)
+                    | {{ $gettext('unsichtbar für Nutzende ohne Schreibrecht') }}
                 </span>
                 <courseware-block-actions
                     :block="block"
@@ -18,6 +20,7 @@
                     @showInfo="displayFeature('Info')"
                     @showExportOptions="displayFeature('ExportOptions')"
                     @deleteBlock="displayDeleteDialog()"
+                    @removeLock="displayRemoveLockDialog()"
                 />
             </header>
             <div v-if="showContent" class="cw-block-content">
@@ -61,6 +64,15 @@
             @confirm="executeDelete"
             @close="showDeleteDialog = false"
         ></studip-dialog>
+        <studip-dialog
+            v-if="showRemoveLockDialog"
+            :title="textRemoveLockTitle"
+            :question="textRemoveLockAlert"
+            height="200"
+            width="450"
+            @confirm="executeRemoveLock"
+            @close="showRemoveLockDialog = false"
+        ></studip-dialog>
     </div>
 </template>
 
@@ -118,15 +130,19 @@ export default {
             showContent: true,
             showEditModeShortcut: false,
             showDeleteDialog: false,
+            showRemoveLockDialog: false,
             currentComments: [],
             textDeleteTitle: this.$gettext('Block unwiderruflich löschen'),
             textDeleteAlert: this.$gettext('Möchten Sie diesen Block wirklich löschen?'),
+            textRemoveLockTitle: this.$gettext('Sperre aufheben'),
+            textRemoveLockAlert: this.$gettext('Möchten Sie die Sperre dieses Block wirklich aufheben? Der Bearbeitungsstand geht dabei unwiderruflich verloren.'),
         };
     },
     computed: {
         ...mapGetters({
             blockTypes: 'blockTypes',
             userId: 'userId',
+            userById: 'users/byId',
             viewMode: 'viewMode',
             containerById: 'courseware-containers/byId',
         }),
@@ -141,10 +157,10 @@ export default {
             return this.viewMode === 'discuss';
         },
         blocked() {
-            return this.block?.relationships['edit-blocker'].data !== null;
+            return this.block?.relationships?.['edit-blocker']?.data !== null;
         },
         blockerId() {
-            return this.blocked ? this.block?.relationships['edit-blocker'].data?.id : null;
+            return this.blocked ? this.block?.relationships?.['edit-blocker']?.data?.id : null;
         },
         blockedByThisUser() {
             return this.blocked && this.userId === this.blockerId;
@@ -152,6 +168,20 @@ export default {
         blockedByAnotherUser() {
             return this.blocked && this.userId !== this.blockerId;
         },
+        blockingUser() {
+            if (this.blockedByAnotherUser) {
+                const user = this.$store.getters["users/related"]({
+                    parent: { type: this.block.type, id: this.block.id },
+                    relationship: "edit-blocker"
+                });
+                return user ? user : null;
+            }
+
+            return null;
+        },
+        blockingUserName() {
+            return this.blockingUser ? this.blockingUser.attributes['formatted-name'] : '';
+        },
         blockTitle() {
             const type = this.block.attributes['block-type'];
 
@@ -163,6 +193,9 @@ export default {
             if (this.blockedByThisUser) {
                 this.displayFeature('Edit');
             }
+            if (this.blockedByAnotherUser) {
+                this.loadUserById({ id: this.blockerId });
+            }
         }
         if (this.userProgress && this.userProgress.attributes.grade === 0 && this.defaultGrade) {
             this.userProgress = 1;
@@ -176,6 +209,7 @@ export default {
             unlockObject: 'unlockObject',
             loadContainer: 'loadContainer',
             updateContainer: 'updateContainer',
+            loadUserById: 'users/loadById'
         }),
         async displayFeature(element) {
             if (this.showEdit && element === 'Edit') {
@@ -273,6 +307,18 @@ export default {
                 containerId: containerId,
             });
         },
+        displayRemoveLockDialog() {
+            this.showRemoveLockDialog = true;
+        },
+        executeRemoveLock() {
+            this.unlockObject({ id: this.block.id , type: 'courseware-blocks' });
+            this.showRemoveLockDialog = false;
+        }
     },
+    watch: {
+        showEdit(state) {
+            this.$emit('showEdit', state);
+        }
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareDefaultContainer.vue b/resources/vue/components/courseware/CoursewareDefaultContainer.vue
index a24e9a8bd510d76e96111b4765450eec0046eca8..774cc7f46a07f6177724f270c7e2b62a56c85f4b 100755
--- a/resources/vue/components/courseware/CoursewareDefaultContainer.vue
+++ b/resources/vue/components/courseware/CoursewareDefaultContainer.vue
@@ -5,13 +5,18 @@
     >
         <div class="cw-container-content">
             <header v-if="showEditMode && canEdit" class="cw-container-header">
+                <studip-icon v-if="blockedByAnotherUser" shape="lock-locked" />
                 <span>{{ container.attributes.title }} ({{container.attributes.width}})</span>
+                <span v-if="blockedByAnotherUser" class="cw-default-container-blocker-warning">
+                    | {{ $gettextInterpolate('wird im Moment von %{ userName } bearbeitet', { userName: this.blockingUserName }) }}
+                </span>
                 <courseware-container-actions
                     :canEdit="canEdit"
                     :container="container"
                     @editContainer="displayEditDialog"
                     @deleteContainer="displayDeleteDialog"
                     @sortBlocks="sortBlocks"
+                    @removeLock="displayRemoveLockDialog()"
                 />
             </header>
             <div class="cw-block-wrapper" :class="{ 'cw-block-wrapper-active': showEditMode }">
@@ -44,6 +49,16 @@
                 @confirm="executeDelete"
                 @close="closeDeleteDialog"
             ></studip-dialog>
+
+            <studip-dialog
+                v-if="showRemoveLockDialog"
+                :title="textRemoveLockTitle"
+                :question="textRemoveLockAlert"
+                height="200"
+                width="450"
+                @confirm="executeRemoveLock"
+                @close="showRemoveLockDialog = false"
+            ></studip-dialog>
         </div>
     </div>
 </template>
@@ -69,11 +84,14 @@ export default {
         return {
             showDeleteDialog: false,
             showEditDialog: false,
+            showRemoveLockDialog: false,
             textEditConfirm: this.$gettext('Speichern'),
             textEditClose: this.$gettext('Schließen'),
             textEditTitle: this.$gettext('Abschnitt bearbeiten'),
             textDeleteTitle: this.$gettext('Abschnitt unwiderruflich löschen'),
             textDeleteAlert: this.$gettext('Möchten Sie diesen Abschnitt wirklich löschen?'),
+            textRemoveLockTitle: this.$gettext('Sperre aufheben'),
+            textRemoveLockAlert: this.$gettext('Möchten Sie die Sperre dieses Block wirklich aufheben? Der Bearbeitungsstand geht dabei unwiderruflich verloren.'),
         };
     },
     computed: {
@@ -87,10 +105,10 @@ export default {
             return this.container.attributes.payload.colspan ? this.container.attributes.payload.colspan : 'full';
         },
         blocked() {
-            return this.container?.relationships['edit-blocker'].data !== null;
+            return this.container?.relationships?.['edit-blocker']?.data !== null;
         },
         blockerId() {
-            return this.blocked ? this.container?.relationships['edit-blocker'].data?.id : null;
+            return this.blocked ? this.container?.relationships?.['edit-blocker']?.data?.id : null;
         },
         blockedByThisUser() {
             return this.blocked && this.userId === this.blockerId;
@@ -98,6 +116,20 @@ export default {
         blockedByAnotherUser() {
             return this.blocked && this.userId !== this.blockerId;
         },
+        blockingUser() {
+            if (this.blockedByAnotherUser) {
+                const user = this.$store.getters["users/related"]({
+                    parent: { type: this.container.type, id: this.container.id },
+                    relationship: "edit-blocker"
+                });
+                return user ? user : null;
+            }
+
+            return null;
+        },
+        blockingUserName() {
+            return this.blockingUser ? this.blockingUser.attributes['formatted-name'] : '';
+        },
     },
     methods: {
         ...mapActions({
@@ -172,7 +204,25 @@ export default {
                 return false;
             }
             this.$emit('sortBlocks');
-        }
+        },
+        displayRemoveLockDialog() {
+            this.showRemoveLockDialog = true;
+        },
+        executeRemoveLock() {
+            this.unlockObject({ id: this.container.id , type: 'courseware-containers' });
+            this.showRemoveLockDialog = false;
+        },
     },
+    watch: {
+        showEditDialog(state) {
+            this.$emit('showEdit', state);
+        },
+        blockedByThisUser(newState, oldState) {
+            if (oldState && !newState) {
+                this.showDeleteDialog = false;
+                this.showEditDialog = false;
+            }
+        }
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareDialogCardsBlock.vue b/resources/vue/components/courseware/CoursewareDialogCardsBlock.vue
index 2256795d4ca461bb89bdeb1e0602f4f99d32816e..5c013d93d0d94ab8f44350cc3c0d8a0bea368eb3 100755
--- a/resources/vue/components/courseware/CoursewareDialogCardsBlock.vue
+++ b/resources/vue/components/courseware/CoursewareDialogCardsBlock.vue
@@ -5,8 +5,9 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <div class="cw-block-dialog-cards-content">
@@ -134,6 +135,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentCards: [],
         };
     },
@@ -168,10 +170,13 @@ export default {
         }),
         initCurrentData() {
             if (this.cards !== '') {
-                this.currentCards = JSON.parse(JSON.stringify(this.cards));
+                this.currentCards = this.cards;
             }
             this.activateCard(0);
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         storeBlock() {
             let cards = JSON.parse(JSON.stringify(this.currentCards));
             // don't store the file object
@@ -261,6 +266,21 @@ export default {
                 }
             });
         },
+        cardsEqual(a1, a2) {
+            return a1.length === a2.length && a1.every((o, idx) => {
+                return  o.back_file_id === a2[idx].back_file_id &&
+                        o.back_text === a2[idx].back_text &&
+                        o.front_file_id === a2[idx].front_file_id &&
+                        o.front_text === a2[idx].front_text;
+            });
+        }
+    },
+    watch: {
+        cards() {
+            if (!this.showEdit && !this.cardsEqual(this.currentCards, this.cards)) {
+                this.initCurrentData();
+            }
+        },
     },
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareDocumentBlock.vue b/resources/vue/components/courseware/CoursewareDocumentBlock.vue
index 134e167ca45527d746aa626d46807f727103d2ec..f2d243dd3a4510bb0a1077bf67b32a1aba9e2745 100755
--- a/resources/vue/components/courseware/CoursewareDocumentBlock.vue
+++ b/resources/vue/components/courseware/CoursewareDocumentBlock.vue
@@ -5,8 +5,9 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="false"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <div v-if="hasFile" class="cw-pdf-header cw-block-title">
@@ -87,6 +88,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentTitle: '',
             currentFileId: '',
             currentFile: {},
@@ -123,29 +125,16 @@ export default {
         currentUrl() {
             if (this.currentFile?.meta) {
                 return this.currentFile.meta['download-url'];
-            } else {
-                return '';
             }
+            if (this.currentFile?.['download_url']) {
+                return this.currentFile['download_url'];
+            }
+            return '';
         },
         hasFile() {
             return this.currentFileId !== '';
         }
     },
-    watch: {
-        browseDirection: function (val) {
-            if (val.length > 6) {
-                this.evaluateBrowseAction();
-            }
-        },
-    },
-    mounted() {
-        this.loadFileRefs(this.block.id).then((response) => {
-            this.file = response[0];
-            this.currentFile = this.file;
-            this.loadPdfViewer();
-        });
-        this.initCurrentData();
-    },
     methods: {
         ...mapActions({
             updateBlock: 'updateBlockInContainer',
@@ -158,6 +147,9 @@ export default {
             this.currentFileId = this.fileId;
             this.currentDocType = this.docType;
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         updateCurrentFile(file) {
             this.currentFile = file;
             this.currentFileId = file.id;
@@ -256,7 +248,44 @@ export default {
                     containerId: this.block.relationships.container.data.id,
                 });
             }
-
+        },
+        loadDocument() {
+            this.loadFileRefs(this.block.id).then((response) => {
+                this.file = response[0];
+                this.currentFile = this.file;
+                this.loadPdfViewer();
+            });
+        }
+    },
+    mounted() {
+        this.loadDocument();
+        this.initCurrentData();
+    },
+    watch: {
+        browseDirection: function (val) {
+            if (val.length > 6) {
+                this.evaluateBrowseAction();
+            }
+        },
+        title() {
+            if (!this.showEdit) {
+                this.currentTitle = this.title;
+            }
+        },
+        downloadable() {
+            if (!this.showEdit) {
+                this.currentDownloadable = this.downloadable;
+            }
+        },
+        fileId() {
+            if (!this.showEdit) {
+                this.currentFileId = this.fileId;
+            }
+        },
+        title() {
+            if (!this.showEdit) {
+                this.currentDocType = this.docType;
+            }
         },
     },
 };
diff --git a/resources/vue/components/courseware/CoursewareDownloadBlock.vue b/resources/vue/components/courseware/CoursewareDownloadBlock.vue
index 2094cfa7133cb9b63ae69be7cf98da1dfe32c9d5..c9ad453e23545bbe7c406407490375083a1d57c7 100755
--- a/resources/vue/components/courseware/CoursewareDownloadBlock.vue
+++ b/resources/vue/components/courseware/CoursewareDownloadBlock.vue
@@ -6,8 +6,9 @@
             :isTeacher="isTeacher"
             :preview="true"
             :defaultGrade="false"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <div v-if="currentTitle !== ''" class="cw-block-title">{{ currentTitle }}</div>
@@ -88,6 +89,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentTitle: '',
             currentInfo: '',
             currentSuccess: '',
@@ -152,6 +154,9 @@ export default {
                 this.loadFile();
             }
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         async loadFile() {
             const id = `${this.currentFileId}`;
             const options = { include: 'terms-of-use' };
@@ -258,5 +263,35 @@ export default {
             this.userProgress = 1;
         },
     },
+    watch: {
+        title() {
+            if (!this.showEdit) {
+                this.currentTitle = this.title;
+            }
+        },
+        info() {
+            if (!this.showEdit) {
+                this.currentInfo = this.info;
+            }
+        },
+        fileId() {
+            if (!this.showEdit) {
+                this.currentFileId = this.fileId;
+                if (this.currentFileId !== '') {
+                    this.loadFile();
+                }
+            }
+        },
+        success() {
+            if (!this.showEdit) {
+                this.currentSuccess = this.success;
+            }
+        },
+        grade() {
+            if (!this.showEdit) {
+                this.currentGrade = this.grade;
+            }
+        },
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareEmbedBlock.vue b/resources/vue/components/courseware/CoursewareEmbedBlock.vue
index 2808ffa2478ecce82eb5b4b51671b6febcad8cd3..80795bc72effcd266cd92f291749d230d61426aa 100755
--- a/resources/vue/components/courseware/CoursewareEmbedBlock.vue
+++ b/resources/vue/components/courseware/CoursewareEmbedBlock.vue
@@ -5,8 +5,9 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="false"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <div v-if="currentTitle !== ''" class="cw-block-title">{{ currentTitle }}</div>
@@ -26,7 +27,7 @@
                         <img :src="oembedData.fullsize_url" />
                     </div>
                 </div>
-                <div class="cw-block-embed-info" v-if="oembedData !== null">
+                <div class="cw-block-embed-info" v-if="oembedData">
                     <span class="cw-block-embed-title">{{ oembedData.title }}</span>
                     <span class="cw-block-embed-author-name">
                         <translate>erstellt von</translate>
@@ -102,6 +103,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentTitle: '',
             currentSource: '',
             currentUrl: '',
@@ -176,6 +178,9 @@ export default {
                 this.updateTime();
             }
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         addTimeData(data) {
             if (this.currentSource === 'youtube') {
                 if (this.currentStartTime !== '') {
@@ -230,5 +235,41 @@ export default {
             });
         },
     },
+    watch: {
+        title() {
+            if (!this.showEdit) {
+                this.currentTitle = this.title;
+            }
+        },
+        source() {
+            if (!this.showEdit) {
+                this.currentSource = this.source;
+            }
+        },
+        url() {
+            if (!this.showEdit) {
+                this.currentUrl = this.url;
+            }
+        },
+        startTime() {
+            if (!this.showEdit) {
+                this.currentStartTime = this.startTime;
+            }
+        },
+        endTime() {
+            if (!this.showEdit) {
+                this.currentEndTime = this.endTime;
+            }
+        },
+        oembed() {
+            if (!this.showEdit) {
+                this.oembedData = this.oembed;
+                if (this.oembedData !== null) {
+                    this.calcContentHeight();
+                    this.updateTime();
+                }
+            }
+        },
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareEmptyElementBox.vue b/resources/vue/components/courseware/CoursewareEmptyElementBox.vue
index b64413d26c8b7f5db556ab0874622021bd28dd38..8e1ab2fc6d3b60376dfe6efe95d0760a7fcffd8c 100755
--- a/resources/vue/components/courseware/CoursewareEmptyElementBox.vue
+++ b/resources/vue/components/courseware/CoursewareEmptyElementBox.vue
@@ -2,8 +2,8 @@
     <div class="cw-wellcome-screen">
         <courseware-companion-box :msgCompanion="this.$gettext('Es wurden bisher noch keine Inhalte eingepflegt.')">
             <template v-slot:companionActions>
-                <button v-if="canEdit && noContainers" class="button" @click="addContainer"><translate>Einen Abschnitt hinzufügen</translate></button>
-                <button v-if="canEdit && !noContainers && !editMode" class="button" @click="switchToEditView"><translate>Seite bearbeiten</translate></button>
+                <button v-show="canEdit && noContainers" class="button" @click="addContainer"><translate>Einen Abschnitt hinzufügen</translate></button>
+                <button v-show="canEdit && !noContainers && !editMode" class="button" @click="switchToEditView"><translate>Seite bearbeiten</translate></button>
             </template>
         </courseware-companion-box>
     </div>
@@ -48,4 +48,4 @@ export default {
     }
 
 }
-</script>
\ No newline at end of file
+</script>
diff --git a/resources/vue/components/courseware/CoursewareFolderBlock.vue b/resources/vue/components/courseware/CoursewareFolderBlock.vue
index a1b97490d09da6b5c9e9cbed9df1e5e03fac1c21..7f7276d4425b83c00c68081f3dae9b14beb76b8c 100755
--- a/resources/vue/components/courseware/CoursewareFolderBlock.vue
+++ b/resources/vue/components/courseware/CoursewareFolderBlock.vue
@@ -5,8 +5,9 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <div v-if="currentTitle !== ''" class="cw-block-title">{{ currentTitle }}</div>
@@ -64,6 +65,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentTitle: '',
             currentFolderId: '',
             currentFileType: '',
@@ -99,13 +101,21 @@ export default {
             this.currentFolderId = this.folderId;
             this.currentFolderType = this.folderType;
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         async getFolderFiles() {
-            const parent = { type: 'folders', id: `${this.currentFolderId}` };
-            const relationship = 'file-refs';
-            const options = { include: 'terms-of-use' };
-            await this.loadRelatedFileRefs({ parent, relationship, options });
-            const fileRefs = this.relatedFileRefs({ parent, relationship }) ?? [];
-            this.processFiles(fileRefs);
+            if (this.currentFolderId) {
+                const parent = { type: 'folders', id: `${this.currentFolderId}` };
+                const relationship = 'file-refs';
+                const options = { include: 'terms-of-use' };
+                await this.loadRelatedFileRefs({ parent, relationship, options });
+                const fileRefs = this.relatedFileRefs({ parent, relationship }) ?? [];
+                this.processFiles(fileRefs);
+            } else {
+                this.files = [];
+            }
+
         },
         processFiles(files) {
             this.files = files
@@ -189,6 +199,21 @@ export default {
         currentFolderId() {
             this.getFolderFiles();
         },
+        title() {
+            if (!this.showEdit) {
+                this.currentTitle = this.title;
+            }
+        },
+        folderId() {
+            if (!this.showEdit) {
+                this.currentFolderId = this.folderId;
+            }
+        },
+        folderType() {
+            if (!this.showEdit) {
+                this.currentFolderType = this.folderType;
+            }
+        },
     },
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareGalleryBlock.vue b/resources/vue/components/courseware/CoursewareGalleryBlock.vue
index 9d0549b25c9f887f3c44de70246d0491b333e82c..1066e53b32d4d8fc396cccb7874a29032fc2db83 100755
--- a/resources/vue/components/courseware/CoursewareGalleryBlock.vue
+++ b/resources/vue/components/courseware/CoursewareGalleryBlock.vue
@@ -5,8 +5,9 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <div v-if="files.length !== 0" class="cw-block-gallery-content" :style="{ 'max-height': currentHeight + 'px' }">
@@ -99,6 +100,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentFolderId: '',
             currentAutoplay: '',
             currentNav: '',
@@ -150,6 +152,9 @@ export default {
             this.currentHeight = this.height;
             this.currentShowFileNames = this.showFileNames;
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         startGallery() {
             this.slideIndex = 0;
             this.showSlides(0);
@@ -254,6 +259,38 @@ export default {
                 this.currentAutoplayTimer = '2';
             }
         },
+        folderId() {
+            if (!this.showEdit) {
+                this.currentFolderId = this.folderId;
+            }
+        },
+        autoplay() {
+            if (!this.showEdit) {
+                this.currentAutoplay = this.autoplay;
+                this.startGallery();
+            }
+        },
+        autoplayTimer() {
+            if (!this.showEdit) {
+                this.currentAutoplayTimer = this.autoplayTimer;
+                this.startGallery();
+            }
+        },
+        nav() {
+            if (!this.showEdit) {
+                this.currentNav = this.nav;
+            }
+        },
+        height() {
+            if (!this.showEdit) {
+                this.currentHeight = this.height;
+            }
+        },
+        showFileNames() {
+            if (!this.showEdit) {
+                this.currentShowFileNames = this.showFileNames;
+            }
+        },
     },
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareHeadlineBlock.vue b/resources/vue/components/courseware/CoursewareHeadlineBlock.vue
index 9cc3e5557fc46578224a0caab59e3f0cb62a3fb9..ae95b4061da0d9cb5ab32cbbdde356ba14ec3095 100755
--- a/resources/vue/components/courseware/CoursewareHeadlineBlock.vue
+++ b/resources/vue/components/courseware/CoursewareHeadlineBlock.vue
@@ -5,8 +5,9 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeText"
-            @closeEdit="closeEdit"
+            @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <div
@@ -182,6 +183,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentTitle: '',
             currentSubtitle: '',
             currentStyle: '',
@@ -320,6 +322,9 @@ export default {
                 this.loadFile();
             }
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         async loadFile() {
             const id = this.currentBackgroundImageId;
             const options = { include: 'terms-of-use' };
@@ -342,10 +347,7 @@ export default {
             this.currentBackgroundImageId = file.id;
             this.currentBackgroundURL = file.download_url;
         },
-        closeEdit() {
-            this.initCurrentData();
-        },
-        storeText() {
+        storeBlock() {
             let attributes = {};
             attributes.payload = {};
             attributes.payload.title = this.currentTitle;
@@ -407,5 +409,60 @@ export default {
             return hex.length === 1 ? '0' + hex : hex;
         },
     },
+    watch: {
+        title() {
+            if (!this.showEdit) {
+                this.currentTitle = this.title;
+            }
+        },
+        subtitle() {
+            if (!this.showEdit) {
+                this.currentSubtitle = this.subtitle;
+            }
+        },
+        style() {
+            if (!this.showEdit) {
+                this.currentStyle = this.style;
+            }
+        },
+        height() {
+            if (!this.showEdit) {
+                this.currentHeight = this.height;
+            }
+        },
+        backgroundColor() {
+            if (!this.showEdit) {
+                this.currentBackgroundColor = this.backgroundColor;
+            }
+        },
+        textColor() {
+            if (!this.showEdit) {
+                this.currentTextColor = this.textColor;
+            }
+        },
+        icon() {
+            if (!this.showEdit) {
+                this.currentIcon = this.icon;
+            }
+        },
+        iconColor() {
+            if (!this.showEdit) {
+                this.currentIconColor = this.iconColor;
+            }
+        },
+        backgroundType() {
+            if (!this.showEdit) {
+                this.currentBackgroundType = this.backgroundType;
+            }
+        },
+        backgroundImageId() {
+            if (!this.showEdit) {
+                this.currentBackgroundImageId = this.backgroundImageId;
+                if (this.currentBackgroundImageId !== '') {
+                    this.loadFile();
+                }
+            }
+        },
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareIframeBlock.vue b/resources/vue/components/courseware/CoursewareIframeBlock.vue
index 1f0f5bf9b3a5e4bca8240bb352860c117c24ee1c..ff9c6475626184809b45205752e24de7ba28d4b7 100755
--- a/resources/vue/components/courseware/CoursewareIframeBlock.vue
+++ b/resources/vue/components/courseware/CoursewareIframeBlock.vue
@@ -5,8 +5,9 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <div v-if="currentTitle !== ''" class="cw-block-title">{{ currentTitle }}</div>
@@ -18,7 +19,7 @@
                     allowfullscreen
                     sandbox="allow-forms allow-popups allow-pointer-lock allow-same-origin allow-scripts"
                 />
-                <div v-if="currentCcInfo" class="cw-block-iframe-cc-data">
+                <div v-if="currentCcInfo !== 'false'" class="cw-block-iframe-cc-data">
                     <span class="cw-block-iframe-cc" :class="['cw-block-iframe-cc-' + currentCcInfo]"></span>
                     <div class="cw-block-iframe-cc-infos">
                         <p v-if="currentCcWork !== ''"><translate>Werk</translate> {{ currentCcWork }}</p>
@@ -120,6 +121,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentTitle: '',
             currentUrl: '',
             currentHeight: '',
@@ -197,6 +199,9 @@ export default {
             this.currentCcBase = this.ccBase;
             this.setProtocol();
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         setProtocol() {
             if (location.protocol === 'https:') {
                 if (!this.currentUrl.includes('https:')) {
@@ -234,5 +239,58 @@ export default {
             });
         },
     },
+    watch: {
+        title() {
+            if (!this.showEdit) {
+                this.currentTitle = this.title;
+            }
+        },
+        url() {
+            if (!this.showEdit) {
+                this.currentUrl = this.url;
+                this.setProtocol();
+            }
+        },
+        height() {
+            if (!this.showEdit) {
+                this.currentHeight = this.height;
+            }
+        },
+        submitUserId() {
+            if (!this.showEdit) {
+                this.currentSubmitUserId = this.submitUserId;
+            }
+        },
+        submitParam() {
+            if (!this.showEdit) {
+                this.currentSubmitParam = this.submitParam;
+            }
+        },
+        salt() {
+            if (!this.showEdit) {
+                this.currentSalt = this.salt;
+            }
+        },
+        ccInfo() {
+            if (!this.showEdit) {
+                this.currentCcInfo = this.ccInfo;
+            }
+        },
+        ccWork() {
+            if (!this.showEdit) {
+                this.currentCcWork = this.ccWork;
+            }
+        },
+        ccAuthor() {
+            if (!this.showEdit) {
+                this.currentCcAuthor = this.ccAuthor;
+            }
+        },
+        ccBase() {
+            if (!this.showEdit) {
+                this.currentCcBase = this.ccBase;
+            }
+        },
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareImageMapBlock.vue b/resources/vue/components/courseware/CoursewareImageMapBlock.vue
index 9ba60d662c1137e45b00033f15c9ebba8590b5f6..df16aceba3037b0d7d09bd86e0ec00fadc5717f4 100755
--- a/resources/vue/components/courseware/CoursewareImageMapBlock.vue
+++ b/resources/vue/components/courseware/CoursewareImageMapBlock.vue
@@ -5,11 +5,12 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
-                <img :src="currentUrl" class="cw-image-map-original-img" ref="original_img" @load="buildCanvas" />
+                <img v-if="currentUrl" :src="currentUrl" class="cw-image-map-original-img" ref="original_img" @load="buildCanvas" />
                 <canvas class="cw-image-map-canvas" ref="canvas"></canvas>
                 <img
                     class="cw-image-from-canvas"
@@ -178,6 +179,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentFileId: '',
             currentFile: {},
             currentShapes: {},
@@ -215,11 +217,11 @@ export default {
             return this.block?.attributes?.payload?.shapes;
         },
         currentUrl() {
-            if (this.currentFile.download_url !== 'undefined') {
+            if (this.currentFile.download_url) {
                 return this.currentFile.download_url;
-            } else {
-                return '';
             }
+
+            return '';
         },
     },
     mounted() {
@@ -236,10 +238,17 @@ export default {
             await this.loadFile();
             this.buildCanvas();
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         async loadFile() {
             const id = this.currentFileId;
-            await this.loadFileRef({ id });
-            const fileRef = this.fileRefById({ id });
+            let fileRef = null;
+
+            if (id) {
+                await this.loadFileRef({ id });
+                fileRef = this.fileRefById({ id });
+            }
 
             if (fileRef) {
                 this.updateCurrentFile({
@@ -271,16 +280,18 @@ export default {
         },
 
         buildCanvas() {
-            let canvas = this.$refs.canvas;
-            let original_img = this.$refs.original_img;
-            canvas.width = 1085;
-            if (original_img.height > 0) {
-                canvas.height = Math.round((canvas.width / original_img.width) * original_img.height);
-            } else {
-                canvas.height = 484;
+            if (this.currentUrl) {
+                let canvas = this.$refs.canvas;
+                let original_img = this.$refs.original_img;
+                canvas.width = 1085;
+                if (original_img.height > 0) {
+                    canvas.height = Math.round((canvas.width / original_img.width) * original_img.height);
+                } else {
+                    canvas.height = 484;
+                }
+                this.context = canvas.getContext('2d');
+                this.drawScreen();
             }
-            this.context = canvas.getContext('2d');
-            this.drawScreen();
         },
         drawScreen() {
             let context = this.context;
@@ -519,5 +530,17 @@ export default {
             this.currentShapes[index].target_external = url;
         },
     },
+    watch: {
+        fileId() {
+            if (!this.showEdit) {
+                this.initCurrentData();
+            }
+        },
+        shapes() {
+            if (!this.showEdit) {
+                this.initCurrentData();
+            }
+        }
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareKeyPointBlock.vue b/resources/vue/components/courseware/CoursewareKeyPointBlock.vue
index 39124e548b9d1e4b6de11ac93d738d9c550157f5..fab09e2f42df78bc5fb8099e4761e9e71bd3d2d7 100755
--- a/resources/vue/components/courseware/CoursewareKeyPointBlock.vue
+++ b/resources/vue/components/courseware/CoursewareKeyPointBlock.vue
@@ -5,8 +5,10 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeBlock"
             @closeEdit="closeEdit"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
+            
         >
             <template #content>
                 <div class="cw-keypoint-content" :class="['cw-keypoint-' + currentColor]">
@@ -94,6 +96,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentText: '',
             currentColor: '',
             currentIcon: '',
@@ -181,6 +184,9 @@ export default {
             this.currentColor = this.color;
             this.currentIcon = this.icon;
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         storeBlock() {
             let attributes = {};
             attributes.payload = {};
@@ -201,5 +207,22 @@ export default {
     mounted() {
         this.initCurrentData();
     },
+    watch: {
+        text() {
+            if (!this.showEdit) {
+                this.currentText = this.text;
+            }
+        },
+        color() {
+            if (!this.showEdit) {
+                this.currentColor = this.color;
+            }
+        },
+        icon() {
+            if (!this.showEdit) {
+                this.currentIcon = this.icon;
+            }
+        },
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareLinkBlock.vue b/resources/vue/components/courseware/CoursewareLinkBlock.vue
index a2fce7d0045edb8cfca864b155fd5100eed2f3ab..270660eea10bfe59e8ad52b78db89f4544ff439e 100755
--- a/resources/vue/components/courseware/CoursewareLinkBlock.vue
+++ b/resources/vue/components/courseware/CoursewareLinkBlock.vue
@@ -5,8 +5,9 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <div v-if="currentType === 'external'">
@@ -76,6 +77,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentType: '',
             currentTarget: '',
             currentUrl: '',
@@ -114,6 +116,9 @@ export default {
             this.currentTitle = this.title;
             this.fixUrl();
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         fixUrl() {
             if (
                 this.currentUrl.indexOf('http://') !== 0 &&
@@ -145,5 +150,27 @@ export default {
 
         },
     },
+    watch: {
+        type() {
+            if (!this.showEdit) {
+                this.currentType = this.type;
+            }
+        },
+        target() {
+            if (!this.showEdit) {
+                this.currentTarget = this.target;
+            }
+        },
+        url() {
+            if (!this.showEdit) {
+                this.currentUrl = this.url;
+            }
+        },
+        title() {
+            if (!this.showEdit) {
+                this.currentTitle = this.title;
+            }
+        },
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareStructuralElement.vue b/resources/vue/components/courseware/CoursewareStructuralElement.vue
index 313e6a586ac5ffa87107f31c58a2567aa287f2e4..e1bfd938cad0e9a41deb1b43d5147c6313997a0c 100755
--- a/resources/vue/components/courseware/CoursewareStructuralElement.vue
+++ b/resources/vue/components/courseware/CoursewareStructuralElement.vue
@@ -720,16 +720,17 @@ export default {
             }
         },
         containers() {
-            if (!this.structuralElement) {
-                return [];
+            let containers = [];
+            let relatedContainers = this.structuralElement?.relationships?.containers?.data;
+
+            if (relatedContainers) {
+                for (const container of relatedContainers) {
+                    containers.push(this.containerById({ id: container.id}));
+                }
             }
 
-            return (
-                this.relatedContainers({
-                    parent: this.structuralElement,
-                    relationship: 'containers',
-                }) ?? []
-            );
+            return containers;
+
         },
         noContainers() {
             if (this.containers === null) {
@@ -960,10 +961,10 @@ export default {
             return '';
         },
         blocked() {
-            return this.structuralElement?.relationships['edit-blocker'].data !== null;
+            return this.structuralElement?.relationships?.['edit-blocker']?.data !== null;
         },
         blockerId() {
-            return this.blocked ? this.structuralElement?.relationships['edit-blocker'].data?.id : null;
+            return this.blocked ? this.structuralElement?.relationships?.['edit-blocker']?.data?.id : null;
         },
         blockedByThisUser() {
             return this.blocked && this.userId === this.blockerId;
diff --git a/resources/vue/components/courseware/CoursewareTableOfContentsBlock.vue b/resources/vue/components/courseware/CoursewareTableOfContentsBlock.vue
index 2b2e0b8e579d59d617c11cea6a7be443f18bbd89..a3e590c98a6d81ada255b0aea6b04497465cb6c2 100755
--- a/resources/vue/components/courseware/CoursewareTableOfContentsBlock.vue
+++ b/resources/vue/components/courseware/CoursewareTableOfContentsBlock.vue
@@ -5,8 +5,9 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeText"
-            @closeEdit="closeEdit"
+            @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <div v-if="currentStyle !== 'tiles' && currentTitle !== ''" class="cw-block-title">{{ currentTitle }}</div>
@@ -95,6 +96,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentTitle: '',
             currentStyle: '',
         };
@@ -128,10 +130,10 @@ export default {
             this.currentTitle = this.title;
             this.currentStyle = this.style;
         },
-        closeEdit() {
-            this.initCurrentData();
+        setShowEdit(state) {
+            this.showEdit = state;
         },
-        storeText() {
+        storeBlock() {
             let attributes = {};
             attributes.payload = {};
             attributes.payload.title = this.currentTitle;
@@ -159,5 +161,17 @@ export default {
             return child.relationships?.image?.data !== null;
         },
     },
+    watch: {
+        title() {
+            if (!this.showEdit) {
+                this.currentTitle = this.title;
+            }
+        },
+        style() {
+            if (!this.showEdit) {
+                this.currentStyle = this.style;
+            }
+        },
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareTabsContainer.vue b/resources/vue/components/courseware/CoursewareTabsContainer.vue
index 747b24a5930127c6148782093d80a9f7db27ab87..6615b0f69b9a830da0e70a1d073cc6ebe0efd4b7 100755
--- a/resources/vue/components/courseware/CoursewareTabsContainer.vue
+++ b/resources/vue/components/courseware/CoursewareTabsContainer.vue
@@ -4,9 +4,10 @@
         containerClass="cw-container-tabs"
         :canEdit="canEdit"
         :isTeacher="isTeacher"
-        @storeContainer="storeContainer"
         @closeEdit="initCurrentData"
+        @showEdit="setShowEdit"
         @sortBlocks="enableSort"
+        @storeContainer="storeContainer"
     >
         <template v-slot:containerContent>
             <courseware-tabs v-if="!sortMode">
@@ -129,6 +130,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentContainer: null,
             currentSections: [],
             textDeleteSection: this.$gettext('Sektion entfernen'),
@@ -181,6 +183,9 @@ export default {
 
             this.currentSections = sections;
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         addSection() {
             this.currentContainer.attributes.payload.sections.push({ name: '', icon: '', blocks: [] });
         },
@@ -243,7 +248,9 @@ export default {
     },
     watch: {
         blocks() {
-            this.initCurrentData();
+            if (!this.showEdit) {
+                this.initCurrentData();
+            }
         }
     }
 };
diff --git a/resources/vue/components/courseware/CoursewareTypewriterBlock.vue b/resources/vue/components/courseware/CoursewareTypewriterBlock.vue
index abdc8ebe368380db8955c1562f8543003ab25aef..5d131a280cc6a3abb8d9c3417e072ec0d6210c80 100755
--- a/resources/vue/components/courseware/CoursewareTypewriterBlock.vue
+++ b/resources/vue/components/courseware/CoursewareTypewriterBlock.vue
@@ -5,11 +5,12 @@
         :canEdit="canEdit"
         :isTeacher="isTeacher"
         :preview="true"
-        @storeEdit="storeText"
-        @closeEdit="closeEdit"
+        @closeEdit="initCurrentData"
+        @showEdit="setShowEdit"
+        @storeEdit="storeBlock"
         >
             <template #content>
-                <div class="cw-typewriter-content">
+                <div v-if="currentText !== ''" class="cw-typewriter-content">
                     <vue-typer
                         :text="currentText"
                         initial-action="typing"
@@ -83,8 +84,8 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             speeds: [200, 100, 50, 25],
-            typing: false,
             speedClasses: [
                 'cw-typewriter-letter-fadein-slow',
                 'cw-typewriter-letter-fadein-normal',
@@ -127,6 +128,9 @@ export default {
             this.currentFont = this.font;
             this.currentSize = this.size;
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         restartTyping() {
             let text = this.currentText;
             this.currentText = ' ';
@@ -134,10 +138,7 @@ export default {
                 this.currentText = text;
             });
         },
-        closeEdit() {
-            this.initCurrentData();
-        },
-        storeText() {
+        storeBlock() {
             let attributes = {};
             attributes.payload = {};
             attributes.payload.text = this.currentText;
@@ -152,5 +153,28 @@ export default {
             });
         }
     },
+    watch: {
+        text() {
+            if (!this.showEdit) {
+                this.currentText = this.text;
+            }
+        },
+        speed() {
+            if (!this.showEdit) {
+                this.currentSpeed = this.speed;
+                this.restartTyping();
+            }
+        },
+        font() {
+            if (!this.showEdit) {
+                this.currentFont = this.font;
+            }
+        },
+        size() {
+            if (!this.showEdit) {
+                this.currentSize = this.size;
+            }
+        },
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareVideoBlock.vue b/resources/vue/components/courseware/CoursewareVideoBlock.vue
index e5e31fcab435ae82a5997fb65e58e9a5c7ecfb5c..ee607e047dc8af7e1af03cd1fbb793a656d15c01 100755
--- a/resources/vue/components/courseware/CoursewareVideoBlock.vue
+++ b/resources/vue/components/courseware/CoursewareVideoBlock.vue
@@ -5,11 +5,13 @@
             :canEdit="canEdit"
             :isTeacher="isTeacher"
             :preview="true"
-            @storeEdit="storeBlock"
             @closeEdit="initCurrentData"
+            @showEdit="setShowEdit"
+            @storeEdit="storeBlock"
         >
             <template #content>
                 <div v-if="currentTitle !== '' && currentURL" class="cw-block-title">{{ currentTitle }}</div>
+                <div v-if="!currentURL" class="cw-block-title">{{ currentTitle ? currentTitle : $gettext('Video') }}</div>
                 <video
                     v-show="currentURL"
                     :src="currentURL"
@@ -18,6 +20,9 @@
                     :autoplay="currentAutoplay === 'enabled'"
                     @contextmenu="contextHandler"
                 />
+                <div v-if="!currentURL" class="cw-file-empty">
+                    <p><translate>Es ist keine Video-Datei verfügbar</translate></p>
+                </div>
             </template>
             <template v-if="canEdit" #edit>
                 <form class="default" @submit.prevent="">
@@ -77,6 +82,7 @@ import CoursewareDefaultBlock from './CoursewareDefaultBlock.vue';
 import CoursewareFileChooser from './CoursewareFileChooser.vue';
 import { mapActions, mapGetters } from 'vuex';
 
+
 export default {
     name: 'courseware-video-block',
     components: {
@@ -90,6 +96,7 @@ export default {
     },
     data() {
         return {
+            showEdit: false,
             currentSource: '',
             currentTitle: '',
             currentFile: {},
@@ -176,7 +183,7 @@ export default {
                 containerId: this.block.relationships.container.data.id,
             });
         },
-        async initCurrentData() {
+        initCurrentData() {
             this.currentSource = this.source;
             this.currentTitle = this.title;
             this.currentWebUrl = this.webUrl;
@@ -185,9 +192,12 @@ export default {
             this.currentContextMenu = this.contextMenu;
             this.currentAutoplay = this.autoplay;
             if (this.fileId !== '') {
-                await this.loadFile();
+                this.loadFile();
             }
         },
+        setShowEdit(state) {
+            this.showEdit = state;
+        },
         async loadFile() {
             const id = this.currentFileId;
             await this.loadFileRef({ id });
@@ -215,5 +225,45 @@ export default {
             }
         },
     },
+    watch: {
+        source() {
+            if (!this.showEdit) {
+                this.currentSource = this.source;
+            }
+        },
+        title() {
+            if (!this.showEdit) {
+                this.currentTitle = this.title;
+            }
+        },
+        webUrl() {
+            if (!this.showEdit) {
+                this.currentWebUrl = this.webUrl;
+            }
+        },
+        fileId() {
+            if (!this.showEdit) {
+                this.currentFileId = this.fileId;
+                if (this.fileId !== '') {
+                    this.loadFile();
+                }
+            }
+        },
+        aspect() {
+            if (!this.showEdit) {
+                this.currentAspect = this.aspect;
+            }
+        },
+        contextMenu() {
+            if (!this.showEdit) {
+                this.currentContextMenu = this.contextMenu;
+            }
+        },
+        autoplay() {
+            if (!this.showEdit) {
+                this.currentAutoplay = this.autoplay;
+            }
+        },
+    }
 };
 </script>
diff --git a/resources/vue/components/courseware/IndexApp.vue b/resources/vue/components/courseware/IndexApp.vue
index 432a4a6ed5a8001e28ba4bea316f7fea5dbbd747..1c39d2011b8d0527bb17de9290b06d18a9a2fc8c 100755
--- a/resources/vue/components/courseware/IndexApp.vue
+++ b/resources/vue/components/courseware/IndexApp.vue
@@ -52,7 +52,8 @@ export default {
         canVisit: null,
         selected: null,
         structureLoadingState: 'idle',
-        loadingErrorStatus: null
+        loadingErrorStatus: null,
+        polling: null
     }),
     computed: {
         ...mapGetters({
@@ -75,6 +76,9 @@ export default {
                 default:
                     return this.$gettext('Beim Laden der Seite ist ein Fehler aufgetreten.');
             }
+        },
+        selectedId() {
+            return this.$route.params?.id;
         }
     },
     methods: {
@@ -95,6 +99,11 @@ export default {
             this.canVisit = this.structuralElementLastMeta['can-visit'];
             this.selected = this.structuralElementById({ id });
         },
+        pollData () {
+            this.polling = setInterval(async () => {
+                await this.selectStructuralElement(this.selectedId);
+            }, 4000);
+        }
     },
     async mounted() {
         this.structureLoadingState = 'loading';
@@ -112,6 +121,10 @@ export default {
         this.structureLoadingState = 'done';
         const selectedId = this.$route.params?.id;
         await this.selectStructuralElement(selectedId);
+        this.pollData();
+    },
+    beforeDestroy () {
+        clearInterval(this.polling)
     },
     watch: {
         $route(to) {
diff --git a/resources/vue/components/courseware/block-mixin.js b/resources/vue/components/courseware/block-mixin.js
index 2e084baf116885a4362940dd1618c28d575d47f3..eb544c77258ae5c0153d9ba5b3d5c11398b4354a 100755
--- a/resources/vue/components/courseware/block-mixin.js
+++ b/resources/vue/components/courseware/block-mixin.js
@@ -20,5 +20,11 @@ export const blockMixin = {
         ...mapActions({
             updateUserProgress: 'courseware-user-progresses/update',
         }),
+        contentsEqual(o1, o2) {
+            return  typeof o1 === 'object' && Object.keys(o1).length > 0 
+                    ? Object.keys(o1).length === Object.keys(o2).length 
+                    && Object.keys(o1).every(p => this.contentsEqual(o1[p], o2[p]))
+                    : o1 === o2;
+        }
     },
 };
diff --git a/resources/vue/store/courseware/courseware.module.js b/resources/vue/store/courseware/courseware.module.js
index 57f2f9aa29f846dd2cac47a30406dd3354300481..5a6e479620ef63b38766522e3bf6af0571df2929 100755
--- a/resources/vue/store/courseware/courseware.module.js
+++ b/resources/vue/store/courseware/courseware.module.js
@@ -202,7 +202,7 @@ export const state = { ...initialState };
 export const actions = {
     loadContainer({ dispatch }, containerId) {
         const options = {
-            include: 'blocks',
+            include: 'blocks,blocks.edit-blocker',
         };
 
         return dispatch('courseware-containers/loadById', { id: containerId, options }, { root: true });