| /** |
| * @license |
| * Copyright (C) 2016 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. |
| */ |
| import '../../../scripts/bundled-polymer.js'; |
| |
| import '@polymer/iron-input/iron-input.js'; |
| import '../../shared/gr-autocomplete/gr-autocomplete.js'; |
| import '../../shared/gr-button/gr-button.js'; |
| import '../../shared/gr-rest-api-interface/gr-rest-api-interface.js'; |
| import '../../../styles/gr-form-styles.js'; |
| import '../../../styles/shared-styles.js'; |
| import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js'; |
| import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js'; |
| import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js'; |
| import {PolymerElement} from '@polymer/polymer/polymer-element.js'; |
| import {htmlTemplate} from './gr-watched-projects-editor_html.js'; |
| |
| const NOTIFICATION_TYPES = [ |
| {name: 'Changes', key: 'notify_new_changes'}, |
| {name: 'Patches', key: 'notify_new_patch_sets'}, |
| {name: 'Comments', key: 'notify_all_comments'}, |
| {name: 'Submits', key: 'notify_submitted_changes'}, |
| {name: 'Abandons', key: 'notify_abandoned_changes'}, |
| ]; |
| |
| /** @extends Polymer.Element */ |
| class GrWatchedProjectsEditor extends GestureEventListeners( |
| LegacyElementMixin( |
| PolymerElement)) { |
| static get template() { return htmlTemplate; } |
| |
| static get is() { return 'gr-watched-projects-editor'; } |
| |
| static get properties() { |
| return { |
| hasUnsavedChanges: { |
| type: Boolean, |
| value: false, |
| notify: true, |
| }, |
| |
| _projects: Array, |
| _projectsToRemove: { |
| type: Array, |
| value() { return []; }, |
| }, |
| _query: { |
| type: Function, |
| value() { |
| return this._getProjectSuggestions.bind(this); |
| }, |
| }, |
| }; |
| } |
| |
| loadData() { |
| return this.$.restAPI.getWatchedProjects().then(projs => { |
| this._projects = projs; |
| }); |
| } |
| |
| save() { |
| let deletePromise; |
| if (this._projectsToRemove.length) { |
| deletePromise = this.$.restAPI.deleteWatchedProjects( |
| this._projectsToRemove); |
| } else { |
| deletePromise = Promise.resolve(); |
| } |
| |
| return deletePromise |
| .then(() => this.$.restAPI.saveWatchedProjects(this._projects)) |
| .then(projects => { |
| this._projects = projects; |
| this._projectsToRemove = []; |
| this.hasUnsavedChanges = false; |
| }); |
| } |
| |
| _getTypes() { |
| return NOTIFICATION_TYPES; |
| } |
| |
| _getTypeCount() { |
| return this._getTypes().length; |
| } |
| |
| _computeCheckboxChecked(project, key) { |
| return project.hasOwnProperty(key); |
| } |
| |
| _getProjectSuggestions(input) { |
| return this.$.restAPI.getSuggestedProjects(input) |
| .then(response => { |
| const projects = []; |
| for (const key in response) { |
| if (!response.hasOwnProperty(key)) { continue; } |
| projects.push({ |
| name: key, |
| value: response[key], |
| }); |
| } |
| return projects; |
| }); |
| } |
| |
| _handleRemoveProject(e) { |
| const el = dom(e).localTarget; |
| const index = parseInt(el.getAttribute('data-index'), 10); |
| const project = this._projects[index]; |
| this.splice('_projects', index, 1); |
| this.push('_projectsToRemove', project); |
| this.hasUnsavedChanges = true; |
| } |
| |
| _canAddProject(project, text, filter) { |
| if ((!project || !project.id) && !text) { return false; } |
| |
| // This will only be used if not using the auto complete |
| if (!project && text) { return true; } |
| |
| // Check if the project with filter is already in the list. Compare |
| // filters using == to coalesce null and undefined. |
| for (let i = 0; i < this._projects.length; i++) { |
| if (this._projects[i].project === project.id && |
| this._projects[i].filter == filter) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| _getNewProjectIndex(name, filter) { |
| let i; |
| for (i = 0; i < this._projects.length; i++) { |
| if (this._projects[i].project > name || |
| (this._projects[i].project === name && |
| this._projects[i].filter > filter)) { |
| break; |
| } |
| } |
| return i; |
| } |
| |
| _handleAddProject() { |
| const newProject = this.$.newProject.value; |
| const newProjectName = this.$.newProject.text; |
| const filter = this.$.newFilter.value || null; |
| |
| if (!this._canAddProject(newProject, newProjectName, filter)) { return; } |
| |
| const insertIndex = this._getNewProjectIndex(newProjectName, filter); |
| |
| this.splice('_projects', insertIndex, 0, { |
| project: newProjectName, |
| filter, |
| _is_local: true, |
| }); |
| |
| this.$.newProject.clear(); |
| this.$.newFilter.bindValue = ''; |
| this.hasUnsavedChanges = true; |
| } |
| |
| _handleCheckboxChange(e) { |
| const el = dom(e).localTarget; |
| const index = parseInt(el.getAttribute('data-index'), 10); |
| const key = el.getAttribute('data-key'); |
| const checked = el.checked; |
| this.set(['_projects', index, key], !!checked); |
| this.hasUnsavedChanges = true; |
| } |
| |
| _handleNotifCellClick(e) { |
| const checkbox = dom(e.target).querySelector('input'); |
| if (checkbox) { checkbox.click(); } |
| } |
| } |
| |
| customElements.define(GrWatchedProjectsEditor.is, GrWatchedProjectsEditor); |