Skip to content
Snippets Groups Projects
IndexApp.vue 3.81 KiB
Newer Older
<template>
    <div v-if="courseware">
        <courseware-structural-element
            :structural-element="selected"
            :ordered-structural-elements="orderedStructuralElements"
            @select="selectStructuralElement"
        ></courseware-structural-element>
        <MountingPortal mountTo="#courseware-action-widget" name="sidebar-actions">
            <courseware-action-widget :structural-element="selected"></courseware-action-widget>
        </MountingPortal>
        <MountingPortal mountTo="#courseware-view-widget" name="sidebar-views">
            <courseware-view-widget></courseware-view-widget>
        </MountingPortal>
    </div>
    <div v-else><translate>Inhalte werden geladen</translate>...</div>
</template>

<script>
import CoursewareStructuralElement from './CoursewareStructuralElement.vue';
import CoursewareViewWidget from './CoursewareViewWidget.vue';
import CoursewareActionWidget from './CoursewareActionWidget.vue';
import { mapActions, mapGetters } from 'vuex';

export default {
    components: {
        CoursewareStructuralElement,
        CoursewareViewWidget,
        CoursewareActionWidget,
    },
    data: () => ({
        selected: null,
        orderedStructuralElements: [],
    }),
        ...mapGetters({
            courseware: 'courseware',
            relatedStructuralElement: 'courseware-structural-elements/related',
            structuralElements: 'courseware-structural-elements/all',
            structuralElementById: 'courseware-structural-elements/byId',
            userId: 'userId',
        }),
        ...mapActions([
            'coursewareBlockAdder',
            'loadCoursewareStructure',
            'loadStructuralElement',
            'loadTeacherStatus',
        ]),
        async selectStructuralElement(id) {
            if (!id) {
                return;
            }

            await this.loadStructuralElement(id);
            this.selected = this.structuralElementById({ id });
        },
    },
    async mounted() {
        await this.loadCoursewareStructure();
        await this.loadTeacherStatus(this.userId);
        const selectedId = this.$route.params?.id;
        await this.selectStructuralElement(selectedId);
        $route(to) {
            // reset block adder on navigate
            this.coursewareBlockAdder({});

            const selectedId = to.params?.id;
            this.selectStructuralElement(selectedId);
        },
        structuralElements(newElements, oldElements) {
            const nodes = buildNodes(this.structuralElements, this.relatedStructuralElement.bind(this));
            this.orderedStructuralElements = [...visitTree(nodes, findRoot(nodes))];
        },
    },
};

function buildNodes(structuralElements, relatedStructuralElement) {
    return structuralElements.reduce((memo, element) => {
Ron Lucke's avatar
Ron Lucke committed
        if (element.attributes['can-read']) {
            memo.push({
                id: element.id,
                parent:
                    relatedStructuralElement({
                        parent: element,
                        relationship: 'parent',
                    })?.id ?? null,
Ron Lucke's avatar
Ron Lucke committed
                children:
                    relatedStructuralElement({
                        parent: element,
                        relationship: 'children',
                    })?.map((child) => child.id) ?? [],
            });
        }

        return memo;
    }, []);
}

function findRoot(nodes) {
    return nodes.find((node) => node.parent === null);
}

function findNode(nodes, id) {
    return nodes.find((node) => node.id === id);
}

function* visitTree(nodes, current) {
    if (current) {
        yield current.id;

        for (let index = 0; index < current.children.length; index++) {
            yield* visitTree(nodes, findNode(nodes, current.children[index]));