From 872a1a9591ceceb716e7ce4766c881811499a382 Mon Sep 17 00:00:00 2001
From: Ron Lucke <lucke@elan-ev.de>
Date: Tue, 10 May 2022 04:42:09 +0000
Subject: [PATCH] fix #954

Closes #954

Merge request studip/studip!597
---
 .../assets/stylesheets/scss/courseware.scss   | 13 +++
 .../CoursewareTableOfContentsBlock.vue        | 82 ++++++++++++++-----
 2 files changed, 76 insertions(+), 19 deletions(-)

diff --git a/resources/assets/stylesheets/scss/courseware.scss b/resources/assets/stylesheets/scss/courseware.scss
index 66620cbea6f..c1a8d90b7c6 100755
--- a/resources/assets/stylesheets/scss/courseware.scss
+++ b/resources/assets/stylesheets/scss/courseware.scss
@@ -4237,6 +4237,19 @@ cw tiles
         &.default-image {
                 @include background-icon(courseware, clickable, 128);
         }
+
+        .overlay-text {
+            padding: 0.25em;
+            margin: 0.25em;
+            background-color: rgba(255,255,255,0.8);
+            width: fit-content;
+            max-width: 100%;
+            height: 1.25em;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            float: right;
+            text-align: right;
+        }
     }
     .description {
         height: 220px;
diff --git a/resources/vue/components/courseware/CoursewareTableOfContentsBlock.vue b/resources/vue/components/courseware/CoursewareTableOfContentsBlock.vue
index 8b74759d43e..8f43d08fa9b 100755
--- a/resources/vue/components/courseware/CoursewareTableOfContentsBlock.vue
+++ b/resources/vue/components/courseware/CoursewareTableOfContentsBlock.vue
@@ -14,33 +14,40 @@
                     v-if="currentStyle === 'list-details' || currentStyle === 'list'"
                     :class="['cw-block-table-of-contents-' + currentStyle]"
                 >
-                    <li v-for="child in childElements" :key="child.id">
+                    <li v-for="child in childElementsWithTasks" :key="child.id">
                         <router-link :to="'/structural_element/' + child.id">
                             <div class="cw-block-table-of-contents-title-box" :class="[child.attributes.payload.color]">
                                 {{ child.attributes.title }}
+                                <span v-if="child.attributes.purpose === 'task'"> | {{ child.solverName }}</span>
                                 <p v-if="currentStyle === 'list-details'">{{ child.attributes.payload.description }}</p>
                             </div>
                         </router-link>
                     </li>
                 </ul>
                 <ul
-                    v-if="currentStyle === 'tiles'" 
+                    v-if="currentStyle === 'tiles'"
                     class="cw-block-table-of-contents-tiles cw-tiles"
                 >
                     <li
-                        v-for="child in childElements"
+                        v-for="child in childElementsWithTasks"
                         :key="child.id"
                         class="tile"
                         :class="[child.attributes.payload.color]"
                     >
-                        <router-link :to="'/structural_element/' + child.id" :title="child.attributes.title">
+                        <router-link :to="'/structural_element/' + child.id" :title="child.attributes.purpose === 'task' ? child.attributes.title + ' | ' + child.solverName : child.attributes.title">
                             <div
                                 class="preview-image"
                                 :class="[hasImage(child) ? '' : 'default-image']"
                                 :style="getChildStyle(child)"
-                            ></div>
+                            >
+                                <div v-if="child.attributes.purpose === 'task'" class="overlay-text">{{ child.solverName }}</div>
+                            </div>
                             <div class="description">
-                                <header>{{ child.attributes.title }}</header>
+                                <header
+                                    :class="[child.attributes.purpose !== '' ? 'description-icon-' + child.attributes.purpose : '']"
+                                >
+                                    {{ child.attributes.title || "–"}}
+                                </header>
                                 <div class="description-text-wrapper">
                                     <p>{{ child.attributes.payload.description }}</p>
                                 </div>
@@ -103,6 +110,10 @@ export default {
         ...mapGetters({
             childrenById: 'courseware-structure/children',
             structuralElementById: 'courseware-structural-elements/byId',
+            context: 'context',
+            taskById: 'courseware-tasks/byId',
+            userById: 'users/byId',
+            groupById: 'status-groups/byId',
         }),
         structuralElement() {
             return this.structuralElementById({ id: this.$route.params.id });
@@ -116,29 +127,42 @@ export default {
         style() {
             return this.block?.attributes?.payload?.style;
         },
-        childSets() {
-            let childSets = [];
-            let childElements = this.childElements;
-            while (childElements.length > 0) {
-                let set = [];
-                for (let i = 0; i < 4; i++) {
-                    let elem = childElements.shift();
-                    if (elem !== undefined) {
-                        set.push(elem);
+        childElementsWithTasks() {
+            let children = [];
+            this.childElements.forEach(element => {
+                if (element.relationships.task.data) {
+                    let solverName = this.getSolverName(element.relationships.task.data.id);
+                    if (solverName) {
+                        element.solverName = solverName;
+                        children.push(element);
                     }
+                } else {
+                    children.push(element);
                 }
-                childSets.push(set);
-            }
+            });
 
-            return childSets;
+            return children;
         }
     },
     mounted() {
         this.initCurrentData();
+        this.childElements.forEach(element => {
+            if (element.relationships.task.data) {
+                const taskId = element.relationships.task.data.id;
+                try {
+                    this.loadTask({
+                        taskId: taskId,
+                    });
+                } catch(error) {
+                    console.debug(error);
+                }
+            }
+        });
     },
     methods: {
         ...mapActions({
             updateBlock: 'updateBlockInContainer',
+            loadTask: 'loadTask',
         }),
         initCurrentData() {
             this.currentTitle = this.title;
@@ -169,11 +193,31 @@ export default {
             }
         },
         countChildChildren(child) {
-            return this.childrenById(child.id).length;
+            return this.childrenById(child.id).length + 1;
         },
         hasImage(child) {
             return child.relationships?.image?.data !== null;
         },
+
+        getSolverName(taskId) {
+            const task = this.taskById({ id: taskId});
+            if (task === undefined) {
+                return false;
+            }
+            const solver = task.relationships.solver.data;
+            if (solver.type === 'users') {
+                const user = this.userById({ id: solver.id });
+
+                return user.attributes['formatted-name'];
+            }
+            if (solver.type === 'status-groups') {
+                const group = this.groupById({ id: solver.id });
+
+                return group.attributes.name;
+            }
+
+            return false;
+        }
     },
 };
 </script>
-- 
GitLab