blob: df309f599432962cfa28087db979e85d65db7d63 [file] [log] [blame]
/********************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
********************************************************************************/
import {Injectable} from "@angular/core";
import {Actions, createEffect, ofType} from "@ngrx/effects";
import {Action} from "@ngrx/store";
import {concat, EMPTY, Observable, of, throwError} from "rxjs";
import {catchError, endWith, filter, map, mergeMap, startWith, switchMap} from "rxjs/operators";
import {AttachmentsApiService} from "../../../../core/api/attachments";
import {arrayJoin, endWithObservable, ignoreError} from "../../../../util";
import {setErrorAction} from "../../../root/actions";
import {EErrorCode} from "../../../root/model";
import {setStatementLoadingAction, submitConsiderationFilesAction} from "../../../statements/actions";
import {addAttachmentEntityAction, setAttachmentCacheAction} from "../../actions";
import {IAttachmentControlValue, IAttachmentError} from "../../model";
import {FetchAttachmentsEffect} from "../fetch";
@Injectable({providedIn: "root"})
export class SubmitConsiderationsEffect {
public submit$ = createEffect(() => this.actions.pipe(
ofType(submitConsiderationFilesAction),
switchMap((action) => {
return this.submit(action.statementId, action.value).pipe(
ignoreError()
);
})
));
public constructor(
public readonly actions: Actions,
public readonly attachmentsApiService: AttachmentsApiService,
public readonly fetchAttachmentsEffect: FetchAttachmentsEffect
) {
}
public submit(
statementId: number,
value: IAttachmentControlValue[]
): Observable<Action> {
const errors: IAttachmentError[] = [];
return concat(
this.addConsiderations(statementId, value, errors),
this.fetchAttachmentsEffect.fetchAttachments(statementId)
).pipe(
endWithObservable(() => {
const lastError = errors.reverse()[0];
return lastError == null ? EMPTY : concat(
of(setErrorAction({statementId, error: lastError.message})),
throwError(lastError.error)
);
}),
startWith(setStatementLoadingAction({loading: {submittingConsiderationFiles: true}})),
endWith(setStatementLoadingAction({loading: {submittingConsiderationFiles: false}}))
);
}
public addConsiderations(
statementId: number,
considerations: IAttachmentControlValue[],
errors: IAttachmentError[] = []
): Observable<Action> {
const items: IAttachmentControlValue[] = [];
return of(...arrayJoin(considerations)).pipe(
filter((item) => item?.file instanceof File),
mergeMap((item) => {
return this.addSingleConsiderationFile(statementId, item.file).pipe(
catchError((error) => {
items.push(item);
errors.push({statementId, attachment: item, error, message: EErrorCode.FAILED_FILE_UPLOAD});
return EMPTY;
})
);
}, 2),
startWith(setAttachmentCacheAction({statementId, items: considerations})),
endWithObservable(() => of(setAttachmentCacheAction({statementId, items})))
);
}
private addSingleConsiderationFile(
statementId: number,
file: File
): Observable<Action> {
return this.attachmentsApiService.postConsideration(statementId, file).pipe(
map((entity) => addAttachmentEntityAction({statementId, entity}))
);
}
}