Skip to content
Snippets Groups Projects
Commit c4ec909e authored by mlunzena's avatar mlunzena Committed by Ron Lucke
Browse files

fix courseware's contentbar navigation

Fixes #280.
parent ac2575c6
No related branches found
No related tags found
No related merge requests found
...@@ -396,7 +396,7 @@ ...@@ -396,7 +396,7 @@
<script> <script>
import ContainerComponents from './container-components.js'; import ContainerComponents from './container-components.js';
import CoursewarePluginComponents from './plugin-components.js' import CoursewarePluginComponents from './plugin-components.js';
import CoursewareStructuralElementPermissions from './CoursewareStructuralElementPermissions.vue'; import CoursewareStructuralElementPermissions from './CoursewareStructuralElementPermissions.vue';
import CoursewareAccordionContainer from './CoursewareAccordionContainer.vue'; import CoursewareAccordionContainer from './CoursewareAccordionContainer.vue';
import CoursewareCompanionBox from './CoursewareCompanionBox.vue'; import CoursewareCompanionBox from './CoursewareCompanionBox.vue';
...@@ -430,7 +430,7 @@ export default { ...@@ -430,7 +430,7 @@ export default {
IsoDate, IsoDate,
StudipDialog, StudipDialog,
}, },
props: {}, props: ['orderedStructuralElements'],
mixins: [CoursewareExport], mixins: [CoursewareExport],
...@@ -481,6 +481,9 @@ export default { ...@@ -481,6 +481,9 @@ export default {
courseware: 'courseware', courseware: 'courseware',
consumeMode: 'consumeMode', consumeMode: 'consumeMode',
containerById: 'courseware-containers/byId', containerById: 'courseware-containers/byId',
relatedContainers: 'courseware-containers/related',
relatedStructuralElements: 'courseware-structural-elements/related',
relatedUsers: 'users/related',
structuralElementById: 'courseware-structural-elements/byId', structuralElementById: 'courseware-structural-elements/byId',
userIsTeacher: 'userIsTeacher', userIsTeacher: 'userIsTeacher',
pluginManager: 'pluginManager', pluginManager: 'pluginManager',
...@@ -494,7 +497,7 @@ export default { ...@@ -494,7 +497,7 @@ export default {
oerTitle: 'oerTitle', oerTitle: 'oerTitle',
licenses: 'licenses', licenses: 'licenses',
exportState: 'exportState', exportState: 'exportState',
exportProgress: 'exportProgress' exportProgress: 'exportProgress',
}), }),
textOer() { textOer() {
...@@ -502,7 +505,7 @@ export default { ...@@ -502,7 +505,7 @@ export default {
title: this.$gettext('Seite auf') + ' ' + this.oerTitle + ' ' + this.$gettext('veröffentlichen'), title: this.$gettext('Seite auf') + ' ' + this.oerTitle + ' ' + this.$gettext('veröffentlichen'),
confirm: this.$gettext('Veröffentlichen'), confirm: this.$gettext('Veröffentlichen'),
close: this.$gettext('Schließen'), close: this.$gettext('Schließen'),
} };
}, },
inCourse() { inCourse() {
...@@ -555,87 +558,38 @@ export default { ...@@ -555,87 +558,38 @@ export default {
}, },
ancestors() { ancestors() {
if (!this.currentElement) {
return [];
}
if (this.currentElement.relationships.ancestors.data) {
return this.currentElement.relationships.ancestors.data.map(({ id }) =>
this.structuralElementById({ id })
);
}
return [];
},
parent() {
if (!this.structuralElement) { if (!this.structuralElement) {
return []; return [];
} }
if (this.structuralElement.relationships.parent.data) {
let id = this.structuralElement.relationships.parent.data.id; return this.relatedStructuralElements({ parent: this.structuralElement, relationship: 'ancestors' });
return this.structuralElementById({ id });
}
return [];
},
hasSiblings() {
if (this.parent.length !== 0) {
return this.parent.relationships.children.data.length > 1;
} else {
return false;
}
}, },
prevElement() { prevElement() {
if (this.hasSiblings) { const currentIndex = this.orderedStructuralElements.indexOf(this.structuralElement.id);
let view = this; if (currentIndex <= 0) {
let siblings = this.parent.relationships.children.data;
let id = '';
siblings.forEach((el, index) => {
if (el.id === view.currentId && index !== 0) {
id = siblings[index - 1].id;
}
});
if (id === '') {
return this.parent;
} else {
return this.structuralElementById({ id });
}
} else if (this.parent.length !== 0) {
return this.parent;
} else {
return null; return null;
} }
const previousId = this.orderedStructuralElements[currentIndex - 1];
const previous = this.structuralElementById({ id: previousId });
return previous;
}, },
nextElement() { nextElement() {
let view = this; const currentIndex = this.orderedStructuralElements.indexOf(this.structuralElement.id);
if (this.structuralElement.relationships.children.data.length > 0) { const lastIndex = this.orderedStructuralElements.length - 1;
let id = this.structuralElement.relationships.children.data[0].id; if (currentIndex === -1 || currentIndex === lastIndex) {
return this.structuralElementById({ id }); return null;
} else if (this.hasSiblings) {
let siblings = this.parent.relationships.children.data;
let id = '';
siblings.forEach((el, index) => {
if (el.id === view.currentId && siblings.length > index + 1) {
id = siblings[index + 1].id;
}
});
if (id === '') {
return this.getNextParentSibling(this.currentId);
} else {
return this.structuralElementById({ id });
}
} else {
return this.getNextParentSibling(this.currentId);
} }
const nextId = this.orderedStructuralElements[currentIndex + 1];
const next = this.structuralElementById({ id: nextId });
return next;
}, },
empty() { empty() {
if (this.containers === null) { if (this.containers === null) {
return true; return true;
} else { } else {
let noBlockFound = true; return !this.containers.some((container) => container.relationships.blocks.data.length > 0);
this.containers.forEach((container) => {
if (container.relationships.blocks.data.length > 0) {
noBlockFound = false;
}
});
return noBlockFound;
} }
}, },
containers() { containers() {
...@@ -643,12 +597,12 @@ export default { ...@@ -643,12 +597,12 @@ export default {
return []; return [];
} }
const containers = this.$store.getters['courseware-containers/related']({ return (
this.relatedContainers({
parent: this.structuralElement, parent: this.structuralElement,
relationship: 'containers', relationship: 'containers',
}); }) ?? []
);
return containers;
}, },
noContainers() { noContainers() {
if (this.containers === null) { if (this.containers === null) {
...@@ -679,7 +633,7 @@ export default { ...@@ -679,7 +633,7 @@ export default {
}, },
owner() { owner() {
const owner = this.$store.getters['users/related']({ const owner = this.relatedUsers({
parent: this.structuralElement, parent: this.structuralElement,
relationship: 'owner', relationship: 'owner',
}); });
...@@ -688,7 +642,7 @@ export default { ...@@ -688,7 +642,7 @@ export default {
}, },
editor() { editor() {
const editor = this.$store.getters['users/related']({ const editor = this.relatedUsers({
parent: this.structuralElement, parent: this.structuralElement,
relationship: 'editor', relationship: 'editor',
}); });
...@@ -764,7 +718,7 @@ export default { ...@@ -764,7 +718,7 @@ export default {
}, },
}, },
async mounted() { mounted() {
if (!this.currentId) { if (!this.currentId) {
this.setCurrentId(this.$route.params.id); this.setCurrentId(this.$route.params.id);
} }
...@@ -797,7 +751,7 @@ export default { ...@@ -797,7 +751,7 @@ export default {
this.initCurrent(); this.initCurrent();
}, },
initCurrent() { initCurrent() {
this.currentElement = JSON.parse(JSON.stringify(this.structuralElement)); this.currentElement = _.cloneDeep(this.structuralElement);
this.uploadFileError = ''; this.uploadFileError = '';
}, },
async menuAction(action) { async menuAction(action) {
...@@ -941,29 +895,6 @@ export default { ...@@ -941,29 +895,6 @@ export default {
containerComponent(container) { containerComponent(container) {
return 'courseware-' + container.attributes['container-type'] + '-container'; return 'courseware-' + container.attributes['container-type'] + '-container';
}, },
getNextParentSibling(element_id) {
let current = this.structuralElementById({ id: element_id });
if (current.relationships.parent.data === null) {
return null;
}
let parent = this.structuralElementById({ id: current.relationships.parent.data.id });
if (parent.relationships.parent.data === null) {
return null;
}
let grandParent = this.structuralElementById({ id: parent.relationships.parent.data.id });
let parentSiblings = grandParent.relationships.children.data;
let id = '';
parentSiblings.forEach((el, index) => {
if (parseInt(el.id, 10) === parseInt(parent.id, 10) && parentSiblings.length > index + 1) {
id = parentSiblings[index + 1].id;
}
});
if (id === '') {
this.getNextParentSibling(parent.id);
} else {
return this.structuralElementById({ id });
}
},
setBookmark() { setBookmark() {
this.addBookmark(this.structuralElement); this.addBookmark(this.structuralElement);
this.companionInfo({ info: this.$gettext('Das Lesezeichen wurde gesetzt') }); this.companionInfo({ info: this.$gettext('Das Lesezeichen wurde gesetzt') });
......
<template> <template>
<div v-if="courseware"> <div v-if="courseware">
<courseware-structural-element></courseware-structural-element> <courseware-structural-element
:ordered-structural-elements="orderedStructuralElements"
></courseware-structural-element>
<MountingPortal mountTo="#courseware-action-widget" name="sidebar-actions"> <MountingPortal mountTo="#courseware-action-widget" name="sidebar-actions">
<courseware-action-widget></courseware-action-widget> <courseware-action-widget></courseware-action-widget>
</MountingPortal> </MountingPortal>
...@@ -25,8 +27,14 @@ export default { ...@@ -25,8 +27,14 @@ export default {
CoursewareViewWidget, CoursewareViewWidget,
CoursewareActionWidget, CoursewareActionWidget,
}, },
data: () => ({ orderedStructuralElements: [] }),
computed: { computed: {
...mapGetters(['courseware', 'userId', 'blockAdder']), ...mapGetters({
courseware: 'courseware',
relatedStructuralElement: 'courseware-structural-elements/related',
structuralElements: 'courseware-structural-elements/all',
userId: 'userId',
}),
}, },
methods: { methods: {
...mapActions(['loadCoursewareStructure', 'loadTeacherStatus', 'coursewareBlockAdder']), ...mapActions(['loadCoursewareStructure', 'loadTeacherStatus', 'coursewareBlockAdder']),
...@@ -34,12 +42,54 @@ export default { ...@@ -34,12 +42,54 @@ export default {
async mounted() { async mounted() {
await this.loadCoursewareStructure(); await this.loadCoursewareStructure();
await this.loadTeacherStatus(this.userId); await this.loadTeacherStatus(this.userId);
// console.debug('IndexApp mounted for courseware:', this.courseware, this.$store);
}, },
watch: { watch: {
$route() { $route() {
this.coursewareBlockAdder({}); //reset block adder on navigate this.coursewareBlockAdder({}); //reset block adder on navigate
},
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) => {
memo.push({
id: element.id,
parent:
relatedStructuralElement({
parent: element,
relationship: 'parent',
})?.id ?? null,
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]));
}
} }
} }
};
</script> </script>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment