/* global bpGroupManageMembersSettings, _, Backbone */ /* @version 5.0.0 */ ( function( wp, bp, $ ) { // Bail if not set if ( typeof bpGroupManageMembersSettings === 'undefined' ) { return; } // Copy useful WP Objects into BP. _.extend( bp, _.pick( wp, 'Backbone', 'template' ) ); bp.Models = bp.Models || {}; bp.Collections = bp.Collections || {}; bp.Views = bp.Views || {}; /** * Model for the Member of the displayed group. */ bp.Models.groupMember = Backbone.Model.extend( { defaults: { id: 0, name: '', avatar_urls : {}, is_admin: false, is_banned: false, is_confirmed: false, is_mod: false, link: '' }, options : { path: bpGroupManageMembersSettings.path, type: 'POST', data: {}, dataType: 'json' }, initialize: function() { // Make sure to reset data & path on model's sync. this.on( 'sync', this.resetRequestOptions, this ); }, resetRequestOptions: function() { this.options.data = {}; this.options.path = bpGroupManageMembersSettings.path; }, sync: function( method, model, options ) { options = options || {}; options.context = this; var data = options.data || {}; this.options.path = this.options.path.concat( '/' + model.get( 'id' ) ); _.extend( options, this.options ); _.extend( options.data, data ); if ( 'delete' === method || 'update' === method ) { if ( 'delete' === method ) { options.headers = { 'X-HTTP-Method-Override': 'DELETE' }; } else { options.headers = { 'X-HTTP-Method-Override': 'PUT' }; } return wp.apiRequest( options ); } }, parse: function( response ) { if ( _.isArray( response ) ) { response = _.first( response ); } return response; } } ); /** * Collection for the Members of the displayed group. */ bp.Collections.groupMembers = Backbone.Collection.extend( { model: bp.Models.groupMember, options : { path: bpGroupManageMembersSettings.path, type: 'GET', data: {}, dataType: 'json' }, initialize: function() { // Make sure to reset data on collection's reset. this.on( 'reset', function() { this.options.data = {}; }, this ); }, sync: function( method, collection, options ) { options = options || {}; options.context = this; var data = options.data || {}; _.extend( options, this.options ); _.extend( options.data, data ); if ( 'read' === method ) { var self = this, success = options.success; options.success = function( data, textStatus, request ) { if ( ! _.isUndefined( request ) ) { self.totalPages = parseInt( request.getResponseHeader( 'X-WP-TotalPages' ), 10 ); self.totalGroupMembers = parseInt( request.getResponseHeader( 'X-WP-Total' ), 10 ); } self.currentPage = options.data.page || 1; if ( success ) { return success.apply( this, arguments ); } }; return wp.apiRequest( options ); } } } ); // Extend wp.Backbone.View with .prepare(). bp.View = bp.View || bp.Backbone.View.extend( { prepare: function() { if ( ! _.isUndefined( this.model ) && _.isFunction( this.model.toJSON ) ) { return this.model.toJSON(); } else { return {}; } } } ); bp.Views.GroupMemberUpdatingInfo = bp.View.extend( { tagName: 'p', template : bp.template( 'bp-manage-members-updating' ), initialize: function() { this.model = new Backbone.Model( { type: this.options.value } ); } } ); bp.Views.GroupMemberErrorInfo = bp.View.extend( { tagName: 'p', template : bp.template( 'bp-manage-members-error' ), initialize: function() { this.model = new Backbone.Model( { message: this.options.value } ); } } ); bp.Views.GroupsMembersLabel = bp.Views.GroupMemberUpdatingInfo.extend( { tagName: 'label', template: bp.template( 'bp-manage-members-label' ) } ); bp.Views.GroupRolesDropDown = bp.View.extend( { tagName: 'select', filters: _.extend( { all: { name: bpGroupManageMembersSettings.strings.allMembers } }, bpGroupManageMembersSettings.roles ), events: { change: 'change' }, initialize: function() { if ( this.options.omits ) { this.filters = _.omit( this.filters, this.options.omits ); } // Build `' ).val( value ).html( filter.name )[0]; if ( this.options.currentRole && value === this.options.currentRole ) { return { el: $( optionOutput ).prop( 'selected', true ) }; } else { return { el: optionOutput }; } }, this ).pluck( 'el' ).value() ); }, change: function( event ) { var role = $( event.target ).val(), queryArgs = { roles: [ role ] }; if ( ! this.collection ) { return; } if ( 'all' === role ) { // Unset the current role. this.collection.currentRole = ''; queryArgs = { 'exclude_admins': false }; } else { // Set the current role. this.collection.currentRole = role; } // Reset the current page. this.collection.currentPage = 1; queryArgs.page = 1; $( '#manage-members-search' ).val( '' ); this.collection.fetch( { data: queryArgs, reset: true } ); } } ); bp.Views.GroupMembersSearch = bp.View.extend( { className: 'bp-dir-search-form', tagName: 'form', template: bp.template( 'bp-manage-members-search' ), events: { 'click #manage-members-search-submit' : 'searchMember' }, searchMember: function( event ) { event.preventDefault(); var searchTerms = $( '#manage-members-search' ).val(), queryArgs = _.extend( this.collection.options.data, { search: searchTerms, page: 1 } ); // Reset the current page. this.collection.currentPage = 1; if ( ! this.collection.currentRole ) { queryArgs.exclude_admins = false; } else { queryArgs.roles = [ this.collection.currentRole ]; } this.collection.fetch( { data: queryArgs, reset: true } ); } } ); bp.Views.GroupsMembersPagination = bp.View.extend( { className: 'bp-pagination', template: bp.template( 'bp-manage-members-paginate' ), events: { 'click .group-members-paginate-button' : 'queryPage' }, initialize: function() { this.collection.on( 'reset', this.setPagination, this ); }, setPagination: function( collection ) { var attributes = _.pick( collection, [ 'currentPage', 'totalGroupMembers', 'totalPages' ] ); if ( attributes.totalPages > 1 ) { attributes.nextPage = attributes.currentPage + 1; attributes.prevPage = attributes.currentPage - 1; } this.model = new Backbone.Model( attributes ); this.render(); }, queryPage: function( event ) { event.preventDefault(); var page = $( event.currentTarget ).data( 'page' ), searchTerms = $( '#manage-members-search' ).val(), queryArgs = _.extend( this.collection.options.data, { search: searchTerms, page: page } ); if ( ! this.collection.currentRole ) { queryArgs.exclude_admins = false; } else { queryArgs.roles = [ this.collection.currentRole ]; } this.collection.fetch( { data: queryArgs, reset: true } ); } } ); bp.Views.GroupMembersNoMatches = bp.View.extend( { tagName: 'tr', template : bp.template( 'bp-manage-members-empty-row' ) } ); bp.Views.GroupMembersListRow = bp.View.extend( { tagName: 'tr', template : bp.template( 'bp-manage-members-row' ), events: { 'click .group-member-actions a' : 'doMemberAction', 'change .group-member-edit select' : 'editMemberRole' }, initialize: function() { var roleProps = [ 'is_admin', 'is_banned', 'is_confirmed', 'is_mod' ], self = this; _.each( bpGroupManageMembersSettings.roles, function( props ) { if ( _.isMatch( self.model.attributes, _.pick( props, roleProps ) ) ) { self.model.set( 'role', _.pick( props, ['id', 'name'] ), { silent: true } ); } } ); this.model.collection.on( 'reset', this.clearRow, this ); }, clearRow: function() { this.views.view.remove(); }, renderEditForm: function() { var userId = this.model.get( 'id' ); this.render(); this.views.set( '#edit-group-member-' + userId, [ new bp.Views.GroupsMembersLabel( { value: userId, attributes: { 'for': 'group-member' + userId + '-role' } } ), new bp.Views.GroupRolesDropDown( { id: 'group-member' + userId + '-role', omits: [ 'all', 'banned' ], currentRole: this.model.get( 'role' ).id } ).render() ] ); }, resetRow: function() { this.model.set( 'editing', false ); return this.render(); }, getRoleObject: function( roleId ) { var roles = bpGroupManageMembersSettings.roles; if ( _.isUndefined( roles[ roleId ] ) ) { return {}; } return _.extend( { role: _.pick( roles[ roleId ], ['id', 'name'] ) }, _.pick( roles[ roleId ], [ 'is_admin', 'is_banned', 'is_confirmed', 'is_mod' ] ) ); }, doMemberAction: function( event ) { event.preventDefault(); var action = $( event.target ).data( 'action' ), self = this; if ( 'edit' === action ) { this.model.set( 'editing', true ); return this.renderEditForm(); } else if ( 'abort' === action ) { return this.resetRow(); } else if ( 'ban' === action || 'unban' === action ) { var newRole = ( 'ban' === action ) ? 'banned' : 'member', roleObject = this.getRoleObject( newRole ); if ( ! roleObject ) { return this.resetRow(); } else { this.model.set( 'managingBan', true ); this.render(); } // Display user feedback. this.views.set( '#edit-group-member-' + this.model.get( 'id' ), new bp.Views.GroupMemberUpdatingInfo( { value: action } ).render() ); // Update Group member's role. this.model.save( roleObject, { wait: true, data: { action: action }, success: function( model) { self.model.collection.remove( model ); return self.clearRow(); }, error: function( model, response ) { self.views.set( '#edit-group-member-' + model.get( 'id' ), new bp.Views.GroupMemberErrorInfo( { value: response.responseJSON.message } ).render() ); // Make sure to reset request options. model.resetRequestOptions(); model.set( 'managingBan', false ); } } ); } else if ( 'remove' === action ) { this.model.set( 'removing', true ); this.render(); // Display user feedback. this.views.set( '#edit-group-member-' + this.model.get( 'id' ), new bp.Views.GroupMemberUpdatingInfo( { value: action } ).render() ); // Destroy the membership model. this.model.destroy( { wait: true, data: {}, success: function() { return self.clearRow(); }, error: function( model, response ) { self.views.set( '#edit-group-member-' + model.get( 'id' ), new bp.Views.GroupMemberErrorInfo( { value: response.responseJSON.message } ).render() ); // Make sure to reset request options. model.resetRequestOptions(); model.set( 'removing', false ); } } ); } }, editMemberRole: function( event ) { var newRole = $( event.target ).val(), roleObject = this.getRoleObject( newRole ), currentRole = this.model.get( 'role').id, roleAction = 'promote', self = this; if ( newRole === this.model.get( 'role' ).id || ! roleObject ) { return this.resetRow(); } this.views.set( '#edit-group-member-' + this.model.get( 'id' ), new bp.Views.GroupMemberUpdatingInfo().render() ); if ( 'admin' === currentRole || ( 'mod' === currentRole && 'member' === newRole ) ) { roleAction = 'demote'; } // Update Group member's role this.model.save( roleObject, { wait: true, data: { action: roleAction, role: newRole }, success: function( model ) { if ( self.model.collection.currentRole && newRole !== self.model.collection.currentRole ) { self.model.collection.remove( model ); return self.clearRow(); } else { return self.resetRow(); } }, error: function( model, response ) { self.views.set( '#edit-group-member-' + model.get( 'id' ), new bp.Views.GroupMemberErrorInfo( { value: response.responseJSON.message } ).render() ); // Make sure to reset request options. model.resetRequestOptions(); model.set( 'editing', false ); } } ); } } ); bp.Views.GroupMembersListHeader = bp.View.extend( { tagName: 'thead', template : bp.template( 'bp-manage-members-header' ) } ); bp.Views.GroupMembersListTable = bp.View.extend( { tagName: 'tbody', initialize: function() { var preloaded = bpGroupManageMembersSettings.preloaded || {}, models = []; this.collection.on( 'reset', this.addListTableRows, this ); if ( preloaded.body && preloaded.body.length > 0 ) { _.each( preloaded.body, function( member ) { models.push( new bp.Models.groupMember( member ) ); } ); this.collection.currentPage = 1; if ( preloaded.headers && preloaded.headers[ 'X-WP-TotalPages' ] ) { this.collection.totalPages = parseInt( preloaded.headers[ 'X-WP-TotalPages' ], 10 ); } if ( preloaded.headers && preloaded.headers[ 'X-WP-Total' ] ) { this.collection.totalGroupMembers = parseInt( preloaded.headers[ 'X-WP-Total' ], 10 ); } this.collection.reset( models ); } else { this.collection.fetch( { data: { 'exclude_admins': false }, reset: true } ); } }, addListTableRows: function( collection ) { if ( this.views._views ) { var noMembersRow = _.findWhere( this.views._views[''] , { id: 'bp-no-group-members' } ); if ( noMembersRow ) { noMembersRow.remove(); } } if ( ! collection.length ) { this.views.add( new bp.Views.GroupMembersNoMatches( { id: 'bp-no-group-members' } ) ); } else { _.each( collection.models, function( member ) { this.views.add( new bp.Views.GroupMembersListRow( { model: member } ) ); }, this ); } } } ); bp.Views.GroupMembersUI = bp.View.extend( { className: 'group-members', initialize: function() { var groupMembers = new bp.Collections.groupMembers(); // Set filters. this.views.set( '#group-roles-filter', [ new bp.Views.GroupsMembersLabel( { attributes: { 'for': 'group-members-role-filter' } } ), new bp.Views.GroupRolesDropDown( { id: 'group-members-role-filter', collection: groupMembers } ) ] ); // Set the search form. this.views.set( '#group-members-search-form', new bp.Views.GroupMembersSearch( { id: 'group-members-search', collection: groupMembers } ) ); // Set Paginate links. this.views.set( '#group-members-pagination', new bp.Views.GroupsMembersPagination( { collection: groupMembers } ) ); // Set Group members list header and body. this.views.set( '#group-members-list-table', [ new bp.Views.GroupMembersListHeader(), new bp.Views.GroupMembersListTable( { collection: groupMembers } ) ] ); } } ); // Inject the UI to manage Group Members into the DOM. bp.manageGroupMembersUI = new bp.Views.GroupMembersUI( { el:'#group-manage-members-ui' } ).render(); } )( window.wp || {}, window.bp || {}, jQuery );