| /** |
| * @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. |
| */ |
| |
| import {SuggestionsState} from './code-owners-model.js'; |
| import {ServerConfigurationError} from './code-owners-api.js'; |
| |
| /** |
| * ModelLoader provides a method for loading data into the model. |
| * It is a bridge between an ownersModel and an ownersService. |
| * When UI elements depends on a model property XXX, the element should |
| * observe (or bind to) the property and call modelLoader.loadXXX method |
| * to load the value. |
| * It is recommended to use CodeOwnersModelMixin and call all load... methods |
| * in the loadPropertiesAfterModelChanged method |
| */ |
| export class ModelLoader { |
| constructor(ownersService, ownersModel) { |
| this.ownersService = ownersService; |
| this.ownersModel = ownersModel; |
| } |
| |
| async _loadProperty(propertyName, propertyLoader, propertySetter) { |
| // Load property only if it was not already loaded |
| if (this.ownersModel[propertyName] !== undefined) return; |
| let newValue; |
| try { |
| newValue = await propertyLoader(); |
| } catch (e) { |
| if (e instanceof ServerConfigurationError) { |
| this.ownersModel.setServerConfigurationError(e.message); |
| return; |
| } |
| console.error(e); |
| this.ownersModel.setPluginFailed(e.message); |
| return; |
| } |
| // It is possible, that several requests is made in parallel. |
| // Store only the first result and discard all other results. |
| // (also, due to the CodeOwnersCacheApi all result must be identical) |
| if (this.ownersModel[propertyName] !== undefined) return; |
| propertySetter(newValue); |
| } |
| |
| async loadBranchConfig() { |
| await this._loadProperty('branchConfig', |
| () => this.ownersService.getBranchConfig(), |
| value => this.ownersModel.setBranchConfig(value) |
| ); |
| } |
| |
| async loadStatus() { |
| await this._loadProperty('status', |
| () => this.ownersService.getStatus(), |
| value => this.ownersModel.setStatus(value) |
| ); |
| } |
| |
| async loadUserRole() { |
| await this._loadProperty('userRole', |
| () => this.ownersService.getLoggedInUserInitialRole(), |
| value => this.ownersModel.setUserRole(value) |
| ); |
| } |
| |
| async loadPluginStatus() { |
| await this._loadProperty('pluginStatus', |
| () => this.ownersService.isCodeOwnerEnabled(), |
| value => this.ownersModel.setPluginEnabled(value) |
| ); |
| } |
| |
| async loadAreAllFilesApproved() { |
| await this._loadProperty('areAllFilesApproved', |
| () => this.ownersService.areAllFilesApproved(), |
| value => this.ownersModel.setAreAllFilesApproved(value) |
| ); |
| } |
| |
| async loadSuggestions(suggestionsType) { |
| this.pauseActiveSuggestedOwnersLoading(); |
| this.activeLoadSuggestionType = suggestionsType; |
| if (this.ownersModel.suggestionsByTypes[suggestionsType].state === |
| SuggestionsState.Loading) { |
| this.ownersService.resumeSuggestedOwnersLoading(suggestionsType); |
| return; |
| } |
| |
| // If a loading has been started already, do nothing |
| if (this.ownersModel.suggestionsByTypes[suggestionsType].state !== |
| SuggestionsState.NotLoaded) return; |
| |
| this.ownersModel.setSuggestionsState(suggestionsType, |
| SuggestionsState.Loading); |
| let suggestedOwners; |
| try { |
| suggestedOwners = |
| await this.ownersService.getSuggestedOwners(suggestionsType); |
| } catch (e) { |
| console.error(e); |
| this.ownersModel.setSuggestionsState(suggestionsType, |
| SuggestionsState.LoadFailed); |
| // The selectedSuggestionsType can be changed while getSuggestedOwners |
| // is executed. The plugin should fail only if the selectedSuggestionsType |
| // is the same. |
| if (this.ownersModel.selectedSuggestionsType === suggestionsType) { |
| this.ownersModel.setPluginFailed(e.message); |
| } |
| return; |
| } |
| this.ownersModel.setSuggestionsFiles(suggestionsType, |
| suggestedOwners.files); |
| this.ownersModel.setSuggestionsState(suggestionsType, |
| SuggestionsState.Loaded); |
| } |
| |
| pauseActiveSuggestedOwnersLoading() { |
| if (!this.activeLoadSuggestionType) return; |
| this.ownersService.pauseSuggestedOwnersLoading( |
| this.activeLoadSuggestionType); |
| } |
| |
| async updateLoadSelectedSuggestionsProgress() { |
| const suggestionsType = this.ownersModel.selectedSuggestionsType; |
| let suggestedOwners; |
| try { |
| suggestedOwners = |
| await this.ownersService.getSuggestedOwnersProgress(suggestionsType); |
| } catch { |
| // Ignore any error, keep progress unchanged. |
| return; |
| } |
| this.ownersModel.setSuggestionsLoadProgress(suggestionsType, |
| suggestedOwners.progress); |
| this.ownersModel.setSuggestionsFiles(suggestionsType, |
| suggestedOwners.files); |
| } |
| } |