Matthias Mullie has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/89012


Change subject: Add link to history
......................................................................

Add link to history

* link to history added behind "timestamp"
* add edit post icon
* only display hide/delete/censor in flagging flyout
* hide flag icon if no actions are available to the user
* refactored PostActionMenu, it was impractical to build multiple different
  buttons per actions (still not entirely happy with the new class, but it's an
  improvement)
* removed "timestamp" border-bottom, should probably only show underline, on
  hover, if there's a link

Change-Id: Ifff327500780998c0faea12f5a6f2fbb0daa4b61
---
M includes/Model/PostRevision.php
M includes/Templating.php
M includes/View/PostActionMenu.php
M modules/base/styles/various.less
M modules/discussion/forms.js
M modules/discussion/styles/post.less
M modules/discussion/ui.js
M templates/post.html.php
8 files changed, 228 insertions(+), 95 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Flow 
refs/changes/12/89012/1

diff --git a/includes/Model/PostRevision.php b/includes/Model/PostRevision.php
index d6f6e71..d5d4fe7 100644
--- a/includes/Model/PostRevision.php
+++ b/includes/Model/PostRevision.php
@@ -159,6 +159,7 @@
                        return false;
                }
        }
+
        public function isAllowedToEdit( $user ) {
                if ( $user->isAnon() ) {
                        return false;
diff --git a/includes/Templating.php b/includes/Templating.php
index f647189..b254c3a 100644
--- a/includes/Templating.php
+++ b/includes/Templating.php
@@ -88,6 +88,8 @@
        }
 
        public function renderPost( PostRevision $post, Block $block, $return = 
true ) {
+               global $wgUser, $wgFlowTokenSalt;
+
                return $this->render(
                        'flow:post.html.php',
                        array(
@@ -95,7 +97,13 @@
                                'post' => $post,
                                // An ideal world may pull this from the 
container, but for now this is fine.  This templating
                                // class has too many responsibilities to keep 
receiving all required objects in the constructor.
-                               'postActionMenu' => new PostActionMenu( 
$this->urlGenerator ),
+                               'postActionMenu' => new PostActionMenu(
+                                       $this->urlGenerator,
+                                       $wgUser,
+                                       $block,
+                                       $post,
+                                       $wgUser->getEditToken( $wgFlowTokenSalt 
)
+                               ),
                        ),
                        $return
                );
diff --git a/includes/View/PostActionMenu.php b/includes/View/PostActionMenu.php
index 9c41ce9..43d1ea9 100644
--- a/includes/View/PostActionMenu.php
+++ b/includes/View/PostActionMenu.php
@@ -6,85 +6,171 @@
 use Flow\Model\PostRevision;
 use Flow\UrlGenerator;
 use Html;
+use User;
 
 class PostActionMenu {
        // Received via constructor
        protected $urlGenerator;
-
-       // Received for each call of self::get
        protected $block;
        protected $editToken;
        protected $post;
        protected $user;
 
-       public function __construct( UrlGenerator $urlGenerator ) {
+       public function __construct( UrlGenerator $urlGenerator, User $user, 
Block $block, PostRevision $post, $editToken ) {
                $this->urlGenerator = $urlGenerator;
-       }
-
-       public function get( $user, Block $block, PostRevision $post, 
$editToken ) {
-               // For this type of shared-state to remain consistent self::get 
*must* be the only public methodctio
                $this->user = $user;
                $this->block = $block;
                $this->post = $post;
                $this->editToken = $editToken;
-
-               $actions = array();
-
-               switch( $post->getModerationState() ) {
-               case $post::MODERATED_NONE:
-                       if ( $user->isAllowed( 'flow-hide' ) ) {
-                               $actions['hide'] = $this->postAction( 
'hide-post', array( 'postId' => $post->getPostId()->getHex() ), 
'flow-hide-post-link mw-ui-destructive mw-ui-destructive-low' );
-                       }
-                       if ( $user->isAllowed( 'flow-delete' ) ) {
-                               $actions['delete'] = $this->postAction( 
'delete-post', array( 'postId' => $post->getPostId()->getHex() ), 
'flow-delete-post-link mw-ui-destructive mw-ui-destructive-medium' );
-                       }
-                       if ( $user->isAllowed( 'flow-censor' ) ) {
-                               $actions['censor'] = $this->postAction( 
'censor-post', array( 'postId' => $post->getPostId()->getHex() ), 
'flow-censor-post-link mw-ui-destructive' );
-                       }
-                       $actions['history'] = $this->getAction( 'post-history' 
);
-                       if ( $post->isAllowedToEdit( $user ) ) {
-                               $actions['edit-post'] = $this->getAction( 
'edit-post' );
-                       }
-                       break;
-
-               case $post::MODERATED_HIDDEN:
-                       if ( $user->isAllowed( 'flow-hide' ) ) {
-                               $actions['restore'] = $this->postAction( 
'restore-post', array( 'postId' => $post->getPostId()->getHex() ), 
'flow-restore-post-link mw-ui-constructive mw-ui-destructive-low' );
-                       }
-                       if ( $user->isAllowed( 'flow-delete' ) ) {
-                               $actions['delete'] = $this->postAction( 
'delete-post', array( 'postId' => $post->getPostId()->getHex() ), 
'flow-delete-post-link mw-ui-destructive mw-ui-destructive-medium' );
-                       }
-                       if ( $user->isAllowed( 'flow-censor' ) ) {
-                               $actions['censor'] = $this->postAction( 
'censor-post', array( 'postId' => $post->getPostId()->getHex() ), 
'flow-censor-post-link mw-ui-destructive' );
-                       }
-                       $actions['history'] = $this->getAction( 'post-history' 
);
-                       break;
-
-               case $post::MODERATED_DELETED:
-                       if ( $user->isAllowedAny( 'flow-delete', 'flow-censor' 
) ) {
-                               $actions['restore'] = $this->postAction( 
'restore-post', array( 'postId' => $post->getPostId()->getHex() ), 
'flow-restore-post-link mw-ui-constructive' );
-                       }
-                       $actions['history'] = $this->getAction( 'post-history' 
);
-                       break;
-
-               case $post::MODERATED_CENSORED:
-                       if ( !$user->isAllowed( 'flow-censor' ) ) {
-                               // no children, no nothing
-                               return;
-                       }
-                       $actions['restore'] = $this->postAction( 
'restore-post', array( 'postId' => $post->getPostId()->getHex() ), 
'flow-restore-post-link mw-ui-constructive' );
-                       $actions['history'] = $this->getAction( 'post-history' 
);
-                       break;
-               }
-
-               // Default always-available actions
-               $actions['permalink'] = $this->getAction( 'view' );
-
-               return $actions;
        }
 
-       protected function postAction( $action, array $data = array(), $class ) 
{
-               // actions that change things must be post requests
+       /**
+        * Returns action details.
+        *
+        * @param string $action
+        * @return array|bool Array of action details or false if invalid
+        */
+       protected function getActionDetails( $action ) {
+               $actions = array(
+                       'hide-post' => array(
+                               'method' => 'POST',
+                               'permissions' => array(
+                                       PostRevision::MODERATED_NONE => 
'flow-hide',
+                                       PostRevision::MODERATED_HIDDEN => 
'flow-hide',
+                               ),
+                       ),
+                       'delete-post' => array(
+                               'method' => 'POST',
+                               'permissions' => array(
+                                       PostRevision::MODERATED_NONE => 
'flow-delete',
+                                       PostRevision::MODERATED_HIDDEN => 
'flow-delete',
+                               ),
+                       ),
+                       'censor-post' => array(
+                               'method' => 'POST',
+                               'permissions' => array(
+                                       PostRevision::MODERATED_NONE => 
'flow-censor',
+                                       PostRevision::MODERATED_HIDDEN => 
'flow-censor',
+                               ),
+                       ),
+                       'restore-post' => array(
+                               'method' => 'POST',
+                               'permissions' => array(
+                                       PostRevision::MODERATED_DELETED => 
array( 'flow-delete', 'flow-censor' ),
+                                       PostRevision::MODERATED_CENSORED => 
'flow-censor',
+                               ),
+                       ),
+                       'post-history' => array(
+                               'method' => 'GET',
+                               'permissions' => array(
+                                       PostRevision::MODERATED_NONE => '',
+                                       PostRevision::MODERATED_HIDDEN => '',
+                                       PostRevision::MODERATED_DELETED => '',
+                                       PostRevision::MODERATED_CENSORED => 
'flow-censor',
+                               ),
+                       ),
+                       'edit-post' => array(
+                               'method' => 'GET',
+                               'permissions' => array(
+                                       // no permissions needed for own posts
+                                       PostRevision::MODERATED_NONE => 
$this->post->isAllowedToEdit( $this->user ) ? '' : 'flow-edit-post',
+                                       PostRevision::MODERATED_HIDDEN => 
$this->post->isAllowedToEdit( $this->user ) ? '' : 'flow-edit-post',
+                                       PostRevision::MODERATED_DELETED => 
$this->post->isAllowedToEdit( $this->user ) ? '' : 'flow-edit-post',
+                                       PostRevision::MODERATED_CENSORED => 
$this->post->isAllowedToEdit( $this->user ) ? '' : 'flow-edit-post',
+                               ),
+                       ),
+                       'view' => array(
+                               'method' => 'GET',
+                               'permissions' => array(
+                                       PostRevision::MODERATED_NONE => '',
+                                       PostRevision::MODERATED_HIDDEN => '',
+                                       PostRevision::MODERATED_DELETED => '',
+                                       PostRevision::MODERATED_CENSORED => '',
+                               ),
+                       ),
+               );
+
+               return isset( $actions[$action] ) ? $actions[$action] : false;
+       }
+
+       /**
+        * Build a button for a certain action
+        *
+        * @param string $action
+        * @param string $content Make sure $content is safe HTML!
+        * @param string $class
+        * @return string|bool Button HTML or false on failure
+        */
+       public function getButton( $action, $content, $class ) {
+               $details = $this->getActionDetails( $action );
+
+               if ( !$this->isAllowed( $action ) ) {
+                       return false;
+               }
+
+               $data = array( $this->block->getName() . '[postId]' => 
$this->post->getPostId()->getHex() );
+               if ( $details['method'] === 'POST' ) {
+                       return $this->postAction( $action, $data, $content, 
$class );
+               } else {
+                       return $this->getAction( $action, $data, $content, 
$class );
+               }
+       }
+
+       /**
+        * Check if a user is allowed to perform (a) certain action(s).
+        *
+        * @param string $action
+        * @param string[optional] $action2 Overloadable to check if either of 
the provided actions are allowed
+        * @return bool
+        */
+       public function isAllowed( $action /* [, $action2 [, ... ]] */ ) {
+               $details = $this->getActionDetails( $action );
+
+               // check if permission is set for this action
+               if ( !isset( 
$details['permissions'][$this->post->getModerationState()] ) ) {
+                       return false;
+               }
+
+               // check if user is allowed to perform action
+               return call_user_func_array(
+                       array( $this->user, 'isAllowedAny' ),
+                       (array) 
$details['permissions'][$this->post->getModerationState()]
+               );
+       }
+
+       /**
+        * Check if a user is allowed to perform certain actions.
+        *
+        * @param string $action
+        * @param string[optional] $action2 Overloadable to check if either of 
the provided actions are allowed
+        * @return bool
+        */
+       public function isAllowedAny( $action /* [, $action2 [, ... ]] */ ) {
+               $actions = func_get_args();
+               $allowed = false;
+
+               foreach ( $actions as $action ) {
+                       $allowed |= $this->isAllowed( $action );
+
+                       // as soon as we've found one that is allowed, break
+                       if ( $allowed ) {
+                               break;
+                       }
+               }
+
+               return $allowed;
+       }
+
+       /**
+        * Create form for actions that require POST.
+        *
+        * @param string $action
+        * @param array $data
+        * @param string $content
+        * @param string $class
+        * @return string
+        */
+       protected function postAction( $action, array $data, $content, $class ) 
{
                $output = array(
                        Html::openElement( 'form', array(
                                'method' => 'POST',
@@ -96,37 +182,44 @@
                foreach ( $data as $name => $value ) {
                        $output[] = Html::element( 'input', array(
                                'type' => 'hidden',
-                               'name' => $this->block->getName() . "[$name]",
+                               'name' => $name,
                                'value' => $value,
                        ) );
                }
-               // Messages: flow-post-action-censor-post, 
flow-post-action-delete-post,
-               // flow-post-action-hide-post, flow-post-action-restore-post
+
                $output[] = Html::element( 'input', array(
                        'type' => 'submit',
-                       'class' => "mw-ui-button $class",
-                       'value' => wfMessage( "flow-post-action-$action" 
)->plain(),
+                       'class' => $class,
+                       'value' => $content,
                ) ) .
                Html::closeElement( 'form' );
 
                return implode( '', $output );
        }
 
-       protected function getAction( $action ) {
+       /**
+        * Create link for actions that require GET.
+        *
+        * @param string $action
+        * @param array $data
+        * @param string $content
+        * @param string $class
+        * @return string
+        */
+       protected function getAction( $action, array $data, $content, $class ) {
                $url = $this->urlGenerator->generateUrl(
                        $this->block->getWorkflowId(),
                        $action,
-                       array(
-                               $this->block->getName() . '[postId]' => 
$this->post->getPostId()->getHex(),
-                       )
+                       $data
                );
-               // Messages: flow-post-action-view, 
flow-post-action-post-history, flow-post-action-edit-post
-               return Html::element(
+
+               return Html::rawElement(
                        'a',
                        array(
                                'href' => $url,
+                               'class' => $class,
                        ),
-                       wfMessage( "flow-post-action-$action" )->plain()
+                       $content
                );
        }
 }
diff --git a/modules/base/styles/various.less b/modules/base/styles/various.less
index f5ddcec..773c6c4 100644
--- a/modules/base/styles/various.less
+++ b/modules/base/styles/various.less
@@ -12,9 +12,4 @@
 
 .flow-datestamp {
        color: #aaa;
-
-       span {
-               line-height: 18px;
-               border-bottom: 1px solid #ccc;
-       }
 }
diff --git a/modules/discussion/forms.js b/modules/discussion/forms.js
index cd9327f..7ec80dc 100644
--- a/modules/discussion/forms.js
+++ b/modules/discussion/forms.js
@@ -79,7 +79,7 @@
        );
 
        // Overload 'edit post' link.
-       $container.find( '.flow-action-edit-post a' )
+       $container.find( '.flow-edit-post-link' )
                .click( function ( e ) {
                        e.preventDefault();
                        var $postContainer = $( this ).closest( '.flow-post' ),
diff --git a/modules/discussion/styles/post.less 
b/modules/discussion/styles/post.less
index 4f1c1d7..6b713de 100644
--- a/modules/discussion/styles/post.less
+++ b/modules/discussion/styles/post.less
@@ -20,9 +20,29 @@
                padding-bottom: 20px;
        }
 
+       .flow-edit-post-link {
+               margin-top: -60px; // default -40px + -20px to be pushed up 
(because of .flow-post-content bottom padding)
+
+               background-position: center;
+               background-size: 20px auto;
+               background-repeat: no-repeat;
+       }
+
+       &:hover .flow-edit-post-link {
+               .background-image-svg('../../base/images/edit_normal.svg', 
'../../base/images/edit_normal.png');
+
+               &:hover {
+                       
.background-image-svg('../../base/images/edit_hover.svg', 
'../../base/images/edit_hover.png');
+               }
+       }
+
        .flow-datestamp {
                float: right;
                padding-right: 22px;
+
+               a.flow-action-history-link {
+                       color: inherit;
+               }
        }
 
        .flow-actions {
diff --git a/modules/discussion/ui.js b/modules/discussion/ui.js
index b5a68ab..e863619 100644
--- a/modules/discussion/ui.js
+++ b/modules/discussion/ui.js
@@ -22,8 +22,8 @@
                // Set up timestamp on-hover
                $container.find( '.flow-topic-datestamp, .flow-datestamp' )
                        .hover(function () {
-                               $(this).children( '.flow-agotime' ).toggle();
-                               $(this).children( '.flow-utctime' ).toggle();
+                               $(this).find( '.flow-agotime' ).toggle();
+                               $(this).find( '.flow-utctime' ).toggle();
                        } );
 
                // Set up post creator on-hover
diff --git a/templates/post.html.php b/templates/post.html.php
index ec68a02..2b6c5ca 100644
--- a/templates/post.html.php
+++ b/templates/post.html.php
@@ -38,8 +38,6 @@
                Html::closeElement( 'form' );
 }
 
-$actions = array();
-
 
 // The actual output
 echo Html::openElement( 'div', array(
@@ -76,14 +74,25 @@
                        <div class="flow-post-content">
                                <?php echo $post->getContent( $user, 'html' ); 
?>
                        </div>
+                       <?php if ( $postActionMenu->isAllowed( 'edit-post' ) ) {
+                               echo $postActionMenu->getButton( 'edit-post', 
wfMessage( 'flow-post-action-edit-post' )->plain(), 'flow-edit-post-link 
flow-icon flow-icon-bottom-aligned' );
+                       }
+                       ?>
 
                        <p class="flow-datestamp">
-                               <span class="flow-agotime" style="display: 
inline">
-                                       <?php echo 
$post->getPostId()->getHumanTimestamp(); ?>
-                               </span>
-                               <span class="flow-utctime" style="display: 
none">
-                                       <?php echo 
$post->getPostId()->getTimestampObj()->getTimestamp( TS_RFC2822 ); ?>
-                               </span>
+                               <?php
+                                       // timestamp html
+                                       $content = '
+                                               <span class="flow-agotime" 
style="display: inline">'. $post->getPostId()->getHumanTimestamp() .'</span>
+                                               <span class="flow-utctime" 
style="display: none">'. $post->getPostId()->getTimestampObj()->getTimestamp( 
TS_RFC2822 ) .'</span>';
+
+                                       // build history button with timestamp 
html as content
+                                       if ( $postActionMenu->isAllowed( 
'post-history' ) ) {
+                                               echo 
$postActionMenu->getButton( 'post-history', $content, 
'flow-action-history-link' );
+                                       } else {
+                                               echo $content;
+                                       }
+                               ?>
                        </p>
 
                        <div class="flow-post-interaction">
@@ -102,19 +111,26 @@
                        </div>
                </div>
 
+               <?php if ( $postActionMenu->isAllowedAny( 'hide-post', 
'delete-post', 'censor-post' ) ): ?>
                <div class="flow-actions">
                        <a class="flow-actions-link flow-icon 
flow-icon-bottom-aligned" href="#"><?php echo wfMessage( 'flow-post-actions' 
)->escaped(); ?></a>
                        <div class="flow-actions-flyout">
                                <ul>
                                        <?php
-                                       foreach( $postActionMenu->get( $user, 
$block, $post, $editToken ) as $key => $action ) {
-                                               // @todo: $actions currently 
includes a lot of actions, design only wants censor actions here; figure out 
where others belong
-                                               echo "<li 
class=\"flow-action-$key\">$action</li>";
+                                       if ( $postActionMenu->isAllowed( 
'hide-post' ) ) {
+                                               echo '<li 
class="flow-action-hide">'. $postActionMenu->getButton( 'hide-post', wfMessage( 
'flow-post-action-hide-post' )->plain(), 'flow-hide-post-link mw-ui-button 
mw-ui-destructive mw-ui-destructive-low' ) .'</li>';
+                                       }
+                                       if ( $postActionMenu->isAllowed( 
'delete-post' ) ) {
+                                               echo '<li 
class="flow-action-delete">'. $postActionMenu->getButton( 'delete-post', 
wfMessage( 'flow-post-action-delete-post' )->plain(), 'flow-delete-post-link 
mw-ui-button mw-ui-destructive mw-ui-destructive-medium' ) .'</li>';
+                                       }
+                                       if ( $postActionMenu->isAllowed( 
'censor-post' ) ) {
+                                               echo '<li 
class="flow-action-censor">'. $postActionMenu->getButton( 'censor-post', 
wfMessage( 'flow-post-action-censor-post' )->plain(), 'flow-censor-post-link 
mw-ui-button mw-ui-destructive' ) .'</li>';
                                        }
                                        ?>
                                </ul>
                        </div>
                </div>
+               <?php endif; ?>
 
        </div>
 

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ifff327500780998c0faea12f5a6f2fbb0daa4b61
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: master
Gerrit-Owner: Matthias Mullie <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to