| /** |
| * @license |
| * Copyright (C) 2020 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. |
| */ |
| |
| export const SuggestionsState = { |
| NotLoaded: 'NotLoaded', |
| Loaded: 'Loaded', |
| Loading: 'Loading', |
| LoadFailed: 'LoadFailed', |
| }; |
| |
| export const PluginState = { |
| Enabled: 'Enabled', |
| Disabled: 'Disabled', |
| ServerConfigurationError: 'ServerConfigurationError', |
| Failed: 'Failed', |
| }; |
| |
| export function isPluginErrorState(state) { |
| return state === PluginState.ServerConfigurationError || |
| state === PluginState.Failed; |
| } |
| |
| export const SuggestionsType = { |
| BEST_SUGGESTIONS: 'BEST_SUGGESTIONS', |
| ALL_SUGGESTIONS: 'ALL_SUGGESTIONS', |
| }; |
| |
| /** |
| * @enum |
| */ |
| export const UserRole = { |
| ANONYMOUS: 'ANONYMOUS', |
| AUTHOR: 'AUTHOR', |
| CHANGE_OWNER: 'CHANGE_OWNER', |
| REVIEWER: 'REVIEWER', |
| CC: 'CC', |
| REMOVED_REVIEWER: 'REMOVED_REVIEWER', |
| OTHER: 'OTHER', |
| }; |
| |
| export const BestSuggestionsLimit = 5; |
| export const AllSuggestionsLimit = 1000; |
| |
| /** |
| * Maintain the state of code-owners. |
| * Raises 'model-property-changed' event when a property is changed. |
| * The plugin shares the same model between all UI elements (if it is not, |
| * the plugin can't maintain showSuggestions state across different UI elements). |
| * UI elements use values from this model to display information |
| * and listens for the model-property-changed event. To do so, UI elements |
| * add CodeOwnersModelMixin, which is doing the listening and the translation |
| * from model-property-changed event to Polymer property-changed-event. The |
| * translation allows to use model properties in observables, bindings, |
| * computed properties, etc... |
| * The CodeOwnersModelLoader updates the model. |
| * |
| * It would be good to use RxJs Observable for implementing model properties. |
| * However, RxJs library is imported by Gerrit and there is no |
| * good way to reuse the same library in the plugin. |
| */ |
| export class CodeOwnersModel extends EventTarget { |
| constructor(change) { |
| super(); |
| this.change = change; |
| this.branchConfig = undefined; |
| this.status = undefined; |
| this.userRole = undefined; |
| this.isCodeOwnerEnabled = undefined; |
| this.areAllFilesApproved = undefined; |
| this.suggestionsByTypes = {}; |
| for (const suggestionType of Object.values(SuggestionsType)) { |
| this.suggestionsByTypes[suggestionType] = { |
| files: undefined, |
| state: SuggestionsState.NotLoaded, |
| loadProgress: undefined, |
| }; |
| } |
| this.selectedSuggestionsType = SuggestionsType.BEST_SUGGESTIONS; |
| this.showSuggestions = false; |
| this.pluginStatus = undefined; |
| } |
| |
| get selectedSuggestions() { |
| return this.suggestionsByTypes[this.selectedSuggestionsType]; |
| } |
| |
| setBranchConfig(config) { |
| if (this.branchConfig === config) return; |
| this.branchConfig = config; |
| this._firePropertyChanged('branchConfig'); |
| } |
| |
| setStatus(status) { |
| if (this.status === status) return; |
| this.status = status; |
| this._firePropertyChanged('status'); |
| } |
| |
| setUserRole(userRole) { |
| if (this.userRole === userRole) return; |
| this.userRole = userRole; |
| this._firePropertyChanged('userRole'); |
| } |
| |
| setIsCodeOwnerEnabled(enabled) { |
| if (this.isCodeOwnerEnabled === enabled) return; |
| this.isCodeOwnerEnabled = enabled; |
| this._firePropertyChanged('isCodeOwnerEnabled'); |
| } |
| |
| setAreAllFilesApproved(approved) { |
| if (this.areAllFilesApproved === approved) return; |
| this.areAllFilesApproved = approved; |
| this._firePropertyChanged('areAllFilesApproved'); |
| } |
| |
| setSuggestionsFiles(suggestionsType, files) { |
| const suggestions = this.suggestionsByTypes[suggestionsType]; |
| if (suggestions.files === files) return; |
| suggestions.files = files; |
| this._fireSuggestionsChanged(suggestionsType, 'files'); |
| } |
| |
| setSuggestionsState(suggestionsType, state) { |
| const suggestions = this.suggestionsByTypes[suggestionsType]; |
| if (suggestions.state === state) return; |
| suggestions.state = state; |
| this._fireSuggestionsChanged(suggestionsType, 'state'); |
| } |
| |
| setSuggestionsLoadProgress(suggestionsType, progress) { |
| const suggestions = this.suggestionsByTypes[suggestionsType]; |
| if (suggestions.loadProgress === progress) return; |
| suggestions.loadProgress = progress; |
| this._fireSuggestionsChanged(suggestionsType, 'loadProgress'); |
| } |
| |
| setSelectedSuggestionType(suggestionsType) { |
| if (this.selectedSuggestionsType === suggestionsType) return; |
| this.selectedSuggestionsType = suggestionsType; |
| this._firePropertyChanged('selectedSuggestionsType'); |
| this._firePropertyChanged('selectedSuggestions'); |
| } |
| |
| setShowSuggestions(show) { |
| if (this.showSuggestions === show) return; |
| this.showSuggestions = show; |
| this._firePropertyChanged('showSuggestions'); |
| } |
| |
| setPluginEnabled(enabled) { |
| this._setPluginStatus({state: enabled ? |
| PluginState.Enabled : PluginState.Disabled}); |
| } |
| |
| setServerConfigurationError(failedMessage) { |
| this._setPluginStatus({state: PluginState.ServerConfigurationError, |
| failedMessage}); |
| } |
| |
| setPluginFailed(failedMessage) { |
| this._setPluginStatus({state: PluginState.Failed, failedMessage}); |
| } |
| |
| _setPluginStatus(status) { |
| if (this._arePluginStatusesEqual(this.pluginStatus, status)) return; |
| this.pluginStatus = status; |
| this._firePropertyChanged('pluginStatus'); |
| } |
| |
| _arePluginStatusesEqual(status1, status2) { |
| if (status1 === undefined || status2 === undefined) { |
| return status1 === status2; |
| } |
| if (status1.state !== status2.state) return false; |
| return isPluginErrorState(status1.state)? |
| status1.failedMessage === status2.failedMessage : |
| true; |
| } |
| |
| _firePropertyChanged(propertyName) { |
| this.dispatchEvent(new CustomEvent('model-property-changed', { |
| detail: { |
| propertyName, |
| }, |
| })); |
| } |
| |
| _fireSuggestionsChanged(suggestionsType, propertyName) { |
| this._firePropertyChanged( |
| `suggestionsByTypes.${suggestionsType}.${propertyName}`); |
| if (suggestionsType === this.selectedSuggestionsType) { |
| this._firePropertyChanged(`selectedSuggestions.${propertyName}`); |
| } |
| } |
| |
| static getModel(change) { |
| if (!this.model || this.model.change !== change) { |
| this.model = new CodeOwnersModel(change); |
| } |
| return this.model; |
| } |
| } |