From 5bb4a5c090f3bd72780a8c0cb475cd5f71761f2f Mon Sep 17 00:00:00 2001
From: NinaHerrmann <nina.herrmann@uni-muenster.de>
Date: Fri, 19 May 2023 13:38:28 +0200
Subject: [PATCH 1/2] WIP add link to overview to profile page TODO put content
 on pages

---
 lang/en/moodleoverflow.php |  9 +++++++-
 lib.php                    | 35 +++++++++++++++++++++++++++++-
 settings.php               |  5 +++++
 viewcontributingposts.php  | 43 +++++++++++++++++++++++++++++++++++++
 viewstartingdiscussion.php | 44 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 134 insertions(+), 2 deletions(-)
 create mode 100644 viewcontributingposts.php
 create mode 100644 viewstartingdiscussion.php

diff --git a/lang/en/moodleoverflow.php b/lang/en/moodleoverflow.php
index 13d0e76ec1..aca5b27209 100644
--- a/lang/en/moodleoverflow.php
+++ b/lang/en/moodleoverflow.php
@@ -196,6 +196,14 @@
 $string['answer'] = '{$a} Answer';
 $string['answers'] = '{$a} Answers';
 
+// Strings for Overview Pages
+$string['overviewdiscussions'] = 'Overview of all started discussions';
+$string['overviewposts'] = 'Overview of all posts';
+$string['viewdiscussions'] = 'View started Moodleoverflow discussions';
+$string['viewposts'] = 'View answers to Moodleoverflow discussions';
+$string['showoverviewprofilpage'] = 'Link Overview on Profile Page';
+$string['showoverviewprofilpage_desc'] = 'Show Links to Overview Pages in User Profile Page';
+
 // Strings for the readtracking.php.
 $string['markreadfailed'] = 'A post of the discussion could not be marked as read.';
 $string['markdiscussionreadsuccessful'] = 'The discussion has been marked as read.';
@@ -465,7 +473,6 @@
 $string['your_post_was_rejected_with_reason'] = 'Your post was rejected with the following reason:';
 $string['original_post'] = 'Original post';
 
-
 // Daily mail message.
 $string['digestunreadpost'] = 'Course: {$a->linktocourse} -> {$a->linktoforum}, Topic: {$a->linktodiscussion} has {$a->unreadposts} unread posts.';
 
diff --git a/lib.php b/lib.php
index 5ee67061d7..d2b46a8792 100644
--- a/lib.php
+++ b/lib.php
@@ -552,7 +552,40 @@ function moodleoverflow_extend_settings_navigation(settings_navigation $settings
         }
     }
 }
-
+/**
+ * Insert Overview of discussions and post in the Miscellaneous block in the my profile page.
+ *
+ * @param tree $tree tree
+ * @param stdClass $user user
+ * @param int $iscurrentuser iscurrentuser
+ */
+function moodleoverflow_myprofile_navigation(core_user\output\myprofile\tree $tree, $user, $iscurrentuser, $course) {
+    global $DB, $CFG, $USER;
+    if (isguestuser($user)) {
+        // Coopy from forum - the guest user cannot post, so it is not possible to view any posts.
+        // May as well just bail aggressively here.
+        return false;
+    }
+    if (get_config('moodleoverflow', 'showoverviewprofilpage')) {
+        $viewdiscussionurl = new moodle_url('/mod/moodleoverflow/viewstartingdiscussion.php');
+        if (!empty($course)) {
+            $viewdiscussionurl->param('course', $course->id);
+        }
+        $discussionnode = new core_user\output\myprofile\node('miscellaneous', 'moodleoverflowdiscussions',
+            get_string('viewdiscussions', 'moodleoverflow'), null, $viewdiscussionurl);
+        $tree->add_node($discussionnode);
+        $viewposturl = new moodle_url('/mod/moodleoverflow/viewcontributingposts.php');
+        if (!empty($course)) {
+            $viewposturl->param('course', $course->id);
+        }
+        $postnode = new core_user\output\myprofile\node('miscellaneous', 'moodleoverflowposts',
+            get_string('viewposts', 'moodleoverflow'), null, $viewposturl);
+        $tree->add_node($postnode);
+        return true;
+    } else {
+        return false;
+    }
+}
 /**
  * Determine the current context if one wa not already specified.
  *
diff --git a/settings.php b/settings.php
index 02376d7b9f..941ec44741 100644
--- a/settings.php
+++ b/settings.php
@@ -97,6 +97,11 @@
     $settings->add(new admin_setting_configcheckbox('moodleoverflow/allowreview',
         get_string('allowreview', 'moodleoverflow'), get_string('allowreview_desc', 'moodleoverflow'), 1));
 
+    // Allow teachers to enable review before publish.
+    $settings->add(new admin_setting_configcheckbox('moodleoverflow/showoverviewprofilpage',
+        get_string('showoverviewprofilpage', 'moodleoverflow'),
+        get_string('showoverviewprofilpage_desc', 'moodleoverflow'), 1));
+
     $settings->add(new admin_setting_configtext('moodleoverflow/reviewpossibleaftertime',
         get_string('reviewpossibleaftertime', 'moodleoverflow'),
         get_string('reviewpossibleaftertime_desc', 'moodleoverflow'), 1800, PARAM_INT));
diff --git a/viewcontributingposts.php b/viewcontributingposts.php
new file mode 100644
index 0000000000..cba854c9e6
--- /dev/null
+++ b/viewcontributingposts.php
@@ -0,0 +1,43 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Prints a particular instance of moodleoverflow
+ *
+ * You can have a rather longer description of the file as well,
+ * if you like, and it can span multiple lines.
+ *
+ * @package   mod_moodleoverflow
+ * @copyright 2017 Kennet Winter <k_wint10@uni-muenster.de>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+// Include config and locallib.
+require_once(__DIR__.'/../../config.php');
+global $PAGE, $OUTPUT;
+$params = array();
+$PAGE->set_url('/mod/moodleoverflow/viewcontributingposts.php', $params);
+require_login();
+
+// Systemwide context as all post in moodleoverflows are displayed.
+$PAGE->set_context(context_system::instance());
+
+$PAGE->set_title(get_string('overviewposts', 'mod_moodleoverflow'));
+$PAGE->set_heading(get_string('overviewposts', 'mod_moodleoverflow'));
+
+echo $OUTPUT->header();
+echo "hello world";
+echo $OUTPUT->footer();
diff --git a/viewstartingdiscussion.php b/viewstartingdiscussion.php
new file mode 100644
index 0000000000..12df6426df
--- /dev/null
+++ b/viewstartingdiscussion.php
@@ -0,0 +1,44 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Prints a particular instance of moodleoverflow
+ *
+ * You can have a rather longer description of the file as well,
+ * if you like, and it can span multiple lines.
+ *
+ * @package   mod_moodleoverflow
+ * @copyright 2017 Kennet Winter <k_wint10@uni-muenster.de>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+// Include config and locallib.
+require_once(__DIR__.'/../../config.php');
+
+global $PAGE, $OUTPUT;
+$params = array();
+$PAGE->set_url('/mod/moodleoverflow/viewstartingdiscussion.php', $params);
+require_login();
+
+// Systemwide context as all started discussion in moodleoverflows are displayed.
+$PAGE->set_context(context_system::instance());
+
+$PAGE->set_title(get_string('overviewdiscussions', 'mod_moodleoverflow'));
+$PAGE->set_heading(get_string('overviewdiscussions', 'mod_moodleoverflow'));
+
+echo $OUTPUT->header();
+echo "hello world";
+echo $OUTPUT->footer();
\ No newline at end of file

From 98a93c6800b4ee8cfaf8f7f1f87e149ffb37570b Mon Sep 17 00:00:00 2001
From: NinaHerrmann <nina.herrmann@uni-muenster.de>
Date: Fri, 19 May 2023 16:32:19 +0200
Subject: [PATCH 2/2] WIP started startingdiscussion overview page TODO check
 for unread post in normal overview check for redirects in overviewpage
 implement second page - nice to have filter for pages

---
 lib.php                                    |   2 +-
 locallib.php                               | 422 ++++++++++++---------
 renderer.php                               |  10 +
 styles.css                                 |   3 +
 templates/discussion_started_list.mustache | 149 ++++++++
 viewcontributingposts.php                  |   7 +
 viewstartingdiscussion.php                 |  59 ++-
 7 files changed, 464 insertions(+), 188 deletions(-)
 create mode 100644 templates/discussion_started_list.mustache

diff --git a/lib.php b/lib.php
index d2b46a8792..0b900a34b7 100644
--- a/lib.php
+++ b/lib.php
@@ -569,7 +569,7 @@ function moodleoverflow_myprofile_navigation(core_user\output\myprofile\tree $tr
     if (get_config('moodleoverflow', 'showoverviewprofilpage')) {
         $viewdiscussionurl = new moodle_url('/mod/moodleoverflow/viewstartingdiscussion.php');
         if (!empty($course)) {
-            $viewdiscussionurl->param('course', $course->id);
+            $viewdiscussionurl->param('courseid', $course->id);
         }
         $discussionnode = new core_user\output\myprofile\node('miscellaneous', 'moodleoverflowdiscussions',
             get_string('viewdiscussions', 'moodleoverflow'), null, $viewdiscussionurl);
diff --git a/locallib.php b/locallib.php
index 71ff6052eb..5bb4aeacbf 100644
--- a/locallib.php
+++ b/locallib.php
@@ -174,9 +174,6 @@ function moodleoverflow_print_latest_discussions($moodleoverflow, $cm, $page = -
         echo $OUTPUT->paging_bar($numberofdiscussions, $page, $perpage, "view.php?id=$cm->id");
     }
 
-    // Get the number of replies for each discussion.
-    $replies = moodleoverflow_count_discussion_replies($cm);
-
     // Check whether the moodleoverflow instance can be tracked and is tracked.
     if ($cantrack = \mod_moodleoverflow\readtracking::moodleoverflow_can_track_moodleoverflows($moodleoverflow)) {
         $istracked = \mod_moodleoverflow\readtracking::moodleoverflow_is_tracked($moodleoverflow);
@@ -213,9 +210,6 @@ function moodleoverflow_print_latest_discussions($moodleoverflow, $cm, $page = -
         echo $OUTPUT->paging_bar($numberofdiscussions, $page, $perpage, "view.php?id=$cm->id");
     }
 
-    // Get the number of replies for each discussion.
-    $replies = moodleoverflow_count_discussion_replies($cm);
-
     // Check whether the user can subscribe to the discussion.
     $cansubtodiscussion = false;
     if ((!is_guest($context, $USER) && isloggedin()) && has_capability('mod/moodleoverflow:viewdiscussion', $context)
@@ -230,221 +224,241 @@ function moodleoverflow_print_latest_discussions($moodleoverflow, $cm, $page = -
     }
 
     // Iterate through every visible discussion.
-    $i = 0;
     $preparedarray = array();
     foreach ($discussions as $discussion) {
-        $preparedarray[$i] = array();
+        $preparedarray[] = prepare_data_for_discussions($discussion, $istracked, $canreviewposts, $moodleoverflow, $context, $cm);
+    }
 
-        // Handle anonymized discussions.
-        if ($discussion->userid == 0) {
-            $discussion->name = get_string('privacy:anonym_discussion_name', 'mod_moodleoverflow');
-        }
+    // Include the renderer.
+    $renderer = $PAGE->get_renderer('mod_moodleoverflow');
 
-        // Set the amount of replies for every discussion.
-        if (!empty($replies[$discussion->discussion])) {
-            $discussion->replies = $replies[$discussion->discussion]->replies;
-            $discussion->lastpostid = $replies[$discussion->discussion]->lastpostid;
-        } else {
-            $discussion->replies = 0;
-        }
+    // Collect the needed data being submitted to the template.
+    $mustachedata = new stdClass();
+    $mustachedata->cantrack = $cantrack;
+    $mustachedata->canviewdiscussions = $canviewdiscussions;
+    $mustachedata->canreview = $canreviewposts;
+    $mustachedata->discussions = $preparedarray;
+    $mustachedata->hasdiscussions = (count($discussions) >= 0) ? true : false;
+    $mustachedata->istracked = $istracked;
+    $mustachedata->markallread = $markallread;
+    $mustachedata->cansubtodiscussion = $cansubtodiscussion;
+    $mustachedata->canmovetopic = $canmovetopic;
+    $mustachedata->cannormoveorsub = ((!$canmovetopic) && (!$cansubtodiscussion));
+    // Print the template.
+    echo $renderer->render_discussion_list($mustachedata);
+
+    // Show the paging bar if paging is activated.
+    if ($page != -1) {
+        echo $OUTPUT->paging_bar($numberofdiscussions, $page, $perpage, "view.php?id=$cm->id");
+    }
+}
+
+/**
+ * @param array $discussions
+ * @param bool $istracked
+ * @param bool $canreviewposts
+ * @param object $moodleoverflow
+ * @return array
+ * @throws coding_exception
+ * @throws moodle_exception
+ */
+function prepare_data_for_discussions($discussion, $istracked, $canreviewposts, $moodleoverflow, $context, $cm, $onlystarted = false): stdClass {
+    global $CFG, $OUTPUT, $USER, $DB;
+    // Get the number of replies for each discussion.
+    $replies = moodleoverflow_count_discussion_replies($cm);
+    // Handle anonymized discussions.
+    if ($discussion->userid == 0) {
+        $discussion->name = get_string('privacy:anonym_discussion_name', 'mod_moodleoverflow');
+    }
 
-        // Set the right text.
-        $preparedarray[$i]['answertext'] = ($discussion->replies == 1) ? 'answer' : 'answers';
+    // Set the amount of replies for every discussion.
+    if (!empty($replies[$discussion->discussion])) {
+        $discussion->replies = $replies[$discussion->discussion]->replies;
+        $discussion->lastpostid = $replies[$discussion->discussion]->lastpostid;
+    } else {
+        $discussion->replies = 0;
+    }
 
-        // Set the amount of unread messages for each discussion.
-        if (!$istracked) {
-            $discussion->unread = '-';
-        } else if (empty($USER)) {
+    // Set the right text.
+    $discussion->answertext = ($discussion->replies == 1) ? 'answer' : 'answers';
+    // Set the amount of unread messages for each discussion.
+    if (!$istracked) {
+        $discussion->unread = '-';
+    } else if (empty($USER)) {
+        $discussion->unread = 0;
+    } else {
+        if (empty($unreads[$discussion->discussion])) {
             $discussion->unread = 0;
         } else {
-            if (empty($unreads[$discussion->discussion])) {
-                $discussion->unread = 0;
-            } else {
-                $discussion->unread = $unreads[$discussion->discussion];
-            }
+            $discussion->unread = $unreads[$discussion->discussion];
         }
+    }
 
-        // Check if the question owner marked the question as helpful.
-        $markedhelpful = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussion->discussion, false);
-        $preparedarray[$i]['starterlink'] = null;
-        if ($markedhelpful) {
-            $link = '/mod/moodleoverflow/discussion.php?d=';
-            $markedhelpful = $markedhelpful[array_key_first($markedhelpful)];
+    // Check if the question owner marked the question as helpful.
+    $markedhelpful = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussion->discussion, false);
+    $discussion->starterlink = null;
+    if ($markedhelpful) {
+        $link = '/mod/moodleoverflow/discussion.php?d=';
+        $markedhelpful = $markedhelpful[array_key_first($markedhelpful)];
 
-            $preparedarray[$i]['starterlink'] = new moodle_url($link .
-                $markedhelpful->discussionid . '#p' . $markedhelpful->postid);
-        }
+        $discussion->starterlink = new moodle_url($link .
+            $markedhelpful->discussionid . '#p' . $markedhelpful->postid);
+    }
 
-        // Check if a teacher marked a post as solved.
-        $markedsolution = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussion->discussion, true);
-        $preparedarray[$i]['teacherlink'] = null;
-        if ($markedsolution) {
-            $link = '/mod/moodleoverflow/discussion.php?d=';
-            $markedsolution = $markedsolution[array_key_first($markedsolution)];
+    // Check if a teacher marked a post as solved.
+    $markedsolution = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussion->discussion, true);
+    $discussion->teacherlink = null;
+    if ($markedsolution) {
+        $link = '/mod/moodleoverflow/discussion.php?d=';
+        $markedsolution = $markedsolution[array_key_first($markedsolution)];
 
-            $preparedarray[$i]['teacherlink'] = new moodle_url($link .
-                $markedsolution->discussionid . '#p' . $markedsolution->postid);
-        }
+        $discussion->teacherlink = new moodle_url($link .
+            $markedsolution->discussionid . '#p' . $markedsolution->postid);
+    }
 
-        // Check if a single post was marked by the question owner and a teacher.
-        $statusboth = false;
-        if ($markedhelpful  && $markedsolution) {
-            if ($markedhelpful->postid == $markedsolution->postid) {
-                $statusboth = true;
-            }
+    // Check if a single post was marked by the question owner and a teacher.
+    $statusboth = false;
+    if ($markedhelpful  && $markedsolution) {
+        if ($markedhelpful->postid == $markedsolution->postid) {
+            $statusboth = true;
         }
+    }
 
-        // Get the amount of votes for the discussion.
+    // Get the amount of votes for the discussion.
+    if (!$onlystarted) {
         $votes = \mod_moodleoverflow\ratings::moodleoverflow_get_ratings_by_discussion($discussion->discussion, $discussion->id);
-        $votes = $votes->upvotes - $votes->downvotes;
-        $preparedarray[$i]['votetext'] = ($votes == 1) ? 'vote' : 'votes';
+    } else {
+        $votes = \mod_moodleoverflow\ratings::moodleoverflow_get_ratings_by_discussion($discussion->id, $discussion->firstpost);
+    }
+    $votes = $votes->upvotes - $votes->downvotes;
+    $discussion->votetext = ($votes == 1) ? 'vote' : 'votes';
+    $discussion->votes = $votes;
 
-        // Use the discussions name instead of the subject of the first post.
-        $discussion->subject = $discussion->name;
+    // Use the discussions name instead of the subject of the first post.
+    $discussion->subject = $discussion->name;
 
-        // Format the subjectname and the link to the topic.
-        $preparedarray[$i]['subjecttext'] = format_string($discussion->subject);
-        $preparedarray[$i]['subjectlink'] = $CFG->wwwroot . '/mod/moodleoverflow/discussion.php?d=' . $discussion->discussion;
+    // Format the subjectname and the link to the topic.
+    $discussion->subjecttext = format_string($discussion->subject);
+    $discussion->subjectlink = $CFG->wwwroot . '/mod/moodleoverflow/discussion.php?d=' . $discussion->discussion;
 
-        // Get information about the user who started the discussion.
-        $startuser = new stdClass();
-        if ($CFG->branch >= 311) {
-            $startuserfields = \core_user\fields::get_picture_fields();
-        } else {
-            $startuserfields = explode(',', user_picture::fields());
-        }
+    // Get information about the user who started the discussion.
+    $startuser = new stdClass();
+    if ($CFG->branch >= 311) {
+        $startuserfields = \core_user\fields::get_picture_fields();
+    } else {
+        $startuserfields = explode(',', user_picture::fields());
+    }
 
-        $startuser = username_load_fields_from_object($startuser, $discussion, null, $startuserfields);
-        $startuser->id = $discussion->userid;
+    $startuser = username_load_fields_from_object($startuser, $discussion, null, $startuserfields);
+    $startuser->id = $discussion->userid;
 
-        // Discussion was anonymized.
-        if ($startuser->id == 0 || $moodleoverflow->anonymous != anonymous::NOT_ANONYMOUS) {
-            // Get his picture, his name and the link to his profile.
-            if ($startuser->id == $USER->id) {
-                $preparedarray[$i]['username'] = get_string('anonym_you', 'mod_moodleoverflow');
-                // Needs to be included for reputation to update properly.
-                $preparedarray[$i]['userlink'] = $CFG->wwwroot . '/user/view.php?id=' .
-                    $discussion->userid . '&course=' . $moodleoverflow->course;
+    if ($onlystarted) {
+        $startuser = $DB->get_record('user', array('id' => $discussion->userid));
+    }
+    // Discussion was anonymized.
+    if ($startuser->id == 0 || $moodleoverflow->anonymous != anonymous::NOT_ANONYMOUS) {
+        // Get his picture, his name and the link to his profile.
+        if ($startuser->id == $USER->id) {
+            $discussion->username = get_string('anonym_you', 'mod_moodleoverflow');
+            // Needs to be included for reputation to update properly.
+            $discussion->userlink = $CFG->wwwroot . '/user/view.php?id=' .
+                $discussion->userid . '&course=' . $moodleoverflow->course;
 
-            } else {
-                $preparedarray[$i]['username'] = get_string('privacy:anonym_user_name', 'mod_moodleoverflow');
-                $preparedarray[$i]['userlink'] = null;
-            }
         } else {
-            // Get his picture, his name and the link to his profile.
-            $preparedarray[$i]['picture'] = $OUTPUT->user_picture($startuser, array('courseid' => $moodleoverflow->course,
-                                                                                    'link' => false));
-            $preparedarray[$i]['username'] = fullname($startuser, has_capability('moodle/site:viewfullnames', $context));
-            $preparedarray[$i]['userlink'] = $CFG->wwwroot . '/user/view.php?id=' .
-                $discussion->userid . '&course=' . $moodleoverflow->course;
+            $discussion->username = get_string('privacy:anonym_user_name', 'mod_moodleoverflow');
+            $discussion->userlink = null;
         }
-
-        // Get the amount of replies and the link to the discussion.
-        $preparedarray[$i]['replyamount'] = $discussion->replies;
-        $preparedarray[$i]['questionunderreview'] = $discussion->reviewed == 0;
-
-        // Are there unread messages? Create a link to them.
-        $preparedarray[$i]['unreadamount'] = $discussion->unread;
-        $preparedarray[$i]['unread'] = ($preparedarray[$i]['unreadamount'] > 0) ? true : false;
-        $preparedarray[$i]['unreadlink'] = $CFG->wwwroot .
-            '/mod/moodleoverflow/discussion.php?d=' . $discussion->discussion . '#unread';
-        $link = '/mod/moodleoverflow/markposts.php?m=';
-        $preparedarray[$i]['markreadlink'] = $CFG->wwwroot . $link . $moodleoverflow->id . '&d=' . $discussion->discussion;
-
-        // Check the date of the latest post. Just in case the database is not consistent.
-        $usedate = (empty($discussion->timemodified)) ? $discussion->modified : $discussion->timemodified;
-
-        // Get the name and the link to the profile of the user, that is related to the latest post.
-        $usermodified = new stdClass();
-        $usermodified->id = $discussion->usermodified;
-
-        if ($usermodified->id == 0 || $moodleoverflow->anonymous) {
-            if ($usermodified->id == $USER->id) {
-                $preparedarray[$i]['lastpostusername'] = null;
-                $preparedarray[$i]['lastpostuserlink'] = null;
-            } else {
-                $preparedarray[$i]['lastpostusername'] = null;
-                $preparedarray[$i]['lastpostuserlink'] = null;
-            }
+    } else {
+        // Get his picture, his name and the link to his profile.
+        $discussion->picture = $OUTPUT->user_picture($startuser, array('courseid' => $moodleoverflow->course,
+            'link' => false));
+        $discussion->username = fullname($startuser, has_capability('moodle/site:viewfullnames', $context));
+        $discussion->userlink = $CFG->wwwroot . '/user/view.php?id=' .
+            $discussion->userid . '&course=' . $moodleoverflow->course;
+    }
+
+    // Get the amount of replies and the link to the discussion.
+    $discussion->replyamount = $discussion->replies;
+    $discussion->questionunderreview = $discussion->reviewed == 0;
+
+    // Are there unread messages? Create a link to them.
+    $discussion->unreadamount = $discussion->unread;
+    $discussion->unread = ($discussion->unreadamount > 0) ? true : false;
+    $discussion->unreadlink = $CFG->wwwroot .
+        '/mod/moodleoverflow/discussion.php?d=' . $discussion->discussion . '#unread';
+    $link = '/mod/moodleoverflow/markposts.php?m=';
+    $discussion->markreadlink = $CFG->wwwroot . $link . $moodleoverflow->id . '&d=' . $discussion->discussion;
+
+    // Check the date of the latest post. Just in case the database is not consistent.
+    $usedate = (empty($discussion->timemodified)) ? $discussion->modified : $discussion->timemodified;
+
+    // Get the name and the link to the profile of the user, that is related to the latest post.
+    $usermodified = new stdClass();
+    $usermodified->id = $discussion->usermodified;
+
+    if ($usermodified->id == 0 || $moodleoverflow->anonymous) {
+        if ($usermodified->id == $USER->id) {
+            $discussion->lastpostusername = null;
+            $discussion->lastpostuserlink = null;
         } else {
-            $usermodified = username_load_fields_from_object($usermodified, $discussion, 'um');
-            $preparedarray[$i]['lastpostusername'] = fullname($usermodified);
-            $preparedarray[$i]['lastpostuserlink'] = $CFG->wwwroot . '/user/view.php?id=' .
-                $discussion->usermodified . '&course=' . $moodleoverflow->course;
+            $discussion->lastpostusername = null;
+            $discussion->lastpostuserlink = null;
         }
-
-        // Get the date of the latest post of the discussion.
-        $parenturl = (empty($discussion->lastpostid)) ? '' : '&parent=' . $discussion->lastpostid;
-        $preparedarray[$i]['lastpostdate'] = userdate($usedate, get_string('strftimerecentfull'));
-        $preparedarray[$i]['lastpostlink'] = $preparedarray[$i]['subjectlink'] . $parenturl;
-
-        // Check whether the discussion is subscribed.
-        $preparedarray[$i]['discussionsubicon'] = false;
-        if ((!is_guest($context, $USER) && isloggedin()) && has_capability('mod/moodleoverflow:viewdiscussion', $context)) {
-            // Discussion subscription.
-            if (\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, $context)) {
-                $preparedarray[$i]['discussionsubicon'] = \mod_moodleoverflow\subscriptions::get_discussion_subscription_icon(
-                    $moodleoverflow, $context, $discussion->discussion);
-            }
+    } else {
+        $usermodified = username_load_fields_from_object($usermodified, $discussion, 'um');
+        if ($onlystarted) {
+            $usermodified = $DB->get_record('user', array('id' => $discussion->usermodified));
         }
-
-        if ($canreviewposts) {
-            $reviewinfo = review::get_short_review_info_for_discussion($discussion->discussion);
-            $preparedarray[$i]['needreview'] = $reviewinfo->count;
-            $preparedarray[$i]['reviewlink'] = (new moodle_url('/mod/moodleoverflow/discussion.php', [
-                'd' => $discussion->discussion
-            ], 'p' . $reviewinfo->first))->out(false);
+        $discussion->lastpostusername = fullname($usermodified);
+        $discussion->lastpostuserlink = $CFG->wwwroot . '/user/view.php?id=' .
+            $discussion->usermodified . '&course=' . $moodleoverflow->course;
+    }
+
+    // Get the date of the latest post of the discussion.
+    $parenturl = (empty($discussion->lastpostid)) ? '' : '&parent=' . $discussion->lastpostid;
+    $discussion->lastpostdate = userdate($usedate, get_string('strftimerecentfull'));
+    $discussion->lastpostlink = $discussion->subjectlink . $parenturl;
+
+    // Check whether the discussion is subscribed.
+    $discussion->discussionsubicon = false;
+    if ((!is_guest($context, $USER) && isloggedin()) && has_capability('mod/moodleoverflow:viewdiscussion', $context)) {
+        // Discussion subscription.
+        if (\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, $context)) {
+            $discussion->discussionsubicon = \mod_moodleoverflow\subscriptions::get_discussion_subscription_icon(
+                $moodleoverflow, $context, $discussion->discussion);
         }
+    }
 
-        // Build linktopopup to move a topic.
-        $linktopopup = $CFG->wwwroot . '/mod/moodleoverflow/view.php?id=' . $cm->id . '&movetopopup=' . $discussion->discussion;
-        $preparedarray[$i]['linktopopup'] = $linktopopup;
-
-        // Add all created data to an array.
-        $preparedarray[$i]['markedhelpful'] = $markedhelpful;
-        $preparedarray[$i]['markedsolution'] = $markedsolution;
-        $preparedarray[$i]['statusboth'] = $statusboth;
-        $preparedarray[$i]['votes'] = $votes;
+    if ($canreviewposts) {
+        $reviewinfo = review::get_short_review_info_for_discussion($discussion->discussion);
+        $discussion->needreview = $reviewinfo->count;
+        $discussion->reviewlink = (new moodle_url('/mod/moodleoverflow/discussion.php', [
+            'd' => $discussion->discussion
+        ], 'p' . $reviewinfo->first))->out(false);
+    }
 
-        // Did the user rated this post?
-        $rating = \mod_moodleoverflow\ratings::moodleoverflow_user_rated($discussion->firstpost);
+    // Build linktopopup to move a topic.
+    $linktopopup = $CFG->wwwroot . '/mod/moodleoverflow/view.php?id=' . $cm->id . '&movetopopup=' . $discussion->discussion;
+    $discussion->linktopopup = $linktopopup;
 
-        $firstpost = moodleoverflow_get_post_full($discussion->firstpost);
+    // Add all created data to an array.
+    $discussion->markedhelpful = $markedhelpful;
+    $discussion->markedsolution = $markedsolution;
+    $discussion->statusboth = $statusboth;
 
-        $preparedarray[$i]['userupvoted'] = ($rating->rating ?? null) == RATING_UPVOTE;
-        $preparedarray[$i]['userdownvoted'] = ($rating->rating ?? null) == RATING_DOWNVOTE;
-        $preparedarray[$i]['canchange'] = \mod_moodleoverflow\ratings::moodleoverflow_user_can_rate($firstpost, $context) &&
-                $startuser->id != $USER->id;
-        $preparedarray[$i]['postid'] = $discussion->firstpost;
+    // Did the user rated this post?
+    $rating = \mod_moodleoverflow\ratings::moodleoverflow_user_rated($discussion->firstpost);
 
-        // Go to the next discussion.
-        $i++;
-    }
+    $firstpost = moodleoverflow_get_post_full($discussion->firstpost);
 
-    // Include the renderer.
-    $renderer = $PAGE->get_renderer('mod_moodleoverflow');
+    $discussion->userupvoted = ($rating->rating ?? null) == RATING_UPVOTE;
+    $discussion->userdownvoted = ($rating->rating ?? null) == RATING_DOWNVOTE;
+    $discussion->canchange = \mod_moodleoverflow\ratings::moodleoverflow_user_can_rate($firstpost, $context) &&
+        $startuser->id != $USER->id;
+    $discussion->postid = $discussion->firstpost;
 
-    // Collect the needed data being submitted to the template.
-    $mustachedata = new stdClass();
-    $mustachedata->cantrack = $cantrack;
-    $mustachedata->canviewdiscussions = $canviewdiscussions;
-    $mustachedata->canreview = $canreviewposts;
-    $mustachedata->discussions = $preparedarray;
-    $mustachedata->hasdiscussions = (count($discussions) >= 0) ? true : false;
-    $mustachedata->istracked = $istracked;
-    $mustachedata->markallread = $markallread;
-    $mustachedata->cansubtodiscussion = $cansubtodiscussion;
-    $mustachedata->canmovetopic = $canmovetopic;
-    $mustachedata->cannormoveorsub = ((!$canmovetopic) && (!$cansubtodiscussion));
-    // Print the template.
-    echo $renderer->render_discussion_list($mustachedata);
-
-    // Show the paging bar if paging is activated.
-    if ($page != -1) {
-        echo $OUTPUT->paging_bar($numberofdiscussions, $page, $perpage, "view.php?id=$cm->id");
-    }
+    return $discussion;
 }
-
 /**
  * Prints a popup with a menu of other moodleoverflow in the course.
  * Menu to move a topic to another moodleoverflow forum.
@@ -639,6 +653,46 @@ function moodleoverflow_get_discussions_unread($cm) {
     }
 }
 
+/**
+ * Gets the number of unread post for a single discussion.
+ * @param int $discussionid
+ * @param $cm
+ * @return false|mixed
+ * @throws coding_exception
+ * @throws dml_exception
+ */
+function get_discussion_unread($discussionid, $cm) {
+    global $USER, $DB;
+    $now = round(time(), -2);
+    $cutoffdate = $now - (get_config('moodleoverflow', 'oldpostdays') * 24 * 60 * 60);
+
+    $params = [
+        'userid' => $USER->id,
+        'cutoffdate' => $cutoffdate,
+        'discussionid' => $discussionid
+    ];
+
+    $modcontext = context_module::instance($cm->id);
+    $whereconditions = ['p.modified >= :cutoffdate', 'r.id is NULL', 'd.id = :discussionid'];
+
+    if (!has_capability('mod/moodleoverflow:reviewpost', $modcontext)) {
+        $whereconditions[] = '(p.reviewed = 1 OR p.userid = :userid2)';
+        $params['userid2'] = $USER->id;
+    }
+
+    $wheresql = join(' AND ', $whereconditions);
+
+    // Define the sql-query.
+    $sql = "SELECT d.id, COUNT(p.id) AS unread
+            FROM {moodleoverflow_discussions} d
+                JOIN {moodleoverflow_posts} p ON p.discussion = d.id
+                LEFT JOIN {moodleoverflow_read} r ON (r.postid = p.id AND r.userid = :userid)
+            WHERE $wheresql
+            GROUP BY d.id";
+
+    return $DB->get_record_sql($sql, $params);
+}
+
 /**
  * Gets a post with all info ready for moodleoverflow_print_post.
  * Most of these joins are just to get the forum id.
diff --git a/renderer.php b/renderer.php
index 905bc3d12d..ed9e6bb81d 100644
--- a/renderer.php
+++ b/renderer.php
@@ -46,6 +46,16 @@ class mod_moodleoverflow_renderer extends plugin_renderer_base {
     public function render_discussion_list($data) {
         return $this->render_from_template('mod_moodleoverflow/discussions', $data);
     }
+    /**
+     * Display the discussion list for the viewstartingdiscussion.php.
+     *
+     * @param object $data The prepared variables.
+     *
+     * @return string
+     */
+    public function render_discussion_started_list($data) {
+        return $this->render_from_template('mod_moodleoverflow/discussion_started_list', $data);
+    }
 
     /**
      * Display the forum list in the view.php if a discussion needs to be moved to another forum.
diff --git a/styles.css b/styles.css
index f0c92ff5bf..2adfa93825 100644
--- a/styles.css
+++ b/styles.css
@@ -12,6 +12,9 @@
 /*
  * The discussionlist in the view.php
  */
+.moodleoverflowheaderlist {
+    border-spacing: 0;
+}
 
 .moodleoverflowheaderlist th.header.replies .iconsmall {
     margin: 0 .3em;
diff --git a/templates/discussion_started_list.mustache b/templates/discussion_started_list.mustache
new file mode 100644
index 0000000000..14673f18a3
--- /dev/null
+++ b/templates/discussion_started_list.mustache
@@ -0,0 +1,149 @@
+{{!
+  This file is part of Moodle - http://moodle.org/
+
+  Moodle is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Moodle is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}
+{{!
+  @template mod_moodleoverflow/discussion_list
+
+  Moodleoverflow discussion_list template.
+  The purpose of this template is to render a list of discussions for the view.php.
+
+  Example context (json):
+  {
+  }
+}}
+
+{{! There are no discussions. Print the string that specifies it. }}
+{{^hasdiscussions}}
+    <div class="moodleoverflowdiscussions">
+        ( {{#str}} nodiscussions, moodleoverflow {{/str}} )
+    </div>
+{{/hasdiscussions}}
+
+{{! There are discussions. Start to print the table. }}
+{{#hasdiscussions}}
+
+    {{#discussions}}
+        <div class="moodleoverflowdiscussion d-flex border p-2 mb-3" data-moodleoverflow-postid="{{postid}}">
+            <div class="leftbox text-center mr-2">
+                <div class="votes text-center mb-1">
+                    {{> mod_moodleoverflow/postvoting }}
+                </div>
+                <div class="status moodleoverflow-icon-no-margin">
+                    {{# questionunderreview }}
+                        {{#pix}}i/duration, moodle, {{#str}}pending_review, mod_moodleoverflow{{/str}}{{/pix}}
+                    {{/ questionunderreview }}
+                    {{^ questionunderreview }}
+                        {{#markedsolution}}
+                            <a href="{{teacherlink}}">{{! avoid whitespace
+                                !}}{{# pix}} i/status-solved, moodleoverflow, {{#str}}containsteacherrating, moodleoverflow{{/str}} {{/ pix}}{{!
+                            !}}</a>
+                        {{/markedsolution}}
+                        {{#markedhelpful}}
+                            <a href="{{starterlink}}">{{! avoid whitespace
+                                !}}{{# pix}} i/status-helpful, moodleoverflow, {{#str}}containsstarterrating, moodleoverflow{{/str}} {{/ pix}}{{!
+                            !}}</a>
+                        {{/ markedhelpful }}
+                    {{/ questionunderreview }}
+                </div>
+                <div class="d-flex flex-colum flex-wrap justify-content-around">
+                    {{# canreview }}
+                        {{# needreview }}
+                            <div class="reviews my-1">
+                                <a href="{{{reviewlink}}}" class="text-danger bold"
+                                   title="{{#str}}amount_waiting_for_review, mod_moodleoverflow, {{needreview}}{{/str}}">
+                                    {{#pix}}i/commenting, mod_moodleoverflow{{/pix}}{{ needreview }}
+                                </a>
+                            </div>
+                        {{/ needreview }}
+                    {{/ canreview }}
+                    <div class="replies my-1" title="{{#str}}answers, mod_moodleoverflow, {{replyamount}}{{/str}}">
+                        <span><span class="reply-correction">{{#pix}}i/reply, mod_moodleoverflow {{/pix}}</span>{{ replyamount }}</span>
+                    </div>
+                </div>
+
+            </div>
+            <div class="w-100 d-flex flex-column justify-content-between">
+                <div class="d-flex justify-content-between">
+                    <a class="subject mb-3 mr-3" href="{{{subjectlink}}}">{{{ subjecttext }}}</a>
+
+                    <div class="pt-2 text-right">
+                        {{#cansubtodiscussion}}
+                            <div class="discussionsubscription">{{{discussionsubicon}}}</div>
+                        {{/cansubtodiscussion}}
+                        {{#canmovetopic}}
+                            <div class="discussionmove"><a href='{{ linktopopup }}'>{{#pix}} i/arrow-right, core, {{#str}}movetopicicon, moodleoverflow{{/str}} {{/pix}}</a></div>
+                        {{/canmovetopic}}
+                        {{#unread}}
+                            <div class="mod_moodleoverflow-no-wrap unread-part d-flex align-items-baseline">
+                                <a class="mark-read" href="{{markreadlink}}"
+                                   title="{{#str}}markallread, moodleoverflow{{/str}}">
+                                    {{#pix}}i/delete, core {{/pix}}
+                                </a>
+                                <a class="d-inline-block mt-3" href="{{ unreadlink }}"
+                                   title="{{#str}}amount_unread_posts_in_discussion, mod_moodleoverflow, {{unreadamount}} {{/str}}">
+                                    <span class="fa fa-envelope icon mr-0 moodleoverflow-icon-1_5x text-muted">
+                                    </span><span class="unread-bubble">
+                                    {{ unreadamount }}
+                                </span>
+                                </a>
+                            </div>
+                        {{/unread}}
+                    </div>
+                </div>
+                <div class="d-flex justify-content-between flex-wrap moodleoverflow-gap-small">
+                    {{#userlink}}
+                    <a href="{{{userlink}}}" class="user-info d-flex questioner px-2 py-1 align-items-center">
+                    {{/userlink}}
+                    {{^userlink}}
+                    <div class="user-info d-flex questioner px-2 py-1 align-items-center">
+                    {{/userlink}}
+
+                    {{# picture }}
+                        <div class="user-avatar">
+                            {{{ picture }}}
+                        </div>
+                    {{/ picture }}
+                    <div class="user-details">
+                        {{{ username }}}
+                    </div>
+                    {{^userlink}}
+                    </div>
+                    {{/userlink}}
+                    {{#userlink}}
+                    </a>
+                    {{/userlink}}
+                    <div class="d-flex flex-wrap align-items-center">
+                        <span class="text-muted">Last post:</span>
+                        <div>
+                            <a href="{{{lastpostlink}}}" class="user-info d-flex px-2 py-1 align-items-center">
+                                {{# lastpostuserpicture }}
+                                    <div class="user-avatar">
+                                        {{{ lastpostuserpicture }}}
+                                    </div>
+                                {{/ lastpostuserpicture }}
+                                <div class="user-details line-height-3">
+                                    {{{ lastpostusername }}}<br>
+                                    {{{ lastpostdate }}}
+                                </div>
+                            </a>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    {{/discussions}}
+
+{{/hasdiscussions}}
diff --git a/viewcontributingposts.php b/viewcontributingposts.php
index cba854c9e6..83086ce397 100644
--- a/viewcontributingposts.php
+++ b/viewcontributingposts.php
@@ -28,7 +28,14 @@
 // Include config and locallib.
 require_once(__DIR__.'/../../config.php');
 global $PAGE, $OUTPUT;
+// If invoked from a course show the discussions from the course.
+$courseid = optional_param('courseid', 0, PARAM_INT);
 $params = array();
+
+if ($courseid) {
+    $params['courseid'] = $courseid;
+}
+
 $PAGE->set_url('/mod/moodleoverflow/viewcontributingposts.php', $params);
 require_login();
 
diff --git a/viewstartingdiscussion.php b/viewstartingdiscussion.php
index 12df6426df..c73a8d38be 100644
--- a/viewstartingdiscussion.php
+++ b/viewstartingdiscussion.php
@@ -27,9 +27,17 @@
 
 // Include config and locallib.
 require_once(__DIR__.'/../../config.php');
+require_once(__DIR__.'/locallib.php');
+use mod_moodleoverflow\readtracking;
 
-global $PAGE, $OUTPUT;
+global $PAGE, $OUTPUT, $USER, $DB;
+// If invoked from a course show the discussions from the course.
+$courseid = optional_param('courseid', 0, PARAM_INT);
 $params = array();
+if ($courseid) {
+    $params['courseid'] = $courseid;
+}
+
 $PAGE->set_url('/mod/moodleoverflow/viewstartingdiscussion.php', $params);
 require_login();
 
@@ -39,6 +47,51 @@
 $PAGE->set_title(get_string('overviewdiscussions', 'mod_moodleoverflow'));
 $PAGE->set_heading(get_string('overviewdiscussions', 'mod_moodleoverflow'));
 
+// Get all started discussions (in a course).
+$discussions = $DB->get_records('moodleoverflow_discussions', array('userid' => $USER->id));
+// Collect the needed data being submitted to the template.
+$discussionswithdetails = array();
+$tracking = new readtracking();
 echo $OUTPUT->header();
-echo "hello world";
-echo $OUTPUT->footer();
\ No newline at end of file
+
+foreach ($discussions as $discussion) {
+    $moodleoverflow = $DB->get_record('moodleoverflow', array('id' => $discussion->moodleoverflow));
+    $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id, $discussion->course,
+        false, MUST_EXIST);
+    $context = context_module::instance($cm->id);
+
+    $canreviewposts = has_capability('mod/moodleoverflow:reviewpost', $context);
+
+    if (has_capability('mod/moodleoverflow:viewdiscussion', $context)) {
+        if ($cantrack = \mod_moodleoverflow\readtracking::moodleoverflow_can_track_moodleoverflows($moodleoverflow)) {
+            $istracked = \mod_moodleoverflow\readtracking::moodleoverflow_is_tracked($moodleoverflow);
+        } else {
+            $istracked = false;
+        }
+        $discussion->discussion = $discussion->id;
+
+        $firstpost = $DB->get_record('moodleoverflow_posts', array('id' => $discussion->firstpost));
+        $discussion->reviewed = $firstpost->reviewed;
+        $newdiscussion = prepare_data_for_discussions($discussion, $istracked, $canreviewposts, $moodleoverflow, $context, $cm, true);
+        $newdiscussion->istracked = $istracked;
+        $newdiscussion->cantrack = $cantrack;
+        if ($unreadpost = get_discussion_unread($discussion->id, $cm)) {
+            $newdiscussion->unread = true;
+            $newdiscussion->unreadamount = $unreadpost->unread;
+        }
+        $newdiscussion->cansubtodiscussion = false;
+        if ((!is_guest($context, $USER) && isloggedin()) && has_capability('mod/moodleoverflow:viewdiscussion', $context)
+            && \mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, $context)) {
+            $newdiscussion->cansubtodiscussion = true;
+        }
+        array_push($discussionswithdetails, $newdiscussion);
+    }
+}
+$mustachedata = new stdClass();
+$mustachedata->discussions = $discussionswithdetails;
+$mustachedata->hasdiscussions = count($discussionswithdetails) >= 0;
+
+// Include the renderer.
+$renderer = $PAGE->get_renderer('mod_moodleoverflow');
+echo $renderer->render_discussion_started_list($mustachedata);
+echo $OUTPUT->footer();