No-JS special page: One-click mark as read

Bug: T136361
Change-Id: I7896dbdf25d2c1624f97777f4c8d0af41b195ef0
Depends-On: Ic31f857c749d62a32cafae68dc3f1cbd86e1e382
This commit is contained in:
Matthew Flaschen 2016-05-27 17:02:55 -07:00
parent 1bef12c3e7
commit 188e8d7395
8 changed files with 190 additions and 22 deletions

View file

@ -253,7 +253,8 @@ $wgResourceModules += array(
'ext.echo.styles.notifications' => $echoResourceTemplate + array( 'ext.echo.styles.notifications' => $echoResourceTemplate + array(
'position' => 'top', 'position' => 'top',
'styles' => array( 'styles' => array(
'nojs/mw.echo.notifications.less' 'nojs/mw.echo.notifications.less',
'styles/LabelIconWidget.less',
), ),
'targets' => array( 'desktop', 'mobile' ), 'targets' => array( 'desktop', 'mobile' ),
), ),

View file

@ -41,8 +41,8 @@ $wgAutoloadClasses += [
'EchoEmailFormat' => __DIR__ . '/includes/EmailFormat.php', 'EchoEmailFormat' => __DIR__ . '/includes/EmailFormat.php',
'EchoEmailFormatter' => __DIR__ . '/includes/EmailFormatter.php', 'EchoEmailFormatter' => __DIR__ . '/includes/EmailFormatter.php',
'EchoEmailFormatterTest' => __DIR__ . '/tests/phpunit/EmailFormatterTest.php', 'EchoEmailFormatterTest' => __DIR__ . '/tests/phpunit/EmailFormatterTest.php',
'EchoEmailMode' => __DIR__ . '/includes/EmailFormatter.php',
'EchoEmailFrequency' => __DIR__ . '/includes/EmailFrequency.php', 'EchoEmailFrequency' => __DIR__ . '/includes/EmailFrequency.php',
'EchoEmailMode' => __DIR__ . '/includes/EmailFormatter.php',
'EchoEmailSingle' => __DIR__ . '/includes/EmailFormatter.php', 'EchoEmailSingle' => __DIR__ . '/includes/EmailFormatter.php',
'EchoEmailUserPresentationModel' => __DIR__ . '/includes/formatters/EmailUserPresentationModel.php', 'EchoEmailUserPresentationModel' => __DIR__ . '/includes/formatters/EmailUserPresentationModel.php',
'EchoEvent' => __DIR__ . '/includes/model/Event.php', 'EchoEvent' => __DIR__ . '/includes/model/Event.php',
@ -57,8 +57,9 @@ $wgAutoloadClasses += [
'EchoForeignNotifications' => __DIR__ . '/includes/ForeignNotifications.php', 'EchoForeignNotifications' => __DIR__ . '/includes/ForeignNotifications.php',
'EchoForeignPresentationModel' => __DIR__ . '/includes/formatters/EchoForeignPresentationModel.php', 'EchoForeignPresentationModel' => __DIR__ . '/includes/formatters/EchoForeignPresentationModel.php',
'EchoHTMLEmailDecorator' => __DIR__ . '/includes/EmailFormatter.php', 'EchoHTMLEmailDecorator' => __DIR__ . '/includes/EmailFormatter.php',
'LegacyEchoHTMLEmailFormatter' => __DIR__ . '/includes/EmailFormatter.php',
'EchoHooks' => __DIR__ . '/Hooks.php', 'EchoHooks' => __DIR__ . '/Hooks.php',
'EchoHtmlDigestEmailFormatter' => __DIR__ . '/includes/formatters/EchoHtmlDigestEmailFormatter.php',
'EchoHtmlEmailFormatter' => __DIR__ . '/includes/formatters/EchoHtmlEmailFormatter.php',
'EchoIteratorDecorator' => __DIR__ . '/includes/iterator/IteratorDecorator.php', 'EchoIteratorDecorator' => __DIR__ . '/includes/iterator/IteratorDecorator.php',
'EchoLocalCache' => __DIR__ . '/includes/cache/LocalCache.php', 'EchoLocalCache' => __DIR__ . '/includes/cache/LocalCache.php',
'EchoMentionFormatter' => __DIR__ . '/includes/formatters/MentionFormatter.php', 'EchoMentionFormatter' => __DIR__ . '/includes/formatters/MentionFormatter.php',
@ -76,14 +77,13 @@ $wgAutoloadClasses += [
'EchoNotificationMapperTest' => __DIR__ . '/tests/phpunit/mapper/NotificationMapperTest.php', 'EchoNotificationMapperTest' => __DIR__ . '/tests/phpunit/mapper/NotificationMapperTest.php',
'EchoNotificationTest' => __DIR__ . '/tests/phpunit/model/NotificationTest.php', 'EchoNotificationTest' => __DIR__ . '/tests/phpunit/model/NotificationTest.php',
'EchoNotifier' => __DIR__ . '/includes/Notifier.php', 'EchoNotifier' => __DIR__ . '/includes/Notifier.php',
'EchoOOUI\\LabelIconWidget' => __DIR__ . '/includes/ooui/LabelIconWidget.php',
'EchoOnWikiList' => __DIR__ . '/includes/ContainmentSet.php', 'EchoOnWikiList' => __DIR__ . '/includes/ContainmentSet.php',
'EchoPageLinkFormatter' => __DIR__ . '/includes/formatters/PageLinkFormatter.php', 'EchoPageLinkFormatter' => __DIR__ . '/includes/formatters/PageLinkFormatter.php',
'EchoPageLinkedPresentationModel' => __DIR__ . '/includes/formatters/PageLinkedPresentationModel.php', 'EchoPageLinkedPresentationModel' => __DIR__ . '/includes/formatters/PageLinkedPresentationModel.php',
'EchoPresentationModelSectionTrait' => __DIR__ . '/includes/formatters/PresentationModelSectionTrait.php',
'EchoPlainTextDigestEmailFormatter' => __DIR__ . '/includes/formatters/EchoPlainTextDigestEmailFormatter.php', 'EchoPlainTextDigestEmailFormatter' => __DIR__ . '/includes/formatters/EchoPlainTextDigestEmailFormatter.php',
'EchoPlainTextEmailFormatter' => __DIR__ . '/includes/formatters/EchoPlainTextEmailFormatter.php', 'EchoPlainTextEmailFormatter' => __DIR__ . '/includes/formatters/EchoPlainTextEmailFormatter.php',
'EchoHtmlEmailFormatter' => __DIR__ . '/includes/formatters/EchoHtmlEmailFormatter.php', 'EchoPresentationModelSectionTrait' => __DIR__ . '/includes/formatters/PresentationModelSectionTrait.php',
'EchoHtmlDigestEmailFormatter' => __DIR__ . '/includes/formatters/EchoHtmlDigestEmailFormatter.php',
'EchoRevertedPresentationModel' => __DIR__ . '/includes/formatters/RevertedPresentationModel.php', 'EchoRevertedPresentationModel' => __DIR__ . '/includes/formatters/RevertedPresentationModel.php',
'EchoRevisionLocalCache' => __DIR__ . '/includes/cache/RevisionLocalCache.php', 'EchoRevisionLocalCache' => __DIR__ . '/includes/cache/RevisionLocalCache.php',
'EchoSeenTime' => __DIR__ . '/includes/SeenTime.php', 'EchoSeenTime' => __DIR__ . '/includes/SeenTime.php',
@ -106,6 +106,7 @@ $wgAutoloadClasses += [
'EchoUserRightsPresentationModel' => __DIR__ . '/includes/formatters/UserRightsPresentationModel.php', 'EchoUserRightsPresentationModel' => __DIR__ . '/includes/formatters/UserRightsPresentationModel.php',
'EchoWelcomePresentationModel' => __DIR__ . '/includes/formatters/WelcomePresentationModel.php', 'EchoWelcomePresentationModel' => __DIR__ . '/includes/formatters/WelcomePresentationModel.php',
'FilteredSequentialIteratorTest' => __DIR__ . '/tests/phpunit/iterator/FilteredSequentialIteratorTest.php', 'FilteredSequentialIteratorTest' => __DIR__ . '/tests/phpunit/iterator/FilteredSequentialIteratorTest.php',
'LegacyEchoHTMLEmailFormatter' => __DIR__ . '/includes/EmailFormatter.php',
'MWEchoDbFactory' => __DIR__ . '/includes/EchoDbFactory.php', 'MWEchoDbFactory' => __DIR__ . '/includes/EchoDbFactory.php',
'MWEchoDbFactoryTest' => __DIR__ . '/tests/phpunit/EchoDbFactoryTest.php', 'MWEchoDbFactoryTest' => __DIR__ . '/tests/phpunit/EchoDbFactoryTest.php',
'MWEchoEmailBatch' => __DIR__ . '/includes/EmailBatch.php', 'MWEchoEmailBatch' => __DIR__ . '/includes/EmailBatch.php',

View file

@ -8,7 +8,7 @@
*/ */
class SpecialNotificationsFormatter extends EchoEventFormatter { class SpecialNotificationsFormatter extends EchoEventFormatter {
protected function formatModel( EchoEventPresentationModel $model ) { protected function formatModel( EchoEventPresentationModel $model ) {
$markReadSpecialPage = SpecialPage::getTitleFor( 'NotificationsMarkRead' ); $markReadSpecialPage = new SpecialNotificationsMarkRead();
$id = $model->getEventId(); $id = $model->getEventId();
$icon = Html::element( $icon = Html::element(
@ -20,14 +20,25 @@ class SpecialNotificationsFormatter extends EchoEventFormatter {
); );
OutputPage::setupOOUI(); OutputPage::setupOOUI();
$markAsReadButton = new OOUI\ButtonWidget( array(
$markAsReadIcon = new OOUI\IconWidget( array(
'icon' => 'close', 'icon' => 'close',
'framed' => false, 'title' => wfMessage( 'echo-notification-markasread' ),
'href' => $markReadSpecialPage->getLocalUrl() . '/' . $id,
'classes' => array( 'mw-echo-markAsReadButton' ),
'title' => wfMessage( 'echo-notification-markasread' )
) ); ) );
$markAsReadForm = $markReadSpecialPage->getMinimalForm(
$id,
$this->msg( 'echo-notification-markasread' )->text(),
false,
$markAsReadIcon->toString()
);
$markAsReadButton = Html::rawElement(
'div',
array( 'class' => 'mw-echo-markAsReadButton' ),
$markAsReadForm->prepareForm()->getHTML( /* First submission attempt */ false )
);
$html = Xml::tags( $html = Xml::tags(
'div', 'div',
array( 'class' => 'mw-echo-title' ), array( 'class' => 'mw-echo-title' ),

View file

@ -0,0 +1,44 @@
<?php
namespace EchoOOUI;
use OOUI\IconElement;
use OOUI\LabelElement;
use OOUI\TitledElement;
use OOUI\Tag;
use OOUI\Widget;
/**
* Widget combining a label and icon
*/
class LabelIconWidget extends Widget {
use IconElement;
use LabelElement;
use TitledElement;
/**
* @param array $config Configuration options
* @param string|HtmlSnippet $config['label'] Label text
* @param string $config['title'] Title text
* @param string $config['icon'] Icon key
*/
public function __construct( $config ) {
parent::__construct( $config );
$this->tableRow = new Tag( 'div' );
$this->tableRow->setAttributes( array(
'class' => 'oo-ui-labelIconWidget-row',
) );
$this->icon = new Tag( 'div' );
$this->label = new Tag( 'div' );
$this->initializeIconElement( array_merge( $config, [ 'iconElement' => $this->icon ] ) );
$this->initializeLabelElement( array_merge( $config, [ 'labelElement' => $this->label ] ) );
$this->initializeTitledElement( $config );
$this->addClasses( [ 'oo-ui-labelIconWidget' ] );
$this->tableRow->appendContent( $this->icon, $this->label );
$this->appendContent( $this->tableRow );
}
}

View file

@ -102,18 +102,35 @@ class SpecialNotifications extends SpecialPage {
// Build the HTML // Build the HTML
$notices = ''; $notices = '';
$markReadSpecialPage = SpecialPage::getTitleFor( 'NotificationsMarkRead' ); $markReadSpecialPage = new SpecialNotificationsMarkRead();
foreach ( $notifArray as $section => $data ) { foreach ( $notifArray as $section => $data ) {
$sectionTitle = Html::element( 'span', array( 'class' => 'mw-echo-date-section-text' ), $section ); $dateSectionText = Html::element( 'span', array( 'class' => 'mw-echo-date-section-text' ), $section );
$sectionTitle = $dateSectionText;
if ( count( $data[ 'unread' ] ) > 0 ) { if ( count( $data[ 'unread' ] ) > 0 ) {
// There are unread notices. Add the 'mark section as read' button $markReadSectionText = $this->msg( 'echo-specialpage-section-markread' )->text();
$markSectionAsReadButton = new OOUI\ButtonWidget( array(
'label' => $this->msg( 'echo-specialpage-section-markread' )->text(), $markAsReadLabelIcon = new EchoOOUI\LabelIconWidget( array(
'href' => $markReadSpecialPage->getLocalURL() . '/' . join( ',', $data[ 'unread' ] ), 'label' => $markReadSectionText,
'classes' => array( 'mw-echo-markAsReadSectionButton' ),
'icon' => 'doubleCheck', 'icon' => 'doubleCheck',
) ); ) );
$sectionTitle .= $markSectionAsReadButton;
// There are unread notices. Add the 'mark section as read' button
$markSectionAsReadForm = $markReadSpecialPage->getMinimalForm(
$data[ 'unread' ],
$markReadSectionText,
true,
$markAsReadLabelIcon->toString()
);
$formHtml = $markSectionAsReadForm->prepareForm()->getHTML( /* First submission attempt */ false );
$formWrapper = Html::rawElement(
'div',
array(
'class' => 'mw-echo-markAsReadSectionButton',
),
$formHtml
);
$sectionTitle .= $formWrapper;
} }
// Heading // Heading

View file

@ -1,5 +1,13 @@
<?php <?php
/**
* Form for marking notifications as read by ID.
*
* This uses the normal HTMLForm handling when receiving POSTs.
* However, for a better user no-JS user experience, we integrate
* a version of the form into Special:Notifications. Thus, this
* page should normally not need to be visited directly.
*/
class SpecialNotificationsMarkRead extends FormSpecialPage { class SpecialNotificationsMarkRead extends FormSpecialPage {
protected $eventId; protected $eventId;
@ -25,6 +33,10 @@ class SpecialNotificationsMarkRead extends FormSpecialPage {
return false; return false;
} }
public function getDisplayFormat() {
return 'ooui';
}
/** /**
* Get an HTMLForm descriptor array * Get an HTMLForm descriptor array
* @return array * @return array
@ -55,8 +67,59 @@ class SpecialNotificationsMarkRead extends FormSpecialPage {
); );
} }
/**
* Gets a pre-filled version of the form; this should not have a legend or anything
* visible, except the button.
*
* @param int|array $idValue ID or array of IDs
* @param string $submitButtonValue Value attribute for button
* @param boolean $framed Whether the button should be framed
* @param string Raw HTML to use for button label
*
* @return HTMLForm
*/
public function getMinimalForm( $idValue, $submitButtonValue, $framed, $submitLabelHtml ) {
if ( !is_array( $idValue ) ) {
$idValue = array( $idValue );
}
$idString = join( ',', $idValue );
$this->setParameter( $idString );
$form = HTMLForm::factory(
$this->getDisplayFormat(),
$this->getFormFields(),
$this->getContext(),
$this->getMessagePrefix()
);
// HTMLForm assumes that the main submit button is always 'primary',
// which means it is colored. Since this form is being embedded multiple
// places on the page, it has to be neutral, so we make the button
// manually.
$form->suppressDefaultSubmit();
$form->setAction( $this->getPageTitle()->getLocalURL() );
$form->addButton( array(
'name' => 'submit',
'value' => $submitButtonValue,
'label-raw' => $submitLabelHtml,
'framed' => $framed,
) );
return $form;
}
/**
* Sets a custom label
*
* This is only called when the form is actually visited directly, which is not the
* main intended use.
*/
protected function alterForm( HTMLForm $form ) { protected function alterForm( HTMLForm $form ) {
$form->setSubmitText( $this->msg( 'echo-notification-markasread' ) ); $form->setSubmitText( $this->msg( 'echo-notification-markasread' )->text() );
} }
/** /**

View file

@ -59,10 +59,15 @@
text-transform: uppercase; text-transform: uppercase;
font-size: 1.1em; font-size: 1.1em;
font-weight: 800; font-weight: 800;
display: inline-block;
} }
ul.mw-echo-special-notifications { ul.mw-echo-special-notifications {
max-width: 600px; max-width: 600px;
div.mw-htmlform-submit-buttons {
margin: 0;
}
list-style: none none; list-style: none none;
padding: 0; padding: 0;
margin: 0; margin: 0;
@ -84,11 +89,20 @@ ul.mw-echo-special-notifications {
.mw-echo-markAsReadButton { .mw-echo-markAsReadButton {
display: none; display: none;
button {
padding: 0;
}
} }
} }
.mw-echo-markAsReadSectionButton { .mw-echo-markAsReadSectionButton {
float: right; float: right;
display: inline-block;
button.oo-ui-buttonElement-button {
padding: 2px 12px 2px 12px;
}
// HACK: temporary workaround for T136024 // HACK: temporary workaround for T136024
line-height: normal; line-height: normal;
@ -124,7 +138,7 @@ ul.mw-echo-special-notifications {
.mw-echo-markAsReadButton { .mw-echo-markAsReadButton {
float: right; float: right;
display: inline-block; display: inline-block;
margin-left: 1em; margin: 0;
opacity: 0.5; opacity: 0.5;
&:hover { &:hover {
@ -134,3 +148,7 @@ ul.mw-echo-special-notifications {
} }
} }
} }
div.mw-htmlform-ooui-wrapper {
margin: 0;
}

View file

@ -0,0 +1,13 @@
.oo-ui-labelIconWidget {
display: table;
}
.oo-ui-labelIconWidget-row {
display: table-row;
.oo-ui-iconElement-icon,
.oo-ui-labelElement-label {
display: table-cell;
vertical-align: middle;
}
}