Sebschlicht2 has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/340760 )

Change subject: MOOC overview view added
......................................................................


MOOC overview view added

The MOOC overview allows to render a whole MOOC with all its
lessons and to add lessons. This branch implements a basic version
of this view, including rudimentary style directives and JavaScript
code to add lessons via the MW-API in the background.

Change-Id: I6d7ed1cbebb264622ca117402dec5d460dc9f90b
---
M extension.json
M i18n/de.json
M i18n/en.json
M i18n/qqq.json
M includes/model/MoocEntity.php
A includes/model/MoocOverview.php
M includes/rendering/MoocContentRenderer.php
M includes/rendering/MoocLessonRenderer.php
A includes/rendering/MoocOverviewRenderer.php
M resources/js/ext.mooc.edit.js
M resources/less/ext.mooc.less
11 files changed, 256 insertions(+), 50 deletions(-)



diff --git a/extension.json b/extension.json
index 15d3cac..36590ff 100644
--- a/extension.json
+++ b/extension.json
@@ -18,9 +18,11 @@
     "MoocScript": "includes/model/MoocScript.php",
     "MoocQuiz": "includes/model/MoocQuiz.php",
     "MoocItem": "includes/model/MoocItem.php",
+    "MoocOverview": "includes/model/MoocOverview.php",
     "MoocLesson": "includes/model/MoocLesson.php",
     "MoocUnit": "includes/model/MoocUnit.php",
     "MoocContentRenderer": "includes/rendering/MoocContentRenderer.php",
+    "MoocOverviewRenderer": "includes/rendering/MoocOverviewRenderer.php",
     "MoocLessonRenderer": "includes/rendering/MoocLessonRenderer.php",
     "MoocUnitRenderer": "includes/rendering/MoocUnitRenderer.php",
     "MoocContentStructureProvider": 
"includes/structure/MoocContentStructureProvider.php",
diff --git a/i18n/de.json b/i18n/de.json
index 566cba7..f78aaaa 100644
--- a/i18n/de.json
+++ b/i18n/de.json
@@ -9,22 +9,24 @@
   "mooc-section-learning-goals-title": "Lernziele",
   "mooc-section-learning-goals-button-title-edit": "Lernziele bearbeiten",
   "mooc-section-video-title": "Video",
-  "mooc-section-video-button-title-edit": "Video ändern",
+  "mooc-section-video-edit-title": "Video ändern",
   "mooc-section-script-title": "Skript",
-  "mooc-section-script-button-title-edit": "Skript bearbeiten",
+  "mooc-section-script-edit-title": "Skript bearbeiten",
   "mooc-section-quiz-title": "Quiz",
-  "mooc-section-quiz-button-title-edit": "Quiz bearbeiten",
+  "mooc-section-quiz-edit-title": "Quiz bearbeiten",
   "mooc-section-further-reading-title": "Weiterführende Literatur",
-  "mooc-section-further-reading-button-title-edit": "Weiterführende Literatur 
bearbeiten",
+  "mooc-section-further-reading-edit-title": "Weiterführende Literatur 
bearbeiten",
   "mooc-section-units-title": "Lerneinheiten",
-  "mooc-section-units-button-title-edit": "Lerneinheiten bearbeiten",
-  "mooc-section-units-button-title-add": "Lerneinheit hinzufügen",
+  "mooc-section-units-edit-title": "Lerneinheiten bearbeiten",
+  "mooc-section-units-add-title": "Lerneinheit hinzufügen",
   "mooc-section-units-unit-link-video": "Zum Video springen",
   "mooc-section-units-unit-link-download-video": "Video herunterladen",
   "mooc-section-units-unit-link-script": "Zum Skript springen",
   "mooc-section-units-unit-link-quiz": "Zum Quiz springen",
   "mooc-section-lessons-title": "Lektionen",
+  "mooc-section-lessons-add-title": "Lektion hinzufügen",
   "mooc-lesson-add-unit-summary": "Lerneinheit \"$1\" zur Lektion 
hinzugefügt.",
+  "mooc-overview-add-lesson-summary": "Lektion \"$1\" zum MOOC hinzugefügt.",
   "_mooc-comment-modal-button-title-<action>": "// Label für Aktionen in 
modalen Boxen.",
   "mooc-modal-button-title-save": "Speichern",
   "mooc-modal-button-title-add": "Hinzufügen",
diff --git a/i18n/en.json b/i18n/en.json
index 7e97920..683e840 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -24,7 +24,9 @@
   "mooc-section-units-unit-link-script": "Jump to the script",
   "mooc-section-units-unit-link-quiz": "Jump to the quiz",
   "mooc-section-lessons-title": "Lessons",
+  "mooc-section-lessons-add-title": "Add lesson",
   "mooc-lesson-add-unit-summary": "Unit \"$1\" added to the lesson.",
+  "mooc-overview-add-lesson-summary": "Lesson \"$1\" added to the MOOC.",
   "_mooc-comment-modal-button-title-<action>": "// Labels for action buttons 
in modal boxes.",
   "mooc-modal-button-title-save": "Save",
   "mooc-modal-button-title-add": "Add",
diff --git a/i18n/qqq.json b/i18n/qqq.json
index dbbb217..febca51 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -28,7 +28,9 @@
   "mooc-section-units-unit-link-script": "Title of the link to the unit's 
script section.",
   "mooc-section-units-unit-link-quiz": "Title of the link to the unit's quiz 
section.",
   "mooc-section-lessons-title": "Title of the lessons section.",
-  "mooc-lesson-add-unit-summary": "Edit summary when adding a unit to a 
lesson. Parameters: 1. name of the unit",
+  "mooc-section-lessons-add-title": "Title of the button to add a lesson.",
+  "mooc-lesson-add-unit-summary": "Edit summary when adding an unit to a 
lesson. Parameters: 1. unit name",
+  "mooc-overview-add-lesson-summary": "Edit summary when adding a lesson to a 
MOOC. Parameters: 1. lesson name",
   "mooc-modal-button-title-save": "Label of the button to save the changes 
made in the modal box.",
   "mooc-modal-button-title-add": "Label of the button to add the item 
specified in the modal box.",
   "mooc-modal-button-title-cancel": "Label of the button to close the modal 
box and cancel the current action.",
diff --git a/includes/model/MoocEntity.php b/includes/model/MoocEntity.php
index d33bf88..fc030bc 100644
--- a/includes/model/MoocEntity.php
+++ b/includes/model/MoocEntity.php
@@ -64,6 +64,9 @@
             case MoocLesson::ENTITY_TYPE_LESSON:
                 return new MoocLesson( $title, $moocContentJson );
 
+            case MoocOverview::ENTITY_TYPE_MOOC:
+                return new MoocOverview( $title, $moocContentJson );
+
             case MoocScript::ENTITY_TYPE_SCRIPT:
                 return new MoocScript( $title, $moocContentJson );
 
diff --git a/includes/model/MoocOverview.php b/includes/model/MoocOverview.php
new file mode 100644
index 0000000..ca2f133
--- /dev/null
+++ b/includes/model/MoocOverview.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * MOOC itself with all its lessons and units it contains.
+ *
+ * @author Sebastian Schlicht <sebast...@jablab.de>
+ *
+ * @file
+ */
+class MoocOverview extends MoocItem {
+
+    /**
+     * MOOC entity type for MOOCs
+     */
+    const ENTITY_TYPE_MOOC = 'mooc';
+
+    public function toJson() {
+        return [
+            self::JFIELD_TYPE => $this->type,
+        ];
+    }
+}
\ No newline at end of file
diff --git a/includes/rendering/MoocContentRenderer.php 
b/includes/rendering/MoocContentRenderer.php
index 81adb38..7b2618e 100644
--- a/includes/rendering/MoocContentRenderer.php
+++ b/includes/rendering/MoocContentRenderer.php
@@ -75,6 +75,9 @@
             case MoocLesson::ENTITY_TYPE_LESSON:
                 return new MoocLessonRenderer();
 
+            case MoocOverview::ENTITY_TYPE_MOOC:
+                return new MoocOverviewRenderer();
+
             default:
                 return null;
         }
diff --git a/includes/rendering/MoocLessonRenderer.php 
b/includes/rendering/MoocLessonRenderer.php
index 2c73a4f..8777063 100644
--- a/includes/rendering/MoocLessonRenderer.php
+++ b/includes/rendering/MoocLessonRenderer.php
@@ -32,20 +32,24 @@
     }
 
     protected function addChildrenSection() {
-        $this->beginSection(self::SECTION_KEY_UNITS);
+        $this->beginSection( self::SECTION_KEY_UNITS );
 
-        if ($this->item->hasChildren()) {
-            // list child units if any
-            foreach ($this->item->children as $unit) {
-                $this->addChildUnit($unit);
-            }
-        } else {
-            // show info box if no child units added yet
-            $this->addEmptySectionBox(self::SECTION_KEY_UNITS);
-        }
+        $this->addUnitsSectionContent( $this->item );
         // TODO add controls to add units somewhere
 
         $this->endSection();
+    }
+
+    protected function addUnitsSectionContent( $lesson ) {
+        if ( $lesson->hasChildren() ) {
+            // list child units if any
+            foreach ( $lesson->children as $unit ) {
+                $this->addChildUnit( $unit );
+            }
+        } else {
+            // show info box if no child units added yet
+            $this->addEmptySectionBox( self::SECTION_KEY_UNITS );
+        }
     }
 
     /**
@@ -166,19 +170,12 @@
         $this->out->addHTML("</a>");
     }
 
-    protected function fillModalBoxForm($sectionKey, $action) {
-        if ($sectionKey == self::SECTION_KEY_UNITS && $action == 'add') {
-            $this->fillModalAddBoxForm();
+    protected function fillModalBoxForm( $sectionKey, $action ) {
+        if ( $sectionKey == self::SECTION_KEY_UNITS && $action == 
self::ACTION_ADD ) {
+            $this->out->addHTML( '<input type="text" class="value" />' );
         } else {
-            parent::fillModalBoxForm($sectionKey, $action);
+            parent::fillModalBoxForm( $sectionKey, $action );
         }
-    }
-
-    /**
-     * Fills the add form of the modal box to add units.
-     */
-    protected function fillModalAddBoxForm() {
-        $this->out->addHTML('<input type="text" class="value" />');
     }
 
     protected function addModalBoxActions($sectionKey, $action) {
diff --git a/includes/rendering/MoocOverviewRenderer.php 
b/includes/rendering/MoocOverviewRenderer.php
new file mode 100644
index 0000000..a1e8edd
--- /dev/null
+++ b/includes/rendering/MoocOverviewRenderer.php
@@ -0,0 +1,128 @@
+<?php
+
+/**
+ * Renderer for MOOC overview pages.
+ *
+ * @author Sebastian Schlicht <sebast...@jablab.de>
+ *
+ * @file
+ */
+class MoocOverviewRenderer extends MoocLessonRenderer {
+
+    /**
+     * key of the child lessons section
+     */
+    const SECTION_KEY_LESSONS = 'lessons';
+
+    /**
+     * add action identifier
+     */
+    const ACTION_ADD = 'add';
+
+    /**
+     * Adds the MOOC overview sections to the output.
+     */
+    protected function addSections() {
+        $this->addLessonsSection();
+    }
+
+    protected function addLessonsSection() {
+        $this->beginSection( self::SECTION_KEY_LESSONS );
+
+        if ( $this->item->hasChildren() ) {
+            // list child lessons if any
+            $i = 1;
+            foreach ( $this->item->children as $lesson ) {
+                $this->addChildLesson( $lesson, $i );
+                $i += 1;
+            }
+        } else {
+            // show info box if no child lessons added yet
+            $this->addEmptySectionBox( self::SECTION_KEY_LESSONS );
+        }
+        // TODO add controls to add lessons somewhere
+
+        $this->endSection();
+    }
+
+    /**
+     * Adds a lesson to the lessons section.
+     *
+     * @param MoocLesson $lesson lesson to add
+     * @param int $iLesson (1-based) lesson position
+     */
+    protected function addChildLesson( $lesson, $iLesson ) {
+        $this->out->addHTML( '<div class="lesson">' );
+
+        // header
+        $this->out->addHTML( '<div class="title">' );
+        $this->out->addWikiText( sprintf( '[[%s|%d. %s]]', $lesson->title, 
$iLesson, $lesson->getName() ) );
+        $this->out->addHTML( '</div>' );
+
+        // units
+        $this->addUnitsSectionContent( $lesson );
+
+        $this->out->addHTML( '</div>' );
+    }
+
+    protected function fillModalBoxForm( $sectionKey, $action ) {
+        if ( $sectionKey == self::SECTION_KEY_LESSONS && $action == 
self::ACTION_ADD ) {
+            $this->out->addHTML( '<input type="text" class="value" />' );
+        } else {
+            parent::fillModalBoxForm( $sectionKey, $action );
+        }
+    }
+
+    protected function addModalBoxActions( $sectionKey, $action ) {
+        if ( $sectionKey == self::SECTION_KEY_LESSONS && $action == 
self::ACTION_ADD ) {
+            $titleAdd = $this->loadMessage( 'modal-button-title-add' );
+            $this->out->addHTML( "<input type=\"submit\" class=\"btn btn-add 
btn-submit\" value=\"$titleAdd\" />" );
+            $titleCancel = $this->loadMessage( 'modal-button-title-cancel' );
+            $this->out->addHTML( "<input type=\"button\" class=\"btn 
btn-cancel\" value=\"$titleCancel\" />" );
+        } else {
+            parent::addModalBoxActions( $sectionKey, $action );
+        }
+    }
+
+    /**
+     * Adds the UI elements to the lessons section header that allow to add a 
lesson.
+     *
+     * @param string $sectionKey section key
+     */
+    protected function addSectionActionAddLesson( $sectionKey ) {
+        // TODO link to add lesson function instead
+        $btnHref = '/SpecialPage:MoocEdit?title=' . $this->item->title . 
'&section=' . $sectionKey;
+        $btnTitle = $this->loadMessage( "section-$sectionKey-add-title" );
+
+        $this->addSectionActionButton( 'add', $btnTitle, $btnHref );
+        $this->addModalBox( $sectionKey, 'add' );
+    }
+
+    protected function addSectionActions( $sectionKey ) {
+        if ( $sectionKey == self::SECTION_KEY_LESSONS ) {
+            // add lesson
+            $this->addSectionActionAddLesson( $sectionKey );
+        } else {
+            // TODO always add edit button
+            parent::addSectionActions( $sectionKey );
+        }
+    }
+
+    protected function getSectionActionIconFilename( $action ) {
+        if ( $action == 'add' ) {
+            return "ic_$action.png";
+        } else {
+            return "ic_$action.svg";
+        }
+    }
+
+    protected function getSectionIconFilename( $sectionKey ) {
+        switch ( $sectionKey ) {
+            case self::SECTION_KEY_LESSONS:
+                return parent::getSectionIconFilename( 'children' );
+
+            default:
+                return parent::getSectionIconFilename( $sectionKey );
+        }
+    }
+}
\ No newline at end of file
diff --git a/resources/js/ext.mooc.edit.js b/resources/js/ext.mooc.edit.js
index 3dc561a..0ff6fc6 100644
--- a/resources/js/ext.mooc.edit.js
+++ b/resources/js/ext.mooc.edit.js
@@ -21,10 +21,13 @@
    * Registers the API calls with the corresponding UI elements.
    */
   function registerApiCalls() {
-    new mw.Api().loadMessagesIfMissing( ['mooc-lesson-add-unit-summary'] 
).then( function () {
+    new mw.Api().loadMessagesIfMissing( [
+      'mooc-overview-add-lesson-summary', 'mooc-lesson-add-unit-summary'
+    ] ).then( function () {
       // initialize modal edit boxes
       initModalEditBoxes( item );
-      // initialize modal add box
+      // initialize modal add boxes
+      $( '#lessons' ).find( '.header form.add .btn-submit' ).on( 'click', 
addLessonToCurrentMooc );
       $( '#units' ).find( '.header form.add .btn-submit' ).on( 'click', 
addUnitToCurrentLesson );
     } );
   }
@@ -42,6 +45,25 @@
     // TODO show loading indicator
     // create unit
     apiAddUnitToLesson( mw.config.get( 'wgPageName' ), unitName ).then( 
function () {
+      // reload page on success
+      reloadPage();
+    } );
+    return false;
+  }
+
+  /**
+   * Adds the lesson specified by the modal add lesson box to the MOOC 
represented by this page.
+   *
+   * @returns {boolean} whether the mouse event should be delegated or not
+   */
+  function addLessonToCurrentMooc() {
+    var $form = $( this ).parents( 'form.add' );
+    var lessonName = $form.find( '.value' ).val();
+    // TODO validate lesson name
+
+    // TODO show loading indicator
+    // create lesson
+    apiAddLessonToMooc( mw.config.get( 'wgPageName' ), lessonName ).then( 
function () {
       // reload page on success
       reloadPage();
     } );
@@ -187,10 +209,22 @@
     var summary = mw.message( 'mooc-lesson-add-unit-summary', unitName 
).text();
 
     mw.log( 'adding unit ' + unitName + ' (' + unitTitle + ') to lesson ' + 
lessonTitle );
-    return apiCreatePage( unitTitle, content, summary, {
-        // TODO currently not possible when logged out (or even if logged-in 
as non-admin?)
-        'contentmodel': 'mooc-item'
-      });
+    return apiCreatePage( unitTitle, content, summary );
+  }
+
+  /**
+   * Adds a lesson to a MOOC using the MediaWiki API in the background.
+   * @param moocTitle title of the MOOC
+   * @param lessonName name of the lesson to be added
+   * @returns {*} jQuery-promise on the AJAX request
+   */
+  function apiAddLessonToMooc( moocTitle, lessonName ) {
+    var lessonTitle = moocTitle + '/' + lessonName;
+    var content = '{"type":"mooc"}';
+    var summary = mw.message( 'mooc-overview-add-lesson-summary', lessonName 
).text();
+
+    mw.log( 'adding lesson ' + lessonName + ' (' + lessonTitle + ') to MOOC ' 
+ moocTitle );
+    return apiCreatePage( lessonTitle, content, summary );
   }
 
   /**
@@ -208,16 +242,18 @@
    * @param item MOOC item being currently displayed
    */
   function initModalEditBoxes( item ) {
-    // learning goals
-    initModalEditBox( 'learning-goals', item );
-    // video
-    initModalEditBox( 'video', item );
-    // script
-    initModalEditBox( 'script', item );
-    // quiz
-    initModalEditBox( 'quiz', item );
-    // further reading
-    initModalEditBox( 'further-reading', item );
+    if ( item.type !== 'mooc' ) {
+      // learning goals
+      initModalEditBox( 'learning-goals', item );
+      // video
+      initModalEditBox( 'video', item );
+      // script
+      initModalEditBox( 'script', item );
+      // quiz
+      initModalEditBox( 'quiz', item );
+      // further reading
+      initModalEditBox( 'further-reading', item );
+    }
   }
 
   /**
@@ -386,7 +422,7 @@
    */
   function buildHtmlList( $list, items ) {
     $list.empty();
-    if ( items !== undefined && items.length > 0 ) {
+    if ( items !== undefined && items !== null && items.length > 0 ) {
       for ( var i = 0; i < items.length; i++ ) {
         addListItem( $list, items[i] );
       }
diff --git a/resources/less/ext.mooc.less b/resources/less/ext.mooc.less
index ab19ac9..4e537b0 100644
--- a/resources/less/ext.mooc.less
+++ b/resources/less/ext.mooc.less
@@ -2,7 +2,6 @@
  * @author Sebastian Schlicht (User:sebschlicht), Rene Pickhardt 
(User:renepick)
  * @website https://www.mediawiki.org/wiki/Extension:MOOC
  */
-
 // IMPORTS
 @import "elements.less";
 
@@ -91,7 +90,7 @@
       cursor: pointer;
       .gradient(#FFF, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0));
       .transition(.3s, ease-in);
-      
+
       text-align: center;
       padding-top: 70px;
       font-size: 150%;
@@ -109,7 +108,7 @@
       padding: 40px;
       cursor: default;
       z-index: 1000;
-      
+
       .modal-bg {
         position: fixed;
         width: 100%;
@@ -132,7 +131,7 @@
     }
   }
   .section:first-child {
-       border-top: none;
+    border-top: none;
   }
   .section.default-collapsed {
     .content {
@@ -151,10 +150,11 @@
     }
   }
 }
+
 #mooc-navigation-bar {
   position: absolute;
   right: 0;
-  
+
   #mooc-navigation {
     #mooc-sections .section;
 
@@ -255,6 +255,15 @@
   }
 }
 
+#mooc #lessons {
+  .lesson {
+    > .title {
+      font-size: 1.5em;
+      font-weight: bold;
+    }
+  }
+}
+
 /* MODAL BOX FORMS */
 #mooc .modal-box form {
   ol.value {

-- 
To view, visit https://gerrit.wikimedia.org/r/340760
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I6d7ed1cbebb264622ca117402dec5d460dc9f90b
Gerrit-PatchSet: 2
Gerrit-Project: mediawiki/extensions/MOOC
Gerrit-Branch: master
Gerrit-Owner: Sebschlicht2 <sebschli...@uni-koblenz.de>
Gerrit-Reviewer: Sebschlicht <sebschli...@uni-koblenz.de>
Gerrit-Reviewer: Sebschlicht2 <sebschli...@uni-koblenz.de>
Gerrit-Reviewer: Siebrand <siebr...@kitano.nl>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to