mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Echo
synced 2024-11-30 18:45:07 +00:00
No-JS special page: One-click mark as read
Bug: T136361 Change-Id: I7896dbdf25d2c1624f97777f4c8d0af41b195ef0 Depends-On: Ic31f857c749d62a32cafae68dc3f1cbd86e1e382
This commit is contained in:
parent
1bef12c3e7
commit
188e8d7395
|
@ -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' ),
|
||||||
),
|
),
|
||||||
|
|
11
autoload.php
11
autoload.php
|
@ -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',
|
||||||
|
|
|
@ -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' ),
|
||||||
|
|
44
includes/ooui/LabelIconWidget.php
Normal file
44
includes/ooui/LabelIconWidget.php
Normal 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 );
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
13
modules/styles/LabelIconWidget.less
Normal file
13
modules/styles/LabelIconWidget.less
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue