jenkins-bot has submitted this change and it was merged.
Change subject: Add ability to remove/add new members to a collection via search
......................................................................
Add ability to remove/add new members to a collection via search
Bug: T90991
Change-Id: Ie262761519a29ad695695dcdf0f85f82e71d2dd0
---
M resources/Resources.php
M resources/ext.gather.page.search/CollectionPageList.js
M resources/ext.gather.page.search/CollectionSearchPanel.hogan
M resources/ext.gather.page.search/CollectionSearchPanel.js
M resources/ext.gather.page.search/item.hogan
5 files changed, 167 insertions(+), 17 deletions(-)
Approvals:
Robmoen: Looks good to me, approved
jenkins-bot: Verified
diff --git a/resources/Resources.php b/resources/Resources.php
index b103deb..5a5319d 100644
--- a/resources/Resources.php
+++ b/resources/Resources.php
@@ -213,6 +213,7 @@
'dependencies' => array(
'ext.gather.api',
'mobile.pagelist.scripts',
+ 'mobile.search',
),
'messages' => array(
// FIXME: Duplicates messages in ext.gather.watchstar
diff --git a/resources/ext.gather.page.search/CollectionPageList.js
b/resources/ext.gather.page.search/CollectionPageList.js
index a580afd..8c537a9 100644
--- a/resources/ext.gather.page.search/CollectionPageList.js
+++ b/resources/ext.gather.page.search/CollectionPageList.js
@@ -38,9 +38,11 @@
events: $.extend( {}, PageList.prototype.events, {
'click li': 'onChangeMemberStatus'
} ),
+ /** @inheritdoc */
templatePartials: {
item: mw.template.get( 'ext.gather.page.search',
'item.hogan' )
},
+ /** @inheritdoc */
initialize: function () {
// FIXME: PageList in MobileFrontend should be
rewritten as PageListWatchstar.
View.prototype.initialize.apply( this, arguments );
@@ -54,29 +56,54 @@
// FIXME: PageList in MobileFrontend should be
rewritten as PageListWatchstar.
View.prototype.postRender.apply( this, arguments );
},
+ /**
+ * Event handler for when a member changes status in the
collection
+ * @param {jQuery.Event} ev
+ */
onChangeMemberStatus: function ( ev ) {
var $target = $( ev.currentTarget ),
collection = this.options.collection,
+ $listThumb = $target.find( '.list-thumb' ),
self = this,
title = $target.data( 'title' ),
inCollection = $target.data( 'is-member' ),
- page = new Page( { title: title } );
+ page = new Page( {
+ title: title
+ } );
+
+ // FIXME: So hacky. Move/use methods on Page
+ page.heading = title;
+ page.pageimageClass = $listThumb.attr( 'class' );
+ page.listThumbStyleAttribute = $listThumb.attr( 'style'
);
if ( inCollection ) {
this.api.removePageFromCollection(
collection.id, page ).done( function () {
$target.find( '.status' ).replaceWith(
self.options.iconDisabledButton );
$target.data( 'is-member', false );
toast.show( mw.msg(
'gather-remove-toast', collection.title ), 'toast' );
+ /**
+ * @event member-removed
+ * @param {Page} page
+ * Fired when member is removed from
collection
+ */
+ self.emit( 'member-removed', page );
} );
} else {
this.api.addPageToCollection( collection.id,
page ).done( function () {
$target.find( '.status' ).replaceWith(
self.options.iconButton );
$target.data( 'is-member', true );
toast.show( mw.msg( 'gather-add-toast',
collection.title ), 'toast' );
+ page.isMember = true;
+ /**
+ * @event member-added
+ * @param {Page} page
+ * Fired when member is removed from
collection
+ */
+ self.emit( 'member-added', page );
} );
}
return false;
- },
+ }
} );
M.define( 'ext.gather.page.search/CollectionPageList',
CollectionPageList );
diff --git a/resources/ext.gather.page.search/CollectionSearchPanel.hogan
b/resources/ext.gather.page.search/CollectionSearchPanel.hogan
index 40c7061..f43b407 100644
--- a/resources/ext.gather.page.search/CollectionSearchPanel.hogan
+++ b/resources/ext.gather.page.search/CollectionSearchPanel.hogan
@@ -1 +1,4 @@
+<div class="search">
+ {{{searchIcon}}}<input type="text">
+</div>
<div class="results"></div>
diff --git a/resources/ext.gather.page.search/CollectionSearchPanel.js
b/resources/ext.gather.page.search/CollectionSearchPanel.js
index 14aab5e..0052206 100644
--- a/resources/ext.gather.page.search/CollectionSearchPanel.js
+++ b/resources/ext.gather.page.search/CollectionSearchPanel.js
@@ -1,6 +1,9 @@
-( function ( M ) {
+( function ( M, $ ) {
var Panel = M.require( 'Panel' ),
+ Icon = M.require( 'Icon' ),
+ SearchApi = M.require( 'modules/search/SearchApi' ),
+ SEARCH_DELAY = 500,
CollectionPageList = M.require(
'ext.gather.page.search/CollectionPageList' ),
CollectionSearchPanel;
@@ -8,9 +11,15 @@
* Class for a showing page search results in a panel
* @class CollectionPageSearchPanel
* @extends Panel
+ * @uses CollectionPageList
*/
CollectionSearchPanel = Panel.extend( {
+ /** @inheritdoc */
template: mw.template.get( 'ext.gather.page.search',
'CollectionSearchPanel.hogan' ),
+ /** @inheritdoc */
+ events: $.extend( {}, Panel.prototype.events, {
+ 'input .search input': 'onSearchInput'
+ } ),
/**
* @inheritdoc
* @cfg {Array} defaults.pages a list of pages in the collection
@@ -19,22 +28,132 @@
className: 'panel visible collection-search-panel',
defaults: {
pages: [],
- collection: undefined
+ collection: undefined,
+ searchIcon: new Icon( {
+ name: 'search',
+ // FIXME:
+ label: mw.msg( 'search' ),
+ additionalClassNames: 'indicator'
+ } ).toHtmlString()
},
- postRender: function( options ) {
+ /** @inheritdoc */
+ initialize: function ( options ) {
+ var self = this;
+ // FIXME: In future we'll want to use CollectionApi for
this
+ this.api = new SearchApi();
+ Panel.prototype.initialize.call( this, options );
+ this._members = {};
+ $.each( options.pages, function ( i, page ) {
+ self._members[page.title] = true;
+ } );
+ },
+ /** @inheritdoc */
+ postRender: function ( options ) {
Panel.prototype.postRender.apply( this, arguments );
this._renderResults( options.pages );
},
+ /**
+ * Updates the members of the collection associated with the
panel
+ * @param {Page} page
+ * @param {Boolean} isRemoved whether page has been removed
from this collection
+ */
+ _updateCollectionMembers: function ( page, isRemoved ) {
+ var newPages = [],
+ options = this.options;
+
+ if ( isRemoved ) {
+ delete this._members[page.title];
+ } else {
+ this._members[page.title] = true;
+ }
+ if ( isRemoved ) {
+ $.each( options.pages, function ( i, curPage ) {
+ if ( curPage.title !== page.title ) {
+ newPages.push( curPage );
+ }
+ } );
+ this.options.pages = newPages;
+ } else {
+ this.options.pages.push( page );
+ }
+ },
+ /**
+ * Updates the rendering of the internal CollectionPageList
+ * @private
+ * @param {Page[]} pages
+ */
_renderResults: function ( pages ) {
- var collectionPageList = new CollectionPageList( {
- pages: pages,
- collection: this.options.collection,
- el: this.$( '.results' )
- } );
- collectionPageList.renderPageImages();
+ var self = this;
+ if ( this.pageList ) {
+ this.pageList.options.pages = pages;
+ this.pageList.render();
+ } else {
+ this.pageList = new CollectionPageList( {
+ pages: pages,
+ collection: this.options.collection,
+ el: this.$( '.results' )
+ } );
+ this.pageList.on( 'member-removed', function (
page ) {
+ self._updateCollectionMembers( page,
true );
+ } );
+ this.pageList.on( 'member-added', function (
page ) {
+ self._updateCollectionMembers( page );
+ } );
+ }
+ this.pageList.renderPageImages();
+ },
+ /**
+ * Check whether a member is a known member of the current
collection.
+ * @param {String} title
+ * @returns {Boolean}
+ */
+ hasMember: function ( title ) {
+ return this._members[title] !== undefined;
+ },
+ /**
+ * Event handler for when search input changes
+ */
+ onSearchInput: function () {
+ var self = this,
+ $input = this.$( 'input' ),
+ query = $input.val(),
+ $results = this.$( '.results' );
+
+ if ( query !== this.lastQuery ) {
+ this.api.abort();
+ clearTimeout( this.timer );
+ $results.empty();
+
+ if ( query.length ) {
+ this.$( '.spinner' ).show();
+
+ this.timer = setTimeout( function () {
+ self.api.search( query ).done(
function ( data ) {
+ var results;
+
+ // check if we're
getting the rights response in case of out of
+ // order responses
(need to get the current value of the input)
+ if ( data.query ===
$input.val() ) {
+ results =
$.map( data.results, function ( page ) {
+
page.isMember = self.hasMember( page.title );
+ return
page;
+ } );
+ self.$(
'.spinner' ).hide();
+
self._renderResults( results );
+ }
+ } );
+ }, SEARCH_DELAY );
+ } else {
+ // re-render the members of the
collection
+ this._renderResults( this.options.pages
);
+ }
+
+ // keep track of last query to take into
account backspace usage
+ this.lastQuery = query;
+ }
}
} );
M.define( 'ext.gather.page.search/CollectionSearchPanel',
CollectionSearchPanel );
-}( mw.mobileFrontend ) );
+}( mw.mobileFrontend, jQuery ) );
diff --git a/resources/ext.gather.page.search/item.hogan
b/resources/ext.gather.page.search/item.hogan
index e9d5ab4..85c9cfe 100644
--- a/resources/ext.gather.page.search/item.hogan
+++ b/resources/ext.gather.page.search/item.hogan
@@ -1,9 +1,9 @@
<li class="page-summary" title="{{title}}" data-title="{{title}}"
{{#isMember}}data-is-member="true"{{/isMember}}>
- <a href="#" class="title">
- <div class="list-thumb {{pageimageClass}}"
style="{{listThumbStyleAttribute}}"></div>
- <h3>{{{heading}}}</h3>
- {{#isMember}}{{{iconButton}}}{{/isMember}}
+ <div class="title">
+ <div class="list-thumb {{pageimageClass}}"
style="{{listThumbStyleAttribute}}"></div>
+ <h3>{{{heading}}}</h3>
+ {{#isMember}}{{{iconButton}}}{{/isMember}}
{{^isMember}}{{{iconDisabledButton}}}{{/isMember}}
- </a>
+ </div>
</li>
--
To view, visit https://gerrit.wikimedia.org/r/202935
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ie262761519a29ad695695dcdf0f85f82e71d2dd0
Gerrit-PatchSet: 9
Gerrit-Project: mediawiki/extensions/Gather
Gerrit-Branch: master
Gerrit-Owner: Jdlrobson <[email protected]>
Gerrit-Reviewer: Robmoen <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits