Commit 4cb386fe authored by Hando Lukats's avatar Hando Lukats
Browse files

Merge branch 'develop' into 'master'

Release: merge 'develop' into 'master' created by Hando Lukats

See merge request teis/public-web-client!595
parents e22739b0 d66b1572
{
"name": "te-is",
"version": "1.20.3",
"version": "1.21.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......
{
"name": "te-is",
"version": "1.20.3",
"version": "1.21.0",
"license": "MIT",
"scripts": {
"ng": "ng",
......
......@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
import { ApiOffice } from '@teis/services/api-office';
import { HttpClient } from '@angular/common/http';
import {
RiskAssessmentPublicDto
RiskAssessmentPublicDto, RiskAssessmentTitleBody, RiskAssessmentViewingReasonBody
} from '@teis/services/risk-assessments/risk-assessments.models';
import { Observable } from 'rxjs';
import { CreateRiskAssessmentBody } from '@official/api-services/risk-assessments/risk-assessments-office.model';
......@@ -20,4 +20,14 @@ export class RiskAssessmentsOfficeApiService extends ApiOffice {
const url = `${this.baseUrl}/risk-assessments`;
return this.http.post<RiskAssessmentPublicDto>(url, body);
}
updateRiskAssessmentTitle(riskAssessmentId: string, body: RiskAssessmentTitleBody): Observable<RiskAssessmentPublicDto> {
const url = `${this.baseUrl}/risk-assessments/${riskAssessmentId}/title`;
return this.http.patch<RiskAssessmentPublicDto>(url, body);
}
sendRiskAssessmentViewingReason(riskAssessmentId: string, body: RiskAssessmentViewingReasonBody): Observable<any> {
const url = `${this.baseUrl}/risk-assessments/${riskAssessmentId}/viewing-reason`;
return this.http.post(url, body);
}
}
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { concatMap, map } from 'rxjs/operators';
import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
import { concatMap, map, switchMap } from 'rxjs/operators';
import { BreadcrumbsService } from '@teis/modules/breadcrumbs/services/breadcrumbs.service';
import { ModalService } from '@teis/modules/modal/modal.service';
import { PersonDto } from '@teis/services/person/persons.models';
......@@ -10,13 +10,20 @@ import { AuthenticationService } from '@teis/services/authentication/authenticat
import { LocationService } from '@teis/services/location/location.service';
import { LegalPersonsParams } from '@teis/services/legal-person/legal-person.models';
import { RiskAssessmentsApiService } from '@teis/services/risk-assessments/risk-assessments-api.service';
import { RiskAssessmentPublicDto, RiskAssessmentStatus } from '@teis/services/risk-assessments/risk-assessments.models';
import {
RiskAssessmentPublicDto,
RiskAssessmentStatus,
RiskAssessmentTitleBody
} from '@teis/services/risk-assessments/risk-assessments.models';
import { FileReferenceDto } from '@teis/services/file/file.model';
import { FileService } from '@teis/services/file/file.service';
import { RiskAssessmentsOfficeApiService } from '@official/api-services/risk-assessments/risk-assessments-office-api.service';
import { CreateRiskAssessmentBody } from '@official/api-services/risk-assessments/risk-assessments-office.model';
import { EmployerIdParam } from '@teis/services/proceedings/proceedings.model';
import { ProceedingsApi } from '@teis/services/proceedings/proceedings.api.service';
import { ConfirmationOptions } from '@teis/modules/modal/confirmation/confirmation.component';
import { TranslateService } from '@ngx-translate/core';
import { MessageContext } from '@ska-angular/core';
@Injectable()
export class CompanyDetailsFacade {
......@@ -37,6 +44,8 @@ export class CompanyDetailsFacade {
private riskAssessmentsApi: RiskAssessmentsApiService,
private fileService: FileService,
private proceedingsApi: ProceedingsApi,
private translate: TranslateService,
private message: MessageContext,
private riskAssessmentsOfficialApi: RiskAssessmentsOfficeApiService,
) { }
......@@ -73,7 +82,7 @@ export class CompanyDetailsFacade {
this.legalPersonDetails$.next(value);
}
getCompanyDetails(regCode: string, name: string) {
getCompanyDetails(regCode: string, name?: string) {
const params: LegalPersonsParams = { regCode };
if (name) params.name = name;
this.loading$.next(true);
......@@ -125,13 +134,7 @@ export class CompanyDetailsFacade {
this.breadcrumbsService.setDynamicBreadcrumbs({
companyDetail: legalPerson,
});
this.breadcrumbsService.setCustomBreadcrumbs([
{
position: 4,
url: '',
label: riskAssessment.title,
},
]);
this.changeRiskAssessmentTitleOnBreadcrumbs(riskAssessment);
});
}
......@@ -168,4 +171,45 @@ export class CompanyDetailsFacade {
})
);
}
deleteRiskAssessmentFile(file: FileReferenceDto) {
const fileDeletionConfirmationOptions: ConfirmationOptions = {
title: 'delete_files_confirm',
question: this.translate.instant('delete_file_name_question', { fileName: file.fileName })
};
const riskAssessmentId = file.objectId;
this.modal.confirmDelete(fileDeletionConfirmationOptions)
.pipe(
switchMap((confirm) => {
if (confirm) {
return this.fileService.deleteFile(riskAssessmentId, file.fileId, 'risk-assessments');
}
this.closeModal();
return of('cancelled');
}),
).subscribe((result) => {
this.fetchRiskAssessmentFileReferences(riskAssessmentId);
if (result !== 'cancelled') this.message.addToastSuccess(this.translate.instant('file_deleted_successfully'), 3000);
this.closeModal();
});
}
saveRiskAssessmentTitle(riskAssessmentId: string, title: string) {
const body: RiskAssessmentTitleBody = { title };
this.riskAssessmentsOfficialApi.updateRiskAssessmentTitle(riskAssessmentId, body)
.subscribe((riskAssessment) => {
this.currentRiskAssessment$.next(riskAssessment);
this.changeRiskAssessmentTitleOnBreadcrumbs(riskAssessment);
});
}
private changeRiskAssessmentTitleOnBreadcrumbs(riskAssessment: RiskAssessmentPublicDto) {
this.breadcrumbsService.setCustomBreadcrumbs([
{
position: 4,
url: '',
label: riskAssessment.title,
},
]);
}
}
......@@ -14,9 +14,9 @@ import { ProceedingsApi } from '@teis/services/proceedings/proceedings.api.servi
import { RepresentativesModule } from '@teis/features/representatives/representatives.module';
import { LocationsModule } from '@teis/features/locations';
import { AssignmentsComponent } from './containers/assignments/assignments.component';
import { RiskAssessmentsComponent } from './containers/risk-assessments/risk-assessments.component';
import { RiskAssessmentFilesComponent } from './containers/risk-assessment-files/risk-assessment-files.component';
import { RiskAssessmentAddDocumentsComponent } from './containers/risk-assessment-add-documents/risk-assessment-add-documents.component';
import { RiskAssessmentsListComponent } from '@official/features/company-details/containers/risk-assessment/risk-assessments-list/risk-assessments-list.component';
import { RiskAssessmentFilesComponent } from '@official/features/company-details/containers/risk-assessment/risk-assessment-files/risk-assessment-files.component';
import { RiskAssessmentAddDocumentsComponent } from '@official/features/company-details/containers/risk-assessment/risk-assessment-add-documents/risk-assessment-add-documents.component';
import { RiskAssessmentsOfficeApiService } from '@official/api-services/risk-assessments/risk-assessments-office-api.service';
@NgModule({
......@@ -26,7 +26,7 @@ import { RiskAssessmentsOfficeApiService } from '@official/api-services/risk-ass
CompanyRepresentativesComponent,
CompanyProceedingsComponent,
AssignmentsComponent,
RiskAssessmentsComponent,
RiskAssessmentsListComponent,
RiskAssessmentFilesComponent,
RiskAssessmentAddDocumentsComponent,
],
......
......@@ -31,13 +31,13 @@ export class CompanyDetailsComponent extends TabContainer implements OnInit {
public router: Router,
private companyDetailsFacade: CompanyDetailsFacade,
private translate: TranslateService,
private autorization: AuthorizationService,
private authorization: AuthorizationService,
) {
super(route, router);
}
ngOnInit() {
this.hasLocationPermission = this.autorization.hasViewPermission(['TI_VIEW_LOCATIONS']);
this.hasLocationPermission = this.authorization.hasViewPermission(['TI_VIEW_LOCATIONS']);
const companyRegCode: string = this.route.snapshot.paramMap.get('regCode');
const companyName: string = this.route.snapshot.queryParams.companyName;
this.companyDetailsFacade.getCompanyDetails(companyRegCode, companyName);
......
import { Component, OnDestroy, OnInit } from '@angular/core';
import { BehaviorSubject, of, Subject, Subscription } from 'rxjs';
import { EntityFile } from '@teis/modules/files/entity-file';
import { TranslateService } from '@ngx-translate/core';
import * as moment from 'moment';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { CompanyDetailsFacade } from '@official/features/company-details/company-details.facade.service';
import { catchError, skip } from 'rxjs/operators';
import { HttpErrorResponse } from '@angular/common/http';
import { RiskAssessmentPublicDto } from '@teis/services/risk-assessments/risk-assessments.models';
import { removeArrayItem } from '@teis/utils';
import { MessageContext } from '@ska-angular/core';
@Component({
selector: 'teis-risk-assessment-add-documents',
templateUrl: './risk-assessment-add-documents.component.html',
styleUrls: ['./risk-assessment-add-documents.component.scss']
})
export class RiskAssessmentAddDocumentsComponent implements OnInit, OnDestroy {
readonly referencePath = 'risk-assessments';
employerId: string;
objectId$ = new Subject<string>();
defaultTitle: string;
form: FormGroup;
noFiles: boolean;
saving = false;
private selectedFiles: EntityFile[];
private isSomeFileUploading$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(null);
private subscriptions$: Subscription[] = [];
constructor(
private translate: TranslateService,
private facade: CompanyDetailsFacade,
private message: MessageContext,
) { }
ngOnInit(): void {
this.defaultTitle = this.setDefaultTitle();
this.form = new FormGroup({
title: new FormControl(this.defaultTitle, Validators.required)
});
}
ngOnDestroy() {
this.subscriptions$.forEach(subscription => subscription.unsubscribe());
}
private setDefaultTitle(): string {
const currentDate = moment().format('DD.MM.YYYY');
const text = this.translate.instant('default_risk_assessment_header');
return `${currentDate} ${text}`;
}
filesSelectedHandler(files: EntityFile[]) {
this.selectedFiles = files;
this.noFiles = false;
}
saveRiskAssessment() {
const hasAtLeastOneFile = this.selectedFiles?.length > 0;
if (this.form.valid && hasAtLeastOneFile) {
const title = this.form.controls.title.value;
this.saving = true;
const createRiskAssessment$ = this.facade.createRiskAssessment(this.employerId, title)
.pipe(
catchError((error) => {
this.saving = false;
return of(error);
}),
)
.subscribe((riskAssessment) => {
if (!(riskAssessment instanceof HttpErrorResponse)) {
this.objectId$.next(riskAssessment?.id);
}
});
const filesUploading$ = this.isSomeFileUploading$.asObservable()
.pipe(skip(1))
.subscribe((uploading) => {
if (!uploading) {
this.saving = false;
this.facade.closeModal();
this.message.addToastSuccess('risk_assessment_saved', 3000);}
});
this.subscriptions$ = [createRiskAssessment$, filesUploading$];
} else {
this.noFiles = true;
}
}
cancel() {
this.facade.closeModal();
}
fileRemoved(file: EntityFile) {
this.selectedFiles = removeArrayItem(file, 'localId', [...this.selectedFiles]);
}
handleLoading(isLoading: boolean) {
this.isSomeFileUploading$.next(isLoading);
}
}
<teis-modal title="{{ 'add_risk_assessment_documents' | translate }}">
<teis-modal
title="{{ modalTitle | translate }}"
[icon]="modalIcon">
<form [formGroup]="form" (ngSubmit)="saveRiskAssessment()">
<form-row label="{{ 'risk_assessment_header' | translate }}" comment="{{ 'required' | translate }}">
<form-row
*ngIf="!riskAssessment || currentTitle?.length"
label="{{ 'risk_assessment_header' | translate }}"
comment="{{ 'required' | translate }}">
<ska-input
type="text"
[required]="true"
formControlName="title"></ska-input>
</form-row>
<form-row label="{{ 'files' | translate }}" comment="{{ 'required' | translate }}">
<form-row
*ngIf="!currentTitle?.length"
label="{{ 'files' | translate }}"
comment="{{ 'required' | translate }}">
<tehik-file-manager
[dropzone]="true"
[canDelete]="true"
......@@ -15,18 +23,24 @@
[objectId]="objectId$"
[maxFiles]="20"
[showNoFilesAlert]="noFiles"
[addUploadedFiles]="false"
[fileDeletionConfirmation]="false"
[fileManagerOptions]="{ showMaxFilesMessage: false, displayedExtensionsLimit: 10 }"
(loading)="handleLoading($event)"
(filesSelected)="filesSelectedHandler($event)"
(fileDeleted)="fileRemoved($event)">
(fileDeleted)="fileRemoved($event)"
(fileUploadError)="fileUploadError($event)">
</tehik-file-manager>
</form-row>
<teis-flex>
<form-button-with-confirmation
id="formCancel"
[customIsDirtyFn]="cancelConfirmation()"
[form]="form"
[buttonBackLabel]="'cancel' | translate "
[title]="currentTitle?.length ? ('cancel_risk_assessment_title_edit' | translate) : ('cancel_risk_assessment_uploading' | translate)"
[content]="'unsaved_data_in_form' | translate"
(confirm)="cancel()">
</form-button-with-confirmation>
<button
......
import { Component, OnDestroy, OnInit } from '@angular/core';
import { BehaviorSubject, of, Subject, Subscription } from 'rxjs';
import { EntityFile } from '@teis/modules/files/entity-file';
import { TranslateService } from '@ngx-translate/core';
import * as moment from 'moment';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { CompanyDetailsFacade } from '@official/features/company-details/company-details.facade.service';
import { catchError, skip } from 'rxjs/operators';
import { HttpErrorResponse } from '@angular/common/http';
import { RiskAssessmentPublicDto } from '@teis/services/risk-assessments/risk-assessments.models';
import { removeArrayItem } from '@teis/utils';
import { MessageContext } from '@ska-angular/core';
@Component({
selector: 'teis-risk-assessment-add-documents',
templateUrl: './risk-assessment-add-documents.component.html',
styleUrls: ['./risk-assessment-add-documents.component.scss']
})
export class RiskAssessmentAddDocumentsComponent implements OnInit, OnDestroy {
readonly referencePath = 'risk-assessments';
employerId: string;
riskAssessment: RiskAssessmentPublicDto;
objectId$ = new Subject<string>();
defaultTitle: string;
currentTitle: string;
form: FormGroup = new FormGroup({});
noFiles: boolean;
saving = false;
selectedFiles: EntityFile[];
modalTitle = 'add_risk_assessment_documents';
modalIcon = 'icon-edit';
private isSomeFileUploading$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(null);
private subscriptions$: Subscription[] = [];
constructor(
private translate: TranslateService,
private facade: CompanyDetailsFacade,
private message: MessageContext,
) { }
ngOnInit(): void {
if (this.currentTitle) {
this.modalTitle = 'edit_risk_assessment_title';
this.form.addControl('title', new FormControl(this.currentTitle, Validators.required));
} else if (this.riskAssessment) {
this.modalIcon = 'icon-add';
this.objectId$.next(this.riskAssessment?.id);
} else {
this.modalIcon = 'icon-add';
this.defaultTitle = this.setDefaultTitle();
this.form.addControl('title', new FormControl(this.defaultTitle, Validators.required));
}
}
ngOnDestroy() {
this.subscriptions$.forEach(subscription => subscription.unsubscribe());
}
private setDefaultTitle(): string {
const currentDate = moment().format('DD.MM.YYYY');
const text = this.translate.instant('default_risk_assessment_header');
return `${currentDate} ${text}`;
}
filesSelectedHandler(files: EntityFile[]) {
this.selectedFiles = files;
this.noFiles = false;
}
saveRiskAssessment() {
const hasAtLeastOneFile = this.selectedFiles?.length > 0;
if (this.currentTitle?.length && this.form.valid) {
const newTitle = this.form.controls.title.value;
this.saveRiskAssessmentTitle(newTitle);
} else if (!this.riskAssessment && this.form.valid && hasAtLeastOneFile) {
this.addNewRiskAssessment();
} else if (this.riskAssessment && hasAtLeastOneFile) {
this.updateRiskAssessment();
} else {
this.noFiles = true;
}
}
private addNewRiskAssessment() {
const title = this.form.controls.title.value;
this.saving = true;
const createRiskAssessment$ = this.facade.createRiskAssessment(this.employerId, title)
.pipe(
catchError((error) => {
this.saving = false;
return of(error);
}),
)
.subscribe((riskAssessment) => {
if (!(riskAssessment instanceof HttpErrorResponse)) {
this.objectId$.next(riskAssessment?.id);
}
});
const filesUploading$ = this.isSomeFileUploading$.asObservable()
.pipe(skip(1))
.subscribe((uploading) => {
if (!uploading) {
this.saving = false;
this.facade.closeModal();
this.message.addToastSuccess('risk_assessment_saved', 3000);}
});
this.subscriptions$ = [createRiskAssessment$, filesUploading$];
}
cancel() {
this.facade.closeModal();
}
fileRemoved(file: EntityFile) {
this.selectedFiles = removeArrayItem(file, 'localId', [...this.selectedFiles]);
}
handleLoading(isLoading: boolean) {
this.isSomeFileUploading$.next(isLoading);
}
private updateRiskAssessment() {
this.saving = true;
this.objectId$.next(this.riskAssessment?.id);
const filesUploading$ = this.isSomeFileUploading$.asObservable()
.pipe(skip(1))
.subscribe((uploading) => {
if (!uploading) {
this.saving = false;
this.facade.fetchRiskAssessmentFileReferences(this.riskAssessment.id);
this.message.addToastSuccess('risk_assessment_files_added', 3000);
this.facade.closeModal();
}
});
this.subscriptions$ = [filesUploading$];
}
fileUploadError(error: HttpErrorResponse) {
this.saving = false;
this.facade.closeModal();
this.message.addToastError(this.translate.instant('risk_assessment_file_upload_error'));
if (this.riskAssessment) this.facade.fetchRiskAssessmentFileReferences(this.riskAssessment?.id);
}
private saveRiskAssessmentTitle(currentTitle: string) {
this.facade.saveRiskAssessmentTitle(this.riskAssessment.id, currentTitle);
this.facade.closeModal();
this.message.addToastSuccess('risk_assessment_title_changed', 3000);
}
cancelConfirmation(): boolean {
if (this.currentTitle?.length) {
const newTitle = this.form.controls.title.value;
return this.currentTitle !== newTitle;
}
return !!this.selectedFiles?.length;
}
}
<div id="riskAssessmentInfo" class="risk-assessment-info" *ngIf="riskAssessment">
<teis-header [title]="riskAssessment?.title"></teis-header>
<div id="riskAssessmentInfo" class="risk-assessment-info" *ngIf="showView && riskAssessment">
<teis-header [title]="riskAssessment?.title">
<teis-icon
*ngIf="riskAssessment.uploadedByOfficial && hasUploadRiskAssessmentPrivilege"
subtitle
(click)="editTitle()"
[clickable]="true"
color="blue"
icon="icon-edit"></teis-icon>
</teis-header>
<block>
<div class="mb-4">
<teis-header
title="{{ 'general' | translate }}"
variant="block"></teis-header>
variant="block">
<span *ngIf="riskAssessment.uploadedByOfficial">
<button *canView="['TI_UPLOAD_RISK_ASSESSMENTS']" teis-button (click)="uploadDocuments()">
<i class="icon-upload"></i>
{{ 'upload_files' | translate }}
</button>
</span>