Commit 46f3d24e authored by Pearu Sarv's avatar Pearu Sarv
Browse files

Merge branch 'develop' into 'master'

Release: merge 'develop' into 'master' created by Pearu Sarv

See merge request teis/public-web-client!737
parents bf602fa8 57288cc4
......@@ -28,6 +28,11 @@
"glob": "**/*",
"input": "node_modules/@ska-angular/assets/assets",
"output": "/assets/"
},
{
"glob": "import-map.json",
"input": "projects/official/src/import-map/production",
"output": "/assets/"
}
],
"styles": [
......@@ -76,6 +81,19 @@
]
},
"local": {
"assets": [
"projects/official/src/assets",
{
"glob": "**/*",
"input": "node_modules/@ska-angular/assets/assets",
"output": "/assets/"
},
{
"glob": "import-map.json",
"input": "projects/official/src/import-map/local",
"output": "/assets/"
}
],
"fileReplacements": [
{
"replace": "projects/official/src/environments/environment.ts",
......@@ -162,6 +180,11 @@
"glob": "**/*",
"input": "node_modules/@ska-angular/assets/assets",
"output": "/assets/"
},
{
"glob": "import-map.json",
"input": "projects/public/src/import-map/production",
"output": "/assets/"
}
],
"styles": [
......@@ -205,6 +228,21 @@
]
},
"local": {
"assets": [
"projects/public/src/api",
"projects/public/src/assets",
"projects/public/src/.htaccess",
{
"glob": "**/*",
"input": "node_modules/@ska-angular/assets/assets",
"output": "/assets/"
},
{
"glob": "import-map.json",
"input": "projects/public/src/import-map/local",
"output": "/assets/"
}
],
"fileReplacements": [
{
"replace": "projects/public/src/environments/environment.ts",
......
{
"name": "te-is",
"version": "1.31.3",
"version": "1.32.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......
{
"name": "te-is",
"version": "1.31.3",
"version": "1.32.0",
"license": "MIT",
"scripts": {
"ng": "ng",
......
......@@ -5,7 +5,6 @@ import { SkaAttachment } from '@ska-angular/common';
import { MessageContext } from '@ska-angular/core';
import { DriversInspectionsFacade } from '@teis/features/drivers-inspections/drivers-inspections-facade.service';
import { ModalService } from '@teis/widgets/teis-modal/modal.service';
import { Subject } from 'rxjs';
@Component({
selector: 'add-file',
......@@ -20,7 +19,6 @@ export class AddFileComponent {
form = this.fb.group({
file: []
});
private destroy$ = new Subject<boolean>();
uploadError: string = '';
onFileUpload(files: SkaAttachment[]) {
......@@ -47,10 +45,4 @@ export class AddFileComponent {
cancel() {
this.modal.close();
}
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.complete();
}
}
<teis-modal
[icon]="numberOfInspectedItems ? 'icon-edit' : 'icon-add'"
[title]="numberOfInspectedItems ? 'edit_number_of_inspected_items_' + numberOfInspectedItems.item : ('add_number_of_inspected_items_' + item | translate)"
>
<teis-form-layout [colsize]="18">
<form-row *ngFor="let numbersFormItem of numbersForm.controls | keyvalue: keepOrder" [label]="numbersFormItem.key | translate">
<ska-number min="0" max="999999999" [formControl]="numbersFormItem.value" [name]="numbersFormItem.key" required pattern="\d+"></ska-number>
</form-row>
<div *ngIf="numbersForm.errors" class="pb-2">
<teis-alert *ngFor="let error of numbersForm.errors | keyvalue" class="mb-2" variant="danger" [closeable]="false" [message]="(error.key | translate) + error.value"> </teis-alert>
</div>
<teis-flex>
<button teis-button variant="secondary" (click)="cancel()">
{{ 'abandon' | translate }}
</button>
<button teis-button (click)="save()">
{{ 'save' | translate }}
</button>
</teis-flex>
</teis-form-layout>
</teis-modal>
import { Component, Input, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { DriversInspectionsFacade } from '@teis/features/drivers-inspections/drivers-inspections-facade.service';
import { InspectedItem, NumberOfInspectedItemsDto, CreateOrEditNumberOfInspectedItemsDto, DriversInspectionType } from '@teis/features/drivers-inspections/services/drivers-inspections.model';
import { triggerValidation } from '@teis/utils';
import { ModalService } from '@teis/widgets/teis-modal/modal.service';
import { Subject } from 'rxjs';
import { numberOfInspectedItemsSumsValidator } from './number-of-inspected-items.validator';
@Component({
selector: 'teis-add-or-edit-number-of-inspected-items',
templateUrl: './add-or-edit-number-of-inspected-items.component.html',
styleUrls: ['./add-or-edit-number-of-inspected-items.component.scss'],
})
export class AddOrEditNumberOfInspectedItemsComponent implements OnInit {
constructor(private fb: FormBuilder, private modal: ModalService, private facade: DriversInspectionsFacade) {}
@Input() numberOfInspectedItems: NumberOfInspectedItemsDto;
@Input() item: InspectedItem;
@Input() inspectionType: DriversInspectionType;
private destroy$ = new Subject<boolean>();
numbersForm: FormGroup;
keepOrder = () => 0;
ngOnInit(): void {
this.initializeForm();
}
private initializeForm() {
this.numbersForm = this.fb.group(
{
generallyWithoutM: [this.numberOfInspectedItems?.generallyWithoutM ?? 0],
...(this.inspectionType === DriversInspectionType.GOODS
? { goodsAM: [this.numberOfInspectedItems?.goodsAM ?? 0], goodsDM: [this.numberOfInspectedItems?.goodsDM ?? 0], goodsSM: [this.numberOfInspectedItems?.goodsSM ?? 0] }
: {
passengersAM: [this.numberOfInspectedItems?.passengersAM ?? 0],
passengersDM: [this.numberOfInspectedItems?.passengersDM ?? 0],
passengersSM: [this.numberOfInspectedItems?.passengersSM ?? 0],
}),
earningAM: [this.numberOfInspectedItems?.earningAM ?? 0],
earningDM: [this.numberOfInspectedItems?.earningDM ?? 0],
earningSM: [this.numberOfInspectedItems?.earningDM ?? 0],
ownPurposesAM: [this.numberOfInspectedItems?.ownPurposesAM ?? 0],
ownPurposesDM: [this.numberOfInspectedItems?.ownPurposesDM ?? 0],
ownPurposesSM: [this.numberOfInspectedItems?.ownPurposesDM ?? 0],
},
{
validators: [numberOfInspectedItemsSumsValidator(this.inspectionType)],
}
);
}
cancel() {
this.modal.close();
}
getNumberOfInspectedItemsDto = (): CreateOrEditNumberOfInspectedItemsDto => {
const formValue = this.numbersForm.value;
const { earningAM, ownPurposesAM, earningDM, ownPurposesDM, earningSM, ownPurposesSM, passengersAM, passengersDM, passengersSM, goodsAM, goodsDM, goodsSM } = formValue;
const generallyAM = earningAM + ownPurposesAM;
const generallyDM = earningDM + ownPurposesDM;
const generallySM = earningSM + ownPurposesSM;
return {
...formValue,
generallyAM,
generallyDM,
generallySM,
goodsAM: goodsAM ?? 0,
goodsDM: goodsDM ?? 0,
goodsSM: goodsSM ?? 0,
passengersAM: passengersAM ?? 0,
passengersDM: passengersDM ?? 0,
passengersSM: passengersSM ?? 0,
unspecifiedAM: 0,
unspecifiedDM: 0,
unspecifiedSM: 0,
item: this.item ? this.item : this.numberOfInspectedItems.item,
};
}
save() {
triggerValidation(this.numbersForm);
this.numbersForm.updateValueAndValidity();
if (this.numbersForm.invalid) {
return;
}
const numberOfInspectedItems: CreateOrEditNumberOfInspectedItemsDto = this.getNumberOfInspectedItemsDto();
if (this.numberOfInspectedItems) {
this.facade.putNumberOfInspectedItems(this.numberOfInspectedItems.id, numberOfInspectedItems);
} else {
this.facade.postNumberOfInspectedItems(numberOfInspectedItems);
}
}
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.complete();
}
}
import { FormGroup, ValidationErrors } from '@angular/forms';
import { DriversInspectionType } from '@teis/features/drivers-inspections/services/drivers-inspections.model';
const sumsMatch = (group: FormGroup, type: 'AM' | 'DM' | 'SM'): boolean => {
const goodsValue = group.value[`goods${type}`] ?? 0;
const passengersValue = group.value[`passengers${type}`] ?? 0;
const earningValue = group.value[`earning${type}`];
const ownPurposesValue = group.value[`ownPurposes${type}`];
return goodsValue + passengersValue === earningValue + ownPurposesValue;
};
const isValidForType = (group: FormGroup, type: 'AM' | 'DM' | 'SM') => {
const goodsControl = group.get(`goods${type}`);
const passengersControl = group.get(`passengers${type}`);
const earningControl = group.get(`earning${type}`);
const ownPurposesControl = group.get(`ownPurposes${type}`);
if ((!goodsControl || goodsControl.dirty) && (!passengersControl || passengersControl.dirty) && earningControl.dirty && ownPurposesControl.dirty) {
if (!sumsMatch(group, type)) {
return false;
}
}
return true;
};
export const numberOfInspectedItemsSumsValidator = (inspectionType: DriversInspectionType) => {
return (group: FormGroup): ValidationErrors | null => {
const invalidSums = [];
if (!isValidForType(group, 'AM')) {
invalidSums.push('AM');
}
if (!isValidForType(group, 'DM')) {
invalidSums.push('DM');
}
if (!isValidForType(group, 'SM')) {
invalidSums.push('NM');
}
if (invalidSums.length) {
return { [`sum_error_${inspectionType}`]: `(${invalidSums.join(', ')})` };
}
return null;
};
};
<teis-modal [title]="'edit_data' | translate" icon="icon-edit" [loading]="!form">
<teis-form-layout [colsize]="20">
<form [formGroup]="form" (ngSubmit)="submit()" *ngIf="form">
<div class="mb-4">
<form-row [label]="'controlled_period_start' | translate" [comment]="'required' | translate" labelClass="text-left justify-start col-xs-20 col-md-5" contentClass="col-xs-20 col-md-12">
<ska-datepicker class="flex-grow-1 mr-2" formControlName="controlledPeriodBeginning"> </ska-datepicker>
</form-row>
<form-row [label]="'controlled_period_end' | translate" [comment]="'required' | translate" labelClass="text-left justify-start col-xs-20 col-md-5" contentClass="col-xs-20 col-md-12">
<ska-datepicker class="flex-grow-1 mr-2" formControlName="controlledPeriodEnd"> </ska-datepicker>
</form-row>
<form-row [label]="'inspection_type' | translate" [comment]="'required' | translate" labelClass="text-left justify-start col-xs-20 col-md-5" contentClass="col-xs-20 col-md-12">
<ska-select formControlName="inspectionType" [data]="inspectionTypes" [displayFunc]="classifierDisplayFunc"></ska-select>
</form-row>
<form-row [label]="'number_of_vehicles' | translate" [comment]="'required' | translate" labelClass="text-left justify-start col-xs-20 col-md-5" contentClass="col-xs-20 col-md-12">
<ska-number min="0" max="999999999" formControlName="numberOfVehicles" [name]="'number_of_vehicles' | translate" required pattern="\d+"></ska-number>
</form-row>
<form-row [label]="'number_of_drivers' | translate" [comment]="'required' | translate" labelClass="text-left justify-start col-xs-20 col-md-5" contentClass="col-xs-20 col-md-12">
<ska-number min="0" max="999999999" formControlName="numberOfDrivers" [name]="'number_of_drivers' | translate" required pattern="\d+"></ska-number>
</form-row>
</div>
<teis-flex>
<form-button-with-confirmation [form]="form" [buttonBackLabel]="'abandon' | translate" (confirm)="cancel()"> </form-button-with-confirmation>
<button teis-button teis-submitting type="submit">
{{ 'save' | translate }}
</button>
</teis-flex>
</form>
</teis-form-layout>
</teis-modal>
\ No newline at end of file
import { Component, Input, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { DriversInspectionsFacade } from '@teis/features/drivers-inspections/drivers-inspections-facade.service';
import { DriversInspectionInspectedItemsDto } from '@teis/features/drivers-inspections/services/drivers-inspections.model';
import { ClassifiersApi } from '@teis/services/classifiers/classifiers.api.service';
import { ClassifierItemDefinitionId, ClassifierItemDto } from '@teis/services/classifiers/classifiers.models';
import { triggerValidation } from '@teis/utils';
import { ModalService } from '@teis/widgets/teis-modal/modal.service';
@Component({
selector: 'teis-edit-inspection-data',
templateUrl: './edit-inspection-data.component.html',
styleUrls: ['./edit-inspection-data.component.scss']
})
export class EditInspectionDataComponent implements OnInit {
constructor(private fb: FormBuilder, private classifiersApi: ClassifiersApi, private modal: ModalService, private facade: DriversInspectionsFacade) { }
@Input() inspectionData: DriversInspectionInspectedItemsDto;
form: FormGroup;
inspectionTypes: ClassifierItemDto[] = [];
classifierDisplayFunc = (item: ClassifierItemDto) => item.name;
ngOnInit(): void {
this.classifiersApi.fetchClassifierItems({ definitionId: ClassifierItemDefinitionId.DriversInspectionType }).subscribe((inspectionTypes: ClassifierItemDto[]) => {
this.inspectionTypes = inspectionTypes;
this.initializeForm(inspectionTypes);
});
}
initializeForm(inspectionTypes: ClassifierItemDto[]): void {
const inspectionTypeValue = inspectionTypes.find(inspectionType => inspectionType.id === this.inspectionData.inspectionType?.id);
this.form = this.fb.group({
controlledPeriodBeginning: [this.inspectionData.controlledPeriodBeginning],
controlledPeriodEnd: [this.inspectionData.controlledPeriodEnd],
numberOfDrivers: [this.inspectionData.numberOfDrivers],
numberOfVehicles: [this.inspectionData.numberOfVehicles],
inspectionType: [inspectionTypeValue],
});
}
cancel(): void {
this.modal.close();
}
submit(): void {
triggerValidation(this.form);
if (this.form.valid) {
this.facade.editDriversInspectionData(this.form.value);
}
}
}
<teis-modal [title]="'edit_data' | translate" icon="icon-edit" [loading]="!form">
<teis-form-layout [colsize]="20">
<form [formGroup]="form" (ngSubmit)="submit()" *ngIf="form">
<div class="mb-4">
<form-row [label]="'convicted_person' | translate" labelClass="text-left justify-start col-xs-20 col-md-5" contentClass="col-xs-20 col-md-12">
<div class="d-flex flex-column justify-content-around">
<div class="custom-control custom-radio">
<input
class="custom-control-input"
type="radio"
id="radio-{{convictedPersonType.EmployerUnderProceedings}}"
[value]="convictedPersonType.EmployerUnderProceedings"
formControlName="convictedPersonType"
/>
<label class="custom-control-label" for="radio-{{convictedPersonType.EmployerUnderProceedings}}">{{ convictedPersonType.EmployerUnderProceedings | translate }}</label>
</div>
<div class="custom-control custom-radio">
<input
class="custom-control-input"
type="radio"
id="radio-{{convictedPersonType.NaturalPerson}}"
[value]="convictedPersonType.NaturalPerson"
formControlName="convictedPersonType"
/>
<label class="custom-control-label" for="radio-{{convictedPersonType.NaturalPerson}}">{{ convictedPersonType.NaturalPerson | translate }}</label>
</div>
</div>
</form-row>
<form-row [label]="'misdemeanor_ref_number' | translate" [comment]="'required' | translate" labelClass="text-left justify-start col-xs-20 col-md-5" contentClass="col-xs-20 col-md-12">
<ska-input type="text" formControlName="misdemeanorRefNumber" minlength="12" maxlength="12"></ska-input>
</form-row>
<ng-container *ngIf="form.value.convictedPersonType === convictedPersonType.NaturalPerson">
<form-row [label]="'name' | translate" [comment]="'required' | translate" labelClass="text-left justify-start col-xs-20 col-md-5" contentClass="col-xs-20 col-md-12">
<ska-input type="text" [required]="true" formControlName="convictedPersonName"></ska-input>
</form-row>
<form-row [label]="'id_code' | translate" [comment]="'required' | translate" labelClass="text-left justify-start col-xs-20 col-md-5" contentClass="col-xs-20 col-md-12">
<ska-input type="text" [required]="true" formControlName="convictedPersonCode" minlength="11" maxlength="11"></ska-input>
</form-row>
</ng-container>
</div>
<teis-flex>
<form-button-with-confirmation [form]="form" [buttonBackLabel]="'abandon' | translate" (confirm)="cancel()"> </form-button-with-confirmation>
<button teis-button teis-submitting type="submit">
{{ 'save' | translate }}
</button>
</teis-flex>
</form>
</teis-form-layout>
</teis-modal>
\ No newline at end of file
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { DriversInspectionsFacade } from '@teis/features/drivers-inspections/drivers-inspections-facade.service';
import { EditMisdemeanorDataDto } from '@teis/features/drivers-inspections/services/drivers-inspections.model';
import { triggerValidation } from '@teis/utils';
import { ModalService } from '@teis/widgets/teis-modal/modal.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
enum ConvictedPersonType {
NaturalPerson = 'natural_person',
EmployerUnderProceedings = 'employer_under_proceedings'
}
@Component({
selector: 'teis-edit-misdemeanor-data',
templateUrl: './edit-misdemeanor-data.component.html',
styleUrls: ['./edit-misdemeanor-data.component.scss']
})
export class EditMisdemeanorDataComponent implements OnInit, OnDestroy {
constructor(private fb: FormBuilder, private modal: ModalService, private facade: DriversInspectionsFacade) { }
@Input() misdemeanorData: EditMisdemeanorDataDto;
readonly convictedPersonType = ConvictedPersonType;
private destroy$ = new Subject<boolean>();
form: FormGroup;
ngOnInit(): void {
this.initializeForm();
this.onConvictedPersonTypeChange();
}
initializeForm(): void {
const convictedPersonType = this.misdemeanorData.convictedPersonCode ? ConvictedPersonType.NaturalPerson : ConvictedPersonType.EmployerUnderProceedings;
this.form = this.fb.group({
convictedPersonType: [convictedPersonType],
convictedPersonCode: [this.misdemeanorData.convictedPersonCode],
convictedPersonName: [this.misdemeanorData.convictedPersonName],
misdemeanorRefNumber: [this.misdemeanorData.misdemeanorRefNumber],
});
}
onConvictedPersonTypeChange(): void {
this.form.get('convictedPersonType').valueChanges.pipe(takeUntil(this.destroy$)).subscribe((convictedPersonType: ConvictedPersonType) => {
const codeControl = this.form.get('convictedPersonCode');
const nameControl = this.form.get('convictedPersonName');
if (convictedPersonType === ConvictedPersonType.EmployerUnderProceedings) {
codeControl.clearValidators();
codeControl.reset();
codeControl.markAsPristine();
nameControl.clearValidators();
nameControl.reset();
nameControl.markAsPristine();
}
});
}
cancel(): void {
this.modal.close();
}
submit(): void {
this.form.updateValueAndValidity();
triggerValidation(this.form);
if (this.form.valid) {
const formValue = this.form.value;
const misdemeanorData: EditMisdemeanorDataDto = {
convictedPersonCode: formValue.convictedPersonCode,
convictedPersonName: formValue.convictedPersonName,
misdemeanorRefNumber: formValue.misdemeanorRefNumber,
};
this.facade.editDriversInspectionMisdemeanorData(misdemeanorData);
}
}
ngOnDestroy(): void {
this.destroy$.next(true);
this.destroy$.complete();
}
}
<teis-form-row-details [label]="'controlled_period' | translate">
<span class="font-weight-bold"> {{ itemsDetails.controlledPeriodBeginning | date: 'dd.MM.yyyy' }} - {{ itemsDetails.controlledPeriodEnd | date: 'dd.MM.yyyy' }} </span>
</teis-form-row-details>
<teis-form-row-details [label]="'inspection_type' | translate">
<span class="font-weight-bold">
{{ itemsDetails.inspectionType?.name || '-' }}
</span>
</teis-form-row-details>
<teis-form-row-details [label]="'number_of_vehicles' | translate">
<span class="font-weight-bold">
{{ itemsDetails.numberOfVehicles || '-' }}
</span>
</teis-form-row-details>
<teis-form-row-details [label]="'number_of_drivers' | translate">
<span class="font-weight-bold">
{{ itemsDetails.numberOfDrivers || '-' }}
</span>
</teis-form-row-details>