| /******************************************************************************** |
| * Copyright © 2020 Basys GmbH. |
| * |
| * 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, Injector, OnDestroy, OnInit} from '@angular/core'; |
| import {FormArray, FormControl, Validators} from '@angular/forms'; |
| import {UtilService} from '@core/services/util.service'; |
| import {MasterdataService} from '@masterdata/services/masterdata.service'; |
| import {ReportingService} from '@reporting/services/reporting.service'; |
| import {AbstractFormComponent} from '@shared/abstract/abstract-form/abstract-form.component'; |
| import {CyclicReportObject} from '@shared/model/CyclicReportObject'; |
| import {SelectOptionObject} from '@shared/model/SelectOptionObject'; |
| import {FormUtil} from '@shared/utils/form.util'; |
| import {combineLatest, defer, EMPTY, Observable, of, Subscription} from 'rxjs'; |
| import {catchError, map, switchMap, tap} from 'rxjs/operators'; |
| import {CyclicReportingService} from '../../services/cyclic-reporting.service'; |
| import {CyclicReportingUtilService} from '../../services/cyclic-reporting-util.service'; |
| import {CyclicReportValidators} from '../../validators/cyclic-report.validators'; |
| |
| @Component({ |
| selector: 'ok-cyclic-report-form', |
| styleUrls: ['cyclic-report-form.component.scss'], |
| templateUrl: 'cyclic-report-form.component.html' |
| }) |
| export class CyclicReportFormComponent extends AbstractFormComponent implements OnInit, OnDestroy { |
| |
| public dateTokens = this.cyclicReportingUtilService.dateReplacementTokens; |
| |
| public defaultValue: CyclicReportObject = { |
| id: undefined, |
| name: '', |
| fileNamePattern: '{Date}_{Time}_{Week}', |
| subject: '', |
| to: [], |
| emailText: '', |
| reportName: '', |
| printFormat: this.cyclicReportingUtilService.printFormatOptions[0].value, |
| standByListId: Number.NEGATIVE_INFINITY, |
| statusId: this.cyclicReportingUtilService.planStatusOptions[0].value, |
| triggerWeekDay: 1, |
| triggerHour: 8, |
| triggerMinute: 0, |
| validFromDayOffset: 0, |
| validFromHour: 8, |
| validFromMinute: 0, |
| validToDayOffset: 1, |
| validToHour: 8, |
| validToMinute: 0 |
| }; |
| |
| public excludedReportNames: string[] = this.cyclicReportingUtilService.excludedReportNames; |
| |
| public planStatusOptions = this.cyclicReportingUtilService.planStatusOptions; |
| |
| public printFormats = this.cyclicReportingUtilService.printFormatOptions; |
| |
| public report: CyclicReportObject; |
| |
| public reportNameOptions: SelectOptionObject[] = []; |
| |
| public standByListOptions: SelectOptionObject[] = []; |
| |
| public toFormArray: FormArray; |
| |
| public triggerMinuteStep = 5; |
| |
| public weekDayOptions = this.cyclicReportingUtilService.weekDayOptions; |
| |
| private subscriptions: Subscription[] = []; |
| |
| public constructor( |
| injector: Injector, |
| public utilService: UtilService, |
| public masterdataService: MasterdataService, |
| public reportingService: ReportingService, |
| public cyclicReportingService: CyclicReportingService, |
| public cyclicReportingUtilService: CyclicReportingUtilService |
| ) { |
| super(injector); |
| } |
| |
| public ngOnInit() { |
| this.subscriptions.push(this.initializeForm().subscribe()); |
| } |
| |
| public ngOnDestroy() { |
| this.subscriptions.forEach((subscription) => subscription.unsubscribe()); |
| } |
| |
| public submit() { |
| this.form.markAsTouched(); |
| if (!FormUtil.validate(this.form)) { |
| return; |
| } |
| |
| this.subscriptions.push(...[ |
| of(this.form.value).pipe( |
| switchMap((value) => { |
| this.form.disable(); |
| value = { |
| ...value, |
| to: value.to.filter((_) => _ !== '') |
| }; |
| return value.id == null ? |
| this.cyclicReportingService.putCyclicReport(value) |
| : this.cyclicReportingService.postCyclicReport(value); |
| }), |
| switchMap(() => this.navigateToOverview()), |
| catchError(() => { |
| this.form.enable(); |
| return EMPTY; |
| }) |
| ).subscribe() |
| ]); |
| } |
| |
| public delete() { |
| this.form.disable(); |
| this.subscriptions.push(...[ |
| this.cyclicReportingService.deleteCyclicReport(this.report.id).pipe( |
| switchMap(() => this.navigateToOverview()), |
| catchError(() => { |
| this.form.enable(); |
| return EMPTY; |
| }) |
| ).subscribe() |
| ]); |
| } |
| |
| public addEmailControl() { |
| this.toFormArray.push(this.createEmailControl('')); |
| } |
| |
| public removeEmailControlAt(index: number) { |
| this.toFormArray.removeAt(index); |
| } |
| |
| public navigateToOverview() { |
| return this.router.navigate(['..'], { relativeTo: this.route }); |
| } |
| |
| private initializeForm() { |
| return defer(() => { |
| this.createForm({...this.defaultValue}); |
| this.form.disable(); |
| return combineLatest(this.fetchReport(), this.fetchReportNameOptions(), this.fetchStandByListOptions()); |
| }).pipe( |
| tap(([report, reportNameOptions, standByListOptions]) => { |
| this.reportNameOptions = reportNameOptions.filter((option) => !this.excludedReportNames.includes(option.value)); |
| this.standByListOptions = standByListOptions; |
| this.form.enable(); |
| this.createForm({ |
| ...this.defaultValue, |
| ...report, |
| standByListId: extractValueFromOption( |
| report == null ? this.standByListOptions[0] : findInOptions(report.standByListId, this.standByListOptions) |
| ), |
| reportName: extractValueFromOption( |
| report == null ? this.reportNameOptions[0] : findInOptions(report.reportName, this.reportNameOptions) |
| ) |
| }); |
| }), |
| catchError(() => { |
| this.report = undefined; |
| return EMPTY; |
| }) |
| ); |
| } |
| |
| private fetchReport(): Observable<CyclicReportObject> { |
| return this.route.params.pipe( |
| map((params) => params.id), |
| switchMap((id) => { |
| return id === 'new' ? of(null) : this.cyclicReportingService.getCyclicReports().pipe( |
| map((reports) => { |
| id = parseInt(id, 10); |
| const result = reports.find((entry) => entry.id === id); |
| if (result == null) { |
| throw new Error('Entry not found'); |
| } |
| return result; |
| })); |
| }) |
| ); |
| } |
| |
| private fetchReportNameOptions(): Observable<SelectOptionObject<string>[]> { |
| return this.reportingService.getReportData().pipe( |
| map((data) => data.map((reportObject) => ({ |
| ...reportObject, |
| value: reportObject.reportName, |
| label: reportObject.reportName |
| }))) |
| ); |
| } |
| |
| private fetchStandByListOptions(): Observable<SelectOptionObject<number>[]> { |
| return this.masterdataService.getStandbyListSelection().pipe( |
| map((data) => data.map((reportObject) => ({ |
| ...reportObject, |
| value: reportObject.id, |
| label: reportObject.title |
| }))) |
| ); |
| } |
| |
| private createForm(report: CyclicReportObject) { |
| this.report = report; |
| const to = Array.isArray(report.to) && report.to.length > 0 ? report.to : ['']; |
| this.toFormArray = this.fb.array(to.map((email) => this.createEmailControl(email))); |
| this.form = this.fb.group({...report, to: this.toFormArray}); |
| Object.values(this.form.controls) |
| .forEach((control) => control.setValidators(Validators.required)); |
| this.form.get('id').clearValidators(); |
| this.form.get('emailText').clearValidators(); |
| this.form.get('name').setValidators([Validators.required, Validators.maxLength(256)]); |
| this.form.get('fileNamePattern').setValidators([Validators.required, Validators.maxLength(128)]); |
| this.form.get('subject').setValidators([Validators.required, Validators.maxLength(128)]); |
| this.form.setValidators([CyclicReportValidators.validationDate]); |
| } |
| |
| private createEmailControl(value: string): FormControl { |
| return this.fb.control(value, [Validators.email]); |
| } |
| |
| } |
| |
| function extractValueFromOption<T>(option: SelectOptionObject<T>) { |
| return option == null ? undefined : option.value; |
| } |
| |
| function findInOptions<T>(value: T, options: SelectOptionObject<T>[]) { |
| const selected = options.find((option) => option.value === value); |
| return selected == null ? undefined : selected; |
| } |