diff --git a/lib/classes/JsonApi/Routes/Courseware/StructuralElementsCopy.php b/lib/classes/JsonApi/Routes/Courseware/StructuralElementsCopy.php
index 68b0b4d64862f91396cbe33e1713b98378158e71..abcb26d678382d5c9ad67c34a7b5f95e34613469 100755
--- a/lib/classes/JsonApi/Routes/Courseware/StructuralElementsCopy.php
+++ b/lib/classes/JsonApi/Routes/Courseware/StructuralElementsCopy.php
@@ -34,16 +34,30 @@ class StructuralElementsCopy extends NonJsonApiController
             throw new AuthorizationFailedException();
         }
 
-        $newElement = $this->copyElement($user, $sourceElement, $newParent);
+        if ($data['migrate']) {
+            $newElement = $this->mergeElement($user, $sourceElement, $newParent);
+        } else {
+            $newElement = $this->copyElement($user, $sourceElement, $newParent);
+        }
+        if ($data['remove_purpose']) {
+            $newElement->purpose = '';
+        }
 
         return $this->redirectToStructuralElement($response, $newElement);
     }
 
     private function copyElement(\User $user, StructuralElement $sourceElement, StructuralElement $newParent)
     {
-        $new_element = $sourceElement->copy($user, $newParent);
+        $newElement = $sourceElement->copy($user, $newParent);
+
+        return $newElement;
+    }
+
+    private function mergeElement(\User $user, StructuralElement $sourceElement, StructuralElement $targetElement)
+    {
+        $newElement = $sourceElement->merge($user, $targetElement);
 
-        return $new_element;
+        return $newElement;
     }
 
     /**
diff --git a/lib/models/Courseware/StructuralElement.php b/lib/models/Courseware/StructuralElement.php
index 44451504a56aecefaaf312abfc0eab8a6d5d18f6..add15fbe980746c60c438ec8c76709eba8cedd61 100755
--- a/lib/models/Courseware/StructuralElement.php
+++ b/lib/models/Courseware/StructuralElement.php
@@ -586,17 +586,7 @@ SQL;
      */
     public function copy(User $user, StructuralElement $parent): StructuralElement
     {
-        /** @var ?\FileRef $original_file_ref */
-        $original_file_ref = \FileRef::find($this->image_id);
-        if ($original_file_ref) {
-            $instance = new Instance($this->getCourseware($parent->range_id, $parent->range_type));
-            $folder = \Courseware\Filesystem\PublicFolder::findOrCreateTopFolder($instance);
-            /** @var \FileRef $file_ref */
-            $file_ref = \FileManager::copyFile($original_file_ref->getFileType(), $folder, $user);
-            $file_ref_id = $file_ref->id;
-        } else {
-            $file_ref_id = null;
-        }
+        $file_ref_id = self::copyImage($user, $parent);
 
         $element = self::build([
             'parent_id' => $parent->id,
@@ -621,6 +611,74 @@ SQL;
         return $element;
     }
 
+    private function copyImage(User $user, StructuralElement $parent) : ?String
+    {
+        $file_ref_id = null;
+
+        /** @var ?\FileRef $original_file_ref */
+        $original_file_ref = \FileRef::find($this->image_id);
+        if ($original_file_ref) {
+            $instance = new Instance($this->getCourseware($parent->range_id, $parent->range_type));
+            $folder = \Courseware\Filesystem\PublicFolder::findOrCreateTopFolder($instance);
+            /** @var \FileRef $file_ref */
+            $file_ref = \FileManager::copyFile($original_file_ref->getFileType(), $folder, $user);
+            $file_ref_id = $file_ref->id;
+        }
+
+        return $file_ref_id;
+    }
+
+    public function merge(User $user, StructuralElement $target): StructuralElement
+    {
+        // merge with target
+        if (!$target->image_id) {
+            $target->image_id = self::copyImage($user, $target);
+        }
+
+        if ($target->title === 'neue Seite' || $target->title === 'New page') {
+            $target->title = $this->title;
+        }
+
+        if (!$target->purpose) {
+            $target->purpose = $this->purpose;
+        }
+
+        if (!$target->payload['color']) {
+            $target->payload['color'] = $this->payload['color'];
+        }
+
+        if (!$target->payload['description']) {
+            $target->payload['description'] = $this->payload['description'];
+        }
+
+        if (!$target->payload['license_type']) {
+            $target->payload['license_type'] = $this->payload['license_type'];
+        }
+
+        if (!$target->payload['required_time']) {
+            $target->payload['required_time'] = $this->payload['required_time'];
+        }
+
+        if (!$target->payload['difficulty_start']) {
+            $target->payload['difficulty_start'] = $this->payload['difficulty_start'];
+        }
+
+        if (!$target->payload['difficulty_end']) {
+            $target->payload['difficulty_end'] = $this->payload['difficulty_end'];
+        }
+
+        $target->store();
+
+        // add Containers to target
+        self::copyContainers($user, $target);
+
+        // copy Children
+
+        self::copyChildren($user, $target);
+
+        return $this;
+    }
+
     private function copyContainers(User $user, StructuralElement $newElement): void
     {
         $containers = \Courseware\Container::findBySQL('structural_element_id = ?', [$this->id]);
diff --git a/resources/assets/stylesheets/scss/courseware.scss b/resources/assets/stylesheets/scss/courseware.scss
index c1a8d90b7c66ac2ef608c60d5125c41bb555684b..2d4fb52f6470c51172f97081663f38b922433532 100755
--- a/resources/assets/stylesheets/scss/courseware.scss
+++ b/resources/assets/stylesheets/scss/courseware.scss
@@ -2704,7 +2704,7 @@ a u d i o  b l o c k
                     @include background-icon(file-audio2, clickable, 24);
                     background-repeat: no-repeat;
                     background-position: 1em center;
-    
+
                     margin: 1em 0;
                     padding: 1em;
                     padding-left: 4em;
@@ -4323,3 +4323,87 @@ cw tiles end
 }
 
 /* cw manager copy end*/
+
+/* courseware template preview */
+.cw-template-preview {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: space-between;
+    width: calc(100% - 20px);;
+    padding: 10px;
+    .cw-template-preview-container-wrapper {
+        margin-bottom: 10px;
+
+        &.cw-template-preview-container-full {
+            width: 100%
+        }
+        &.cw-template-preview-container-half {
+            width: calc(50% - 4px);
+        }
+        &.cw-template-preview-container-half-center {
+            width: 100%;
+            .cw-template-preview-container-content {
+                width: 50%;
+                margin: auto;
+            }
+        }
+
+        .cw-template-preview-container-content {
+            border: solid thin $content-color-40;
+        }
+
+        .cw-template-preview-container-title {
+            font-weight: 700;
+            padding: 4px 4px 4px 8px;
+            color: $base-color;
+            background-color: $content-color-20;
+        }
+
+        .cw-template-preview-blocks {
+            border: solid thin $content-color-40;
+            padding: 1em;
+            margin: 5px;
+            background-color: $white;
+
+        }
+    }
+}
+/* courseware template preview end*/
+
+/* contents courseware courses */
+.cw-content-courses {
+    h2 {
+        margin-top: 0;
+    }
+    ul.cw-tiles {
+        margin-bottom: 20px;
+    }
+}
+/* contents courseware courses end*/
+
+/* * * * * * * * * *
+ i n p u t  f i l e
+* * * * * * * * * */
+ .cw-file-input {
+     width: stretch;
+     border: solid thin $base-color;
+     font-size: 14px;
+    cursor: pointer;
+
+    &::file-selector-button {
+        border: none;
+        border-right: solid thin $base-color;
+        background-color: $white;
+        padding: 6px 15px;
+        margin-right: 10px;
+        color: $base-color;
+
+        &:hover {
+            background-color: $base-color;
+            color: $white;
+        }
+     }
+ }
+ /* * * * * * * * * * * * *
+ i n p u t  f i l e  e n d
+* * * * * * * * * * * * * */
diff --git a/resources/vue/components/courseware/CoursewareCourseManager.vue b/resources/vue/components/courseware/CoursewareCourseManager.vue
index 66159d17099c584020e1ea6533f82ee5b50d3612..e9ce152e5429f513e1ea4b4757f16d1136aeb712 100755
--- a/resources/vue/components/courseware/CoursewareCourseManager.vue
+++ b/resources/vue/components/courseware/CoursewareCourseManager.vue
@@ -93,53 +93,7 @@
                 </courseware-tab>
 
                 <courseware-tab :name="$gettext('Importieren')"  :index="3">
-                    <courseware-companion-box v-show="!importRunning && importDone && importErrors.length === 0" :msgCompanion="$gettext('Import erfolgreich!')" mood="special"/>
-                    <courseware-companion-box v-show="!importRunning && importDone && importErrors.length > 0" :msgCompanion="$gettext('Import abgeschlossen. Es sind Fehler aufgetreten!')" mood="unsure"/>
-                    <courseware-companion-box v-show="!importRunning && !importDone && importErrors.length > 0" :msgCompanion="$gettext('Import fehlgeschlagen. Es sind Fehler aufgetreten!')" mood="sad"/>
-                    <courseware-companion-box v-show="importRunning" :msgCompanion="$gettext('Import läuft. Bitte verlassen Sie die Seite nicht bis der Import abgeschlossen wurde.')" mood="pointing"/>
-                    <button
-                        v-show="!importRunning"
-                        class="button"
-                        @click.prevent="chooseFile"
-                    >
-                        <translate>Importdatei auswählen</translate>
-                    </button>
-
-                    <div v-if="importZip" class="cw-import-zip">
-                        <header>{{ importZip.name }}</header>
-                        <p><translate>Größe</translate>: {{ getFileSizeText(importZip.size) }}</p>
-                    </div>
-
-                    <div v-if="importRunning" class="cw-import-zip">
-                        <header><translate>Importiere Dateien</translate>:</header>
-                        <div class="progress-bar-wrapper">
-                            <div class="progress-bar" role="progressbar" :style="{width: importFilesProgress + '%'}" :aria-valuenow="importFilesProgress" aria-valuemin="0" aria-valuemax="100">{{ importFilesProgress }}%</div>
-                        </div>
-                        {{ importFilesState }}
-                    </div>
-
-                    <div v-if="fileImportDone && importRunning" class="cw-import-zip">
-                        <header><translate>Importiere Elemente</translate>:</header>
-                        <div class="progress-bar-wrapper">
-                            <div class="progress-bar" role="progressbar" :style="{width: importStructuresProgress + '%'}" :aria-valuenow="importStructuresProgress" aria-valuemin="0" aria-valuemax="100">{{ importStructuresProgress }}%</div>
-                        </div>
-                        {{ importStructuresState }}
-                    </div>
-
-                    <button
-                        v-show="importZip && !importRunning"
-                        class="button"
-                        @click.prevent="doImportCourseware"
-                    >
-                        <translate>Alles importieren</translate>
-                    </button>
-                    <div v-if="importErrors.length > 0">
-                        <h3><translate>Fehlermeldungen:</translate></h3>
-                        <ul>
-                            <li v-for="(error, index) in importErrors" :key="index"> {{error}} </li>
-                        </ul>
-                    </div>
-                    <input ref="importFile" type="file" accept=".zip" @change="setImport" style="visibility: hidden" />
+                    <courseware-manager-import />
                 </courseware-tab>
             </courseware-tabs>
         </div>
@@ -153,13 +107,10 @@ import CoursewareCollapsibleBox from './CoursewareCollapsibleBox.vue';
 import CoursewareManagerElement from './CoursewareManagerElement.vue';
 import CoursewareManagerCopySelector from './CoursewareManagerCopySelector.vue';
 import CoursewareCompanionBox from './CoursewareCompanionBox.vue';
-import CoursewareImport from '@/vue/mixins/courseware/import.js';
+import CoursewareManagerImport from './CoursewareManagerImport.vue';
 import CoursewareExport from '@/vue/mixins/courseware/export.js';
 import { mapActions, mapGetters } from 'vuex';
 
-import JSZip from 'jszip';
-import FileSaver from 'file-saver';
-
 export default {
     name: 'courseware-course-manager',
     components: {
@@ -169,20 +120,18 @@ export default {
         CoursewareManagerElement,
         CoursewareManagerCopySelector,
         CoursewareCompanionBox,
+        CoursewareManagerImport
     },
 
-    mixins: [CoursewareImport, CoursewareExport],
+    mixins: [CoursewareExport],
 
     data() {
         return {
             exportRunning: false,
-            importRunning: false,
-            importZip: null,
             currentElement: {},
             currentId: null,
             selfElement: {},
             selfId: null,
-            zip: null
         };
     },
 
@@ -190,11 +139,6 @@ export default {
         ...mapGetters({
             courseware: 'courseware',
             structuralElementById: 'courseware-structural-elements/byId',
-            importFilesState: 'importFilesState',
-            importFilesProgress: 'importFilesProgress',
-            importStructuresState: 'importStructuresState',
-            importStructuresProgress: 'importStructuresProgress',
-            importErrors: 'importErrors',
             exportState: 'exportState',
             exportProgress: 'exportProgress'
         }),
@@ -214,12 +158,6 @@ export default {
         moveSelfChildPossible() {
             return this.currentId !== this.selfId;
         },
-        fileImportDone() {
-            return this.importFilesProgress === 100;
-        },
-        importDone() {
-            return this.importFilesProgress === 100 && this.importStructuresProgress === 100;
-        }
     },
 
     methods: {
@@ -233,9 +171,6 @@ export default {
             unlockObject: 'unlockObject',
             addBookmark: 'addBookmark',
             companionInfo: 'companionInfo',
-            setImportFilesProgress: 'setImportFilesProgress',
-            setImportStructuresProgress: 'setImportStructuresProgress',
-            setImportErrors: 'setImportErrors',
         }),
         async reloadElements() {
             await this.setCurrentId(this.currentId);
@@ -274,88 +209,6 @@ export default {
 
             this.exportRunning = false;
         },
-
-        setImport(event) {
-            this.importZip = event.target.files[0];
-            this.setImportErrors([]);
-        },
-
-        async doImportCourseware() {
-            if (this.importZip === null) {
-                return false;
-            }
-
-            this.importRunning = true;
-
-            let view = this;
-
-            view.zip = new JSZip();
-
-            await view.zip.loadAsync(this.importZip).then(async function () {
-                let errors = [];
-                let missingFiles = false;
-                if (view.zip.file('courseware.json') === null) {
-                    errors.push(view.$gettext('Das Archiv enthält keine courseware.json Datei.'));
-                    missingFiles = true;
-                }
-                if (view.zip.file('files.json') === null) {
-                    errors.push(view.$gettext('Das Archiv enthält keine files.json Datei.'));
-                    missingFiles = true;
-                }
-                if (view.zip.file('data.xml') !== null) {
-                    errors.push(view.$gettext('Das Archiv enthält eine data.xml Datei. Möglicherweise handelt es sich um einen Export aus dem Courseware-Plugin. Diese Archive sind nicht kompatibel mit dieser Courseware.'));
-                }
-                if (missingFiles) {
-                    view.setImportErrors(errors);
-                    return;
-                }
-
-                let data = await view.zip.file('courseware.json').async('string');
-                let courseware = null;
-                let data_files = await view.zip.file('files.json').async('string');
-                let files = null;
-                let jsonErrors = false;
-                try {
-                    courseware = JSON.parse(data);
-                } catch (error) {
-                    jsonErrors = true;
-                    errors.push(view.$gettext('Die Beschreibung der Courseware-Inhalte ist nicht valide.'));
-                    errors.push(error);
-                }
-                try {
-                    files = JSON.parse(data_files);
-                } catch (error) {
-                    jsonErrors = true;
-                    errors.push(view.$gettext('Die Beschreibung der Dateien ist nicht valide.'));
-                    errors.push(error);
-                }
-                if (jsonErrors) {
-                    view.setImportErrors(errors);
-                    return;
-                }
-
-                await view.loadCoursewareStructure();
-                let parent_id = view.courseware.relationships.root.data.id;
-
-                await view.importCourseware(courseware, parent_id, files);
-            });
-
-            this.importZip = null;
-            this.importRunning = false;
-        },
-
-        chooseFile() {
-            this.$refs.importFile.click();
-            this.setImportFilesProgress(0);
-            this.setImportStructuresProgress(0);
-        },
-        getFileSizeText(size) {
-            if (size / 1024 < 1000) {
-                return (size / 1024).toFixed(2) + ' kB';
-            } else {
-                return (size / 1048576).toFixed(2) + ' MB';
-            }
-        },
     },
     watch: {
         courseware(newValue, oldValue) {
@@ -364,12 +217,6 @@ export default {
             this.setSelfId(currentId);
         },
     },
-    mounted() {
-        let view = this;
 
-        window.onbeforeunload = function() {
-            return view.importRunning ? true : null
-        }
-    }
 };
 </script>
diff --git a/resources/vue/components/courseware/CoursewareDashboardTasks.vue b/resources/vue/components/courseware/CoursewareDashboardTasks.vue
new file mode 100755
index 0000000000000000000000000000000000000000..fe37539825be76f5746b69fce47ec6dd08ae5551
--- /dev/null
+++ b/resources/vue/components/courseware/CoursewareDashboardTasks.vue
@@ -0,0 +1,265 @@
+<template>
+    <div class="cw-dashboard-tasks-wrapper">
+        <table v-if="tasks.length > 0" class="default">
+            <colgroup>
+                <col />
+            </colgroup>
+            <thead>
+                <tr>
+                    <th><translate>Status</translate></th>
+                    <th class="responsive-hidden"><translate>Aufgabentitel</translate></th>
+                    <th><translate>Seite</translate></th>
+                    <th><translate>bearbeitet</translate></th>
+                    <th><translate>Abgabefrist</translate></th>
+                    <th><translate>Abgabe</translate></th>
+                    <th class="responsive-hidden"><translate>Verlängerungsanfrage</translate></th>
+                    <th class="responsive-hidden"><translate>Feedback</translate></th>
+                    <th><translate>Aktionen</translate></th>
+                </tr>
+            </thead>
+            <tbody>
+                <tr v-for="{ task, taskGroup, status, element, feedback } in tasks" :key="task.id">
+                    <td>
+                        <studip-icon
+                            v-if="status.shape !== undefined"
+                            :shape="status.shape"
+                            :role="status.role"
+                            :title="status.description"
+                        />
+                    </td>
+                    <td class="responsive-hidden">
+                        <studip-icon
+                            v-if="task.attributes['solver-type'] === 'group'"
+                            shape="group2"
+                            role="info"
+                            :title="$gettext('Gruppenaufgabe')"
+                        />
+                        {{ taskGroup.attributes.title }}
+                    </td>
+                    <td>
+                        <a :href="getLinkToElement(element.id)">{{ element.attributes.title }}</a>
+                    </td>
+                    <td>{{ task.attributes.progress }}%</td>
+                    <td>{{ getReadableDate(task.attributes['submission-date']) }}</td>
+                    <td>
+                        <studip-icon v-if="task.attributes.submitted" shape="accept" role="status-green" />
+                    </td>
+                    <td class="responsive-hidden">
+                        <span v-show="task.attributes.renewal === 'declined'">
+                            <studip-icon shape="decline" role="status-red" />
+                            <translate>Anfrage abgelehnt</translate>
+                        </span>
+                        <span v-show="task.attributes.renewal === 'pending'">
+                            <studip-icon shape="date" role="status-yellow" />
+                            <translate>Anfrage wird bearbeitet</translate>
+                        </span>
+                        <span v-show="task.attributes.renewal === 'granted'">
+                            <translate>verlängert bis</translate>: {{getReadableDate(task.attributes['renewal-date'])}}
+                        </span>
+                    </td>
+                    <td class="responsive-hidden">
+                        <studip-icon
+                            v-if="feedback"
+                            :title="$gettext('Feedback anzeigen')"
+                            class="display-feedback"
+                            shape="consultation"
+                            role="clickable"
+                            @click="displayFeedback(feedback)"
+                        />
+                    </td>
+                    <td class="actions">
+                        <studip-action-menu
+                            :items="getTaskMenuItems(task, status)"
+                            @submitTask="displaySubmitDialog(task)"
+                            @renewalRequest="renewalRequest(task)"
+                            @copyContent="copyContent(element)"
+                        />
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+        <div v-else>
+            <courseware-companion-box
+                mood="sad"
+                :msgCompanion="$gettext('Es wurden bisher keine Aufgaben gestellt.')"
+            />
+        </div>
+        <studip-dialog
+            v-if="showFeedbackDialog"
+            :message="currentTaskFeedback"
+            :title="text.feedbackDialog.title"
+            @close="
+                showFeedbackDialog = false;
+                currentTaskFeedback = '';
+            "
+        />
+        <studip-dialog
+            v-if="showSubmitDialog"
+            :title="text.submitDialog.title"
+            :question="text.submitDialog.question"
+            height="200"
+            width="420"
+            @confirm="submitTask"
+            @close="closeSubmitDialog"
+        />
+    </div>
+</template>
+<script>
+import CoursewareCompanionBox from './CoursewareCompanionBox.vue';
+import StudipIcon from './../StudipIcon.vue';
+import StudipActionMenu from './../StudipActionMenu.vue';
+import StudipDialog from './../StudipDialog.vue';
+import taskHelperMixin from '../../mixins/courseware/task-helper.js';
+import { mapActions, mapGetters } from 'vuex';
+
+export default {
+    name: 'courseware-dashboard-tasks',
+    mixins: [taskHelperMixin],
+    components: {
+        CoursewareCompanionBox,
+        StudipIcon,
+        StudipActionMenu,
+        StudipDialog,
+    },
+    data() {
+        return {
+            showFeedbackDialog: false,
+            showSubmitDialog: false,
+            currentTask: null,
+            currentTaskFeedback: '',
+            text: {
+                feedbackDialog: {
+                    title: this.$gettext('Feedback'),
+                },
+                submitDialog: {
+                    title: this.$gettext('Aufgabe abgeben'),
+                    question: this.$gettext(
+                        'Änderungen sind nach Abgabe nicht mehr möglich. Möchten Sie diese Aufgabe jetzt wirklich abgeben?'
+                    ),
+                },
+            },
+        };
+    },
+    computed: {
+        ...mapGetters({
+            context: 'context',
+            allTasks: 'courseware-tasks/all',
+            userId: 'userId',
+            userById: 'users/byId',
+            statusGroupById: 'status-groups/byId',
+            getElementById: 'courseware-structural-elements/byId',
+            getFeedbackById: 'courseware-task-feedback/byId',
+            getTaskGroupById: 'courseware-task-groups/byId',
+        }),
+        tasks() {
+            return this.allTasks.map((task) => {
+                const result = {
+                    task,
+                    taskGroup: this.getTaskGroupById({ id: task.relationships['task-group'].data.id }),
+                    status: this.getStatus(task),
+                    element: this.getElementById({ id: task.relationships['structural-element'].data.id }),
+                    feedback: null,
+                };
+                const feedbackId = task.relationships['task-feedback'].data?.id;
+                if (feedbackId) {
+                    result.feedback = this.getFeedbackById({ id: feedbackId });
+                }
+
+                return result;
+            });
+        },
+    },
+    methods: {
+        ...mapActions({
+            updateTask: 'updateTask',
+            loadRemoteCoursewareStructure: 'loadRemoteCoursewareStructure',
+            copyStructuralElement: 'copyStructuralElement',
+            companionSuccess: 'companionSuccess',
+            companionError: 'companionError',
+        }),
+        getTaskMenuItems(task, status) {
+            let menuItems = [];
+            if (!task.attributes.submitted && status.canSubmit) {
+                menuItems.push({ id: 1, label: this.$gettext('Aufgabe abgeben'), icon: 'service', emit: 'submitTask' });
+            }
+
+            if (!task.attributes.submitted && !task.attributes.renewal) {
+                menuItems.push({
+                    id: 2,
+                    label: this.$gettext('Verlängerung beantragen'),
+                    icon: 'date',
+                    emit: 'renewalRequest',
+                });
+            }
+            if (task.attributes.submitted) {
+                menuItems.push({ id: 3, label: this.$gettext('Inhalt kopieren'), icon: 'export', emit: 'copyContent' });
+            }
+
+            return menuItems;
+        },
+        async renewalRequest(task) {
+            let attributes = {};
+            attributes.renewal = 'pending';
+            await this.updateTask({
+                attributes: attributes,
+                taskId: task.id,
+            });
+            this.companionSuccess({
+                info: this.$gettext('Ihre Anfrage wurde eingereicht.'),
+            });
+        },
+        displaySubmitDialog(task) {
+            this.showSubmitDialog = true;
+            this.currentTask = task;
+        },
+        closeSubmitDialog() {
+            this.showSubmitDialog = false;
+            this.currentTask = null;
+        },
+        async submitTask() {
+            this.showSubmitDialog = false;
+            let attributes = {};
+            attributes.submitted = true;
+            await this.updateTask({
+                attributes: attributes,
+                taskId: this.currentTask.id,
+            });
+            this.companionSuccess({
+                info:
+                    '"' +
+                    this.currentTask.attributes.title +
+                    '" ' +
+                    this.$gettext('wurde erfolgreich abgegeben.'),
+            });
+            this.currentTask = null;
+        },
+        async copyContent(element) {
+            let ownCoursewareInstance = await this.loadRemoteCoursewareStructure({
+                rangeId: this.userId,
+                rangeType: 'users',
+            });
+            if (ownCoursewareInstance !== null) {
+                await this.copyStructuralElement({
+                    parentId: ownCoursewareInstance.relationships.root.data.id,
+                    elementId: element.id,
+                    removeType: true,
+                    migrate: false
+                });
+                this.companionSuccess({
+                    info: this.$gettext('Die Inhalte wurden zu Ihren persönlichen Lernmaterialien hinzugefügt.'),
+                });
+            } else {
+                this.companionError({
+                    info: this.$gettext(
+                        'Die Inhalte konnten nicht zu Ihren persönlichen Lernmaterialien hinzugefügt werden.'
+                    ),
+                });
+            }
+        },
+        displayFeedback(feedback) {
+            this.showFeedbackDialog = true;
+            this.currentTaskFeedback = feedback.attributes.content;
+        },
+    },
+};
+</script>
diff --git a/resources/vue/components/courseware/CoursewareManagerCopySelector.vue b/resources/vue/components/courseware/CoursewareManagerCopySelector.vue
index 01c2c36b7d73f98d39debdf8adf84cabfa1f3424..3c22dcd9a14ec582c7ab8b0e24d29a670dd0ed88 100755
--- a/resources/vue/components/courseware/CoursewareManagerCopySelector.vue
+++ b/resources/vue/components/courseware/CoursewareManagerCopySelector.vue
@@ -5,8 +5,10 @@
             <button class="button" @click="selectSource('remote')"><translate>Aus Veranstaltung kopieren</translate></button>
         </div>
         <div v-else>
+            <courseware-companion-box v-if="copyAllInProgress" :msgCompanion="copyAllInProgressText" mood="pointing" />
             <button class="button" @click="reset"><translate>Quelle auswählen</translate></button>
             <button v-show="!sourceOwn && hasRemoteCid" class="button" @click="selectNewCourse"><translate>Veranstaltung auswählen</translate></button>
+            <button v-show="!sourceOwn && hasRemoteCid" class="button" @click="mergeContent"><translate>Alle Inhalte kopieren</translate></button>
             <div v-if="sourceRemote">
                 <h2 v-if="!hasRemoteCid"><translate>Veranstaltungen</translate></h2>
                 <ul v-if="!hasRemoteCid && semesterMap.length > 0">
@@ -75,24 +77,28 @@ export default {
         CoursewareCompanionBox,
     },
     props: {},
-    data() {return{
-        source: '',
-        courses: [],
-        remoteCid: '',
-        remoteCoursewareInstance: {},
-        remoteId: '',
-        remoteElement: {},
-        ownCoursewareInstance: {},
-        ownId: '',
-        ownElement: {},
-        semesterMap: [],
-
-    }},
+    data() {
+        return {
+            source: '',
+            courses: [],
+            remoteCid: '',
+            remoteCoursewareInstance: {},
+            remoteId: '',
+            remoteElement: {},
+            ownCoursewareInstance: {},
+            ownId: '',
+            ownElement: {},
+            semesterMap: [],
+            copyAllInProgress: false,
+            copyAllInProgressText: ''
+        }
+    },
     computed: {
         ...mapGetters({
-            userId: 'userId',
-            structuralElementById: 'courseware-structural-elements/byId',
+            courseware: 'courseware',
             semesterById: 'semesters/byId',
+            structuralElementById: 'courseware-structural-elements/byId',
+            userId: 'userId',
         }),
         sourceEmpty() {
             return this.source === '';
@@ -116,9 +122,11 @@ export default {
             loadUsersCourses: 'loadUsersCourses',
             loadStructuralElement: 'loadStructuralElement',
             loadSemester: 'semesters/loadById',
+            copyStructuralElement: 'copyStructuralElement',
         }),
         selectSource(source) {
             this.source = source;
+            this.copyAllInProgress = false;
         },
         async loadRemoteCourseware(cid) {
             this.remoteCid = cid;
@@ -140,10 +148,12 @@ export default {
         reset() {
             this.selectSource('');
             this.remoteCid = '';
+            this.copyAllInProgress = false;
         },
         selectNewCourse() {
             this.remoteCid = '';
             this.remoteId = '';
+            this.copyAllInProgress = false;
         },
         async setRemoteId(target) {
             this.remoteId = target;
@@ -196,6 +206,24 @@ export default {
         },
         reloadElement() {
             this.$emit("reloadElement");
+        },
+        async mergeContent() {
+            this.copyAllInProgressText = this.$gettext('Inhalte werden kopiert…');
+            this.copyAllInProgress = true;
+            let parentId = this.courseware.relationships.root.data.id; //current root
+            let elementId = this.remoteCoursewareInstance.relationships.root.data.id; // remote root
+            try {
+                await this.copyStructuralElement({
+                    parentId: parentId,
+                    elementId: elementId,
+                    migrate: true
+                });
+            } catch(error) { 
+                console.debug(error);
+                this.copyAllInProgressText = this.$gettext('Beim Kopiervorgang sind Fehler aufgetreten.');
+            }
+            this.copyAllInProgressText = this.$gettext('Kopiervorgang abgeschlossen.');
+            this.reloadElement();
         }
     },
     async mounted() {
diff --git a/resources/vue/components/courseware/CoursewareManagerElement.vue b/resources/vue/components/courseware/CoursewareManagerElement.vue
index 01858aea7ad43f6289c6698de37a38634d3cd2d5..7dfe67b8836fb89667b74932fc8a7b448ba3a169 100755
--- a/resources/vue/components/courseware/CoursewareManagerElement.vue
+++ b/resources/vue/components/courseware/CoursewareManagerElement.vue
@@ -20,12 +20,12 @@
                     <a
                         v-if="elementInserterActive && moveSelfPossible && canEdit"
                         href="#"
-                        :title="$gettextInterpolate('%{ elementTitle } verschieben', {elementTitle: elementTitle})"
+                        :title="elementTitle"
                         @click="insertElement({element: currentElement, source: type})"
                     >
                         <studip-icon shape="arr_2left" size="24" role="clickable" />
                     </a>
-                    {{ elementTitle }}
+                    {{ elementName }}
                 </header>
             </div>
             <courseware-collapsible-box
@@ -227,12 +227,24 @@ export default {
 
             return [...visitAncestors(this.currentElement)].reverse()
         },
-        elementTitle() {
+        elementName() {
             if (this.currentElement.attributes) {
                 return this.currentElement.attributes.title
-            } else {
-                return '';
             }
+
+            return '';
+        },
+        elementTitle() {
+            let title = this.elementName;
+            if (this.elementInserterActive && this.moveSelfPossible && this.canEdit) {
+                if (this.isRemote || this.isOwn) {
+                    title = this.$gettextInterpolate('%{ elementTitle } kopieren', {elementTitle: this.elementName});
+                } else {
+                    title = this.$gettextInterpolate('%{ elementTitle } verschieben', {elementTitle: this.elementName});
+                }
+            }
+
+            return title;
         },
         hasChildren() {
             if (this.children === null) {
@@ -373,7 +385,8 @@ export default {
                     let parentId = this.filingData.parentItem.id;
                     await this.copyStructuralElement({
                         parentId: parentId,
-                        element: element,
+                        elementId: element.id,
+                        migrate: false
                     }).catch((error) => {
                         let message = this.$gettextInterpolate('%{ pageTitle } konnte nicht kopiert werden.', {pageTitle: element.attributes.title});
                         this.text.copyProcessFailed.push(message);
diff --git a/resources/vue/components/courseware/CoursewareManagerElementItem.vue b/resources/vue/components/courseware/CoursewareManagerElementItem.vue
index c177127629038f9428b733e3679196f0da737051..5fd7a2c04479bdb0b8101d01814a6084275991e9 100755
--- a/resources/vue/components/courseware/CoursewareManagerElementItem.vue
+++ b/resources/vue/components/courseware/CoursewareManagerElementItem.vue
@@ -5,11 +5,11 @@
             href="#"
             class="cw-manager-element-item"
             :class="[inserter ? 'cw-manager-element-item-inserter' : '']"
-            :title="inserter ? $gettextInterpolate('%{ elementTitle } verschieben', {elementTitle: element.attributes.title}) : element.attributes.title"
+            :title="elementTitle"
             @click="clickItem">
                 {{ element.attributes.title }}
         </a>
-        <div 
+        <div
             v-else
             class="cw-manager-element-item cw-manager-element-item-sorting"
         >
@@ -37,6 +37,62 @@ export default {
         canMoveUp: Boolean,
         canMoveDown: Boolean
     },
+    computed: {
+        ...mapGetters({
+            taskById: 'courseware-tasks/byId',
+            userById: 'users/byId',
+            groupById: 'status-groups/byId',
+        }),
+        isTask() {
+            return this.element.attributes.purpose === 'task';
+        },
+        task() {
+            if (this.element.relationships.task.data) {
+                return this.taskById({
+                    id: this.element.relationships.task.data.id,
+                });
+            }
+
+            return null;
+        },
+        solver() {
+            if (this.task) {
+                const solver = this.task.relationships.solver.data;
+                if (solver.type === 'users') {
+                    return this.userById({ id: solver.id });
+                }
+                if (solver.type === 'status-groups') {
+                    return this.groupById({ id: solver.id });
+                }
+            }
+
+            return null;
+        },
+        solverName() {
+            if (this.solver) {
+                if (this.solver.type === 'users') {
+                    return this.solver.attributes['formatted-name'];
+                }
+                if (this.solver.type === 'status-groups') {
+                    return this.solver.attributes.name;
+                }
+            }
+
+            return '';
+        },
+        elementTitle() {
+            let title = this.element.attributes.title;
+            if (this.inserter) {
+                if (this.type === 'remote' || this.type === 'own') {
+                    title = this.$gettextInterpolate('%{ elementTitle } kopieren', {elementTitle: this.element.attributes.title});
+                } else {
+                    title = this.$gettextInterpolate('%{ elementTitle } verschieben', {elementTitle: this.element.attributes.title});
+                }
+            }
+
+            return title;
+        }
+    },
     methods: {
         clickItem() {
             if (this.sortChapters) {
diff --git a/resources/vue/components/courseware/CoursewareManagerImport.vue b/resources/vue/components/courseware/CoursewareManagerImport.vue
new file mode 100644
index 0000000000000000000000000000000000000000..6fd3b476be23930c9f6431642e56b90d58d90e24
--- /dev/null
+++ b/resources/vue/components/courseware/CoursewareManagerImport.vue
@@ -0,0 +1,194 @@
+<template>
+  <div>
+    <courseware-companion-box v-show="!importRunning && importDone && importErrors.length === 0" :msgCompanion="$gettext('Import erfolgreich!')" mood="special"/>
+    <courseware-companion-box v-show="!importRunning && importDone && importErrors.length > 0" :msgCompanion="$gettext('Import abgeschlossen. Es sind Fehler aufgetreten!')" mood="unsure"/>
+    <courseware-companion-box v-show="!importRunning && !importDone && importErrors.length > 0" :msgCompanion="$gettext('Import fehlgeschlagen. Es sind Fehler aufgetreten!')" mood="sad"/>
+    <courseware-companion-box v-show="importRunning" :msgCompanion="$gettext('Import läuft. Bitte verlassen Sie die Seite nicht bis der Import abgeschlossen wurde.')" mood="pointing"/>
+    <form class="default" @submit.prevent="">
+
+        <fieldset v-show="importRunning">
+            <legend><translate>Import läuft...</translate></legend>
+            <div v-if="importRunning" class="cw-import-zip">
+                <header><translate>Importiere Dateien</translate>:</header>
+                <div class="progress-bar-wrapper">
+                    <div class="progress-bar" role="progressbar" :style="{width: importFilesProgress + '%'}" :aria-valuenow="importFilesProgress" aria-valuemin="0" aria-valuemax="100">{{ importFilesProgress }}%</div>
+                </div>
+                {{ importFilesState }}
+            </div>
+            <div v-if="fileImportDone && importRunning" class="cw-import-zip">
+                <header><translate>Importiere Elemente</translate>:</header>
+                <div class="progress-bar-wrapper">
+                    <div class="progress-bar" role="progressbar" :style="{width: importStructuresProgress + '%'}" :aria-valuenow="importStructuresProgress" aria-valuemin="0" aria-valuemax="100">{{ importStructuresProgress }}%</div>
+                </div>
+                {{ importStructuresState }}
+            </div>
+        </fieldset>
+        <fieldset v-show="importErrors.length > 0">
+            <legend><translate>Fehlermeldungen</translate></legend>
+            <ul>
+                <li v-for="(error, index) in importErrors" :key="index"> {{error}} </li>
+            </ul>
+        </fieldset>
+        <fieldset v-show="!importRunning">
+            <legend><translate>Import</translate></legend>
+            <label>
+                <translate>Importdatei</translate>
+                <input class="cw-file-input" ref="importFile" type="file" accept=".zip" @change="setImport" />
+            </label>
+            <label>
+                <translate>Importverhalten</translate>
+                <select v-model="importBehavior">
+                    <option value="default"><translate>Inhalte anhängen</translate></option>
+                    <option value="migrate"><translate>Inhalte zusammenführen</translate></option>
+                </select>
+            </label>
+        </fieldset>
+        <footer v-show="!importRunning">
+            <button
+                class="button"
+                @click.prevent="doImportCourseware"
+                :disabled="!importZip"
+            >
+                <translate>Importieren</translate>
+            </button>
+        </footer>
+    </form>
+  </div>
+</template>
+
+<script>
+import CoursewareCompanionBox from './CoursewareCompanionBox.vue';
+
+import CoursewareImport from '@/vue/mixins/courseware/import.js';
+import { mapActions, mapGetters } from 'vuex';
+import JSZip from 'jszip';
+
+export default {
+    name: 'courseware-manager-import',
+    components: {
+        CoursewareCompanionBox,
+    },
+    mixins: [CoursewareImport],
+    data() {
+        return {
+            importBehavior: 'default',
+            importRunning: false,
+            importZip: null,
+            zip: null
+        }
+    },
+    computed: {
+        ...mapGetters({
+            courseware: 'courseware',
+            importFilesState: 'importFilesState',
+            importFilesProgress: 'importFilesProgress',
+            importStructuresState: 'importStructuresState',
+            importStructuresProgress: 'importStructuresProgress',
+            importErrors: 'importErrors',
+        }),
+        fileImportDone() {
+            return this.importFilesProgress === 100;
+        },
+        importDone() {
+            return this.importFilesProgress === 100 && this.importStructuresProgress === 100;
+        }
+    },
+    methods: {
+        ...mapActions({
+            loadCoursewareStructure: 'courseware-structure/load',
+            setImportFilesProgress: 'setImportFilesProgress',
+            setImportStructuresProgress: 'setImportStructuresProgress',
+            setImportErrors: 'setImportErrors',
+        }),
+
+        setImport(event) {
+            this.importZip = event.target.files[0];
+            this.setImportFilesProgress(0);
+            this.setImportStructuresProgress(0);
+            this.setImportErrors([]);
+        },
+
+        async doImportCourseware() {
+            if (this.importZip === null) {
+                return false;
+            }
+
+            this.importRunning = true;
+
+            let view = this;
+
+            view.zip = new JSZip();
+
+            await view.zip.loadAsync(this.importZip).then(async function () {
+                let errors = [];
+                let missingFiles = false;
+                if (view.zip.file('courseware.json') === null) {
+                    errors.push(view.$gettext('Das Archiv enthält keine courseware.json Datei.'));
+                    missingFiles = true;
+                }
+                if (view.zip.file('files.json') === null) {
+                    errors.push(view.$gettext('Das Archiv enthält keine files.json Datei.'));
+                    missingFiles = true;
+                }
+                if (view.zip.file('data.xml') !== null) {
+                    errors.push(view.$gettext(
+                        'Das Archiv enthält eine data.xml Datei. Möglicherweise handelt es sich um einen Export aus dem Courseware-Plugin. Diese Archive sind nicht kompatibel mit dieser Courseware.'
+                    ));
+                }
+                if (missingFiles) {
+                    view.setImportErrors(errors);
+                    return;
+                }
+
+                let data = await view.zip.file('courseware.json').async('string');
+                let courseware = null;
+                let data_files = await view.zip.file('files.json').async('string');
+                let files = null;
+                let jsonErrors = false;
+                try {
+                    courseware = JSON.parse(data);
+                } catch (error) {
+                    jsonErrors = true;
+                    errors.push(view.$gettext('Die Beschreibung der Courseware-Inhalte ist nicht valide.'));
+                    errors.push(error);
+                }
+                try {
+                    files = JSON.parse(data_files);
+                } catch (error) {
+                    jsonErrors = true;
+                    errors.push(view.$gettext('Die Beschreibung der Dateien ist nicht valide.'));
+                    errors.push(error);
+                }
+                if (jsonErrors) {
+                    view.setImportErrors(errors);
+                    return;
+                }
+
+                await view.loadCoursewareStructure();
+                const rootId = view.courseware.relationships.root.data.id;
+
+                await view.importCourseware(courseware, rootId, files, view.importBehavior);
+            });
+
+            this.importZip = null;
+            this.importRunning = false;
+            this.$refs.importFile.value = '';
+        },
+
+        getFileSizeText(size) {
+            if (size / 1024 < 1000) {
+                return (size / 1024).toFixed(2) + ' kB';
+            } else {
+                return (size / 1048576).toFixed(2) + ' MB';
+            }
+        },
+    },
+    mounted() {
+        let view = this;
+
+        window.onbeforeunload = function() {
+            return view.importRunning ? true : null
+        }
+    }
+}
+</script>
diff --git a/resources/vue/mixins/courseware/import.js b/resources/vue/mixins/courseware/import.js
index 9f84905087908e32d89ba9502e57b48c8175c34c..406a3b81299f17f657b49a5fde6c0b1fe1e20eb3 100755
--- a/resources/vue/mixins/courseware/import.js
+++ b/resources/vue/mixins/courseware/import.js
@@ -14,13 +14,18 @@ export default {
     computed: {
         ...mapGetters({
             context: 'context',
-            courseware: 'courseware-instances/all'
+            courseware: 'courseware-instances/all',
+            structuralElementById: 'courseware-structural-elements/byId',
         }),
     },
 
     methods: {
+        ...mapActions({
+            loadStructuralElementById: 'courseware-structural-elements/loadById',
+            updateStructuralElement: 'updateStructuralElement'
+        }),
 
-        async importCourseware(element, parent_id, files)
+        async importCourseware(element, rootId, files, importBehavior)
         {
             // import all files
             await this.uploadAllFiles(files);
@@ -30,8 +35,12 @@ export default {
             this.importElementCounter = 0;
             this.setImportErrors([]);
 
-            await this.importStructuralElement([element], parent_id, files);
-
+            if (importBehavior === 'default') {
+                await this.importStructuralElement([element], rootId, files);
+            }
+            if (importBehavior === 'migrate') {
+                await this.migrateCourseware(element, rootId, files);
+            }
         },
 
         countImportElements(element) {
@@ -60,32 +69,94 @@ export default {
             return counter;
         },
 
+        async migrateCourseware(element, rootId, files) {
+            let root = this.structuralElementById({ id: rootId });
+            // add containers and blocks
+            if (element.containers?.length > 0) {
+                for (let i = 0; i < element.containers.length; i++) {
+                    await this.importContainer(element.containers[i], root, files);
+                }
+            }
+            //compare payload
+            let changedData = false;
+            if (root.attributes.title === 'neue Seite') {
+                root.attributes.title = element.attributes.title;
+                changedData = true;
+            }
+            if (root.attributes.purpose === '') {
+                root.attributes.purpose = element.attributes.purpose;
+                changedData = true;
+            }
+            if (element.attributes.payload) {
+                if (!root.attributes.payload.color && element.attributes.payload.color) {
+                    root.attributes.payload.color = element.attributes.payload.color;
+                    changedData = true;
+                }
+                if (!root.attributes.payload.description && element.attributes.payload.description) {
+                    root.attributes.payload.description = element.attributes.payload.description;
+                    changedData = true;
+                }
+                if (!root.attributes.payload.license_type && element.attributes.payload.license_type) {
+                    root.attributes.payload.license_type = element.attributes.payload.license_type;
+                    changedData = true;
+                }
+                if (!root.attributes.payload.required_time && element.attributes.payload.required_time) {
+                    root.attributes.payload.required_time = element.attributes.payload.required_time;
+                    changedData = true;
+                }
+                if (!root.attributes.payload.difficulty_start && element.attributes.payload.difficulty_start) {
+                    root.attributes.payload.difficulty_start = element.attributes.payload.difficulty_start;
+                    changedData = true;
+                }
+                if (!root.attributes.payload.difficulty_end && element.attributes.payload.difficulty_end) {
+                    root.attributes.payload.difficulty_end = element.attributes.payload.difficulty_end;
+                    changedData = true;
+                }
+            }
+            if (changedData) {
+                await this.lockObject({ id: root.id, type: 'courseware-structural-elements' });
+                await this.updateStructuralElement({
+                    element: root,
+                    id: root.id,
+                });
+                await this.unlockObject({ id: root.id, type: 'courseware-structural-elements' });
+            }
+            // compare image
+            if (element.imageId && root.relationships.image.data === null) {
+                await this.setStructuralElementImage(root, element.imageId, files);
+            }
+
+            // add children
+            if (element.children) {
+                await this.importStructuralElement(element.children, rootId, files);
+            }
+
+            this.setImportStructuresProgress(100);
+        },
+
         async importStructuralElement(element, parent_id, files) {
             if (element.length) {
                 for (var i = 0; i < element.length; i++) {
                     this.setImportStructuresState(this.$gettext('Lege Seite an:') + ' ' + element[i].attributes.title);
-                    await this.createStructuralElement({
-                        attributes: element[i].attributes,
-                        parentId: parent_id,
-                        currentId: parent_id,
-                    });
+                    try {
+                        await this.createStructuralElement({
+                            attributes: element[i].attributes,
+                            parentId: parent_id,
+                            currentId: parent_id,
+                        });
+                    } catch(error) {
+                        this.currentImportErrors.push(this.$gettext('Seite konnte nicht erstellt werden') + ': ' 
+                        + element.attributes.title);
+
+                        continue;
+                    }
+
                     this.importElementCounter++;
 
                     let new_element = this.$store.getters['courseware-structural-elements/lastCreated'];
 
                     if (element[i].imageId) {
-                        let imageFile = files.find((file) => { return file.id === element[i].imageId});
-                        let zip_filedata = await this.zip.file(imageFile.id).async('blob');
-                        // create new blob with correct type
-                        let filedata = zip_filedata.slice(0, zip_filedata.size, imageFile.attributes['mime-type']);
-                        this.setImportStructuresState(this.$gettext('Lade Vorschaubild hoch'));
-                        this.uploadImageForStructuralElement({
-                            structuralElement: new_element,
-                            file: filedata,
-                        }).catch((error) => {
-                            console.error(error);
-                            this.currentImportErrors.push(this.$gettext('Fehler beim Hochladen des Vorschaubildes.'));
-                        });
+                        await this.setStructuralElementImage(new_element, element[i].imageId, files);
                     }
 
 
@@ -96,28 +167,60 @@ export default {
                     if (element[i].containers?.length > 0) {
                         for (var j = 0; j < element[i].containers.length; j++) {
                             let container = element[i].containers[j];
-                            // TODO: create element on server and fetch new id
-                            this.setImportStructuresState(this.$gettext('Lege Abschnitt an:') + ' ' + container.attributes.title);
-                            await this.createContainer({
-                                attributes: container.attributes,
-                                structuralElementId: new_element.id,
-                            });
-                            this.importElementCounter++;
+                            await this.importContainer(container, new_element, files);
+                        }
+                    }
+                }
+            }
+        },
 
-                            let new_container = this.$store.getters['courseware-containers/lastCreated'];
-                            await this.unlockObject({ id: new_container.id, type: 'courseware-containers' });
+        async setStructuralElementImage(new_element, imageId, files) {
+            let imageFile = files.find((file) => { return file.id === imageId});
+            let zip_filedata = await this.zip.file(imageFile.id).async('blob');
+            // create new blob with correct type
+            let filedata = zip_filedata.slice(0, zip_filedata.size, imageFile.attributes['mime-type']);
+            this.setImportStructuresState(this.$gettext('Lade Vorschaubild hoch'));
+            this.uploadImageForStructuralElement({
+                structuralElement: new_element,
+                file: filedata,
+            }).catch((error) => {
+                console.error(error);
+                this.currentImportErrors.push(this.$gettext('Fehler beim Hochladen des Vorschaubildes.'));
+            });
+        },
 
-                            if (container.blocks?.length) {
-                                let new_block = null;
-                                for (var k = 0; k < container.blocks.length; k++) {
-                                    new_block = await this.importBlock(container.blocks[k], new_container, files, new_element);
-                                    if (new_block !== null) {
-                                        this.importElementCounter++;
-                                        await this.updateContainerPayload(new_container, new_element.id, container.blocks[k].id, new_block.id);
-                                    }
-                                }
+        async importContainer(container, structuralElement, files) {
+            this.setImportStructuresState(this.$gettext('Lege Abschnitt an:') + ' ' + container.attributes.title);
+            try {
+                await this.createContainer({
+                    attributes: container.attributes,
+                    structuralElementId: structuralElement.id,
+                });
+                
+            } catch(error) {
+                this.currentImportErrors.push(this.$gettext('Abschnitt konnte nicht erstellt werden') + ': ' 
+                + structuralElement.attributes.title + '→'
+                + block_container.attributes.title);
 
-                            }
+                return null;
+            }
+
+            this.importElementCounter++;
+            let new_container = this.$store.getters['courseware-containers/lastCreated'];
+            await this.unlockObject({ id: new_container.id, type: 'courseware-containers' });
+
+            if (container.blocks?.length) {
+                let new_block = null;
+                for (var k = 0; k < container.blocks.length; k++) {
+                    new_block = await this.importBlock(container.blocks[k], new_container, files, structuralElement);
+                    if (new_block !== null) {
+                        this.importElementCounter++;
+                        try {
+                            await this.updateContainerPayload(new_container, structuralElement.id, container.blocks[k].id, new_block.id);
+                        } catch(error) {
+                            this.currentImportErrors.push(this.$gettext('Abschnittdaten sind beschädigt. Möglicherweise werden nicht alle Blöcke dargestellt') + ': ' 
+                            + structuralElement.attributes.title + '→'
+                            + block_container.attributes.title);
                         }
                     }
                 }
@@ -164,7 +267,7 @@ export default {
                 });
             } catch(error) {
                 
-                this.currentImportErrors.push(this.$gettext('Blockdaten sind beschädigt. Es werden die Standardwerte eingesetzt.') + ': ' 
+                this.currentImportErrors.push(this.$gettext('Blockdaten sind beschädigt. Es werden die Standardwerte eingesetzt') + ': ' 
                     + element.attributes.title + '→'
                     + block_container.attributes.title + '→'
                     + block.attributes.title);
@@ -194,20 +297,37 @@ export default {
         },
 
         async uploadAllFiles(files) {
+            let createFolder = false;
+            for (let i = 0; i < files.length; i++) {
+                if (files[i].folder !== null) {
+                    createFolder = true;
+                }
+            }
+            if (files.length === 0 || !createFolder) {
+                this.setImportFilesProgress(100);
+                this.setImportFilesState('');
+                return true;
+            }
             // create folder for importing the files into
             this.setImportFilesProgress(0);
             this.setImportFilesState('');
             let now = new Date();
             this.setImportFilesState(this.$gettext('Lege Import Ordner an...'));
-            let main_folder = await this.createRootFolder({
-                context: this.context,
-                folder: {
-                    type: 'StandardFolder',
-                    name: ' CoursewareImport '
-                        + now.toLocaleString('de-DE', { timeZone: 'UTC' })
-                        + ' ' + now.getMilliseconds(),
-                }
-            });
+            let main_folder = null;
+            try {
+                main_folder = await this.createRootFolder({
+                    context: this.context,
+                    folder: {
+                        type: 'StandardFolder',
+                        name: ' CoursewareImport '
+                            + now.toLocaleString('de-DE', { timeZone: 'UTC' })
+                            + ' ' + now.getMilliseconds(),
+                    }
+                });
+            } catch(error) {
+                this.currentImportErrors.push(this.$gettext('Anlegen des Import-Ordners fehlgeschlagen.'));
+            }
+
 
             let folders = {};
 
diff --git a/resources/vue/mixins/courseware/task-helper.js b/resources/vue/mixins/courseware/task-helper.js
new file mode 100755
index 0000000000000000000000000000000000000000..ecf4ff304921c3456d2a117dff14b47b6612ae61
--- /dev/null
+++ b/resources/vue/mixins/courseware/task-helper.js
@@ -0,0 +1,66 @@
+export default {
+    methods: {
+        getStatus(task) {
+            let status = {};
+            const now = new Date(Date.now());
+            const submissionDate = new Date(task.attributes['submission-date']);
+            let limit = new Date();
+            limit.setDate(now.getDate() + 3);
+            status.canSubmit = true;
+
+            if (now < submissionDate) {
+                status.shape = 'span-empty';
+                status.role = 'status-green';
+                status.description = this.$gettext('Aufgabe bereit');
+            }
+            if (task.attributes.renewal !== 'granted') {
+                if (limit > submissionDate) {
+                    status.shape = 'span-3quarter';
+                    status.role = 'status-yellow';
+                    status.description = this.$gettext('Aufgabe muss bald abgegeben werden');
+                }
+
+                if (now >= submissionDate) {
+                    status.canSubmit = false;
+                    status.shape = 'span-full';
+                    status.role = 'status-red';
+                    status.description = this.$gettext('Abgabe ist nicht bis zur Abgabefrist erfolgt');
+                }
+            } else {
+                const renewalDate = new Date(task.attributes['renewal-date']);
+                if (limit > renewalDate) {
+                    status.shape = 'span-3quarter';
+                    status.role = 'status-yellow';
+                    status.description = this.$gettext('Aufgabe muss bald abgegeben werden');
+                }
+
+                if (now >= renewalDate) {
+                    status.canSubmit = false;
+                    status.shape = 'span-full';
+                    status.role = 'status-red';
+                    status.description = this.$gettext('Abgabe ist nicht bis zur verlängerten Abgabefrist erfolgt');
+                }
+            }
+
+            if (task.attributes.submitted) {
+                status.shape = 'span-full';
+                status.role = 'status-green';
+                status.description = this.$gettext('Aufgabe abgegeben');
+            }
+
+            return status;
+        },
+        getLinkToElement(elementId) {
+            return (
+                STUDIP.URLHelper.base_url +
+                'dispatch.php/course/courseware/?cid=' +
+                STUDIP.URLHelper.parameters.cid +
+                '#/structural_element/' +
+                elementId
+            );
+        },
+        getReadableDate(date) {
+            return new Date(date).toLocaleDateString();
+        },
+    },
+};
diff --git a/resources/vue/store/courseware/courseware.module.js b/resources/vue/store/courseware/courseware.module.js
index 94d537824859dfe4113a8957b8fd6e54ba2ec03f..8b67c758b3058eb69dfd51c82c8685cba91c4354 100755
--- a/resources/vue/store/courseware/courseware.module.js
+++ b/resources/vue/store/courseware/courseware.module.js
@@ -321,10 +321,10 @@ export const actions = {
             // console.log(resp);
         });
     },
-    async copyStructuralElement({ dispatch, getters, rootGetters }, { parentId, element }) {
-        const copy = { data: { parent_id: parentId, }, };
+    async copyStructuralElement({ dispatch, getters, rootGetters }, { parentId, elementId, removePurpose, migrate }) {
+        const copy = { data: { parent_id: parentId, remove_purpose: removePurpose, migrate: migrate } };
 
-        const result = await state.httpClient.post(`courseware-structural-elements/${element.id}/copy`, copy);
+        const result = await state.httpClient.post(`courseware-structural-elements/${elementId}/copy`, copy);
         const id = result.data.data.id;
         await dispatch('loadStructuralElement', id);