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 . '§ion=' . $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