SamanthaNguyen has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/380322 )

Change subject: [DNM] v4.4.0 - New form in OOUI with previewing + byte limit 
features
......................................................................

[DNM] v4.4.0 - New form in OOUI with previewing + byte limit features

Not everything is fully implemented yet, but getting there.

New features (outlined plan):
 - You can now preview your comment in wiki markup to help prevent
   mistakes before submitting. This can be done by writing your comment
   and then clicking on the "Preview" tab.
 - As a system administrator, you can decide whether or not to have an
   enforced byte limit turned on or off. By default, it is turned off.
   The variables include:
    - $wgCommentsEnableByteLimit
    - $wgCommentsByteLimitNumber

TODO:
 - Handle buttons properly
 - Handle permissions properly
 - Make sure tabs show up
 - Use core jquery.byteLimit module for enforcing byte limit

Based on original demo/experiment in:
 - https://samanthanguyen.github.io/mediawiki-demos/comments/demo.html

Bug: T156055
Change-Id: I977089eedad5be5f944f8ffeb4ad757b7fda4517
---
M .jshintrc
M extension.json
M i18n/en.json
M i18n/qqq.json
M includes/CommentsPage.class.php
A includes/interfaces/FormInterface.php
M includes/parser/DisplayComments.class.php
M resources/css/Comments.css
A resources/css/ext.comments.form.ooui.styles.css
A resources/js/ext.comments.form.ooui.js
10 files changed, 286 insertions(+), 63 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Comments 
refs/changes/22/380322/1

diff --git a/.jshintrc b/.jshintrc
index 04c3a97..687fe80 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -18,6 +18,7 @@
        "jquery": true,
 
        "globals": {
-               "mediaWiki": false
+               "mediaWiki": false,
+               "OO": false
        }
 }
diff --git a/extension.json b/extension.json
index 143c8dc..719f71a 100644
--- a/extension.json
+++ b/extension.json
@@ -1,6 +1,6 @@
 {
        "name": "Comments",
-       "version": "4.3.2",
+       "version": "4.4.0",
        "author": [
                "David Pean",
                "Misza",
@@ -74,7 +74,8 @@
                "CommentLatestIdAPI": "includes/api/CommentLatestID.api.php",
                "CommentListAPI": "includes/api/CommentList.api.php",
                "CommentSubmitAPI": "includes/api/CommentSubmit.api.php",
-               "CommentVoteAPI": "includes/api/CommentVote.api.php"
+               "CommentVoteAPI": "includes/api/CommentVote.api.php",
+               "FormInterface": "includes/interfaces/FormInterface.php"
        },
        "ResourceModules": {
                "ext.comments.css": {
@@ -95,6 +96,25 @@
                                "comments-block-warning-user",
                                "comments-delete-warning"
                        ]
+               },
+               "ext.comments.form.ooui.styles": {
+                       "styles": 
"resources/css/ext.comments.forms.ooui.styles.css",
+                       "position": "top"
+               },
+               "ext.comments.form.ooui": {
+                       "scripts": "resources/js/ext.comments.form.ooui.js",
+                       "dependencies": [
+                               "oojs-ui-core",
+                               "oojs-ui-widgets",
+                               "oojs-ui.styles.icons-alerts"
+                       ],
+                       "messages": [
+                               "comments-preview-failed",
+                               "comments-tab-write",
+                               "comments-tab-preview",
+                               "comments-post",
+                               "comments-cancel-reply"
+                       ]
                }
        },
        "ResourceFileModulePaths": {
@@ -111,7 +131,9 @@
        "config": {
                "CommentsDefaultAvatar": 
"http://www.shoutwiki.com/w/extensions/SocialProfile/avatars/default_ml.gif";,
                "CommentsSortDescending": false,
-               "CommentsInRecentChanges": false
+               "CommentsInRecentChanges": false,
+               "CommentsEnableByteLimit": false,
+               "CommentsByteLimitNumber": ""
        },
        "manifest_version": 1
 }
diff --git a/i18n/en.json b/i18n/en.json
index 78e4940..c97108b 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -67,6 +67,10 @@
        "comments-ignore-title": "Comment ignore list",
        "commentignorelist": "Comment ignore list",
        "comments-no-comments-of-day": "There are no comments of the day.",
+       "comments-textarea-placeholder": "Add a comment",
+       "comments-tab-write": "Write",
+       "comments-tab-preview": "Preview",
+       "comments-preview-failed": "Previewing failed. Please try again.",
        "log-name-comments": "Comments log",
        "log-description-comments": "This is a log of comments.",
        "logentry-comments-add": "$1 posted a new comment on $3",
diff --git a/i18n/qqq.json b/i18n/qqq.json
index c6e6340..6c81e69 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -75,6 +75,10 @@
        "comments-ignore-title": "Title of Special:CommentIgnoreList, as shown 
on the said page.",
        "commentignorelist": "{{doc-special|CommentIgnoreList}}\nThe comment 
ignore list contains a list of users whose comments you are ignoring; an 
ignored comment won't show up by default and you have to click on a special 
link to view it",
        "comments-no-comments-of-day": "Shown as the output of the 
<code><nowiki><commentsoftheday /></nowiki></code> parser hook if there are no 
comments of the day.",
+       "comments-textarea-placeholder": "Placeholder shown in the comment 
textarea when the end-user hasn't written anything yet.",
+       "comments-tab-write": "A verb as a title for a tab panel that lets the 
end-user write their own comment.",
+       "comments-tab-preview": "A verb as a title for a tab panel that lets 
the end-user preview their comment parsed as wiki markup.",
+       "comments-preview-failed": "Error given when previewing the wikitext of 
the comment fails.",
        "log-name-comments": "Shown on the dropdown on [[Special:Log]].",
        "log-description-comments": "Explanation of the comments log, shown on 
[[Special:Log/comments]].",
        "logentry-comments-add": "Parameters:\n* $1 - contains the user name + 
talk/block/contribs links, as is the standard with log entries nowadays\n* $2 - 
(Optional) username, for <nowiki>{{GENDER}}</nowiki> support\n* $3 - a wikilink 
to the page where the comment was posted; it contains a fragment that directly 
points to the new comment in question, i.e. [[Talk:Main Page#comment-10]] (the 
number is the internal comment identifier)",
diff --git a/includes/CommentsPage.class.php b/includes/CommentsPage.class.php
index b6050cf..c843c4a 100644
--- a/includes/CommentsPage.class.php
+++ b/includes/CommentsPage.class.php
@@ -547,49 +547,15 @@
         * @return string HTML output
         */
        function displayForm() {
-               $output = '<form action="" method="post" name="commentForm">' . 
"\n";
+               $form = new FormInterface;
+               
+               MediaWiki\suppressWarnings();
+               $form->setRef( 'commentPage', $this );
+               $form->setRef( 'user', $this->getUser() );
+               MediaWiki\restoreWarnings();
 
-               if ( $this->allow ) {
-                       $pos = strpos(
-                               strtoupper( addslashes( $this->allow ) ),
-                               strtoupper( addslashes( 
$this->getUser()->getName() ) )
-                       );
-               }
-
-               // 'comment' user right is required to add new comments
-               if ( !$this->getUser()->isAllowed( 'comment' ) ) {
-                       $output .= wfMessage( 'comments-not-allowed' )->parse();
-               } else {
-                       // Blocked users can't add new comments under any 
conditions...
-                       // and maybe there's a list of users who should be 
allowed to post
-                       // comments
-                       if ( $this->getUser()->isBlocked() == false && ( 
$this->allow == '' || $pos !== false ) ) {
-                               $output .= '<div class="c-form-title">' . 
wfMessage( 'comments-submit' )->plain() . '</div>' . "\n";
-                               $output .= '<div id="replyto" 
class="c-form-reply-to"></div>' . "\n";
-                               // Show a message to anons, prompting them to 
register or log in
-                               if ( !$this->getUser()->isLoggedIn() ) {
-                                       $login_title = 
SpecialPage::getTitleFor( 'Userlogin' );
-                                       $register_title = 
SpecialPage::getTitleFor( 'Userlogin', 'signup' );
-                                       $output .= '<div 
class="c-form-message">' . wfMessage(
-                                                       'comments-anon-message',
-                                                       htmlspecialchars( 
$register_title->getFullURL() ),
-                                                       htmlspecialchars( 
$login_title->getFullURL() )
-                                               )->text() . '</div>' . "\n";
-                               }
-
-                               $output .= '<textarea name="commentText" 
id="comment" rows="5" cols="64"></textarea>' . "\n";
-                               $output .= '<div class="c-form-button"><input 
type="button" value="' .
-                                       wfMessage( 'comments-post' )->plain() . 
'" class="site-button" /></div>' . "\n";
-                       }
-                       $output .= '<input type="hidden" name="action" 
value="purge" />' . "\n";
-                       $output .= '<input type="hidden" name="pageId" value="' 
. $this->id . '" />' . "\n";
-                       $output .= '<input type="hidden" name="commentid" />' . 
"\n";
-                       $output .= '<input type="hidden" name="lastCommentId" 
value="' . $this->getLatestCommentID() . '" />' . "\n";
-                       $output .= '<input type="hidden" name="commentParentId" 
/>' . "\n";
-                       $output .= '<input type="hidden" name="' . 
$this->pageQuery . '" value="' . $this->getCurrentPagerPage() . '" />' . "\n";
-                       $output .= Html::hidden( 'token', 
$this->getUser()->getEditToken() );
-               }
-               $output .= '</form>' . "\n";
+               $output = $form->getHTML();
+               
                return $output;
        }
 
diff --git a/includes/interfaces/FormInterface.php 
b/includes/interfaces/FormInterface.php
new file mode 100644
index 0000000..12bee54
--- /dev/null
+++ b/includes/interfaces/FormInterface.php
@@ -0,0 +1,126 @@
+<?php
+
+class FormInterface extends QuickTemplate {
+
+       public function getPermissions() {
+               $user = $this->data['user'];
+               if ( $this->data['commentPage']->allow ) {
+                       $pos = strpos(
+                               strtoupper( addslashes( 
$this->data['commentPage']->allow ) ),
+                               strtoupper( addslashes( $user->getName() ) )
+                       );
+               }
+
+               // is the user allowed to comment?
+               if ( !$user->isAllowed( 'comment' ) ) {
+                       // nope, show a message that they can't
+                       echo wfMessage( 'comments-not-allowed' )->parse();
+                       return false;
+               }
+
+               // is the user blocked?
+               if (    
+                       $user->isBlocked() === false && ( 
+                       $this->data['commentPage']->allow === '' 
+                       || $pos === false ) 
+               ) {
+                       //echo some custom message for blocking
+                       return false;
+               }
+               
+               // is the user not logged in?
+               if ( !$this->getUser()->isLoggedIn() ) {
+                       $title['login'] = SpecialPage::getTitleFor( 'Userlogin' 
);
+                       $title['register'] = SpecialPage::getTitleFor( 
'Userlogin', 'signup' );
+                       echo wfMessage(
+                               'comments-anon-message',
+                               htmlspecialchars( $title['login']->getFullURL() 
),
+                               htmlspecialchars( 
$title['register']->getFullURL() )
+                       )->text();
+                       
+                       return false;
+               }
+       }
+       
+       public function getAvatar() {
+               if ( class_exists( 'wAvatar' ) ) {
+                       $avatar = new wAvatar( $user->getId(), 'ml' );
+                       $avatarUrl = $avatar->getAvatarURL( [ 'class' => 
'avatar comments-form-avatar' ] );
+               } else {
+                       $avatarUrl = '';
+               }
+
+               return $avatarUrl;
+       }
+
+       /**
+        * the OOUI\HiddenInputWidget isn't available
+        * in the oojs-ui package that comes with MediaWiki 1.29,
+        * but available with 1.30.0. For now, let's create 
+        * our own OOUI hidden input widget to handle this, 
+        * and keep everything OOUI-ified.
+        *
+        * @todo: Replace when 1.30.0 becomes the stable version
+        *
+        * @param $name
+        * @param $value
+        * @return $hidden
+        */
+       public function getHidden( $name, $value ) {
+               $hidden = new OOUI\Tag( 'input' );
+               $hidden->setAttributes( [
+                       'type' => 'hidden',
+                       'id' => '',
+                       'name' => $name,
+                       'value' => $value
+               ] );
+               
+               return $hidden;
+       }
+
+       public function getForm() {
+               self::getPermissions();
+
+               $user = $this->data['user'];
+
+               /**
+                * @todo: No PHP version of a OOUI\MultilineTextInputWidget yet,
+                * so use OOUI\TextInputWidget and 'multiline' => true for now
+                *
+                * @see: https://phabricator.wikimedia.org/T166686
+                */
+               $textarea = new OOUI\TextInputWidget( [
+                       'infusable' => true,
+                       'multiline' => true,
+                       'placeholder' => wfMessage( 
'comments-textarea-placeholder' ),
+                       'rows' => 8,
+                       'id' => 'CommentsTextareaWidget',
+                       'name' => 'commentText'
+               ] );
+               
+               $form = new OOUI\FormLayout( [
+                       'infusable' => true,
+                       'method' => 'post',
+                       'action' => '',
+                       'id' => 'CommentsFormLayout',
+                       'name' => 'commentForm',
+                       'items' => [
+                               $textarea,
+                               // hidden input data
+                               self::getHidden( 'action', 'purge' ),
+                               self::getHidden( 'pageId', 
$this->data['commentPage']->id ),
+                               self::getHidden( 'commentid', '' ),
+                               self::getHidden( 'lastCommentId', 
$this->data['commentPage']->getLatestCommentID() ),
+                               self::getHidden( 'commentParentId', '' ),
+                               self::getHidden( 
$this->data['commentPage']->pageQuery, 
$this->data['commentPage']->getCurrentPagerPage() ),
+                               self::getHidden( 'token', $user->getEditToken() 
)
+                       ]
+               ] );
+               
+               return $form;
+       }
+
+       public function execute() {
+               echo self::getForm();
+       }
+}
\ No newline at end of file
diff --git a/includes/parser/DisplayComments.class.php 
b/includes/parser/DisplayComments.class.php
index 110188f..08b34e5 100644
--- a/includes/parser/DisplayComments.class.php
+++ b/includes/parser/DisplayComments.class.php
@@ -14,6 +14,7 @@
        public static function getParserHandler( $input, $args, $parser ) {
                global $wgOut, $wgCommentsSortDescending;
 
+               $parser->enableOOUI();
                $parser->disableCache();
                // If an unclosed <comments> tag is added to a page, the 
extension will
                // go to an infinite loop...this protects against that 
condition.
@@ -25,8 +26,8 @@
                }
 
                // Add required CSS & JS via ResourceLoader
-               $wgOut->addModuleStyles( 'ext.comments.css' );
-               $wgOut->addModules( 'ext.comments.js' );
+               $wgOut->addModuleStyles( [ 'ext.comments.css', 
'ext.comments.form.ooui.styles' ] );
+               $wgOut->addModules( [ 'ext.comments.js', 
'ext.comments.form.ooui' ] );
                $wgOut->addJsConfigVars( array( 'wgCommentsSortDescending' => 
$wgCommentsSortDescending ) );
 
                // Parse arguments
diff --git a/resources/css/Comments.css b/resources/css/Comments.css
index 93aa0f1..ca9e951 100644
--- a/resources/css/Comments.css
+++ b/resources/css/Comments.css
@@ -113,27 +113,12 @@
        margin: -5px 0px 0px 2px
 }
 
-.c-form-title {
-       color: #333;
-       font-weight: bold;
-       font-size: 17px;
-       margin: 0px 0px 5px 0px;
-}
-
 .c-form-message {
        font-size: 11px;
        width: 400px;
        line-height: 13px;
        color: #666;
        padding: 5px 0px 10px 0px;
-}
-
-textarea#comment {
-       width: 530px;
-}
-
-.c-form-button {
-       padding: 10px 0px 0px;
 }
 
 .c-order {
diff --git a/resources/css/ext.comments.form.ooui.styles.css 
b/resources/css/ext.comments.form.ooui.styles.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/resources/css/ext.comments.form.ooui.styles.css
diff --git a/resources/js/ext.comments.form.ooui.js 
b/resources/js/ext.comments.form.ooui.js
new file mode 100644
index 0000000..c77d9b7
--- /dev/null
+++ b/resources/js/ext.comments.form.ooui.js
@@ -0,0 +1,114 @@
+/**
+ * Handles all functions related to the comment
+ * form, such as previewing and the tabs
+ *
+ * @file
+ */
+( function ( $, mw ) {
+       
+var CommentsForm = {
+
+       // infused OOUI widgets + layouts
+       form: oo.ui.infuse( 'CommentsFormLayout' ),
+       textarea: oo.ui.infuse( 'CommentsTextareaWidget' ),
+       avatar: oo.ui.infuse( 'CommentsAvatarWidget' ),
+
+       // other elements
+       container: $( '.comments-body' ),
+       replyto: $( '#replyto' ),
+
+       // configuration
+       isByteLimitEnabled: mw.config.get( 'wgCommentsEnableByteLimit' ),
+       getByteLimitNumber: mw.config.get( 'wgCommentsByteLimitNumber' ),
+       
+       /**
+        * Preview the contents of the <textarea> (more accurately the
+        * wikitext given to this function) and show the parsed HTML
+        * output in the given element.
+        *
+        * @param text {string} Wikitext to be sent to the API for parsing
+        * @param targetElement {string} ID of the element where
+        * the preview text should be inserted
+        */
+       preview: function ( text, targetElement ) {
+               ( new mw.Api() ).get( {
+                       action: 'parse',
+                       text: text,
+                       contentmodel: 'wikitext',
+                       disablelimitreport: true // don't need the NewPP report 
stuff
+               } ).done( function ( data ) {
+                       $( '#' + targetElement ).html( data.parse.text['*'] );
+               } ).fail( function () {
+                       $( '#' + targetElement ).text( mw.msg( 
'comments-preview-failed' ) );
+               } );
+       },
+
+       /**
+        * build the buttons that let the user
+        * either submit or cancel their comment.
+        */
+       buildButtons: function () {
+               var buttons = {
+                       submit: new OO.ui.ButtonInputWidget( {
+                               label: mw.msg( 'comments-post' ),
+                               icon: 'speechBubbleAdd',
+                               type: 'submit',
+                               flags: [ 'primary', 'progressive' ]
+                       } ),
+                       cancel: new OO.ui.ButtonInputWidget( {
+                               label: mw.msg( 'comments-cancel-reply' ),
+                               frameless: true,
+                               flags: [ 'destructive' ]
+                       } )
+               };
+
+               // decide what buttons to show
+               if ( CommentsForm.replyto.text() !== '' ) {
+                       var group = new OO.ui.ButtonGroupWidget( {
+                               items: [
+                                       buttons.submit,
+                                       buttons.cancel
+                               ]
+                       } );
+                       return group;
+               } else {
+                       return buttons.submit;
+               }
+       },
+
+       /**
+        * build the write and preview tab needed
+        * for the comment form
+        */
+       buildTabs: function () {
+               var tabs = {
+                       write: new OO.ui.TabPanelLayout( 'write', {
+                               label: mw.msg( 'comments-tab-write' ),
+                       } ),
+                       preview: new OO.ui.TabPanelLayout( 'preview', {
+                               label: mw.msg( 'comments-tab-preview' )
+                       } )
+               };
+
+               tabs.write.$element.append(
+                       CommentsForm.form.$element
+               );
+
+               tabs.preview.$element.append(
+                       CommentsForm.preview(
+                               textarea.val(),
+                               $( this ).attr( 'data-linked-element' )
+                       )
+               );
+
+               var index = new OO.ui.IndexLayout();
+               index.addTabPanels( [ formTabs.write, tabs.preview ] );
+               CommentsForm.container.html( index.$element );
+       },
+
+       enforceByteLimit: function () {
+               // work in progress
+       }
+}
+
+} );
\ No newline at end of file

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I977089eedad5be5f944f8ffeb4ad757b7fda4517
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Comments
Gerrit-Branch: master
Gerrit-Owner: SamanthaNguyen <samanthanguyen1...@gmail.com>

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

Reply via email to