| /******************************************************************************** |
| * 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, Inject, OnDestroy, OnInit} from "@angular/core"; |
| import {DomSanitizer, SafeUrl} from "@angular/platform-browser"; |
| import {select, Store} from "@ngrx/store"; |
| import {Observable, of, Subject} from "rxjs"; |
| import {map, switchMap, takeUntil} from "rxjs/operators"; |
| import {IAPIDepartmentTable, URL_TOKEN} from "../../../../core"; |
| import { |
| EErrorCode, |
| fetchDepartmentsSettingsAction, |
| getDepartmentsSettingsSelector, |
| getSettingsLoadingSelector, |
| setErrorAction, |
| submitDepartmentsSettingsAction |
| } from "../../../../store"; |
| import {catchErrorTo} from "../../../../util"; |
| import {parseDepartmentTableFromCsv, reduceDepartmentTableToCsv} from "../util"; |
| |
| @Component({ |
| selector: "app-departments-settings", |
| templateUrl: "./departments-settings.component.html", |
| styleUrls: ["./departments-settings.component.scss"] |
| }) |
| export class DepartmentsSettingsComponent implements OnInit, OnDestroy { |
| |
| public currentConfigFileName = "departments.config.csv"; |
| |
| public loading$ = this.store.pipe(select(getSettingsLoadingSelector)); |
| |
| public searching = false; |
| |
| public currentData$ = this.store.pipe(select(getDepartmentsSettingsSelector)); |
| |
| public currentConfigFile$: Observable<File> = this.currentData$.pipe( |
| switchMap((data) => { |
| return of(data).pipe( |
| map(() => new File([reduceDepartmentTableToCsv(data)], this.currentConfigFileName)), |
| catchErrorTo(null) |
| ); |
| }) |
| ); |
| |
| public currentFileUrl: SafeUrl; |
| |
| public selectedFile: File; |
| |
| public selectedFileData: IAPIDepartmentTable; |
| |
| private currentFileObjectUrl: string; |
| |
| private destroy$ = new Subject(); |
| |
| public constructor(public store: Store, @Inject(URL_TOKEN) public url: typeof URL, public sanitizer: DomSanitizer) { |
| |
| } |
| |
| public ngOnInit() { |
| this.currentConfigFile$.pipe(takeUntil(this.destroy$)).subscribe((file) => this.createObjectURLForCurrentFile(file)); |
| this.currentData$.pipe(takeUntil(this.destroy$)).subscribe(() => this.clearFileSelection()); |
| this.store.dispatch(fetchDepartmentsSettingsAction()); |
| } |
| |
| public ngOnDestroy() { |
| this.destroy$.next(); |
| this.destroy$.complete(); |
| this.revokeObjectUrl(); |
| } |
| |
| public submit(data: IAPIDepartmentTable) { |
| this.store.dispatch(submitDepartmentsSettingsAction({data})); |
| } |
| |
| public async selectFile(file: File) { |
| try { |
| const text = await file.text(); |
| this.selectedFileData = parseDepartmentTableFromCsv(text); |
| this.selectedFile = file; |
| } catch (e) { |
| this.store.dispatch(setErrorAction({error: EErrorCode.INVALID_FILE_FORMAT})); |
| } |
| } |
| |
| public clearFileSelection() { |
| this.selectedFile = null; |
| this.selectedFileData = null; |
| } |
| |
| private createObjectURLForCurrentFile(file: File) { |
| this.revokeObjectUrl(); |
| if (file != null) { |
| this.currentFileObjectUrl = this.url.createObjectURL(file); |
| this.currentFileUrl = this.sanitizer.bypassSecurityTrustUrl(this.currentFileObjectUrl); |
| } |
| } |
| |
| private revokeObjectUrl() { |
| if (this.currentFileObjectUrl != null) { |
| this.url.revokeObjectURL(this.currentFileObjectUrl); |
| this.currentFileObjectUrl = null; |
| this.currentFileUrl = null; |
| } |
| } |
| |
| } |