blob: c1b2e9836e5b7b3b8206e1807afe8eb3269d9601 [file] [log] [blame]
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {BehaviorSubject, combineLatest, from, Observable, of} from 'rxjs';
import {catchError, map, shareReplay, switchMap} from 'rxjs/operators';
import {ChangeModel} from '../change/change-model';
import {FlowInfo, FlowInput} from '../../api/rest-api';
import {Model} from '../base/model';
import {define} from '../dependency';
import {NumericChangeId} from '../../types/common';
import {getAppContext} from '../../services/app-context';
export interface FlowsState {
isEnabled: boolean;
flows: FlowInfo[];
loading: boolean;
errorMessage?: string;
}
export const flowsModelToken = define<FlowsModel>('flows-model');
export class FlowsModel extends Model<FlowsState> {
readonly flows$ = this.state$.pipe(map(s => s.flows));
readonly loading$ = this.state$.pipe(map(s => s.loading));
readonly enabled$: Observable<boolean>;
private readonly reload$ = new BehaviorSubject<void>(undefined);
private changeNum?: NumericChangeId;
private readonly restApiService = getAppContext().restApiService;
constructor(private readonly changeModel: ChangeModel) {
super({
isEnabled: false,
flows: [],
loading: true,
});
this.enabled$ = this.changeModel.changeNum$.pipe(
switchMap(changeNum => {
if (!changeNum) {
return of(false);
}
return from(this.restApiService.getIfFlowsIsEnabled(changeNum)).pipe(
map(res => res?.enabled ?? false),
catchError(() => of(false))
);
}),
shareReplay(1)
);
this.subscriptions.push(
this.enabled$.subscribe(isEnabled => {
this.setState({...this.getState(), isEnabled});
})
);
this.subscriptions.push(
this.changeModel.changeNum$.subscribe(changeNum => {
this.changeNum = changeNum;
})
);
this.subscriptions.push(
combineLatest([this.changeModel.changeNum$, this.reload$, this.enabled$])
.pipe(
switchMap(([changeNum, _, enabled]) => {
if (!changeNum || !enabled) return of([]);
this.setState({...this.getState(), loading: true});
return from(this.restApiService.listFlows(changeNum)).pipe(
catchError(err => {
this.setState({
...this.getState(),
errorMessage: `Failed to load flows: ${err}`,
loading: false,
});
return of([]);
})
);
})
)
.subscribe(flows => {
this.setState({
...this.getState(),
flows: flows ?? [],
loading: false,
});
})
);
}
reload() {
this.reload$.next();
}
async deleteFlow(flowId: string) {
if (!this.changeNum) return;
if (!this.getState().isEnabled) return;
await this.restApiService.deleteFlow(this.changeNum, flowId);
this.reload();
}
async createFlow(flowInput: FlowInput) {
if (!this.changeNum) return;
if (!this.getState().isEnabled) return;
await this.restApiService.createFlow(this.changeNum, flowInput);
this.reload();
}
}