mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Echo
synced 2024-09-24 10:49:37 +00:00
Implement subject+talk and null+user page grouping
Make it optional through the unpgrouppages parameter, so that generic usage of the unreadnotificationpages API is still possible. In the front-end, store which display title maps to what set of titles, and pass in the full set rather than just the display title when filtering by a page. Bug: T137502 Change-Id: I443ca00ff5e5d36fd6910101226358942e6aa8ee
This commit is contained in:
parent
9e206ef8f5
commit
4e64643eb7
|
@ -261,6 +261,7 @@
|
||||||
"apihelp-query+notifications-example-1": "List notifications",
|
"apihelp-query+notifications-example-1": "List notifications",
|
||||||
"apihelp-query+notifications-example-2": "List notifications, grouped by section, with counts",
|
"apihelp-query+notifications-example-2": "List notifications, grouped by section, with counts",
|
||||||
"apihelp-query+unreadnotificationpages-description": "Get pages for which there are unread notifications for the current user.",
|
"apihelp-query+unreadnotificationpages-description": "Get pages for which there are unread notifications for the current user.",
|
||||||
|
"apihelp-query+unreadnotificationpages-param-grouppages": "Group talk pages together with their subject page, and group notifications not associated with a page together with the current user's user page.",
|
||||||
"apihelp-query+unreadnotificationpages-param-limit": "The maximum number of pages to return.",
|
"apihelp-query+unreadnotificationpages-param-limit": "The maximum number of pages to return.",
|
||||||
"apihelp-query+unreadnotificationpages-param-wikis": "List of wikis to fetch pages with unread notifications from (defaults to only current wiki).",
|
"apihelp-query+unreadnotificationpages-param-wikis": "List of wikis to fetch pages with unread notifications from (defaults to only current wiki).",
|
||||||
"apihelp-query+unreadnotificationpages-example-1": "List pages with (their amount of) unread notifications"
|
"apihelp-query+unreadnotificationpages-example-1": "List pages with (their amount of) unread notifications"
|
||||||
|
|
|
@ -253,6 +253,7 @@
|
||||||
"apihelp-query+notifications-example-1": "{{doc-apihelp-example|query+notifications}}",
|
"apihelp-query+notifications-example-1": "{{doc-apihelp-example|query+notifications}}",
|
||||||
"apihelp-query+notifications-example-2": "{{doc-apihelp-example|query+notifications}}",
|
"apihelp-query+notifications-example-2": "{{doc-apihelp-example|query+notifications}}",
|
||||||
"apihelp-query+unreadnotificationpages-description": "{{doc-apihelp-description|query+unreadnotificationpages}}",
|
"apihelp-query+unreadnotificationpages-description": "{{doc-apihelp-description|query+unreadnotificationpages}}",
|
||||||
|
"apihelp-query+unreadnotificationpages-param-grouppages": "{{doc-apihelp-param|query+unreadnotificationpages|grouppages}}",
|
||||||
"apihelp-query+unreadnotificationpages-param-limit": "{{doc-apihelp-param|query+unreadnotificationpages|limit}}",
|
"apihelp-query+unreadnotificationpages-param-limit": "{{doc-apihelp-param|query+unreadnotificationpages|limit}}",
|
||||||
"apihelp-query+unreadnotificationpages-param-wikis": "{{doc-apihelp-param|query+unreadnotificationpages|wikis}}",
|
"apihelp-query+unreadnotificationpages-param-wikis": "{{doc-apihelp-param|query+unreadnotificationpages|wikis}}",
|
||||||
"apihelp-query+unreadnotificationpages-example-1": "{{doc-apihelp-example|query+unreadnotificationpages}}"
|
"apihelp-query+unreadnotificationpages-example-1": "{{doc-apihelp-example|query+unreadnotificationpages}}"
|
||||||
|
|
|
@ -28,8 +28,8 @@ class ApiEchoUnreadNotificationPages extends ApiCrossWikiBase {
|
||||||
$params = $this->extractRequestParams();
|
$params = $this->extractRequestParams();
|
||||||
|
|
||||||
$result = array();
|
$result = array();
|
||||||
if ( in_array( wfWikiID(), $this->getRequestedWikis() ) ) {
|
if ( in_array( wfWikiId(), $this->getRequestedWikis() ) ) {
|
||||||
$result[wfWikiID()] = $this->getFromLocal( $params['limit'] );
|
$result[wfWikiID()] = $this->getFromLocal( $params['limit'], $params['grouppages'] );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $this->getRequestedForeignWikis() ) {
|
if ( $this->getRequestedForeignWikis() ) {
|
||||||
|
@ -47,10 +47,14 @@ class ApiEchoUnreadNotificationPages extends ApiCrossWikiBase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $limit
|
* @param int $limit
|
||||||
|
* @param bool $groupPages
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function getFromLocal( $limit ) {
|
protected function getFromLocal( $limit, $groupPages ) {
|
||||||
$dbr = MWEchoDbFactory::newFromDefault()->getEchoDb( DB_SLAVE );
|
$dbr = MWEchoDbFactory::newFromDefault()->getEchoDb( DB_SLAVE );
|
||||||
|
// If $groupPages is true, we need to fetch all pages and apply the ORDER BY and LIMIT ourselves
|
||||||
|
// after grouping.
|
||||||
|
$extraOptions = $groupPages ? array() : array( 'ORDER BY' => 'count DESC', 'LIMIT' => $limit );
|
||||||
$rows = $dbr->select(
|
$rows = $dbr->select(
|
||||||
array( 'echo_event', 'echo_notification' ),
|
array( 'echo_event', 'echo_notification' ),
|
||||||
array( 'event_page_id', 'count' => 'COUNT(*)' ),
|
array( 'event_page_id', 'count' => 'COUNT(*)' ),
|
||||||
|
@ -63,9 +67,7 @@ class ApiEchoUnreadNotificationPages extends ApiCrossWikiBase {
|
||||||
__METHOD__,
|
__METHOD__,
|
||||||
array(
|
array(
|
||||||
'GROUP BY' => 'event_page_id',
|
'GROUP BY' => 'event_page_id',
|
||||||
'ORDER BY' => 'count DESC',
|
) + $extraOptions,
|
||||||
'LIMIT' => $limit,
|
|
||||||
),
|
|
||||||
array( 'echo_notification' => array( 'INNER JOIN', 'notification_event = event_id' ) )
|
array( 'echo_notification' => array( 'INNER JOIN', 'notification_event = event_id' ) )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -73,17 +75,75 @@ class ApiEchoUnreadNotificationPages extends ApiCrossWikiBase {
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$pages = array();
|
$nullCount = 0;
|
||||||
|
$pageCounts = array();
|
||||||
foreach ( $rows as $row ) {
|
foreach ( $rows as $row ) {
|
||||||
$pages[$row->event_page_id] = $row->count;
|
if ( $row->event_page_id !== null ) {
|
||||||
|
$pageCounts[$row->event_page_id] = intval( $row->count );
|
||||||
|
} else {
|
||||||
|
$nullCount = intval( $row->count );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$titles = Title::newFromIDs( array_keys( $pageCounts ) );
|
||||||
|
|
||||||
|
$groupCounts = array();
|
||||||
|
foreach ( $titles as $title ) {
|
||||||
|
if ( $groupPages ) {
|
||||||
|
// If $title is a talk page, add its count to its subject page's count
|
||||||
|
$pageName = $title->getSubjectPage()->getPrefixedText();
|
||||||
|
} else {
|
||||||
|
$pageName = $title->getPrefixedText();
|
||||||
|
}
|
||||||
|
|
||||||
|
$count = $pageCounts[$title->getArticleId()];
|
||||||
|
if ( isset( $groupCounts[$pageName] ) ) {
|
||||||
|
$groupCounts[$pageName] += $count;
|
||||||
|
} else {
|
||||||
|
$groupCounts[$pageName] = $count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$userPageName = $this->getUser()->getUserPage()->getPrefixedText();
|
||||||
|
if ( $nullCount > 0 && $groupPages ) {
|
||||||
|
// Add the count for NULL (not associated with any page) to the count for the user page
|
||||||
|
if ( isset( $groupCounts[$userPageName] ) ) {
|
||||||
|
$groupCounts[$userPageName] += $nullCount;
|
||||||
|
} else {
|
||||||
|
$groupCounts[$userPageName] = $nullCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arsort( $groupCounts );
|
||||||
|
if ( $groupPages ) {
|
||||||
|
$groupCounts = array_slice( $groupCounts, 0, $limit );
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = array();
|
$result = array();
|
||||||
$titles = Title::newFromIDs( array_keys( $pages ) );
|
foreach ( $groupCounts as $pageName => $count ) {
|
||||||
foreach ( $titles as $title ) {
|
if ( $groupPages ) {
|
||||||
$result[] = array(
|
$title = Title::newFromText( $pageName );
|
||||||
|
$pages = array( $title->getSubjectPage()->getPrefixedText(), $title->getTalkPage()->getPrefixedText() );
|
||||||
|
if ( $pageName === $userPageName ) {
|
||||||
|
$pages[] = null;
|
||||||
|
}
|
||||||
|
$pageDescription = array(
|
||||||
|
'ns' => $title->getNamespace(),
|
||||||
'title' => $title->getPrefixedText(),
|
'title' => $title->getPrefixedText(),
|
||||||
'count' => $pages[$title->getArticleID()],
|
'unprefixed' => $title->getText(),
|
||||||
|
'pages' => $pages,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$pageDescription = array( 'title' => $pageName );
|
||||||
|
}
|
||||||
|
$result[] = $pageDescription + array(
|
||||||
|
'count' => $count,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ( !$groupPages && $nullCount > 0 ) {
|
||||||
|
$result[] = array(
|
||||||
|
'title' => null,
|
||||||
|
'count' => $nullCount,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,9 +172,13 @@ class ApiEchoUnreadNotificationPages extends ApiCrossWikiBase {
|
||||||
global $wgEchoMaxUpdateCount;
|
global $wgEchoMaxUpdateCount;
|
||||||
|
|
||||||
return parent::getAllowedParams() + array(
|
return parent::getAllowedParams() + array(
|
||||||
|
'grouppages' => array(
|
||||||
|
ApiBase::PARAM_TYPE => 'boolean',
|
||||||
|
ApiBase::PARAM_DFLT => false,
|
||||||
|
),
|
||||||
'limit' => array(
|
'limit' => array(
|
||||||
ApiBase::PARAM_TYPE => 'limit',
|
ApiBase::PARAM_TYPE => 'limit',
|
||||||
ApiBase::PARAM_DFLT => 20,
|
ApiBase::PARAM_DFLT => 10,
|
||||||
ApiBase::PARAM_MIN => 1,
|
ApiBase::PARAM_MIN => 1,
|
||||||
ApiBase::PARAM_MAX => $wgEchoMaxUpdateCount,
|
ApiBase::PARAM_MAX => $wgEchoMaxUpdateCount,
|
||||||
ApiBase::PARAM_MAX2 => $wgEchoMaxUpdateCount,
|
ApiBase::PARAM_MAX2 => $wgEchoMaxUpdateCount,
|
||||||
|
|
|
@ -68,7 +68,8 @@
|
||||||
var params = {
|
var params = {
|
||||||
action: 'query',
|
action: 'query',
|
||||||
meta: 'unreadnotificationpages',
|
meta: 'unreadnotificationpages',
|
||||||
uselang: this.userLang
|
uselang: this.userLang,
|
||||||
|
unpgrouppages: true
|
||||||
};
|
};
|
||||||
|
|
||||||
if ( !sources || sources === '*' ) {
|
if ( !sources || sources === '*' ) {
|
||||||
|
|
|
@ -132,7 +132,7 @@
|
||||||
{
|
{
|
||||||
continue: continueValue,
|
continue: continueValue,
|
||||||
readState: filters.getReadState(),
|
readState: filters.getReadState(),
|
||||||
titles: filters.getSourcePagesModel().getCurrentPage()
|
titles: filters.getSourcePagesModel().getGroupedPagesForCurrentTitle()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then( function ( data ) {
|
.then( function ( data ) {
|
||||||
|
|
|
@ -123,12 +123,32 @@
|
||||||
* Get all pages in a source
|
* Get all pages in a source
|
||||||
*
|
*
|
||||||
* @param {string} source Symbolic name of the source
|
* @param {string} source Symbolic name of the source
|
||||||
* @return {Object[]} Page definitions in this source
|
* @return {Object} Page definitions in this source
|
||||||
*/
|
*/
|
||||||
mw.echo.dm.SourcePagesModel.prototype.getSourcePages = function ( source ) {
|
mw.echo.dm.SourcePagesModel.prototype.getSourcePages = function ( source ) {
|
||||||
return this.sources[ source ] && this.sources[ source ].pages;
|
return this.sources[ source ] && this.sources[ source ].pages;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of page titles associated with one group title.
|
||||||
|
*
|
||||||
|
* @param {string} source Symbolic name of the source
|
||||||
|
* @param {string} title Group title
|
||||||
|
* @return {string[]} Page titles
|
||||||
|
*/
|
||||||
|
mw.echo.dm.SourcePagesModel.prototype.getGroupedPagesForTitle = function ( source, title ) {
|
||||||
|
return OO.getProp( this.sources, source, 'pages', title, 'pages' ) || [];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of page titles associated with the current group title.
|
||||||
|
*
|
||||||
|
* @return {string[]} Page titles
|
||||||
|
*/
|
||||||
|
mw.echo.dm.SourcePagesModel.prototype.getGroupedPagesForCurrentTitle = function () {
|
||||||
|
return this.getGroupedPagesForTitle( this.getCurrentSource(), this.getCurrentPage() );
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the data
|
* Reset the data
|
||||||
*/
|
*/
|
||||||
|
@ -144,11 +164,17 @@
|
||||||
* @param {Object} details Details object
|
* @param {Object} details Details object
|
||||||
*/
|
*/
|
||||||
mw.echo.dm.SourcePagesModel.prototype.setSourcePagesDetails = function ( source, details ) {
|
mw.echo.dm.SourcePagesModel.prototype.setSourcePagesDetails = function ( source, details ) {
|
||||||
|
var i, page;
|
||||||
this.sources[ source ] = {
|
this.sources[ source ] = {
|
||||||
title: details.source.title,
|
title: details.source.title,
|
||||||
base: details.source.base,
|
base: details.source.base,
|
||||||
totalCount: details.totalCount,
|
totalCount: details.totalCount,
|
||||||
pages: details.pages
|
pages: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for ( i = 0; i < details.pages.length; i++ ) {
|
||||||
|
page = details.pages[ i ];
|
||||||
|
this.sources[ source ].pages[ page.title ] = page;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} )( mediaWiki );
|
} )( mediaWiki );
|
||||||
|
|
|
@ -72,21 +72,18 @@
|
||||||
* Populate the widget from the model
|
* Populate the widget from the model
|
||||||
*/
|
*/
|
||||||
mw.echo.ui.PageFilterWidget.prototype.populateDataFromModel = function () {
|
mw.echo.ui.PageFilterWidget.prototype.populateDataFromModel = function () {
|
||||||
var i, title, widget,
|
var title, widget, isUserPage,
|
||||||
optionWidgets = [],
|
optionWidgets = [],
|
||||||
sourcePages = this.model.getSourcePages( this.source );
|
sourcePages = this.model.getSourcePages( this.source );
|
||||||
|
|
||||||
for ( i = 0; i < sourcePages.length; i++ ) {
|
for ( title in sourcePages ) {
|
||||||
|
isUserPage = sourcePages[ title ].ns === mw.config.get( 'wgNamespaceIds' ).user;
|
||||||
widget = new mw.echo.ui.PageNotificationsOptionWidget( {
|
widget = new mw.echo.ui.PageNotificationsOptionWidget( {
|
||||||
label: sourcePages[ i ].title,
|
label: isUserPage ? sourcePages[ title ].unprefixed : title,
|
||||||
title: sourcePages[ i ].title,
|
title: isUserPage ? sourcePages[ title ].unprefixed : title,
|
||||||
// TODO: Pages that are a user page should
|
icon: isUserPage ? 'userAvatar' : 'article',
|
||||||
// have a user icon
|
unreadCount: sourcePages[ title ].count,
|
||||||
icon: 'article',
|
data: title,
|
||||||
unreadCount: sourcePages[ i ].count,
|
|
||||||
// TODO: When we group pages, this should be
|
|
||||||
// an array of titles
|
|
||||||
data: sourcePages[ i ].title,
|
|
||||||
classes: [ 'mw-echo-ui-pageFilterWidget-page' ]
|
classes: [ 'mw-echo-ui-pageFilterWidget-page' ]
|
||||||
} );
|
} );
|
||||||
optionWidgets.push( widget );
|
optionWidgets.push( widget );
|
||||||
|
|
Loading…
Reference in a new issue