blob: da72d14489aa8d9d01837ac2f117c723d117f4dd [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 {Component, Input, OnDestroy, OnInit} from "@angular/core";
import {select, Store} from "@ngrx/store";
import {combineLatest, Subject} from "rxjs";
import {filter, take, takeUntil} from "rxjs/operators";
import {AUTO_SELECTED_TAGS, IAPIAttachmentModel} from "../../../../core/api/attachments";
import {startAttachmentDownloadAction} from "../../../../store/attachments/actions";
import {IAttachmentControlValue} from "../../../../store/attachments/model";
import {
getAllStatementAttachments,
getAttachmentControlValueSelector,
getFilteredAttachmentTagsSelector
} from "../../../../store/attachments/selectors";
import {queryParamsIdSelector} from "../../../../store/root/selectors";
import {filterDistinctValues} from "../../../../util/store";
import {getMailAttachment} from "../../../forms/attachments/util/mail-attachments.util";
/**
* This component displays the list of attachments saved with the statement.
* It's split up into 3 different categories:
* mail-text, attachments manually added to the statement and the attachments copied from the initial email.
*
* The attachment lists can be filtered to only show attachments with specific tags.
* The available tags for filtering are all the used tags on the statements attachments.
*/
@Component({
selector: "app-statement-details-attachments",
templateUrl: "./statement-details-attachments.component.html",
styleUrls: ["./statement-details-attachments.component.scss"]
})
export class StatementDetailsAttachmentsComponent implements OnInit, OnDestroy {
@Input()
public appCollapsed = false;
public allAttachments$ = this.store.pipe(select(getAllStatementAttachments));
public allAttachments: IAttachmentControlValue[] = [];
public statementAttachments$ = this.store.pipe(select(getAttachmentControlValueSelector, {forbiddenTagIds: AUTO_SELECTED_TAGS}));
public statementAttachments: IAttachmentControlValue[] = [];
public availableTags: { label: string, id: string, isSelected: boolean }[] = [];
public tags$ = this.store.pipe(select(getFilteredAttachmentTagsSelector, {without: AUTO_SELECTED_TAGS}));
public statementId$ = this.store.pipe(select(queryParamsIdSelector));
public mailTextAttachment: IAPIAttachmentModel;
private destroy$ = new Subject();
public constructor(public store: Store) {
}
/**
* Subscribing to the attachment observables to apply the filtering for tags when changes to the statement attachments happen.
*/
public ngOnInit() {
combineLatest([this.allAttachments$, this.tags$]).pipe(
takeUntil(this.destroy$)
).subscribe(([attachments, tags]) => {
const allTags = filterDistinctValues(attachments.map((attachment) => attachment.tagIds).reduce((_, x) => x.concat(_), []));
this.availableTags = tags.filter((_) => allTags.find((a) => a === _.id))
.map((_) => ({..._, isSelected: false}));
});
this.statementAttachments$.pipe(
takeUntil(this.destroy$)
).subscribe((attachments) => {
this.statementAttachments = this.filterBySelectedTags(attachments);
});
this.allAttachments$.pipe(
filter((attachments) => attachments != null)
).subscribe(async (attachments) => {
const mailAttachments = this.filterForEmailAttachments(attachments);
this.mailTextAttachment = getMailAttachment(attachments);
this.allAttachments = this.filterBySelectedTags(mailAttachments);
});
}
public ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
public async toggleTag(tag, state?: boolean) {
tag.isSelected = state != null ? state : !tag.isSelected;
const sAttachments = await this.statementAttachments$.pipe(take(1)).toPromise();
this.statementAttachments = this.filterBySelectedTags(sAttachments);
const aAttachments = await this.allAttachments$.pipe(take(1)).toPromise();
const mailAttachments = this.filterForEmailAttachments(aAttachments);
this.allAttachments = this.filterBySelectedTags(mailAttachments);
}
public filterForEmailAttachments(attachments: IAPIAttachmentModel[]) {
return attachments.filter((attachment) => {
return attachment.tagIds.find((_) => _ === "email") != null &&
attachment.tagIds.find((_) => _ === "email-text") == null;
});
}
public deselectAllTags() {
for (const tag of this.availableTags) {
this.toggleTag(tag, false);
}
}
public async downloadAttachment(attachmentId: number) {
const statementId = await this.statementId$.pipe(take(1)).toPromise();
this.store.dispatch(startAttachmentDownloadAction({statementId, attachmentId}));
}
/**
* Filters the input list of attachments to only return the ones that have the isSelected property set to true.
*/
public filterBySelectedTags(attachments: IAttachmentControlValue[]) {
return attachments.filter((attachment) => {
const selectedTags = this.availableTags?.filter((_) => _.isSelected);
if (selectedTags?.length === 0) {
return true;
}
for (const tagId of attachment?.tagIds) {
const tagIsSelected = this.availableTags.find((_) => _.id === tagId)?.isSelected;
if (tagIsSelected) {
return true;
}
}
return false;
});
}
}