Skip to content
Snippets Groups Projects
CoursewareStructuralElement.vue 80 KiB
Newer Older
            if (!this.structuralElement) {
                return false;
            }
            return this.structuralElement.attributes['can-edit'];
        },
Ron Lucke's avatar
Ron Lucke committed
        canEditParent() {
            if (this.isRoot) {
                return false;
            }
            const parentId = this.structuralElement.relationships.parent.data.id;
            const parent = this.structuralElementById({ id: parentId });

            return parent.attributes['can-edit'];
        },

        isRoot() {
            return this.structuralElement.relationships.parent.data === null;
        },

        editor() {
            const editor = this.relatedUsers({
                parent: this.structuralElement,
                relationship: 'editor',
            });

            return editor ?? null;
        },

        editorName() {
            return this.editor?.attributes['formatted-name'] ?? '?';
        menuItems() {
            let menu = [
Ron Lucke's avatar
Ron Lucke committed
                { id: 4, label: this.$gettext('Informationen anzeigen'), icon: 'info', emit: 'showInfo' },
                { id: 5, label: this.$gettext('Lesezeichen setzen'), icon: 'star', emit: 'setBookmark' },
                { id: 6, label: this.$gettext('Lerninhalt für OER Campus vorschlagen'), icon: 'oer-campus',
                    emit: 'showSuggest' }

            if (!document.documentElement.classList.contains('responsive-display')) {
                menu.push(
                    { id: 7, label: this.$gettext('Als Vollbild anzeigen'), icon: 'screen-full',
                        emit: 'activateFullscreen'},
                );
            }

            if (this.canEdit) {
Ron Lucke's avatar
Ron Lucke committed
                if (!this.blockedByAnotherUser) {
Ron Lucke's avatar
Ron Lucke committed
                    menu.push({
                        id: 1,
                        label: this.$gettext('Seite bearbeiten'),
                        icon: 'edit',
                        emit: 'editCurrentElement',
                    });
Ron Lucke's avatar
Ron Lucke committed
                if (this.blockedByAnotherUser && this.userIsTeacher) {
Ron Lucke's avatar
Ron Lucke committed
                    menu.push({
                        id: 1,
                        label: this.textRemoveLock.title,
                        icon: 'lock-unlocked',
                        emit: 'removeLock',
                    });
                }
Ron Lucke's avatar
Ron Lucke committed
                menu.push({ id: 3, label: this.$gettext('Seite hinzufügen'), icon: 'add', emit: 'addElement' });
            }
            if (this.context.type === 'users') {
                menu.push({ id: 8, label: this.$gettext('Öffentlichen Link erzeugen'), icon: 'group', emit: 'linkElement' });
Ron Lucke's avatar
Ron Lucke committed
            if (!this.isRoot && this.canEdit && !this.isTask && !this.blocked) {
Ron Lucke's avatar
Ron Lucke committed
                menu.push({
                    label: this.$gettext('Seite löschen'),
                    icon: 'trash',
                    emit: 'deleteCurrentElement',
                });
            }
            menu.sort((a, b) => a.id - b.id);

            return menu;
        },
        colors() {
            return this.mixinColors.filter(color => color.darkmode);
        },
        currentLicenseName() {
            for (let i = 0; i < this.licenses.length; i++) {
                if (this.licenses[i]['id'] == this.currentElement.attributes.payload.license_type) {
                    return this.licenses[i]['name'];
                }
            }

            return '';
        },
Ron Lucke's avatar
Ron Lucke committed
        blockingUser() {
            if (this.blockedByAnotherUser) {
                return this.userById({id: this.blockerId});
            }

            return null;
Ron Lucke's avatar
Ron Lucke committed
        },
Ron Lucke's avatar
Ron Lucke committed
        blockingUserName() {
            return this.blockingUser ? this.blockingUser.attributes['formatted-name'] : '';
Ron Lucke's avatar
Ron Lucke committed
        },
Ron Lucke's avatar
Ron Lucke committed
        discussView() {
            return this.viewMode === 'discuss';
        },
        editView() {
            return this.viewMode === 'edit';
        },
Ron Lucke's avatar
Ron Lucke committed
        pdfExportURL() {
            if (this.context.type === 'users') {
                return STUDIP.URLHelper.getURL(
                    'dispatch.php/contents/courseware/pdf_export/' + this.structuralElement.id
                );
            }
            if (this.context.type === 'courses') {
                return STUDIP.URLHelper.getURL(
                    'dispatch.php/course/courseware/pdf_export/' + this.structuralElement.id
                );
            }

            return '';
        },
        isTask() {
            return this.structuralElement?.relationships.task.data !== null;
        },
        task() {
            if (!this.isTask) {
                return null;
            }

            return this.taskById({ id: this.structuralElement.relationships.task.data.id });
        },
Ron Lucke's avatar
Ron Lucke committed
        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 '';
        },
Ron Lucke's avatar
Ron Lucke committed
        canAddElements() {
            if (!this.isTask) {
                return true;
            }

            // still loading
            if (!this.task) {
                return false;
            }

            const taskGroup = this.relatedTaskGroups({ parent: this.task, relationship: 'task-group' });

            return taskGroup?.attributes['solver-may-add-blocks'];
        },
        showEmptyElementBox() {
            if (!this.empty) {
                return false;
            }

            return (
                (!this.isRoot && this.canEdit) || !this.canEdit || (!this.noContainers && this.isRoot && this.canEdit)
            );
        },

        linkedElement() {
            if (this.isLink) {
                return this.structuralElementById({ id: this.structuralElement.attributes['target-id']});
            }

            return null;
        },

        linkedContainers() {
            let containers = [];
            let relatedContainers = this.linkedElement?.relationships?.containers?.data;

            if (relatedContainers) {
                for (const container of relatedContainers) {
                    containers.push(this.containerById({ id: container.id}));
                }
            }

            return containers;
        },
            const owner = this.relatedUsers({
                parent: this.structuralElement,
                relationship: 'owner',
            return owner ?? null;
            return this.owner?.attributes['formatted-name'] ?? '?';
        selectableTemplates() {
            return this.templates.filter(template => {
Ron Lucke's avatar
Ron Lucke committed
                return template.attributes.purpose === this.newChapterPurpose
Ron Lucke's avatar
Ron Lucke committed
            createStructuralElementWithTemplate: 'createStructuralElementWithTemplate',
            updateStructuralElement: 'updateStructuralElement',
            deleteStructuralElement: 'deleteStructuralElement',
            lockObject: 'lockObject',
            unlockObject: 'unlockObject',
            addBookmark: 'addBookmark',
            companionInfo: 'companionInfo',
Ron Lucke's avatar
Ron Lucke committed
            companionWarning: 'companionWarning',
Ron Lucke's avatar
Ron Lucke committed
            companionError: 'companionError',
            uploadImageForStructuralElement: 'uploadImageForStructuralElement',
            deleteImageForStructuralElement: 'deleteImageForStructuralElement',
            companionSuccess: 'companionSuccess',
            showElementEditDialog: 'showElementEditDialog',
            showElementAddDialog: 'showElementAddDialog',
            showElementExportDialog: 'showElementExportDialog',
Ron Lucke's avatar
Ron Lucke committed
            showElementPdfExportDialog: 'showElementPdfExportDialog',
            showElementInfoDialog: 'showElementInfoDialog',
            showElementDeleteDialog: 'showElementDeleteDialog',
            showElementOerDialog: 'showElementOerDialog',
            showElementPublicLinkDialog: 'showElementPublicLinkDialog',
Ron Lucke's avatar
Ron Lucke committed
            showElementRemoveLockDialog: 'showElementRemoveLockDialog',
            updateShowSuggestOerDialog: 'updateShowSuggestOerDialog',
Ron Lucke's avatar
Ron Lucke committed
            updateContainer: 'updateContainer',
            sortContainersInStructualElements: 'sortContainersInStructualElements',
            loadTask: 'loadTask',
            loadStructuralElement: 'loadStructuralElement',
            createLink: 'createLink',
Ron Lucke's avatar
Ron Lucke committed
            setCurrentElementId: 'coursewareCurrentElement',
            this.currentElement = _.cloneDeep(this.structuralElement);
            this.uploadFileError = '';
            this.deletingPreviewImage = false;
        async menuAction(action) {
            switch (action) {
Ron Lucke's avatar
Ron Lucke committed
                case 'removeLock':
                    this.displayRemoveLockDialog();
                    break;
                case 'editCurrentElement':
Ron Lucke's avatar
Ron Lucke committed
                    await this.loadStructuralElement(this.currentId);
Ron Lucke's avatar
Ron Lucke committed
                    if (this.blockedByAnotherUser) {
                        this.companionInfo({ info: this.$gettext('Diese Seite wird bereits bearbeitet.') });

                        return false;
                    }
                    try {
                        await this.lockObject({ id: this.currentId, type: 'courseware-structural-elements' });
Ron Lucke's avatar
Ron Lucke committed
                    } catch(error) {
Ron Lucke's avatar
Ron Lucke committed
                        if (error.status === 409) {
                            this.companionInfo({ info: this.$gettext('Diese Seite wird bereits bearbeitet.') });
                        } else {
                            console.log(error);
                        }

                        return false;
                    }
Ron Lucke's avatar
Ron Lucke committed
                    this.initCurrent();
                    this.showElementEditDialog(true);
                    break;
                case 'addElement':
                    this.newChapterName = '';
                    this.newChapterParent = 'descendant';
Ron Lucke's avatar
Ron Lucke committed
                    this.errorEmptyChapterName = false;
                    this.showElementAddDialog(true);
                    break;
                case 'deleteCurrentElement':
Ron Lucke's avatar
Ron Lucke committed
                    await this.loadStructuralElement(this.currentId);
                    if (this.blockedByAnotherUser) {
                        this.companionInfo({
                            info: this.$gettextInterpolate(
                                this.$gettext('Löschen nicht möglich, da %{blockingUserName} die Seite bearbeitet.'),
                                {blockingUserName: this.blockingUserName}
                            )
                        });
Ron Lucke's avatar
Ron Lucke committed

                        return false;
                    }
                    await this.lockObject({ id: this.currentId, type: 'courseware-structural-elements' });
                    this.showElementDeleteDialog(true);
                    break;
                case 'showInfo':
                    this.showElementInfoDialog(true);
                    break;
                case 'showExportOptions':
                    this.showElementExportDialog(true);
                    break;
                case 'oerCurrentElement':
                    this.showElementOerDialog(true);
                    break;
                case 'showSuggest':
                    this.updateShowSuggestOerDialog(true);
                    break;
                case 'setBookmark':
                    this.setBookmark();
                    break;
                    this.showElementPublicLinkDialog(true);
                case 'activateFullscreen':
                    STUDIP.Fullscreen.activate();
                    break;
            }
        },
        async closeEditDialog() {
Ron Lucke's avatar
Ron Lucke committed
            await this.loadStructuralElement(this.currentElement.id);
            if (this.blockedByThisUser) {
                await this.unlockObject({ id: this.currentId, type: 'courseware-structural-elements' });
                await this.loadStructuralElement(this.currentElement.id);
            }
            this.showElementEditDialog(false);
            this.initCurrent();
        },
        closeAddDialog() {
            this.showElementAddDialog(false);
        },
        checkUploadFile() {
            const file = this.$refs?.upload_image?.files[0];
            if (file.size > 2097152) {
                this.uploadFileError = this.$gettext('Diese Datei ist zu groß. Bitte wählen Sie eine kleinere Datei.');
            } else if (!file.type.includes('image')) {
                this.uploadFileError = this.$gettext('Diese Datei ist kein Bild. Bitte wählen Sie ein Bild aus.');
            } else {
                this.uploadFileError = '';
            }
        },
        deleteImage() {
            if (!this.deletingPreviewImage) {
                this.deletingPreviewImage = true;
            }
        },
        async storeCurrentElement() {
Ron Lucke's avatar
Ron Lucke committed
            await this.loadStructuralElement(this.currentElement.id);
            if (this.blockedByAnotherUser) {
                this.companionWarning({
                    info: this.$gettextInterpolate(
                        this.$gettext('Ihre Änderungen konnten nicht gespeichert werden, da %{blockingUserName} die Bearbeitung übernommen hat.'),
                        {blockingUserName: this.blockingUserName}
                    )
                });
Ron Lucke's avatar
Ron Lucke committed
                this.showElementEditDialog(false);
                return false;
            }
            if (!this.blocked) {
                await this.lockObject({ id: this.currentId, type: 'courseware-structural-elements' });
            }
            const file = this.$refs?.upload_image?.files[0];
            if (file) {
                if (file.size > 2097152) {
                    return false;
                }

                this.uploadFileError = '';
                this.uploadImageForStructuralElement({
                    structuralElement: this.currentElement,
                    file,
                }).catch((error) => {
                    console.error(error);
                    this.uploadFileError = this.$gettext('Fehler beim Hochladen der Datei.');
                });
                await this.loadStructuralElement(this.currentElement.id);
            } else if (this.deletingPreviewImage) {
                await this.deleteImageForStructuralElement(this.currentElement);
Ron Lucke's avatar
Ron Lucke committed
            this.showElementEditDialog(false);

            if (this.currentElement.attributes['release-date'] !== '') {
                this.currentElement.attributes['release-date'] =
                    new Date(this.currentElement.attributes['release-date']).getTime() / 1000;
            }

            if (this.currentElement.attributes['withdraw-date'] !== '') {
                this.currentElement.attributes['withdraw-date'] =
                    new Date(this.currentElement.attributes['withdraw-date']).getTime() / 1000;
            }

            await this.updateStructuralElement({
                element: this.currentElement,
                id: this.currentId,
            });
            await this.unlockObject({ id: this.currentId, type: 'courseware-structural-elements' });
            this.$emit('select', this.currentId);
Ron Lucke's avatar
Ron Lucke committed
            this.initCurrent();
        dropContainer() {
            this.isDragging = false;
            this.storeSort();
Ron Lucke's avatar
Ron Lucke committed
        },

        async storeSort() {
            const timeout = setTimeout(() => this.processing = true, 800);
            if (this.blockedByAnotherUser) {
                this.companionInfo({ info: this.$gettext('Diese Seite wird bereits bearbeitet.') });
                clearTimeout(timeout);
                this.processing = false;
                return false;
            }
            try {
                await this.lockObject({ id: this.currentId, type: 'courseware-structural-elements' });
            } catch (error) {
                if (error.status === 409) {
                    this.companionInfo({ info: this.$gettext('Diese Seite wird bereits bearbeitet.') });
                } else {
                    console.log(error);
                }
Ron Lucke's avatar
Ron Lucke committed

                clearTimeout(timeout);
                this.processing = false;
                return false;
            }

            await this.sortContainersInStructualElements({
Ron Lucke's avatar
Ron Lucke committed
                structuralElement: this.structuralElement,
                containers: this.containerList,
            });
            this.$emit('select', this.currentId);

            clearTimeout(timeout);
            this.processing = false;
Ron Lucke's avatar
Ron Lucke committed
        },

        async exportCurrentElement(data) {
            if (this.exportRunning) {
                return;
            }

            this.exportRunning = true;

            await this.sendExportZip(this.currentElement.id, {
                withChildren: this.exportChildren,
            });

            this.exportRunning = false;
            this.showElementExportDialog(false);
        },

Ron Lucke's avatar
Ron Lucke committed
        pdfExportCurrentElement() {
            this.showElementPdfExportDialog(false);
            let url = '';
            let withChildren = this.pdfExportChildren ? '/1' : '/0';
            if (this.context.type === 'users') {
                url = STUDIP.URLHelper.getURL('dispatch.php/contents/courseware/pdf_export/' + this.structuralElement.id + withChildren);
            }
            if (this.context.type === 'courses') {
                url = STUDIP.URLHelper.getURL('dispatch.php/course/courseware/pdf_export/' + this.structuralElement.id + withChildren);
            }

            if (url) {
                window.open(url , '_blank').focus();
            }
        },

        async publishCurrentElement() {
Ron Lucke's avatar
Ron Lucke committed
            if (this.oerExportRunning) {
                return;
            }
            this.oerExportRunning = true;
            await this.exportToOER(this.currentElement, { withChildren: this.oerChildren });
            this.oerExportRunning = false;
            this.showElementOerDialog(false);
        },

        async closeDeleteDialog() {
Ron Lucke's avatar
Ron Lucke committed
            await this.loadStructuralElement(this.currentElement.id);
            if (this.blockedByThisUser) {
                await this.unlockObject({ id: this.currentId, type: 'courseware-structural-elements' });
            }
            this.showElementDeleteDialog(false);
        },
Ron Lucke's avatar
Ron Lucke committed
        async deleteCurrentElement() {
            await this.loadStructuralElement(this.currentElement.id);
            if (this.blockedByAnotherUser) {
                this.companionWarning({
                    info: this.$gettextInterpolate(
                        this.$gettext('Löschen nicht möglich, da %{blockingUserName} die Bearbeitung übernommen hat.'),
                        {blockingUserName: this.blockingUserName}
                    )
                });
Ron Lucke's avatar
Ron Lucke committed
                this.showElementDeleteDialog(false);
                return false;
            }
            let parent_id = this.structuralElement.relationships.parent.data.id;
Ron Lucke's avatar
Ron Lucke committed
            this.companionInfo({ info: this.$gettext('Lösche Seite und alle darunter liegenden Elemente.') });
            this.deleteStructuralElement({
                id: this.currentId,
                parentId: this.structuralElement.relationships.parent.data.id,
Ron Lucke's avatar
Ron Lucke committed
            })
            .then(response => {
                this.$router.push(parent_id);
                this.companionInfo({ info: this.$gettext('Die Seite wurde gelöscht.') });
            })
            .catch(error => {
                this.companionError({ info: this.$gettext('Die Seite konnte nicht gelöscht werden.') });
        async createElement() {
            const title = this.newChapterName; // this is the title of the new element
            const purpose = this.newChapterPurpose;
            let parent_id = this.currentId; // new page is descandant as default

            this.errorEmptyChapterName = title.trim();
            if (this.errorEmptyChapterName === '') {
Ron Lucke's avatar
Ron Lucke committed
                return;
            }
            if (this.newChapterParent === 'sibling') {
                parent_id = this.structuralElement.relationships.parent.data.id;
            }
            this.showElementAddDialog(false);
Ron Lucke's avatar
Ron Lucke committed
            this.createStructuralElementWithTemplate({
Ron Lucke's avatar
Ron Lucke committed
                    title: title,
                templateId: this.newChapterTemplate ? this.newChapterTemplate.id : null,
                parentId: parent_id,
                currentId: this.currentId,
Ron Lucke's avatar
Ron Lucke committed
            })
            .then(() => {
                let newElement = this.$store.getters['courseware-structural-elements/lastCreated'];
                this.companionSuccess({
                    info:
                        this.$gettextInterpolate(
                            this.$gettext('Die Seite %{ pageTitle } wurde erfolgreich angelegt.'),
Ron Lucke's avatar
Ron Lucke committed
                            { pageTitle: newElement.attributes.title }
                        )
                });
            })
            .catch(e => {
                let errorMessage = this.$gettext('Es ist ein Fehler aufgetreten. Die Seite konnte nicht erstellt werden.');
                if (e.status === 403) {
                    errorMessage = this.$gettext('Die Seite konnte nicht erstellt werden. Sie haben nicht die notwendigen Schreibrechte.');
                }

                this.companionError({ info: errorMessage });
Ron Lucke's avatar
Ron Lucke committed

            let newElement = this.lastCreatedElement;
            this.companionSuccess({
                info: this.$gettextInterpolate(
                    this.$gettext('Die Seite %{ pageTitle } wurde erfolgreich angelegt.'),
                    {pageTitle: newElement.attributes.title}
                )
            });
Ron Lucke's avatar
Ron Lucke committed
            this.newChapterName = '';
        },
        containerComponent(container) {
            return 'courseware-' + container.attributes['container-type'] + '-container';
        },
        setBookmark() {
            this.addBookmark(this.structuralElement);
Ron Lucke's avatar
Ron Lucke committed
            this.companionInfo({ info: this.$gettext('Das Lesezeichen wurde gesetzt.') });
        },
        updateReadApproval(approval) {
            this.currentElement.attributes['read-approval'] = approval;
        },
        updateWriteApproval(approval) {
            this.currentElement.attributes['write-approval'] = approval;
        },
        sendOerSuggestion() {
            this.suggestViaAction(this.currentElement, this.additionalText);
            this.updateShowSuggestOerDialog(false);
            const date = this.publicLink['expire-date'];
            const publicLink = {
                attributes: {
                    password: this.publicLink.password,
                    'expire-date': date === '' ? new Date(0).toISOString() : new Date(date).toISOString()
                },
                relationships: {
                    'structural-element': {
                        data: {
                            id: this.currentElement.id,
                            type: 'courseware-structural-elements'
                        }
                    }
                }
            }

            await this.createLink({ publicLink });
            this.companionSuccess({
                info: this.$gettext('Öffentlicher Link wurde angelegt. Unter Freigaben finden Sie alle Ihre öffentlichen Links.'),
            });
Jan-Hendrik Willms's avatar
Jan-Hendrik Willms committed
            this.closePublicLinkDialog();
Michaela Brückner's avatar
Michaela Brückner committed
            this.publicLink = {
                passsword: '',
                'expire-date': ''
            };
            this.showElementPublicLinkDialog(false);
Ron Lucke's avatar
Ron Lucke committed
        },
        displayRemoveLockDialog() {
            this.showElementRemoveLockDialog(true);
        },
        async executeRemoveLock() {
            await this.unlockObject({ id: this.currentId, type: 'courseware-structural-elements' });
            await this.loadStructuralElement(this.currentElement.id);
            this.showElementRemoveLockDialog(false);
        },
        updateContainerList() {
            this.containerList = this.containers;
            const containerRefs = this.$refs.containers;
            for (let ref of containerRefs) {
                ref.initCurrentData();
            }
        },
        keyHandler(e, containerId) {
            switch (e.keyCode) {
                case 27: // esc
                    this.abortKeyboardSorting(containerId);
                    break;
                case 32: // space
                    e.preventDefault();
                    if (this.keyboardSelected) {
                        this.storeKeyboardSorting(containerId);
                    } else {
                        this.keyboardSelected = containerId;
                        const container = this.containerById({id: containerId});
                        const index = this.containerList.findIndex(c => c.id === container.id);
                        this.assistiveLive =
                            this.$gettextInterpolate(
                                this.$gettext('%{containerTitle} Abschnitt ausgewählt. Aktuelle Position in der Liste: %{pos} von %{listLength}. Drücken Sie die Aufwärts- und Abwärtspfeiltasten, um die Position zu ändern, die Leertaste zum Ablegen, die Escape-Taste zum Abbrechen.')
                                , {containerTitle: container.attributes.title, pos: index + 1, listLength: this.containerList.length}
                            );
                    }
                    break;
            }
            if (this.keyboardSelected) {
                switch (e.keyCode) {
                    case 9: //tab
                        this.abortKeyboardSorting(containerId);
                        break;
                    case 38: // up
                        e.preventDefault();
                        this.moveItemUp(containerId);
                        break;
                    case 40: // down
                        e.preventDefault();
                        this.moveItemDown(containerId);
                        break;
                }
            }
        },
        moveItemUp(containerId) {
            const currentIndex = this.containerList.findIndex(container => container.id === containerId);
            if (currentIndex !== 0) {
                const container = this.containerById({id: containerId});
                const newPos = currentIndex - 1;
                this.containerList.splice(newPos, 0, this.containerList.splice(currentIndex, 1)[0]);
                this.assistiveLive =
                    this.$gettextInterpolate(
                        this.$gettext('%{containerTitle} Abschnitt. Aktuelle Position in der Liste: %{pos} von %{listLength}.')
                        , {containerTitle: container.attributes.title, pos: newPos + 1, listLength: this.containerList.length}
                    );
            }
        },
        moveItemDown(containerId) {
            const currentIndex = this.containerList.findIndex(container => container.id === containerId);
            if (this.containerList.length - 1 > currentIndex) {
                const container = this.containerById({id: containerId});
                const newPos = currentIndex + 1;
                this.containerList.splice(newPos, 0, this.containerList.splice(currentIndex, 1)[0]);
                this.assistiveLive =
                    this.$gettextInterpolate(
                        this.$gettext('%{containerTitle} Abschnitt. Aktuelle Position in der Liste: %{pos} von %{listLength}.')
                        , {containerTitle: container.attributes.title, pos: newPos + 1, listLength: this.containerList.length}
                    );
            }
        },
        abortKeyboardSorting(containerId) {
            const container = this.containerById({id: containerId});
            this.keyboardSelected = null;
            this.assistiveLive =
                    this.$gettext('%{containerTitle} Abschnitt, Neuordnung abgebrochen.')
                    , {containerTitle: container.attributes.title}
                );
            this.$emit('select', this.currentId);
        },
        storeKeyboardSorting(containerId) {
            const container = this.containerById({id: containerId});
            const currentIndex = this.containerList.findIndex(container => container.id === containerId);
            this.keyboardSelected = null;
            this.assistiveLive =
                this.$gettextInterpolate(
                    this.$gettext('%{containerTitle} Abschnitt, abgelegt. Entgültige Position in der Liste: %{pos} von %{listLength}.')
                    , {containerTitle: container.attributes.title, pos: currentIndex + 1, listLength: this.containerList.length}
                );
            this.storeSort();
    },
    created() {
        this.pluginManager.registerComponentsLocally(this);
    },
Ron Lucke's avatar
Ron Lucke committed
        async structuralElement() {
            this.setCurrentElementId(this.structuralElement.id);
Ron Lucke's avatar
Ron Lucke committed
            if (this.isTask) {
                this.loadTask({
                    taskId: this.structuralElement.relationships.task.data.id,
                });
            }

            if (this.isLink) {
                this.loadStructuralElement(this.structuralElement.attributes['target-id']);
            }
Ron Lucke's avatar
Ron Lucke committed
        },
        containers() {
Elmar Ludwig's avatar
Elmar Ludwig committed
            this.containerList = this.containers;
        containerList() {
            if (this.keyboardSelected) {
                this.$nextTick(() => {
                    const selected = this.$refs['sortableHandle' + this.keyboardSelected][0];
                    selected.focus();
                    selected.scrollIntoView({behavior: "smooth", block: "center"});
                });
            }
        },
Ron Lucke's avatar
Ron Lucke committed
        consumeMode(newState) {
            this.consumModeTrap = newState;
        },
    // this line provides all the components to courseware plugins
    provide: () => ({
        containerComponents: ContainerComponents,
        coursewarePluginComponents: CoursewarePluginComponents,
    }),