diff options
-rw-r--r-- | js/views/participantlistview.js | 248 | ||||
-rw-r--r-- | js/views/participantview.js | 238 | ||||
-rw-r--r-- | templates/index.php | 1 |
3 files changed, 277 insertions, 210 deletions
diff --git a/js/views/participantlistview.js b/js/views/participantlistview.js new file mode 100644 index 000000000..22359758e --- /dev/null +++ b/js/views/participantlistview.js @@ -0,0 +1,248 @@ +/* global Marionette, Handlebars */ + +/** + * @author Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +(function(OC, OCA, Marionette, Handlebars) { + 'use strict'; + + OCA.SpreedMe = OCA.SpreedMe || {}; + OCA.SpreedMe.Views = OCA.SpreedMe.Views || {}; + + var uiChannel = Backbone.Radio.channel('ui'); + + var ITEM_TEMPLATE = '' + + '<a class="participant-entry-link {{#if isOffline}}participant-offline{{/if}}" href="#" data-sessionId="{{sessionId}}">' + + '<div class="avatar" data-user-id="{{userId}}" data-displayname="{{displayName}}"></div>' + + ' {{name}}' + + '{{#if participantIsOwner}}<span class="participant-moderator-indicator">(' + t('spreed', 'moderator') + ')</span>{{/if}}' + + '{{#if participantIsModerator}}<span class="participant-moderator-indicator">(' + t('spreed', 'moderator') + ')</span>{{/if}}' + + '</a>'+ + '{{#if canModerate}}' + + '<div class="participant-entry-utils">'+ + '<ul>'+ + '<li class="participant-entry-utils-menu-button"><button></button></li>'+ + '</ul>'+ + '</div>'+ + '<div class="popovermenu bubble menu">'+ + '<ul class="popovermenu-list">'+ + '{{#if participantIsModerator}}' + + '<li>' + + '<button class="demote-moderator">' + + '<span class="icon icon-star"></span>' + + '<span>' + t('spreed', 'Demote from moderator') + '</span>' + + '</button>' + + '</li>' + + '{{else}}' + + '{{#if participantIsUser}}' + + '<li>' + + '<button class="promote-moderator">' + + '<span class="icon icon-rename"></span>' + + '<span>' + t('spreed', 'Promote to moderator') + '</span>' + + '</button>' + + '</li>' + + '{{/if}}' + + '{{/if}}' + + '<li>' + + '<button class="remove-participant">' + + '<span class="icon icon-delete"></span>' + + '<span>' + t('spreed', 'Remove participant') + '</span>' + + '</button>' + + '</li>' + + '</ul>' + + '</div>' + + '{{/if}}'; + + OCA.SpreedMe.Views.ParticipantListView = Marionette.CollectionView.extend({ + tagName: 'ul', + className: 'participantWithList', + collectionEvents: { + 'update': function() { + this.render(); + }, + 'reset': function() { + this.render(); + }, + 'sort': function() { + this.render(); + }, + 'sync': function() { + this.render(); + } + }, + childView: Marionette.View.extend({ + tagName: 'li', + modelEvents: { + 'change:active': function() { + this.render(); + }, + 'change:displayName': function() { + this.render(); + }, + 'change:participants': function() { + this.render(); + }, + 'change:type': function() { + this.render(); + this.checkSharingStatus(); + } + }, + initialize: function() { + this.listenTo(uiChannel, 'document:click', function(event) { + var target = $(event.target); + if (!this.$el.is(target.closest('.participant'))) { + // Click was not triggered by this element -> close menu + this.menuShown = false; + this.toggleMenuClass(); + } + }); + }, + templateContext: function() { + var canModerate = this.model.get('participantType') !== OCA.SpreedMe.app.OWNER && // can not moderate owners + this.model.get('userId') !== oc_current_user && // can not moderate yourself + (OCA.SpreedMe.app.activeRoom.get('participantType') === OCA.SpreedMe.app.OWNER || // current user must be owner + OCA.SpreedMe.app.activeRoom.get('participantType') === OCA.SpreedMe.app.MODERATOR); // or moderator. + + return { + canModerate: canModerate, + name: this.model.get('userId').length ? this.model.get('displayName') : t('spreed', 'Guest'), + participantIsUser: this.model.get('participantType') === OCA.SpreedMe.app.USER, + participantIsModerator: this.model.get('participantType') === OCA.SpreedMe.app.MODERATOR, + participantIsOwner: this.model.get('participantType') === OCA.SpreedMe.app.OWNER + }; + }, + onRender: function() { + this.$el.find('.avatar').each(function() { + var element = $(this); + if (element.data('displayname').length) { + element.avatar(element.data('user-id'), 32, undefined, false, undefined, element.data('displayname')); + } else { + element.imageplaceholder('?', undefined, 32); + element.css('background-color', '#b9b9b9'); + } + }); + + this.$el.attr('data-session-id', this.model.get('sessionId')); + this.$el.attr('data-participant', this.model.get('userId')); + this.$el.addClass('participant'); + + if (!this.model.isOnline()) { + this.$el.addClass('participant-offline'); + } + + this.toggleMenuClass(); + }, + events: { + 'click .participant-entry-utils-menu-button button': 'toggleMenu', + 'click .popovermenu .promote-moderator': 'promoteToModerator', + 'click .popovermenu .demote-moderator': 'demoteFromModerator', + 'click .popovermenu .remove-participant': 'removeParticipant' + }, + ui: { + 'participant': 'li.participant', + 'menu': '.popovermenu' + }, + template: Handlebars.compile(ITEM_TEMPLATE), + menuShown: false, + toggleMenu: function(e) { + e.preventDefault(); + this.menuShown = !this.menuShown; + this.toggleMenuClass(); + }, + toggleMenuClass: function() { + this.ui.menu.toggleClass('open', this.menuShown); + }, + promoteToModerator: function() { + if (this.model.get('participantType') !== OCA.SpreedMe.app.USER) { + return; + } + + var participantId = this.model.get('userId'), + self = this; + + $.ajax({ + type: 'POST', + url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + OCA.SpreedMe.app.activeRoom.get('token') + '/moderators', + data: { + participant: participantId + }, + success: function() { + self.render(); + }, + error: function() { + console.log('Error while promoting user to moderator'); + } + }); + }, + demoteFromModerator: function() { + if (this.model.get('participantType') !== OCA.SpreedMe.app.MODERATOR) { + return; + } + + var participantId = this.model.get('userId'), + self = this; + + $.ajax({ + type: 'DELETE', + url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + OCA.SpreedMe.app.activeRoom.get('token') + '/moderators', + data: { + participant: participantId + }, + success: function() { + self.render(); + }, + error: function() { + console.log('Error while demoting moderator'); + } + }); + }, + removeParticipant: function() { + if (this.model.get('participantType') === OCA.SpreedMe.app.OWNER) { + return; + } + + var self = this, + participantId = this.model.get('userId'), + endpoint = '/participants'; + + if (this.model.get('participantType') === OCA.SpreedMe.app.GUEST) { + participantId = this.model.get('sessionId'); + endpoint += '/guests'; + } + + $.ajax({ + type: 'DELETE', + url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + OCA.SpreedMe.app.activeRoom.get('token') + endpoint, + data: { + participant: participantId + }, + success: function() { + self.render(); + }, + error: function() { + console.log('Error while removing user from room'); + } + }); + } + }) + }); + +})(OC, OCA, Marionette, Handlebars); diff --git a/js/views/participantview.js b/js/views/participantview.js index 5bcd5ce9c..ea2dcf642 100644 --- a/js/views/participantview.js +++ b/js/views/participantview.js @@ -1,7 +1,8 @@ /* global Marionette, Handlebars */ /** - * @author Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com) * * @license GNU AGPL version 3 or any later version * @@ -20,229 +21,46 @@ * */ - (function(OC, OCA, Marionette, Handlebars) { 'use strict'; OCA.SpreedMe = OCA.SpreedMe || {}; OCA.SpreedMe.Views = OCA.SpreedMe.Views || {}; - var uiChannel = Backbone.Radio.channel('ui'); - - var ITEM_TEMPLATE = '' + - '<a class="participant-entry-link {{#if isOffline}}participant-offline{{/if}}" href="#" data-sessionId="{{sessionId}}">' + - '<div class="avatar" data-user-id="{{userId}}" data-displayname="{{displayName}}"></div>' + - ' {{name}}' + - '{{#if participantIsOwner}}<span class="participant-moderator-indicator">(' + t('spreed', 'moderator') + ')</span>{{/if}}' + - '{{#if participantIsModerator}}<span class="participant-moderator-indicator">(' + t('spreed', 'moderator') + ')</span>{{/if}}' + - '</a>'+ - '{{#if canModerate}}' + - '<div class="participant-entry-utils">'+ - '<ul>'+ - '<li class="participant-entry-utils-menu-button"><button></button></li>'+ - '</ul>'+ - '</div>'+ - '<div class="popovermenu bubble menu">'+ - '<ul class="popovermenu-list">'+ - '{{#if participantIsModerator}}' + - '<li>' + - '<button class="demote-moderator">' + - '<span class="icon icon-star"></span>' + - '<span>' + t('spreed', 'Demote from moderator') + '</span>' + - '</button>' + - '</li>' + - '{{else}}' + - '{{#if participantIsUser}}' + - '<li>' + - '<button class="promote-moderator">' + - '<span class="icon icon-rename"></span>' + - '<span>' + t('spreed', 'Promote to moderator') + '</span>' + - '</button>' + - '</li>' + - '{{/if}}' + - '{{/if}}' + - '<li>' + - '<button class="remove-participant">' + - '<span class="icon icon-delete"></span>' + - '<span>' + t('spreed', 'Remove participant') + '</span>' + - '</button>' + - '</li>' + - '</ul>' + - '</div>' + - '{{/if}}'; - - OCA.SpreedMe.Views.ParticipantView = Marionette.CollectionView.extend({ - tagName: 'ul', - className: 'participantWithList', - collectionEvents: { - 'update': function() { - this.render(); - }, - 'reset': function() { - this.render(); - }, - 'sort': function() { - this.render(); - }, - 'sync': function() { - this.render(); - } - }, - childView: Marionette.View.extend({ - tagName: 'li', - modelEvents: { - 'change:active': function() { - this.render(); - }, - 'change:displayName': function() { - this.render(); - }, - 'change:participants': function() { - this.render(); - }, - 'change:type': function() { - this.render(); - this.checkSharingStatus(); - } - }, - initialize: function() { - this.listenTo(uiChannel, 'document:click', function(event) { - var target = $(event.target); - if (!this.$el.is(target.closest('.participant'))) { - // Click was not triggered by this element -> close menu - this.menuShown = false; - this.toggleMenuClass(); - } - }); - }, - templateContext: function() { - var canModerate = this.model.get('participantType') !== OCA.SpreedMe.app.OWNER && // can not moderate owners - this.model.get('userId') !== oc_current_user && // can not moderate yourself - (OCA.SpreedMe.app.activeRoom.get('participantType') === OCA.SpreedMe.app.OWNER || // current user must be owner - OCA.SpreedMe.app.activeRoom.get('participantType') === OCA.SpreedMe.app.MODERATOR); // or moderator. - - return { - canModerate: canModerate, - name: this.model.get('userId').length ? this.model.get('displayName') : t('spreed', 'Guest'), - participantIsUser: this.model.get('participantType') === OCA.SpreedMe.app.USER, - participantIsModerator: this.model.get('participantType') === OCA.SpreedMe.app.MODERATOR, - participantIsOwner: this.model.get('participantType') === OCA.SpreedMe.app.OWNER - }; - }, - onRender: function() { - this.$el.find('.avatar').each(function() { - var element = $(this); - if (element.data('displayname').length) { - element.avatar(element.data('user-id'), 32, undefined, false, undefined, element.data('displayname')); - } else { - element.imageplaceholder('?', undefined, 32); - element.css('background-color', '#b9b9b9'); - } - }); - - this.$el.attr('data-session-id', this.model.get('sessionId')); - this.$el.attr('data-participant', this.model.get('userId')); - this.$el.addClass('participant'); - - if (!this.model.isOnline()) { - this.$el.addClass('participant-offline'); - } + var TEMPLATE = + '<button class="add-person-button">' + + '<span class="icon-add"></span>' + + '<span>' + t('spreed', 'Add person') + '</span>' + + '</button>' + + '<ul class="participantWithList">' + + '</ul>'; - this.toggleMenuClass(); - }, - events: { - 'click .participant-entry-utils-menu-button button': 'toggleMenu', - 'click .popovermenu .promote-moderator': 'promoteToModerator', - 'click .popovermenu .demote-moderator': 'demoteFromModerator', - 'click .popovermenu .remove-participant': 'removeParticipant' - }, - ui: { - 'participant': 'li.participant', - 'menu': '.popovermenu' - }, - template: Handlebars.compile(ITEM_TEMPLATE), - menuShown: false, - toggleMenu: function(e) { - e.preventDefault(); - this.menuShown = !this.menuShown; - this.toggleMenuClass(); - }, - toggleMenuClass: function() { - this.ui.menu.toggleClass('open', this.menuShown); - }, - promoteToModerator: function() { - if (this.model.get('participantType') !== OCA.SpreedMe.app.USER) { - return; - } + OCA.SpreedMe.Views.ParticipantView = Marionette.View.extend({ - var participantId = this.model.get('userId'), - self = this; + tagName: 'div', - $.ajax({ - type: 'POST', - url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + OCA.SpreedMe.app.activeRoom.get('token') + '/moderators', - data: { - participant: participantId - }, - success: function() { - self.render(); - }, - error: function() { - console.log('Error while promoting user to moderator'); - } - }); - }, - demoteFromModerator: function() { - if (this.model.get('participantType') !== OCA.SpreedMe.app.MODERATOR) { - return; - } + ui: { + addButton: '.add-person-button', + participantList: '.participantWithList' + }, - var participantId = this.model.get('userId'), - self = this; + regions: { + participantList: '@ui.participantList' + }, - $.ajax({ - type: 'DELETE', - url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + OCA.SpreedMe.app.activeRoom.get('token') + '/moderators', - data: { - participant: participantId - }, - success: function() { - self.render(); - }, - error: function() { - console.log('Error while demoting moderator'); - } - }); - }, - removeParticipant: function() { - if (this.model.get('participantType') === OCA.SpreedMe.app.OWNER) { - return; - } + template: Handlebars.compile(TEMPLATE), - var self = this, - participantId = this.model.get('userId'), - endpoint = '/participants'; + initialize: function(options) { + this._participantListView = new OCA.SpreedMe.Views.ParticipantListView({ collection: options.collection }); - if (this.model.get('participantType') === OCA.SpreedMe.app.GUEST) { - participantId = this.model.get('sessionId'); - endpoint += '/guests'; - } + // In Marionette 3.0 the view is not rendered automatically if + // needed when showing a child view, so it must be rendered + // explicitly to ensure that the DOM element in which the child view + // will be appended exists. + this.render(); + this.showChildView('participantList', this._participantListView, { replaceElement: true } ); + } - $.ajax({ - type: 'DELETE', - url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + OCA.SpreedMe.app.activeRoom.get('token') + endpoint, - data: { - participant: participantId - }, - success: function() { - self.render(); - }, - error: function() { - console.log('Error while removing user from room'); - } - }); - } - }) }); })(OC, OCA, Marionette, Handlebars); diff --git a/templates/index.php b/templates/index.php index 1b5259b38..2fe1da924 100644 --- a/templates/index.php +++ b/templates/index.php @@ -17,6 +17,7 @@ script( 'models/participant', 'models/participantcollection', 'views/callinfoview', + 'views/participantlistview', 'views/participantview', 'views/roomlistview', 'views/sidebarview', |