|  | /** | 
|  | * @license | 
|  | * Copyright (C) 2017 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | * http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  | (function() { | 
|  | 'use strict'; | 
|  |  | 
|  | const SUGGESTIONS_LIMIT = 15; | 
|  | const SAVING_ERROR_TEXT = 'Group may not exist, or you may not have '+ | 
|  | 'permission to add it'; | 
|  |  | 
|  | const URL_REGEX = '^(?:[a-z]+:)?//'; | 
|  |  | 
|  | Polymer({ | 
|  | is: 'gr-group-members', | 
|  |  | 
|  | properties: { | 
|  | groupId: Number, | 
|  | _groupMemberSearchId: String, | 
|  | _groupMemberSearchName: String, | 
|  | _includedGroupSearchId: String, | 
|  | _includedGroupSearchName: String, | 
|  | _loading: { | 
|  | type: Boolean, | 
|  | value: true, | 
|  | }, | 
|  | _groupName: String, | 
|  | _groupMembers: Object, | 
|  | _includedGroups: Object, | 
|  | _itemName: String, | 
|  | _itemType: String, | 
|  | _queryMembers: { | 
|  | type: Function, | 
|  | value() { | 
|  | return this._getAccountSuggestions.bind(this); | 
|  | }, | 
|  | }, | 
|  | _queryIncludedGroup: { | 
|  | type: Function, | 
|  | value() { | 
|  | return this._getGroupSuggestions.bind(this); | 
|  | }, | 
|  | }, | 
|  | _groupOwner: { | 
|  | type: Boolean, | 
|  | value: false, | 
|  | }, | 
|  | _isAdmin: { | 
|  | type: Boolean, | 
|  | value: false, | 
|  | }, | 
|  | }, | 
|  |  | 
|  | behaviors: [ | 
|  | Gerrit.BaseUrlBehavior, | 
|  | Gerrit.URLEncodingBehavior, | 
|  | ], | 
|  |  | 
|  | attached() { | 
|  | this._loadGroupDetails(); | 
|  |  | 
|  | this.fire('title-change', {title: 'Members'}); | 
|  | }, | 
|  |  | 
|  | _loadGroupDetails() { | 
|  | if (!this.groupId) { return; } | 
|  |  | 
|  | const promises = []; | 
|  |  | 
|  | const errFn = response => { | 
|  | this.fire('page-error', {response}); | 
|  | }; | 
|  |  | 
|  | return this.$.restAPI.getGroupConfig(this.groupId, errFn) | 
|  | .then(config => { | 
|  | if (!config || !config.name) { return Promise.resolve(); } | 
|  |  | 
|  | this._groupName = config.name; | 
|  |  | 
|  | promises.push(this.$.restAPI.getIsAdmin().then(isAdmin => { | 
|  | this._isAdmin = isAdmin ? true : false; | 
|  | })); | 
|  |  | 
|  | promises.push(this.$.restAPI.getIsGroupOwner(config.name) | 
|  | .then(isOwner => { | 
|  | this._groupOwner = isOwner ? true : false; | 
|  | })); | 
|  |  | 
|  | promises.push(this.$.restAPI.getGroupMembers(config.name).then( | 
|  | members => { | 
|  | this._groupMembers = members; | 
|  | })); | 
|  |  | 
|  | promises.push(this.$.restAPI.getIncludedGroup(config.name) | 
|  | .then(includedGroup => { | 
|  | this._includedGroups = includedGroup; | 
|  | })); | 
|  |  | 
|  | return Promise.all(promises).then(() => { | 
|  | this._loading = false; | 
|  | }); | 
|  | }); | 
|  | }, | 
|  |  | 
|  | _computeLoadingClass(loading) { | 
|  | return loading ? 'loading' : ''; | 
|  | }, | 
|  |  | 
|  | _isLoading() { | 
|  | return this._loading || this._loading === undefined; | 
|  | }, | 
|  |  | 
|  | _computeGroupUrl(url) { | 
|  | if (!url) { return; } | 
|  |  | 
|  | const r = new RegExp(URL_REGEX, 'i'); | 
|  | if (r.test(url)) { | 
|  | return url; | 
|  | } | 
|  |  | 
|  | // For GWT compatibility | 
|  | if (url.startsWith('#')) { | 
|  | return this.getBaseUrl() + url.slice(1); | 
|  | } | 
|  | return this.getBaseUrl() + url; | 
|  | }, | 
|  |  | 
|  | _handleSavingGroupMember() { | 
|  | return this.$.restAPI.saveGroupMembers(this._groupName, | 
|  | this._groupMemberSearchId).then(config => { | 
|  | if (!config) { | 
|  | return; | 
|  | } | 
|  | this.$.restAPI.getGroupMembers(this._groupName).then(members => { | 
|  | this._groupMembers = members; | 
|  | }); | 
|  | this._groupMemberSearchName = ''; | 
|  | this._groupMemberSearchId = ''; | 
|  | }); | 
|  | }, | 
|  |  | 
|  | _handleDeleteConfirm() { | 
|  | this.$.overlay.close(); | 
|  | if (this._itemType === 'member') { | 
|  | return this.$.restAPI.deleteGroupMembers(this._groupName, | 
|  | this._itemId) | 
|  | .then(itemDeleted => { | 
|  | if (itemDeleted.status === 204) { | 
|  | this.$.restAPI.getGroupMembers(this._groupName) | 
|  | .then(members => { | 
|  | this._groupMembers = members; | 
|  | }); | 
|  | } | 
|  | }); | 
|  | } else if (this._itemType === 'includedGroup') { | 
|  | return this.$.restAPI.deleteIncludedGroup(this._groupName, | 
|  | this._itemId) | 
|  | .then(itemDeleted => { | 
|  | if (itemDeleted.status === 204 || itemDeleted.status === 205) { | 
|  | this.$.restAPI.getIncludedGroup(this._groupName) | 
|  | .then(includedGroup => { | 
|  | this._includedGroups = includedGroup; | 
|  | }); | 
|  | } | 
|  | }); | 
|  | } | 
|  | }, | 
|  |  | 
|  | _handleConfirmDialogCancel() { | 
|  | this.$.overlay.close(); | 
|  | }, | 
|  |  | 
|  | _handleDeleteMember(e) { | 
|  | const id = e.model.get('item._account_id'); | 
|  | const name = e.model.get('item.name'); | 
|  | const username = e.model.get('item.username'); | 
|  | const email = e.model.get('item.email'); | 
|  | const item = username || name || email || id; | 
|  | if (!item) { | 
|  | return ''; | 
|  | } | 
|  | this._itemName = item; | 
|  | this._itemId = id; | 
|  | this._itemType = 'member'; | 
|  | this.$.overlay.open(); | 
|  | }, | 
|  |  | 
|  | _handleSavingIncludedGroups() { | 
|  | return this.$.restAPI.saveIncludedGroup(this._groupName, | 
|  | this._includedGroupSearchId.replace(/\+/g, ' '), err => { | 
|  | if (err.status === 404) { | 
|  | this.dispatchEvent(new CustomEvent('show-alert', { | 
|  | detail: {message: SAVING_ERROR_TEXT}, | 
|  | bubbles: true, | 
|  | })); | 
|  | return err; | 
|  | } | 
|  | throw Error(err.statusText); | 
|  | }) | 
|  | .then(config => { | 
|  | if (!config) { | 
|  | return; | 
|  | } | 
|  | this.$.restAPI.getIncludedGroup(this._groupName) | 
|  | .then(includedGroup => { | 
|  | this._includedGroups = includedGroup; | 
|  | }); | 
|  | this._includedGroupSearchName = ''; | 
|  | this._includedGroupSearchId = ''; | 
|  | }); | 
|  | }, | 
|  |  | 
|  | _handleDeleteIncludedGroup(e) { | 
|  | const id = decodeURIComponent(e.model.get('item.id')).replace(/\+/g, ' '); | 
|  | const name = e.model.get('item.name'); | 
|  | const item = name || id; | 
|  | if (!item) { return ''; } | 
|  | this._itemName = item; | 
|  | this._itemId = id; | 
|  | this._itemType = 'includedGroup'; | 
|  | this.$.overlay.open(); | 
|  | }, | 
|  |  | 
|  | _getAccountSuggestions(input) { | 
|  | if (input.length === 0) { return Promise.resolve([]); } | 
|  | return this.$.restAPI.getSuggestedAccounts( | 
|  | input, SUGGESTIONS_LIMIT).then(accounts => { | 
|  | const accountSuggestions = []; | 
|  | let nameAndEmail; | 
|  | if (!accounts) { return []; } | 
|  | for (const key in accounts) { | 
|  | if (!accounts.hasOwnProperty(key)) { continue; } | 
|  | if (accounts[key].email !== undefined) { | 
|  | nameAndEmail = accounts[key].name + | 
|  | ' <' + accounts[key].email + '>'; | 
|  | } else { | 
|  | nameAndEmail = accounts[key].name; | 
|  | } | 
|  | accountSuggestions.push({ | 
|  | name: nameAndEmail, | 
|  | value: accounts[key]._account_id, | 
|  | }); | 
|  | } | 
|  | return accountSuggestions; | 
|  | }); | 
|  | }, | 
|  |  | 
|  | _getGroupSuggestions(input) { | 
|  | return this.$.restAPI.getSuggestedGroups(input) | 
|  | .then(response => { | 
|  | const groups = []; | 
|  | for (const key in response) { | 
|  | if (!response.hasOwnProperty(key)) { continue; } | 
|  | groups.push({ | 
|  | name: key, | 
|  | value: decodeURIComponent(response[key].id), | 
|  | }); | 
|  | } | 
|  | return groups; | 
|  | }); | 
|  | }, | 
|  |  | 
|  | _computeHideItemClass(owner, admin) { | 
|  | return admin || owner ? '' : 'canModify'; | 
|  | }, | 
|  | }); | 
|  | })(); |