feature(Avvikelserapporten): Använd nya dialogen (TV-845)
Merge in TEA/mina-sidor-fa-web from feature/TV-845-ersätt-dialogen-i-Avvikelserapporten-(TV-845) to develop
Squashed commit of the following:
commit 780f93baab0891a2f2ba49bf14d2c3add99e03c8
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date: Thu Dec 30 11:27:28 2021 +0100
Update avvikelse-report-form.component.ts
commit bea883f6aedfe2655efbb69d66788c1366e48a43
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date: Thu Dec 30 11:19:03 2021 +0100
cleanup
commit ffdf13dfcb3d97960ddb585b09fa5e6446504a68
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date: Wed Dec 29 15:52:37 2021 +0100
Update app.component.ts
commit 1631cb763bc7023a9e95682272fb63dcbe15d84e
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date: Wed Dec 29 15:52:03 2021 +0100
fix deltagarelist
commit c6080ac50cb6773aac8d4e45336fc1ba2f053a8d
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date: Wed Dec 29 15:24:44 2021 +0100
Update avrop.component.html
commit 85057d0860ddceef8309253c983a1674a57291c4
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date: Wed Dec 29 15:21:33 2021 +0100
wip
commit a73164bda8a8ae06c5700e382e197d823bef6767
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date: Wed Dec 29 15:20:04 2021 +0100
wip
commit 83f3ada5c4c60c9e46d7b01bbbf92053eb1b29ff
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date: Wed Dec 29 15:18:30 2021 +0100
wip
commit 5e184bc0e1a3f7bb6a3040d4da54a9b0e562dad3
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date: Wed Dec 29 14:18:39 2021 +0100
wip
commit 30a90ce726dde31974e26c974215f6a5a60b025e
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date: Tue Dec 28 15:11:14 2021 +0100
added scrollbars inside dialog
commit 600dd20f3281b4206c12d851cba91ae0ecf1e21a
Merge: 7af19054 b9434741
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date: Tue Dec 28 14:30:49 2021 +0100
Merge branch 'develop' into feature/TV-845-ersätt-dialogen-i-Avvikelserapporten-(TV-845)
commit 7af190549c0109f71af87157e8099aa0483c879f
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date: Tue Dec 28 12:05:22 2021 +0100
wip
commit 6e47e4a641daf4cef121e96c3855e4ce4944c6c4
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date: Tue Dec 28 09:38:36 2021 +0100
wip
commit f9354d04f51425cce29f13a10b32555113edaaa2
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date: Tue Dec 28 09:16:54 2021 +0100
feature(Nya deltagare): Använd nya dialogen (TV-845)
This commit is contained in:
@@ -33,6 +33,7 @@ export class AppComponent extends UnsubscribeDirective implements OnInit {
|
||||
private _dialogRef: UiDialogRef;
|
||||
private _userIsIdle$: Observable<boolean> = this.idleService.isIdle$;
|
||||
private _idleDialogConfig: UiDialogConfig = {
|
||||
includeBasicFooter: true,
|
||||
primaryButtonText: 'Fortsätt sessionen',
|
||||
primaryAction: () => this.setUserAsActive(),
|
||||
secondaryButtonText: 'Logga ut',
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
<ng-container *ngIf="deleteEmployeeData$ | async as deleteEmployeeData">
|
||||
<digi-ng-dialog
|
||||
*ngIf="deleteEmployeeData.toDelete"
|
||||
[afActive]="deleteEmployeeData.toDelete"
|
||||
(afOnPrimaryClick)="deleteEmployeeModelPrimaryClick(deleteEmployeeData)"
|
||||
(afOnSecondaryClick)="closeDeleteEmployeeModal()"
|
||||
(afOnInactive)="closeDeleteEmployeeModal()"
|
||||
afHeading="Ta bort personalkonto"
|
||||
afHeadingLevel="h2"
|
||||
[afPrimaryButtonText]="getPrimaryButtonText(deleteEmployeeData.lastDeleted)"
|
||||
[afSecondaryButtonText]="getSecondaryButtonText(deleteEmployeeData.lastDeleted)"
|
||||
>
|
||||
<ng-container *ngIf="deleteEmployeeData.lastDeleted; else deletionWarning">
|
||||
<digi-notification-alert af-variation="success" af-heading="Allt gick bra" af-heading-level="h3">
|
||||
<p>Personalkonto för {{deleteEmployeeData.lastDeleted.fullName}} är borttaget.</p>
|
||||
</digi-notification-alert>
|
||||
</ng-container>
|
||||
<ng-template #deletionWarning>
|
||||
<p>Är du säker på att du vill ta bort personalkontot för {{deleteEmployeeData.toDelete.fullName}}?</p>
|
||||
</ng-template>
|
||||
<!-- <digi-ng-dialog-->
|
||||
<!-- *ngIf="deleteEmployeeData.toDelete"-->
|
||||
<!-- [afActive]="deleteEmployeeData.toDelete"-->
|
||||
<!-- (afOnPrimaryClick)="deleteEmployeeModelPrimaryClick(deleteEmployeeData)"-->
|
||||
<!-- (afOnSecondaryClick)="closeDeleteEmployeeModal()"-->
|
||||
<!-- (afOnInactive)="closeDeleteEmployeeModal()"-->
|
||||
<!-- afHeading="Ta bort personalkonto"-->
|
||||
<!-- afHeadingLevel="h2"-->
|
||||
<!-- [afPrimaryButtonText]="getPrimaryButtonText(deleteEmployeeData.lastDeleted)"-->
|
||||
<!-- [afSecondaryButtonText]="getSecondaryButtonText(deleteEmployeeData.lastDeleted)"-->
|
||||
<!-- >-->
|
||||
<!-- <ng-container *ngIf="deleteEmployeeData.lastDeleted; else deletionWarning">-->
|
||||
<!-- <digi-notification-alert af-variation="success" af-heading="Allt gick bra" af-heading-level="h3">-->
|
||||
<!-- <p>Personalkonto för {{deleteEmployeeData.lastDeleted.fullName}} är borttaget.</p>-->
|
||||
<!-- </digi-notification-alert>-->
|
||||
<!-- </ng-container>-->
|
||||
<!-- <ng-template #deletionWarning>-->
|
||||
<!-- <p>Är du säker på att du vill ta bort personalkontot för {{deleteEmployeeData.toDelete.fullName}}?</p>-->
|
||||
<!-- </ng-template>-->
|
||||
|
||||
<ng-container *ngIf="errorDuringDeletion$ | async as error">
|
||||
<digi-notification-alert af-variation="danger" af-heading="Någonting gick fel" af-heading-level="h3">
|
||||
<p>
|
||||
Vi kunde inte radera personalkontot för {{deleteEmployeeData.toDelete.fullName}}. Ladda om sidan och försök
|
||||
igen.
|
||||
</p>
|
||||
<p class="msfa__small-text" *ngIf="error.message">{{error.message}}</p>
|
||||
</digi-notification-alert>
|
||||
</ng-container>
|
||||
</digi-ng-dialog>
|
||||
<!-- <ng-container *ngIf="errorDuringDeletion$ | async as error">-->
|
||||
<!-- <digi-notification-alert af-variation="danger" af-heading="Någonting gick fel" af-heading-level="h3">-->
|
||||
<!-- <p>-->
|
||||
<!-- Vi kunde inte radera personalkontot för {{deleteEmployeeData.toDelete.fullName}}. Ladda om sidan och försök-->
|
||||
<!-- igen.-->
|
||||
<!-- </p>-->
|
||||
<!-- <p class="msfa__small-text" *ngIf="error.message">{{error.message}}</p>-->
|
||||
<!-- </digi-notification-alert>-->
|
||||
<!-- </ng-container>-->
|
||||
<!-- </digi-ng-dialog>-->
|
||||
</ng-container>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { DigiNgDialogModule } from '@af/digi-ng/_dialog/dialog';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
@@ -7,7 +6,11 @@ import { EmployeeDeleteComponent } from './employee-delete.component';
|
||||
@NgModule({
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
declarations: [EmployeeDeleteComponent],
|
||||
imports: [CommonModule, RouterModule, DigiNgDialogModule],
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule,
|
||||
// DigiNgDialogModule
|
||||
],
|
||||
exports: [EmployeeDeleteComponent],
|
||||
})
|
||||
export class EmployeeDeleteModule {}
|
||||
|
||||
@@ -86,8 +86,6 @@
|
||||
</digi-button>
|
||||
|
||||
<ng-template #informationDialog>
|
||||
<h2>Information</h2>
|
||||
<h3>Genomförandereferens</h3>
|
||||
<p>
|
||||
Genomförandereferens är det referensnummer du ska använda dig av i kontakten med Arbetsförmedlingen.
|
||||
Du kan också använda genomförandereferensen till att leta fram en order i leverantörsportalen.
|
||||
@@ -109,6 +107,7 @@
|
||||
språkstöd som ingår i upphandlingen av olika tjänster och utbildningar. Du hittar mer information om
|
||||
språkstöd och tolk i förfrågningsunderlaget för specifik upphandling.
|
||||
</p>
|
||||
<!-- </ui-dialog-layout>-->
|
||||
</ng-template>
|
||||
</div>
|
||||
<msfa-avrop-list
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Handledare } from '@msfa-models/handledare.model';
|
||||
import { AvropService } from '@msfa-services/avrop.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { UiDialog } from '@ui/dialog/ui-dialog.service';
|
||||
import { UiDialogRef } from '@ui/dialog/ui-dialog-ref';
|
||||
|
||||
@Component({
|
||||
selector: 'msfa-avrop',
|
||||
@@ -13,6 +14,7 @@ import { UiDialog } from '@ui/dialog/ui-dialog.service';
|
||||
})
|
||||
export class AvropComponent implements OnDestroy {
|
||||
@ViewChild('informationDialog') informationDialog: TemplateRef<unknown>;
|
||||
uiDialogRef: UiDialogRef;
|
||||
readonly totalAmountOfSteps = 3;
|
||||
currentStep$: Observable<number> = this.avropService.currentStep$;
|
||||
error$: Observable<string> = this.avropService.error$;
|
||||
@@ -77,6 +79,6 @@ export class AvropComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
openAvropDialog(): void {
|
||||
this.uiDialog.open(this.informationDialog);
|
||||
this.uiDialogRef = this.uiDialog.open(this.informationDialog, { heading: 'Information', includeBasicFooter: true });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { UiSkeletonModule } from '@ui/skeleton/skeleton.module';
|
||||
import { AvropComponent } from './avrop.component';
|
||||
import { AvropFiltersModule } from './components/avrop-filters/avrop-filters.module';
|
||||
import { AvropListModule } from './components/avrop-list/avrop-list.module';
|
||||
import { DigiNgDialogModule } from '@af/digi-ng/_dialog/dialog';
|
||||
import { UiDialogModule } from '@ui/dialog/ui-dialog.module';
|
||||
|
||||
@NgModule({
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
@@ -24,7 +24,7 @@ import { DigiNgDialogModule } from '@af/digi-ng/_dialog/dialog';
|
||||
UiLoaderModule,
|
||||
HandledarePickerFormModule,
|
||||
UnauthorizedAlertModule,
|
||||
DigiNgDialogModule,
|
||||
UiDialogModule,
|
||||
],
|
||||
})
|
||||
export class AvropModule {}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<ui-dialog-layout [isLoading]="submitIsLoading$ | async">
|
||||
<h2 uiDialogHeading>Vill du skicka in Avvikelserapport (avvikelse)</h2>
|
||||
|
||||
<msfa-report-description-list [avrop]="data.avrop">
|
||||
<dt>Orsak till avvikelse:</dt>
|
||||
<dd>{{data.chosenReason.name }}</dd>
|
||||
<ng-container *ngFor="let question of data.avvikelseSubmitData.avvikelseAlternativ.frageformular">
|
||||
<dd>{{question.svar.length === 0 ? 'Inget svar' : question.svar }}</dd>
|
||||
</ng-container>
|
||||
<dt>Dag för avvikelse:</dt>
|
||||
<dd>{{data.avvikelseSubmitData.avvikelseAlternativ.rapporteringsdatum }}</dd>
|
||||
</msfa-report-description-list>
|
||||
|
||||
<digi-notification-alert
|
||||
*ngIf="submitError$ | async as error"
|
||||
class="franvaro-report-form__alert"
|
||||
af-variation="danger"
|
||||
af-heading="Någonting gick fel"
|
||||
>
|
||||
<p>Kunde inte spara Avvikelserapport (frånvaro). Ladda om sidan och försök igen.</p>
|
||||
<p class="msfa__small-text" *ngIf="error.message">{{error.message}}</p>
|
||||
</digi-notification-alert>
|
||||
|
||||
<ng-container uiDialogFooter>
|
||||
<digi-button af-type="button" (click)="submitAndCloseConfirmDialog(data.avvikelseSubmitData)"
|
||||
>Skicka in</digi-button
|
||||
>
|
||||
<digi-button af-type="button" af-variation="secondary" (click)="close()"> Avbryt </digi-button>
|
||||
</ng-container>
|
||||
</ui-dialog-layout>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AvvikelseConfirmDialogComponent } from './avvikelse-confirm-dialog.component';
|
||||
|
||||
describe('AvvikelseConfirmDialogComponent', () => {
|
||||
let component: AvvikelseConfirmDialogComponent;
|
||||
let fixture: ComponentFixture<AvvikelseConfirmDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ AvvikelseConfirmDialogComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AvvikelseConfirmDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { UiDialogRef } from '@ui/dialog/ui-dialog-ref';
|
||||
import { DeltagareAvrop } from '@msfa-models/avrop.model';
|
||||
import { AvvikelseReason } from '@msfa-models/avvikelse-reason.model';
|
||||
import { AvvikelseReportRequest } from '@msfa-models/api/avvikelse-request.model';
|
||||
import { AvvikelseReportFormService } from '../avvikelse-report-form.service';
|
||||
import { CustomError } from '@msfa-models/error/custom-error';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
export interface AvvikelseConfirmDialogData {
|
||||
avrop: DeltagareAvrop;
|
||||
chosenReason: AvvikelseReason;
|
||||
avvikelseSubmitData: AvvikelseReportRequest;
|
||||
}
|
||||
@Component({
|
||||
selector: 'msfa-avvikelse-confirm-dialog',
|
||||
templateUrl: './avvikelse-confirm-dialog.component.html',
|
||||
styleUrls: ['./avvikelse-confirm-dialog.component.scss'],
|
||||
})
|
||||
export class AvvikelseConfirmDialogComponent {
|
||||
submitIsLoading$ = new BehaviorSubject<boolean>(false);
|
||||
submitError$ = new BehaviorSubject<CustomError>(null);
|
||||
|
||||
constructor(public uiDialogRef: UiDialogRef, private avvikelseReportFormService: AvvikelseReportFormService) {}
|
||||
|
||||
get data(): AvvikelseConfirmDialogData {
|
||||
return this.uiDialogRef.config.data as AvvikelseConfirmDialogData;
|
||||
}
|
||||
|
||||
close(): void {
|
||||
this.uiDialogRef.close();
|
||||
}
|
||||
|
||||
submitAndCloseConfirmDialog(avvikelseSubmitData: AvvikelseReportRequest): void {
|
||||
this.submitIsLoading$.next(true);
|
||||
this.avvikelseReportFormService.createAvvikelse$(avvikelseSubmitData).subscribe({
|
||||
next: () => {
|
||||
this.submitIsLoading$.next(false);
|
||||
this.uiDialogRef.close({ submitted: new Date() });
|
||||
},
|
||||
error: (customError: CustomError) => {
|
||||
this.submitError$.next({ ...customError, message: customError.error.message });
|
||||
|
||||
this.submitIsLoading$.next(false);
|
||||
throw { ...customError, avoidToast: true };
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,11 @@
|
||||
</div>
|
||||
|
||||
<ng-template #formRef>
|
||||
<form class="avvikelse-report-form__form" [formGroup]="avvikelseFormGroup" (ngSubmit)="openConfirmDialog()">
|
||||
<form
|
||||
class="avvikelse-report-form__form"
|
||||
[formGroup]="avvikelseFormGroup"
|
||||
(ngSubmit)="openConfirmDialog(avrop)"
|
||||
>
|
||||
<div class="avvikelse-report-form__form-item">
|
||||
<ui-select
|
||||
*ngIf="reasonsAsUiSelectOptions$ | async as reason; else loadingRef"
|
||||
@@ -90,40 +94,15 @@
|
||||
</ui-link-button>
|
||||
</div>
|
||||
</form>
|
||||
<digi-ng-dialog
|
||||
[afActive]="confirmDialogIsOpen$ | async"
|
||||
(afOnPrimaryClick)="submitAndCloseConfirmDialog()"
|
||||
(afOnInactive)="cancelConfirmDialog()"
|
||||
afHeadingLevel="h2"
|
||||
afPrimaryButtonText="Skicka in"
|
||||
afSecondaryButtonText="Avbryt"
|
||||
(afOnSecondaryClick)="cancelConfirmDialog()"
|
||||
afHeading="Vill du skicka in Avvikelserapport (avvikelse)"
|
||||
afAriaLabel="Förhandsgranska och skicka in Avvikelserapport (avvikelse)"
|
||||
id="confirmAvvikelserapport"
|
||||
>
|
||||
<ui-loader *ngIf="submitIsLoading$ | async" uiType="absolute"></ui-loader>
|
||||
<msfa-report-description-list [avrop]="avrop">
|
||||
<dt>Orsak till avvikelse:</dt>
|
||||
<dd>{{(chosenReason$ | async)?.name }}</dd>
|
||||
<ng-container *ngIf="avvikelseSubmitData$ | async as avvikelseSubmitData; else loadingRef">
|
||||
<ng-container *ngFor="let question of avvikelseSubmitData.avvikelseAlternativ.frageformular">
|
||||
<dt>{{getCurrentQuestionFromId(question.fraga).name}}</dt>
|
||||
<dd>{{question.svar.length === 0 ? 'Inget svar' : question.svar }}</dd>
|
||||
</ng-container>
|
||||
<dt>Dag för avvikelse:</dt>
|
||||
<dd>{{avvikelseSubmitData.avvikelseAlternativ.rapporteringsdatum }}</dd>
|
||||
</ng-container>
|
||||
</msfa-report-description-list>
|
||||
|
||||
<digi-notification-alert
|
||||
*ngIf="submitError$ | async as error"
|
||||
af-variation="danger"
|
||||
af-heading="Någonting gick fel"
|
||||
>
|
||||
<p>Kunde inte spara Avvikelserapport (avvikelse). Ladda om sidan och försök igen.</p>
|
||||
<p>Kunde inte spara Avvikelserapport (avvikelse). Försök igen om en stund.</p>
|
||||
<p *ngIf="error.message" class="msfa__small-text">{{error.message}}</p>
|
||||
</digi-notification-alert>
|
||||
</digi-ng-dialog>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
@@ -12,8 +12,14 @@ import { RegexValidator } from '@msfa-utils/validators/regex.validator';
|
||||
import { RequiredValidator } from '@msfa-validators/required.validator';
|
||||
import { addDays } from 'date-fns';
|
||||
import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs';
|
||||
import { map, shareReplay, switchMap, take } from 'rxjs/operators';
|
||||
import { first, map, shareReplay, switchMap, tap } from 'rxjs/operators';
|
||||
import { AvvikelseReportFormService } from './avvikelse-report-form.service';
|
||||
import { UiDialog } from '@ui/dialog/ui-dialog.service';
|
||||
import { UiDialogRef } from '@ui/dialog/ui-dialog-ref';
|
||||
import {
|
||||
AvvikelseConfirmDialogComponent,
|
||||
AvvikelseConfirmDialogData,
|
||||
} from './avvikelse-confirm-dialog/avvikelse-confirm-dialog.component';
|
||||
|
||||
interface Params {
|
||||
genomforandeReferens: string;
|
||||
@@ -34,20 +40,22 @@ type AvvikelseFormKeys = keyof AvvikelseFormData;
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class AvvikelseReportFormComponent implements OnInit, OnDestroy {
|
||||
confirmDialogRef: UiDialogRef;
|
||||
shouldValidate$ = new BehaviorSubject<boolean>(false);
|
||||
|
||||
reasonFormName: AvvikelseFormKeys = 'reason';
|
||||
questionsFormName: AvvikelseFormKeys = 'questions';
|
||||
reportingDateFormName: AvvikelseFormKeys = 'reportingDate';
|
||||
|
||||
submitIsLoading$ = new BehaviorSubject<boolean>(false);
|
||||
submitError$ = new BehaviorSubject<CustomError>(null);
|
||||
|
||||
genomforandeReferens$: Observable<number> = this.activatedRoute.params.pipe(
|
||||
map((params: Params) => +params.genomforandeReferens)
|
||||
);
|
||||
avrop: DeltagareAvrop;
|
||||
avrop$: Observable<DeltagareAvrop> = this.genomforandeReferens$.pipe(
|
||||
switchMap(genomforandeReferens => this.avvikelseReportFormService.fetchAvropInformation$(genomforandeReferens)),
|
||||
tap(avrop => (this.avrop = avrop)),
|
||||
shareReplay(1)
|
||||
);
|
||||
|
||||
@@ -60,8 +68,6 @@ export class AvvikelseReportFormComponent implements OnInit, OnDestroy {
|
||||
chosenReasonId$: Observable<string>;
|
||||
chosenReason$: Observable<AvvikelseReason>;
|
||||
questionsForChosenReason$: Observable<AvvikelseQuestion[]>;
|
||||
avvikelseSubmitData$: Observable<AvvikelseReportRequest>;
|
||||
confirmDialogIsOpen$ = new BehaviorSubject<boolean>(false);
|
||||
submittedDate$ = new BehaviorSubject<Date | null>(null);
|
||||
private subscriptions: Subscription[] = [];
|
||||
private todayDateISO = new Date().toISOString().slice(0, 10);
|
||||
@@ -70,11 +76,19 @@ export class AvvikelseReportFormComponent implements OnInit, OnDestroy {
|
||||
[this.reportingDateFormName]: new FormControl(this.todayDateISO, [RequiredValidator('Datum är obligatoriskt')]),
|
||||
[this.questionsFormName]: new FormArray([]),
|
||||
});
|
||||
private formData$: Observable<AvvikelseFormData> = this.avvikelseFormGroup
|
||||
.valueChanges as Observable<AvvikelseFormData>;
|
||||
private currentQuestions: AvvikelseQuestion[];
|
||||
|
||||
constructor(private avvikelseReportFormService: AvvikelseReportFormService, private activatedRoute: ActivatedRoute) {}
|
||||
constructor(
|
||||
private avvikelseReportFormService: AvvikelseReportFormService,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private uiDialog: UiDialog
|
||||
) {
|
||||
this.chosenReasonId$ = this.reasonFormControl.valueChanges as Observable<string>;
|
||||
this.chosenReason$ = combineLatest([this.chosenReasonId$, this.reasons$]).pipe(
|
||||
map(([chosenReasonId, reasons]) => reasons.find(reason => reason.id.toString() === chosenReasonId)),
|
||||
shareReplay(1)
|
||||
);
|
||||
}
|
||||
|
||||
get reasonFormControl(): AbstractControl | undefined {
|
||||
return this.avvikelseFormGroup.get(this.reasonFormName);
|
||||
@@ -93,11 +107,6 @@ export class AvvikelseReportFormComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.chosenReasonId$ = this.reasonFormControl.valueChanges as Observable<string>;
|
||||
this.chosenReason$ = combineLatest([this.chosenReasonId$, this.reasons$]).pipe(
|
||||
map(([chosenReasonId, reasons]) => reasons.find(reason => reason.id.toString() === chosenReasonId))
|
||||
);
|
||||
|
||||
this.questionsForChosenReason$ = combineLatest([this.chosenReasonId$, this.allAvvikelseQuestions$]).pipe(
|
||||
map(([chosenOrsak, allAvvikelseQuestions]) => {
|
||||
return allAvvikelseQuestions.filter(question => question.id.startsWith(chosenOrsak.toString() + '_'));
|
||||
@@ -105,21 +114,15 @@ export class AvvikelseReportFormComponent implements OnInit, OnDestroy {
|
||||
);
|
||||
|
||||
this.subscriptions.push(
|
||||
this.chosenReason$.subscribe(() => {
|
||||
this.chosenReason$.subscribe(chosenReason => {
|
||||
this.shouldValidate$.next(false);
|
||||
}),
|
||||
|
||||
this.questionsForChosenReason$.subscribe(questions => {
|
||||
this.clearQuestions();
|
||||
questions.forEach(question => this.addQuestionToForm(question));
|
||||
})
|
||||
);
|
||||
|
||||
this.avvikelseSubmitData$ = combineLatest([this.genomforandeReferens$, this.chosenReasonId$, this.formData$]).pipe(
|
||||
map(([genomforandeReferens, chosenReason, formData]) =>
|
||||
this.makeAvvikelseSubmitData(genomforandeReferens, chosenReason, formData)
|
||||
),
|
||||
shareReplay(1)
|
||||
);
|
||||
}
|
||||
|
||||
questionIsRequired(question: AvvikelseQuestion): boolean {
|
||||
@@ -138,6 +141,7 @@ export class AvvikelseReportFormComponent implements OnInit, OnDestroy {
|
||||
private _isAfterStartDate(startDate: Date): boolean {
|
||||
return new Date() > startDate;
|
||||
}
|
||||
|
||||
private _isBeforeLastPossibleReportDay(endDate: Date): boolean {
|
||||
// Reporting is allowed at latest 5 days past avrop end date.
|
||||
// Because it's workdays and not calendar days we temporarily set this to much more. This date should be fetched from API in the future
|
||||
@@ -158,44 +162,41 @@ export class AvvikelseReportFormComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
openConfirmDialog(): void {
|
||||
openConfirmDialog(avrop: DeltagareAvrop): void {
|
||||
this.shouldValidate$.next(true);
|
||||
markControlsAsDirty(Object.values(this.avvikelseFormGroup.controls));
|
||||
this.avvikelseFormGroup.markAllAsTouched();
|
||||
|
||||
if (this.avvikelseFormGroup.valid) {
|
||||
this.confirmDialogIsOpen$.next(true);
|
||||
}
|
||||
}
|
||||
|
||||
submitAndCloseConfirmDialog(): void {
|
||||
this.submitIsLoading$.next(true);
|
||||
this.avvikelseSubmitData$.pipe(take(1)).subscribe(avvikelseSubmitData =>
|
||||
this.avvikelseReportFormService.createAvvikelse$(avvikelseSubmitData).subscribe({
|
||||
next: () => {
|
||||
this.submitIsLoading$.next(false);
|
||||
this.submittedDate$.next(new Date());
|
||||
this.confirmDialogIsOpen$.next(false);
|
||||
},
|
||||
error: (customError: CustomError) => {
|
||||
this.submitError$.next({ ...customError, message: customError.error.message });
|
||||
this.submitIsLoading$.next(false);
|
||||
throw { ...customError, avoidToast: true };
|
||||
},
|
||||
})
|
||||
combineLatest([this.chosenReason$, this.genomforandeReferens$])
|
||||
.pipe(
|
||||
first(),
|
||||
switchMap(([chosenReason, genomforandeReferens]) => {
|
||||
const avvikelseSubmitData: AvvikelseReportRequest = this._makeAvvikelseSubmitData(
|
||||
genomforandeReferens,
|
||||
chosenReason.id.toString(),
|
||||
this.avvikelseFormGroup.value as AvvikelseFormData
|
||||
);
|
||||
}
|
||||
|
||||
cancelConfirmDialog(): void {
|
||||
this.confirmDialogIsOpen$.next(false);
|
||||
const data: AvvikelseConfirmDialogData = { chosenReason, avvikelseSubmitData, avrop };
|
||||
|
||||
return this.uiDialog.open<{ submitted: Date }>(AvvikelseConfirmDialogComponent, { data }).afterClosed$;
|
||||
})
|
||||
)
|
||||
.subscribe(closedResult => {
|
||||
this.submitError$.next(null);
|
||||
if (closedResult.data?.submitted) {
|
||||
this.submittedDate$.next(closedResult.data.submitted);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.subscriptions.forEach(subscription => subscription.unsubscribe());
|
||||
}
|
||||
|
||||
private makeAvvikelseSubmitData(
|
||||
private _makeAvvikelseSubmitData(
|
||||
genomforandeReferens: number,
|
||||
chosenReason: string,
|
||||
formData: AvvikelseFormData
|
||||
@@ -219,6 +220,8 @@ export class AvvikelseReportFormComponent implements OnInit, OnDestroy {
|
||||
|
||||
private addQuestionToForm(question: AvvikelseQuestion): void {
|
||||
// FormArray doesnt hold any IDs so we need to store these seperately and rebuild structure at submit
|
||||
// TODO we can actually just put id in the formgroup, as we do in slutredovisning-form-step1.component.ts. That would simplify this file.
|
||||
|
||||
this.currentQuestions.push(question);
|
||||
|
||||
this.questionsFormArray.push(
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { DigiNgDialogModule } from '@af/digi-ng/_dialog/dialog';
|
||||
import { DigiNgFormDatepickerModule } from '@af/digi-ng/_form/form-datepicker';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
@@ -17,10 +16,12 @@ import { ReportDescriptionListModule } from '../../../components/report-descript
|
||||
import { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
|
||||
import { AvvikelseReportFormComponent } from './avvikelse-report-form.component';
|
||||
import { AvvikelseReportFormService } from './avvikelse-report-form.service';
|
||||
import { AvvikelseConfirmDialogComponent } from './avvikelse-confirm-dialog/avvikelse-confirm-dialog.component';
|
||||
import { UiDialogModule } from '@ui/dialog/ui-dialog.module';
|
||||
|
||||
@NgModule({
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
declarations: [AvvikelseReportFormComponent],
|
||||
declarations: [AvvikelseReportFormComponent, AvvikelseConfirmDialogComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule.forChild([{ path: '', component: AvvikelseReportFormComponent }]),
|
||||
@@ -34,10 +35,10 @@ import { AvvikelseReportFormService } from './avvikelse-report-form.service';
|
||||
UiLoaderModule,
|
||||
UiSelectModule,
|
||||
ReportDescriptionListModule,
|
||||
DigiNgDialogModule,
|
||||
UiTextareaModule,
|
||||
UiLinkButtonModule,
|
||||
PreventDoubleSubmitModule,
|
||||
UiDialogModule,
|
||||
],
|
||||
providers: [AvvikelseReportFormService],
|
||||
exports: [AvvikelseReportFormComponent],
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
<h2>Händelser för {{deltagare.fullName}}</h2>
|
||||
|
||||
<div class="deltagare-list-handelser" *ngIf="deltagare">
|
||||
<h3 *ngIf="activeHandelseMotivation" class="deltagare-list-handelser__sub-heading">{{deltagare.fullName}}</h3>
|
||||
<p>Genomförandereferens: <strong>{{deltagare.genomforandeReferens}}</strong></p>
|
||||
|
||||
@@ -85,7 +85,9 @@ export class DeltagareListTableComponent {
|
||||
openHandelser(singleDeltagare: DeltagareCompact): void {
|
||||
this.uiDialog.open(this.handelserDialogComponent, {
|
||||
data: singleDeltagare,
|
||||
heading: 'Händelser för ' + singleDeltagare.fullName,
|
||||
primaryButtonText: 'Stäng',
|
||||
includeBasicFooter: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<div class="ui-dialog-layout">
|
||||
<ui-loader *ngIf="isLoading" uiType="absolute"></ui-loader>
|
||||
<div class="ui-dialog-layout__heading">
|
||||
<ng-content select="[uiDialogHeading]"></ng-content>
|
||||
</div>
|
||||
|
||||
<div class="ui-dialog-layout__scrollable-content">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
||||
<footer class="ui-dialog-layout__footer">
|
||||
<ng-content select="[uiDialogFooter]"></ng-content>
|
||||
</footer>
|
||||
</div>
|
||||
@@ -0,0 +1,40 @@
|
||||
@import 'variables/shadows';
|
||||
@import 'variables/gutters';
|
||||
|
||||
.ui-dialog-layout {
|
||||
padding-top: $digi--layout--gutter--s;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $digi--layout--gutter--s;
|
||||
max-height: 90vh;
|
||||
&__heading {
|
||||
flex: 1 1 2rem;
|
||||
}
|
||||
&__scrollable-content {
|
||||
overflow: auto;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&__close-button {
|
||||
position: absolute;
|
||||
top: var(--digi--layout--gutter);
|
||||
right: var(--digi--layout--gutter--s);
|
||||
background: transparent;
|
||||
border: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__close-button-text {
|
||||
font-size: var(--digi--typography--font-size--s);
|
||||
}
|
||||
|
||||
&__footer {
|
||||
flex: 1 0 4rem;
|
||||
min-height: var(--digi--layout--gutter);
|
||||
display: flex;
|
||||
margin-top: $digi--layout--gutter--l;
|
||||
gap: var(--digi--layout--gutter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { UiDialogLayoutComponent } from './ui-dialog-layout.component';
|
||||
|
||||
describe('UiDialogLayoutComponent', () => {
|
||||
let component: UiDialogLayoutComponent;
|
||||
let fixture: ComponentFixture<UiDialogLayoutComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ UiDialogLayoutComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(UiDialogLayoutComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ui-dialog-layout',
|
||||
templateUrl: './ui-dialog-layout.component.html',
|
||||
styleUrls: ['./ui-dialog-layout.component.scss'],
|
||||
})
|
||||
export class UiDialogLayoutComponent {
|
||||
@Input() uiHeading: string;
|
||||
@Input() isLoading = false;
|
||||
}
|
||||
@@ -21,12 +21,18 @@ export class UiDialogRef<CloseResponseData = unknown, InputDataType = unknown> {
|
||||
overlay.backdropClick().subscribe(() => this._close('backdropClick', null));
|
||||
}
|
||||
|
||||
get includeBasicFooter(): boolean {
|
||||
return this.config.includeBasicFooter;
|
||||
}
|
||||
get primaryButtonText(): string {
|
||||
return this.config.primaryButtonText;
|
||||
}
|
||||
get secondaryButtonText(): string {
|
||||
return this.config.secondaryButtonText;
|
||||
}
|
||||
get heading(): string {
|
||||
return this.config.heading;
|
||||
}
|
||||
|
||||
close(data?: CloseResponseData): void {
|
||||
this._close('close', data);
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
<div class="ui-dialog">
|
||||
<h2 class="ui-dialog__heading" *ngIf="heading">{{heading}}</h2>
|
||||
<div [ngClass]="{'ui-dialog__scrollable-content': includeBasicFooter}">
|
||||
<ng-container [ngSwitch]="contentType">
|
||||
<ng-container *ngSwitchCase="'string'">
|
||||
<div class="box">
|
||||
<div [innerHTML]="content"></div>
|
||||
</div>
|
||||
<footer class="ui-dialog__footer">
|
||||
<digi-button af-type="button" (click)="close()">Stäng</digi-button>
|
||||
</footer>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="'template'">
|
||||
@@ -14,8 +17,9 @@
|
||||
<ng-container *ngComponentOutlet="content"></ng-container>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<footer class="ui-dialog__footer">
|
||||
<footer class="ui-dialog__footer" *ngIf="includeBasicFooter">
|
||||
<digi-button af-type="button" (click)="primaryAction()">{{primaryButtonText}}</digi-button>
|
||||
<digi-button af-type="button" af-variation="secondary" *ngIf="secondaryButtonText" (click)="secondaryAction()">
|
||||
{{secondaryButtonText}}
|
||||
|
||||
@@ -7,6 +7,18 @@
|
||||
box-shadow: $msfa__shadow;
|
||||
padding: $digi--layout--gutter--s $digi--layout--gutter--xl $digi--layout--gutter--l;
|
||||
position: relative;
|
||||
max-height: 90vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&__heading {
|
||||
flex: 1 1 2rem;
|
||||
}
|
||||
|
||||
&__scrollable-content {
|
||||
overflow: auto;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&__close-button {
|
||||
position: absolute;
|
||||
|
||||
@@ -28,11 +28,18 @@ export class UiDialogComponent implements OnInit {
|
||||
get secondaryButtonText(): string {
|
||||
return this.uiDialogRef.secondaryButtonText;
|
||||
}
|
||||
get heading(): string {
|
||||
return this.uiDialogRef.heading;
|
||||
}
|
||||
|
||||
primaryAction(): void {
|
||||
this.uiDialogRef.primaryAction();
|
||||
}
|
||||
|
||||
get includeBasicFooter(): boolean {
|
||||
return this.uiDialogRef.includeBasicFooter;
|
||||
}
|
||||
|
||||
secondaryAction(): void {
|
||||
this.uiDialogRef.secondaryAction();
|
||||
}
|
||||
|
||||
@@ -9,9 +9,12 @@ export interface UiDialogConfig<DialogInputData = unknown> {
|
||||
minHeight?: string;
|
||||
maxHeight?: string;
|
||||
|
||||
heading?: string;
|
||||
|
||||
/**
|
||||
* primaryButtonText defaults to 'Stäng'
|
||||
*/
|
||||
includeBasicFooter?: boolean;
|
||||
primaryButtonText?: string;
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,11 +3,14 @@ import { CommonModule } from '@angular/common';
|
||||
import { UiDialogComponent } from './ui-dialog.component';
|
||||
import { UiIconModule } from '@ui/icon/icon.module';
|
||||
import { UiDialog } from '@ui/dialog/ui-dialog.service';
|
||||
import { UiDialogLayoutComponent } from './ui-dialog-layout/ui-dialog-layout.component';
|
||||
import { UiLoaderModule } from '@ui/loader/loader.module';
|
||||
|
||||
@NgModule({
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
declarations: [UiDialogComponent],
|
||||
imports: [CommonModule, UiIconModule],
|
||||
declarations: [UiDialogComponent, UiDialogLayoutComponent],
|
||||
imports: [CommonModule, UiIconModule, UiLoaderModule],
|
||||
providers: [UiDialog],
|
||||
exports: [UiDialogLayoutComponent],
|
||||
})
|
||||
export class UiDialogModule {}
|
||||
|
||||
@@ -19,24 +19,24 @@ export class UiDialog {
|
||||
});
|
||||
}
|
||||
|
||||
open<DialogContent = unknown, T = unknown>(
|
||||
open<CloseResponseData = unknown, InputDataType = unknown>(
|
||||
content: string | TemplateRef<unknown> | Type<unknown>,
|
||||
config: UiDialogConfig<T> = {}
|
||||
): UiDialogRef<DialogContent> {
|
||||
config: UiDialogConfig<InputDataType> = { includeBasicFooter: false }
|
||||
): UiDialogRef<CloseResponseData> {
|
||||
const positionStrategy = this.overlay.position().global().centerHorizontally().centerVertically();
|
||||
const configs = new OverlayConfig({
|
||||
positionStrategy,
|
||||
minWidth: config.minWidth ?? '40rem',
|
||||
minHeight: config.minHeight ?? '40rem',
|
||||
minWidth: config.minWidth ?? '20rem',
|
||||
minHeight: config.minHeight ?? '10rem',
|
||||
maxWidth: config.maxWidth ?? '60rem',
|
||||
maxHeight: config.maxHeight ?? '60rem',
|
||||
hasBackdrop: true,
|
||||
scrollStrategy: this.overlay.scrollStrategies.close(),
|
||||
scrollStrategy: this.overlay.scrollStrategies.block(),
|
||||
backdropClass: 'cdk-overlay-dark-backdrop',
|
||||
});
|
||||
|
||||
const overlayRef = this.overlay.create(configs);
|
||||
const uiDialogRef = new UiDialogRef<DialogContent, T>(overlayRef, content, config);
|
||||
const uiDialogRef = new UiDialogRef<CloseResponseData, InputDataType>(overlayRef, content, config);
|
||||
|
||||
const injector = UiDialog._createInjector(uiDialogRef, this.injector, config);
|
||||
overlayRef.attach(new ComponentPortal(UiDialogComponent, null, injector));
|
||||
|
||||
Reference in New Issue
Block a user