|  | /** | 
|  | * @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 {Subscription} from 'rxjs'; | 
|  | import {CodeOwnerService} from './code-owners-service'; | 
|  | import {ModelLoader} from './code-owners-model-loader'; | 
|  | import { | 
|  | CodeOwnersModel, | 
|  | OwnedPathsInfoOpt, | 
|  | PluginStatus, | 
|  | Status, | 
|  | SuggestionsState, | 
|  | SuggestionsType, | 
|  | UserRole, | 
|  | } from './code-owners-model'; | 
|  | import {LitElement, PropertyValues} from 'lit'; | 
|  | import {property, state} from 'lit/decorators'; | 
|  | import {ChangeInfo} from '@gerritcodereview/typescript-api/rest-api'; | 
|  | import {ReportingPluginApi} from '@gerritcodereview/typescript-api/reporting'; | 
|  | import {RestPluginApi} from '@gerritcodereview/typescript-api/rest'; | 
|  | import {CodeOwnerBranchConfigInfo, FetchedFile} from './code-owners-api'; | 
|  |  | 
|  | // eslint-disable-next-line @typescript-eslint/no-explicit-any | 
|  | export type Constructor<T> = new (...args: any[]) => T; | 
|  |  | 
|  | export interface CodeOwnersModelMixinInterface { | 
|  | change?: ChangeInfo; | 
|  | reporting?: ReportingPluginApi; | 
|  | restApi?: RestPluginApi; | 
|  | modelLoader?: ModelLoader; | 
|  | model?: CodeOwnersModel; | 
|  |  | 
|  | pluginStatus?: PluginStatus; | 
|  | branchConfig?: CodeOwnerBranchConfigInfo; | 
|  | userRole?: UserRole; | 
|  | areAllFilesApproved?: boolean; | 
|  | status?: Status; | 
|  | showSuggestions?: boolean; | 
|  | allOwnersLoaded?: boolean; | 
|  | selectedSuggestionsType?: SuggestionsType; | 
|  | selectedSuggestionsFiles?: Array<FetchedFile>; | 
|  | selectedSuggestionsState?: SuggestionsState; | 
|  | selectedSuggestionsLoadProgress?: string; | 
|  | ownedPaths?: OwnedPathsInfoOpt; | 
|  |  | 
|  | loadPropertiesAfterModelChanged(): void; | 
|  | } | 
|  | /** | 
|  | * The CodeOwnersMixin adds several properties to a class and translates | 
|  | * 'model-property-changed' events from the model to the notifyPath calls. | 
|  | * This allows to use properties of the model in observers, calculated | 
|  | * properties and bindings. | 
|  | * It is guaranteed, that model and modelLoader are set only if change, | 
|  | * reporting and restApi properties are set. | 
|  | */ | 
|  |  | 
|  | export const CodeOwnersModelMixin = <T extends Constructor<LitElement>>( | 
|  | superClass: T | 
|  | ) => { | 
|  | /** | 
|  | * @lit | 
|  | * @mixinClass | 
|  | */ | 
|  | class Mixin extends superClass { | 
|  | @property({type: Object}) | 
|  | change?: ChangeInfo; | 
|  |  | 
|  | @property({type: Object}) | 
|  | reporting?: ReportingPluginApi; | 
|  |  | 
|  | @property({type: Object}) | 
|  | restApi?: RestPluginApi; | 
|  |  | 
|  | @state() | 
|  | pluginStatus?: PluginStatus; | 
|  |  | 
|  | @state() | 
|  | branchConfig?: CodeOwnerBranchConfigInfo; | 
|  |  | 
|  | @state() | 
|  | userRole?: UserRole; | 
|  |  | 
|  | @state() | 
|  | areAllFilesApproved?: boolean; | 
|  |  | 
|  | @state() | 
|  | status?: Status; | 
|  |  | 
|  | @property({type: Boolean, attribute: 'show-suggestions', reflect: true}) | 
|  | showSuggestions?: boolean; | 
|  |  | 
|  | @state() | 
|  | selectedSuggestionsType?: SuggestionsType; | 
|  |  | 
|  | @state() | 
|  | selectedSuggestionsFiles?: Array<FetchedFile>; | 
|  |  | 
|  | @state() | 
|  | selectedSuggestionsState?: SuggestionsState; | 
|  |  | 
|  | @state() | 
|  | selectedSuggestionsLoadProgress?: string; | 
|  |  | 
|  | @state() | 
|  | ownedPaths?: OwnedPathsInfoOpt; | 
|  |  | 
|  | private model_?: CodeOwnersModel; | 
|  |  | 
|  | private subscriptions: Array<Subscription> = []; | 
|  |  | 
|  | modelLoader?: ModelLoader; | 
|  |  | 
|  | get model() { | 
|  | return this.model_; | 
|  | } | 
|  |  | 
|  | set model(model: CodeOwnersModel | undefined) { | 
|  | if (this.model_ === model) return; | 
|  | for (const s of this.subscriptions) { | 
|  | s.unsubscribe(); | 
|  | } | 
|  | this.subscriptions = []; | 
|  | this.model_ = model; | 
|  | if (!model) return; | 
|  | this.subscriptions.push( | 
|  | model.state$.subscribe(s => { | 
|  | this.pluginStatus = s.pluginStatus; | 
|  | }) | 
|  | ); | 
|  | this.subscriptions.push( | 
|  | model.state$.subscribe(s => { | 
|  | this.branchConfig = s.branchConfig; | 
|  | }) | 
|  | ); | 
|  | this.subscriptions.push( | 
|  | model.state$.subscribe(s => { | 
|  | this.status = s.status; | 
|  | }) | 
|  | ); | 
|  | this.subscriptions.push( | 
|  | model.state$.subscribe(s => { | 
|  | this.userRole = s.userRole; | 
|  | }) | 
|  | ); | 
|  | this.subscriptions.push( | 
|  | model.state$.subscribe(s => { | 
|  | this.areAllFilesApproved = s.areAllFilesApproved; | 
|  | }) | 
|  | ); | 
|  | this.subscriptions.push( | 
|  | model.showSuggestions$.subscribe(s => { | 
|  | this.showSuggestions = s; | 
|  | }) | 
|  | ); | 
|  | this.subscriptions.push( | 
|  | model.selectedSuggestionsType$.subscribe(s => { | 
|  | this.selectedSuggestionsType = s; | 
|  | }) | 
|  | ); | 
|  | this.subscriptions.push( | 
|  | model.selectedSuggestionsFiles$.subscribe(f => { | 
|  | this.selectedSuggestionsFiles = f; | 
|  | }) | 
|  | ); | 
|  | this.subscriptions.push( | 
|  | model.selectedSuggestionsLoadProgress$.subscribe(p => { | 
|  | this.selectedSuggestionsLoadProgress = p; | 
|  | }) | 
|  | ); | 
|  | this.subscriptions.push( | 
|  | model.selectedSuggestionsState$.subscribe(s => { | 
|  | this.selectedSuggestionsState = s; | 
|  | }) | 
|  | ); | 
|  | this.subscriptions.push( | 
|  | model.ownedPaths$.subscribe(s => { | 
|  | this.ownedPaths = s; | 
|  | }) | 
|  | ); | 
|  | this.loadPropertiesAfterModelChanged(); | 
|  | } | 
|  |  | 
|  | // eslint-disable-next-line @typescript-eslint/no-explicit-any | 
|  | constructor(...args: any[]) { | 
|  | super(...args); | 
|  | } | 
|  |  | 
|  | protected override willUpdate(changedProperties: PropertyValues): void { | 
|  | super.willUpdate(changedProperties); | 
|  |  | 
|  | if ( | 
|  | changedProperties.has('change') || | 
|  | changedProperties.has('restApi') || | 
|  | changedProperties.has('reporting') | 
|  | ) { | 
|  | if (!this.restApi || !this.change || !this.reporting) { | 
|  | this.model = undefined; | 
|  | this.modelLoader = undefined; | 
|  | return; | 
|  | } | 
|  | const ownerService = CodeOwnerService.getOwnerService( | 
|  | this.restApi, | 
|  | this.change | 
|  | ); | 
|  | const model = CodeOwnersModel.getModel(this.change); | 
|  | this.modelLoader = new ModelLoader(ownerService, model); | 
|  | // Assign model after modelLoader, so modelLoader can be used in | 
|  | // the loadPropertiesAfterModelChanged method | 
|  | this.model = model; | 
|  | } | 
|  | } | 
|  |  | 
|  | protected loadPropertiesAfterModelChanged() {} | 
|  | } | 
|  |  | 
|  | return Mixin as unknown as T & Constructor<CodeOwnersModelMixinInterface>; | 
|  | }; |