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 _dialogRef: UiDialogRef;
|
||||||
private _userIsIdle$: Observable<boolean> = this.idleService.isIdle$;
|
private _userIsIdle$: Observable<boolean> = this.idleService.isIdle$;
|
||||||
private _idleDialogConfig: UiDialogConfig = {
|
private _idleDialogConfig: UiDialogConfig = {
|
||||||
|
includeBasicFooter: true,
|
||||||
primaryButtonText: 'Fortsätt sessionen',
|
primaryButtonText: 'Fortsätt sessionen',
|
||||||
primaryAction: () => this.setUserAsActive(),
|
primaryAction: () => this.setUserAsActive(),
|
||||||
secondaryButtonText: 'Logga ut',
|
secondaryButtonText: 'Logga ut',
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
<ng-container *ngIf="deleteEmployeeData$ | async as deleteEmployeeData">
|
<ng-container *ngIf="deleteEmployeeData$ | async as deleteEmployeeData">
|
||||||
<digi-ng-dialog
|
<!-- <digi-ng-dialog-->
|
||||||
*ngIf="deleteEmployeeData.toDelete"
|
<!-- *ngIf="deleteEmployeeData.toDelete"-->
|
||||||
[afActive]="deleteEmployeeData.toDelete"
|
<!-- [afActive]="deleteEmployeeData.toDelete"-->
|
||||||
(afOnPrimaryClick)="deleteEmployeeModelPrimaryClick(deleteEmployeeData)"
|
<!-- (afOnPrimaryClick)="deleteEmployeeModelPrimaryClick(deleteEmployeeData)"-->
|
||||||
(afOnSecondaryClick)="closeDeleteEmployeeModal()"
|
<!-- (afOnSecondaryClick)="closeDeleteEmployeeModal()"-->
|
||||||
(afOnInactive)="closeDeleteEmployeeModal()"
|
<!-- (afOnInactive)="closeDeleteEmployeeModal()"-->
|
||||||
afHeading="Ta bort personalkonto"
|
<!-- afHeading="Ta bort personalkonto"-->
|
||||||
afHeadingLevel="h2"
|
<!-- afHeadingLevel="h2"-->
|
||||||
[afPrimaryButtonText]="getPrimaryButtonText(deleteEmployeeData.lastDeleted)"
|
<!-- [afPrimaryButtonText]="getPrimaryButtonText(deleteEmployeeData.lastDeleted)"-->
|
||||||
[afSecondaryButtonText]="getSecondaryButtonText(deleteEmployeeData.lastDeleted)"
|
<!-- [afSecondaryButtonText]="getSecondaryButtonText(deleteEmployeeData.lastDeleted)"-->
|
||||||
>
|
<!-- >-->
|
||||||
<ng-container *ngIf="deleteEmployeeData.lastDeleted; else deletionWarning">
|
<!-- <ng-container *ngIf="deleteEmployeeData.lastDeleted; else deletionWarning">-->
|
||||||
<digi-notification-alert af-variation="success" af-heading="Allt gick bra" af-heading-level="h3">
|
<!-- <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>
|
<!-- <p>Personalkonto för {{deleteEmployeeData.lastDeleted.fullName}} är borttaget.</p>-->
|
||||||
</digi-notification-alert>
|
<!-- </digi-notification-alert>-->
|
||||||
</ng-container>
|
<!-- </ng-container>-->
|
||||||
<ng-template #deletionWarning>
|
<!-- <ng-template #deletionWarning>-->
|
||||||
<p>Är du säker på att du vill ta bort personalkontot för {{deleteEmployeeData.toDelete.fullName}}?</p>
|
<!-- <p>Är du säker på att du vill ta bort personalkontot för {{deleteEmployeeData.toDelete.fullName}}?</p>-->
|
||||||
</ng-template>
|
<!-- </ng-template>-->
|
||||||
|
|
||||||
<ng-container *ngIf="errorDuringDeletion$ | async as error">
|
<!-- <ng-container *ngIf="errorDuringDeletion$ | async as error">-->
|
||||||
<digi-notification-alert af-variation="danger" af-heading="Någonting gick fel" af-heading-level="h3">
|
<!-- <digi-notification-alert af-variation="danger" af-heading="Någonting gick fel" af-heading-level="h3">-->
|
||||||
<p>
|
<!-- <p>-->
|
||||||
Vi kunde inte radera personalkontot för {{deleteEmployeeData.toDelete.fullName}}. Ladda om sidan och försök
|
<!-- Vi kunde inte radera personalkontot för {{deleteEmployeeData.toDelete.fullName}}. Ladda om sidan och försök-->
|
||||||
igen.
|
<!-- igen.-->
|
||||||
</p>
|
<!-- </p>-->
|
||||||
<p class="msfa__small-text" *ngIf="error.message">{{error.message}}</p>
|
<!-- <p class="msfa__small-text" *ngIf="error.message">{{error.message}}</p>-->
|
||||||
</digi-notification-alert>
|
<!-- </digi-notification-alert>-->
|
||||||
</ng-container>
|
<!-- </ng-container>-->
|
||||||
</digi-ng-dialog>
|
<!-- </digi-ng-dialog>-->
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { DigiNgDialogModule } from '@af/digi-ng/_dialog/dialog';
|
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
@@ -7,7 +6,11 @@ import { EmployeeDeleteComponent } from './employee-delete.component';
|
|||||||
@NgModule({
|
@NgModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
declarations: [EmployeeDeleteComponent],
|
declarations: [EmployeeDeleteComponent],
|
||||||
imports: [CommonModule, RouterModule, DigiNgDialogModule],
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
RouterModule,
|
||||||
|
// DigiNgDialogModule
|
||||||
|
],
|
||||||
exports: [EmployeeDeleteComponent],
|
exports: [EmployeeDeleteComponent],
|
||||||
})
|
})
|
||||||
export class EmployeeDeleteModule {}
|
export class EmployeeDeleteModule {}
|
||||||
|
|||||||
@@ -86,8 +86,6 @@
|
|||||||
</digi-button>
|
</digi-button>
|
||||||
|
|
||||||
<ng-template #informationDialog>
|
<ng-template #informationDialog>
|
||||||
<h2>Information</h2>
|
|
||||||
<h3>Genomförandereferens</h3>
|
|
||||||
<p>
|
<p>
|
||||||
Genomförandereferens är det referensnummer du ska använda dig av i kontakten med Arbetsförmedlingen.
|
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.
|
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 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.
|
språkstöd och tolk i förfrågningsunderlaget för specifik upphandling.
|
||||||
</p>
|
</p>
|
||||||
|
<!-- </ui-dialog-layout>-->
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
<msfa-avrop-list
|
<msfa-avrop-list
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Handledare } from '@msfa-models/handledare.model';
|
|||||||
import { AvropService } from '@msfa-services/avrop.service';
|
import { AvropService } from '@msfa-services/avrop.service';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { UiDialog } from '@ui/dialog/ui-dialog.service';
|
import { UiDialog } from '@ui/dialog/ui-dialog.service';
|
||||||
|
import { UiDialogRef } from '@ui/dialog/ui-dialog-ref';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'msfa-avrop',
|
selector: 'msfa-avrop',
|
||||||
@@ -13,6 +14,7 @@ import { UiDialog } from '@ui/dialog/ui-dialog.service';
|
|||||||
})
|
})
|
||||||
export class AvropComponent implements OnDestroy {
|
export class AvropComponent implements OnDestroy {
|
||||||
@ViewChild('informationDialog') informationDialog: TemplateRef<unknown>;
|
@ViewChild('informationDialog') informationDialog: TemplateRef<unknown>;
|
||||||
|
uiDialogRef: UiDialogRef;
|
||||||
readonly totalAmountOfSteps = 3;
|
readonly totalAmountOfSteps = 3;
|
||||||
currentStep$: Observable<number> = this.avropService.currentStep$;
|
currentStep$: Observable<number> = this.avropService.currentStep$;
|
||||||
error$: Observable<string> = this.avropService.error$;
|
error$: Observable<string> = this.avropService.error$;
|
||||||
@@ -77,6 +79,6 @@ export class AvropComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
openAvropDialog(): void {
|
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 { AvropComponent } from './avrop.component';
|
||||||
import { AvropFiltersModule } from './components/avrop-filters/avrop-filters.module';
|
import { AvropFiltersModule } from './components/avrop-filters/avrop-filters.module';
|
||||||
import { AvropListModule } from './components/avrop-list/avrop-list.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({
|
@NgModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
@@ -24,7 +24,7 @@ import { DigiNgDialogModule } from '@af/digi-ng/_dialog/dialog';
|
|||||||
UiLoaderModule,
|
UiLoaderModule,
|
||||||
HandledarePickerFormModule,
|
HandledarePickerFormModule,
|
||||||
UnauthorizedAlertModule,
|
UnauthorizedAlertModule,
|
||||||
DigiNgDialogModule,
|
UiDialogModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AvropModule {}
|
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>
|
</div>
|
||||||
|
|
||||||
<ng-template #formRef>
|
<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">
|
<div class="avvikelse-report-form__form-item">
|
||||||
<ui-select
|
<ui-select
|
||||||
*ngIf="reasonsAsUiSelectOptions$ | async as reason; else loadingRef"
|
*ngIf="reasonsAsUiSelectOptions$ | async as reason; else loadingRef"
|
||||||
@@ -90,40 +94,15 @@
|
|||||||
</ui-link-button>
|
</ui-link-button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<digi-ng-dialog
|
|
||||||
[afActive]="confirmDialogIsOpen$ | async"
|
<digi-notification-alert
|
||||||
(afOnPrimaryClick)="submitAndCloseConfirmDialog()"
|
*ngIf="submitError$ | async as error"
|
||||||
(afOnInactive)="cancelConfirmDialog()"
|
af-variation="danger"
|
||||||
afHeadingLevel="h2"
|
af-heading="Någonting gick fel"
|
||||||
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>
|
<p>Kunde inte spara Avvikelserapport (avvikelse). Försök igen om en stund.</p>
|
||||||
<msfa-report-description-list [avrop]="avrop">
|
<p *ngIf="error.message" class="msfa__small-text">{{error.message}}</p>
|
||||||
<dt>Orsak till avvikelse:</dt>
|
</digi-notification-alert>
|
||||||
<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 *ngIf="error.message" class="msfa__small-text">{{error.message}}</p>
|
|
||||||
</digi-notification-alert>
|
|
||||||
</digi-ng-dialog>
|
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,8 +12,14 @@ import { RegexValidator } from '@msfa-utils/validators/regex.validator';
|
|||||||
import { RequiredValidator } from '@msfa-validators/required.validator';
|
import { RequiredValidator } from '@msfa-validators/required.validator';
|
||||||
import { addDays } from 'date-fns';
|
import { addDays } from 'date-fns';
|
||||||
import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs';
|
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 { 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 {
|
interface Params {
|
||||||
genomforandeReferens: string;
|
genomforandeReferens: string;
|
||||||
@@ -34,20 +40,22 @@ type AvvikelseFormKeys = keyof AvvikelseFormData;
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class AvvikelseReportFormComponent implements OnInit, OnDestroy {
|
export class AvvikelseReportFormComponent implements OnInit, OnDestroy {
|
||||||
|
confirmDialogRef: UiDialogRef;
|
||||||
shouldValidate$ = new BehaviorSubject<boolean>(false);
|
shouldValidate$ = new BehaviorSubject<boolean>(false);
|
||||||
|
|
||||||
reasonFormName: AvvikelseFormKeys = 'reason';
|
reasonFormName: AvvikelseFormKeys = 'reason';
|
||||||
questionsFormName: AvvikelseFormKeys = 'questions';
|
questionsFormName: AvvikelseFormKeys = 'questions';
|
||||||
reportingDateFormName: AvvikelseFormKeys = 'reportingDate';
|
reportingDateFormName: AvvikelseFormKeys = 'reportingDate';
|
||||||
|
|
||||||
submitIsLoading$ = new BehaviorSubject<boolean>(false);
|
|
||||||
submitError$ = new BehaviorSubject<CustomError>(null);
|
submitError$ = new BehaviorSubject<CustomError>(null);
|
||||||
|
|
||||||
genomforandeReferens$: Observable<number> = this.activatedRoute.params.pipe(
|
genomforandeReferens$: Observable<number> = this.activatedRoute.params.pipe(
|
||||||
map((params: Params) => +params.genomforandeReferens)
|
map((params: Params) => +params.genomforandeReferens)
|
||||||
);
|
);
|
||||||
|
avrop: DeltagareAvrop;
|
||||||
avrop$: Observable<DeltagareAvrop> = this.genomforandeReferens$.pipe(
|
avrop$: Observable<DeltagareAvrop> = this.genomforandeReferens$.pipe(
|
||||||
switchMap(genomforandeReferens => this.avvikelseReportFormService.fetchAvropInformation$(genomforandeReferens)),
|
switchMap(genomforandeReferens => this.avvikelseReportFormService.fetchAvropInformation$(genomforandeReferens)),
|
||||||
|
tap(avrop => (this.avrop = avrop)),
|
||||||
shareReplay(1)
|
shareReplay(1)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -60,8 +68,6 @@ export class AvvikelseReportFormComponent implements OnInit, OnDestroy {
|
|||||||
chosenReasonId$: Observable<string>;
|
chosenReasonId$: Observable<string>;
|
||||||
chosenReason$: Observable<AvvikelseReason>;
|
chosenReason$: Observable<AvvikelseReason>;
|
||||||
questionsForChosenReason$: Observable<AvvikelseQuestion[]>;
|
questionsForChosenReason$: Observable<AvvikelseQuestion[]>;
|
||||||
avvikelseSubmitData$: Observable<AvvikelseReportRequest>;
|
|
||||||
confirmDialogIsOpen$ = new BehaviorSubject<boolean>(false);
|
|
||||||
submittedDate$ = new BehaviorSubject<Date | null>(null);
|
submittedDate$ = new BehaviorSubject<Date | null>(null);
|
||||||
private subscriptions: Subscription[] = [];
|
private subscriptions: Subscription[] = [];
|
||||||
private todayDateISO = new Date().toISOString().slice(0, 10);
|
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.reportingDateFormName]: new FormControl(this.todayDateISO, [RequiredValidator('Datum är obligatoriskt')]),
|
||||||
[this.questionsFormName]: new FormArray([]),
|
[this.questionsFormName]: new FormArray([]),
|
||||||
});
|
});
|
||||||
private formData$: Observable<AvvikelseFormData> = this.avvikelseFormGroup
|
|
||||||
.valueChanges as Observable<AvvikelseFormData>;
|
|
||||||
private currentQuestions: AvvikelseQuestion[];
|
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 {
|
get reasonFormControl(): AbstractControl | undefined {
|
||||||
return this.avvikelseFormGroup.get(this.reasonFormName);
|
return this.avvikelseFormGroup.get(this.reasonFormName);
|
||||||
@@ -93,11 +107,6 @@ export class AvvikelseReportFormComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
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(
|
this.questionsForChosenReason$ = combineLatest([this.chosenReasonId$, this.allAvvikelseQuestions$]).pipe(
|
||||||
map(([chosenOrsak, allAvvikelseQuestions]) => {
|
map(([chosenOrsak, allAvvikelseQuestions]) => {
|
||||||
return allAvvikelseQuestions.filter(question => question.id.startsWith(chosenOrsak.toString() + '_'));
|
return allAvvikelseQuestions.filter(question => question.id.startsWith(chosenOrsak.toString() + '_'));
|
||||||
@@ -105,21 +114,15 @@ export class AvvikelseReportFormComponent implements OnInit, OnDestroy {
|
|||||||
);
|
);
|
||||||
|
|
||||||
this.subscriptions.push(
|
this.subscriptions.push(
|
||||||
this.chosenReason$.subscribe(() => {
|
this.chosenReason$.subscribe(chosenReason => {
|
||||||
this.shouldValidate$.next(false);
|
this.shouldValidate$.next(false);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
this.questionsForChosenReason$.subscribe(questions => {
|
this.questionsForChosenReason$.subscribe(questions => {
|
||||||
this.clearQuestions();
|
this.clearQuestions();
|
||||||
questions.forEach(question => this.addQuestionToForm(question));
|
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 {
|
questionIsRequired(question: AvvikelseQuestion): boolean {
|
||||||
@@ -138,6 +141,7 @@ export class AvvikelseReportFormComponent implements OnInit, OnDestroy {
|
|||||||
private _isAfterStartDate(startDate: Date): boolean {
|
private _isAfterStartDate(startDate: Date): boolean {
|
||||||
return new Date() > startDate;
|
return new Date() > startDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _isBeforeLastPossibleReportDay(endDate: Date): boolean {
|
private _isBeforeLastPossibleReportDay(endDate: Date): boolean {
|
||||||
// Reporting is allowed at latest 5 days past avrop end date.
|
// 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
|
// 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);
|
this.shouldValidate$.next(true);
|
||||||
markControlsAsDirty(Object.values(this.avvikelseFormGroup.controls));
|
markControlsAsDirty(Object.values(this.avvikelseFormGroup.controls));
|
||||||
this.avvikelseFormGroup.markAllAsTouched();
|
this.avvikelseFormGroup.markAllAsTouched();
|
||||||
|
|
||||||
if (this.avvikelseFormGroup.valid) {
|
if (this.avvikelseFormGroup.valid) {
|
||||||
this.confirmDialogIsOpen$.next(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
|
||||||
|
);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 };
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelConfirmDialog(): void {
|
|
||||||
this.confirmDialogIsOpen$.next(false);
|
|
||||||
this.submitError$.next(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.subscriptions.forEach(subscription => subscription.unsubscribe());
|
this.subscriptions.forEach(subscription => subscription.unsubscribe());
|
||||||
}
|
}
|
||||||
|
|
||||||
private makeAvvikelseSubmitData(
|
private _makeAvvikelseSubmitData(
|
||||||
genomforandeReferens: number,
|
genomforandeReferens: number,
|
||||||
chosenReason: string,
|
chosenReason: string,
|
||||||
formData: AvvikelseFormData
|
formData: AvvikelseFormData
|
||||||
@@ -219,6 +220,8 @@ export class AvvikelseReportFormComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
private addQuestionToForm(question: AvvikelseQuestion): void {
|
private addQuestionToForm(question: AvvikelseQuestion): void {
|
||||||
// FormArray doesnt hold any IDs so we need to store these seperately and rebuild structure at submit
|
// 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.currentQuestions.push(question);
|
||||||
|
|
||||||
this.questionsFormArray.push(
|
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 { DigiNgFormDatepickerModule } from '@af/digi-ng/_form/form-datepicker';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
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 { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
|
||||||
import { AvvikelseReportFormComponent } from './avvikelse-report-form.component';
|
import { AvvikelseReportFormComponent } from './avvikelse-report-form.component';
|
||||||
import { AvvikelseReportFormService } from './avvikelse-report-form.service';
|
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({
|
@NgModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
declarations: [AvvikelseReportFormComponent],
|
declarations: [AvvikelseReportFormComponent, AvvikelseConfirmDialogComponent],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
RouterModule.forChild([{ path: '', component: AvvikelseReportFormComponent }]),
|
RouterModule.forChild([{ path: '', component: AvvikelseReportFormComponent }]),
|
||||||
@@ -34,10 +35,10 @@ import { AvvikelseReportFormService } from './avvikelse-report-form.service';
|
|||||||
UiLoaderModule,
|
UiLoaderModule,
|
||||||
UiSelectModule,
|
UiSelectModule,
|
||||||
ReportDescriptionListModule,
|
ReportDescriptionListModule,
|
||||||
DigiNgDialogModule,
|
|
||||||
UiTextareaModule,
|
UiTextareaModule,
|
||||||
UiLinkButtonModule,
|
UiLinkButtonModule,
|
||||||
PreventDoubleSubmitModule,
|
PreventDoubleSubmitModule,
|
||||||
|
UiDialogModule,
|
||||||
],
|
],
|
||||||
providers: [AvvikelseReportFormService],
|
providers: [AvvikelseReportFormService],
|
||||||
exports: [AvvikelseReportFormComponent],
|
exports: [AvvikelseReportFormComponent],
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
<h2>Händelser för {{deltagare.fullName}}</h2>
|
|
||||||
|
|
||||||
<div class="deltagare-list-handelser" *ngIf="deltagare">
|
<div class="deltagare-list-handelser" *ngIf="deltagare">
|
||||||
<h3 *ngIf="activeHandelseMotivation" class="deltagare-list-handelser__sub-heading">{{deltagare.fullName}}</h3>
|
<h3 *ngIf="activeHandelseMotivation" class="deltagare-list-handelser__sub-heading">{{deltagare.fullName}}</h3>
|
||||||
<p>Genomförandereferens: <strong>{{deltagare.genomforandeReferens}}</strong></p>
|
<p>Genomförandereferens: <strong>{{deltagare.genomforandeReferens}}</strong></p>
|
||||||
|
|||||||
@@ -85,7 +85,9 @@ export class DeltagareListTableComponent {
|
|||||||
openHandelser(singleDeltagare: DeltagareCompact): void {
|
openHandelser(singleDeltagare: DeltagareCompact): void {
|
||||||
this.uiDialog.open(this.handelserDialogComponent, {
|
this.uiDialog.open(this.handelserDialogComponent, {
|
||||||
data: singleDeltagare,
|
data: singleDeltagare,
|
||||||
|
heading: 'Händelser för ' + singleDeltagare.fullName,
|
||||||
primaryButtonText: 'Stäng',
|
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));
|
overlay.backdropClick().subscribe(() => this._close('backdropClick', null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get includeBasicFooter(): boolean {
|
||||||
|
return this.config.includeBasicFooter;
|
||||||
|
}
|
||||||
get primaryButtonText(): string {
|
get primaryButtonText(): string {
|
||||||
return this.config.primaryButtonText;
|
return this.config.primaryButtonText;
|
||||||
}
|
}
|
||||||
get secondaryButtonText(): string {
|
get secondaryButtonText(): string {
|
||||||
return this.config.secondaryButtonText;
|
return this.config.secondaryButtonText;
|
||||||
}
|
}
|
||||||
|
get heading(): string {
|
||||||
|
return this.config.heading;
|
||||||
|
}
|
||||||
|
|
||||||
close(data?: CloseResponseData): void {
|
close(data?: CloseResponseData): void {
|
||||||
this._close('close', data);
|
this._close('close', data);
|
||||||
|
|||||||
@@ -1,21 +1,25 @@
|
|||||||
<div class="ui-dialog">
|
<div class="ui-dialog">
|
||||||
<ng-container [ngSwitch]="contentType">
|
<h2 class="ui-dialog__heading" *ngIf="heading">{{heading}}</h2>
|
||||||
<ng-container *ngSwitchCase="'string'">
|
<div [ngClass]="{'ui-dialog__scrollable-content': includeBasicFooter}">
|
||||||
<div class="box">
|
<ng-container [ngSwitch]="contentType">
|
||||||
|
<ng-container *ngSwitchCase="'string'">
|
||||||
<div [innerHTML]="content"></div>
|
<div [innerHTML]="content"></div>
|
||||||
</div>
|
<footer class="ui-dialog__footer">
|
||||||
</ng-container>
|
<digi-button af-type="button" (click)="close()">Stäng</digi-button>
|
||||||
|
</footer>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngSwitchCase="'template'">
|
<ng-container *ngSwitchCase="'template'">
|
||||||
<ng-container *ngTemplateOutlet="content; context: context"></ng-container>
|
<ng-container *ngTemplateOutlet="content; context: context"></ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngSwitchCase="'component'">
|
<ng-container *ngSwitchCase="'component'">
|
||||||
<ng-container *ngComponentOutlet="content"></ng-container>
|
<ng-container *ngComponentOutlet="content"></ng-container>
|
||||||
|
</ng-container>
|
||||||
</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" (click)="primaryAction()">{{primaryButtonText}}</digi-button>
|
||||||
<digi-button af-type="button" af-variation="secondary" *ngIf="secondaryButtonText" (click)="secondaryAction()">
|
<digi-button af-type="button" af-variation="secondary" *ngIf="secondaryButtonText" (click)="secondaryAction()">
|
||||||
{{secondaryButtonText}}
|
{{secondaryButtonText}}
|
||||||
|
|||||||
@@ -7,6 +7,18 @@
|
|||||||
box-shadow: $msfa__shadow;
|
box-shadow: $msfa__shadow;
|
||||||
padding: $digi--layout--gutter--s $digi--layout--gutter--xl $digi--layout--gutter--l;
|
padding: $digi--layout--gutter--s $digi--layout--gutter--xl $digi--layout--gutter--l;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
max-height: 90vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
&__heading {
|
||||||
|
flex: 1 1 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__scrollable-content {
|
||||||
|
overflow: auto;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
&__close-button {
|
&__close-button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@@ -28,11 +28,18 @@ export class UiDialogComponent implements OnInit {
|
|||||||
get secondaryButtonText(): string {
|
get secondaryButtonText(): string {
|
||||||
return this.uiDialogRef.secondaryButtonText;
|
return this.uiDialogRef.secondaryButtonText;
|
||||||
}
|
}
|
||||||
|
get heading(): string {
|
||||||
|
return this.uiDialogRef.heading;
|
||||||
|
}
|
||||||
|
|
||||||
primaryAction(): void {
|
primaryAction(): void {
|
||||||
this.uiDialogRef.primaryAction();
|
this.uiDialogRef.primaryAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get includeBasicFooter(): boolean {
|
||||||
|
return this.uiDialogRef.includeBasicFooter;
|
||||||
|
}
|
||||||
|
|
||||||
secondaryAction(): void {
|
secondaryAction(): void {
|
||||||
this.uiDialogRef.secondaryAction();
|
this.uiDialogRef.secondaryAction();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,12 @@ export interface UiDialogConfig<DialogInputData = unknown> {
|
|||||||
minHeight?: string;
|
minHeight?: string;
|
||||||
maxHeight?: string;
|
maxHeight?: string;
|
||||||
|
|
||||||
|
heading?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* primaryButtonText defaults to 'Stäng'
|
* primaryButtonText defaults to 'Stäng'
|
||||||
*/
|
*/
|
||||||
|
includeBasicFooter?: boolean;
|
||||||
primaryButtonText?: string;
|
primaryButtonText?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,11 +3,14 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { UiDialogComponent } from './ui-dialog.component';
|
import { UiDialogComponent } from './ui-dialog.component';
|
||||||
import { UiIconModule } from '@ui/icon/icon.module';
|
import { UiIconModule } from '@ui/icon/icon.module';
|
||||||
import { UiDialog } from '@ui/dialog/ui-dialog.service';
|
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({
|
@NgModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
declarations: [UiDialogComponent],
|
declarations: [UiDialogComponent, UiDialogLayoutComponent],
|
||||||
imports: [CommonModule, UiIconModule],
|
imports: [CommonModule, UiIconModule, UiLoaderModule],
|
||||||
providers: [UiDialog],
|
providers: [UiDialog],
|
||||||
|
exports: [UiDialogLayoutComponent],
|
||||||
})
|
})
|
||||||
export class UiDialogModule {}
|
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>,
|
content: string | TemplateRef<unknown> | Type<unknown>,
|
||||||
config: UiDialogConfig<T> = {}
|
config: UiDialogConfig<InputDataType> = { includeBasicFooter: false }
|
||||||
): UiDialogRef<DialogContent> {
|
): UiDialogRef<CloseResponseData> {
|
||||||
const positionStrategy = this.overlay.position().global().centerHorizontally().centerVertically();
|
const positionStrategy = this.overlay.position().global().centerHorizontally().centerVertically();
|
||||||
const configs = new OverlayConfig({
|
const configs = new OverlayConfig({
|
||||||
positionStrategy,
|
positionStrategy,
|
||||||
minWidth: config.minWidth ?? '40rem',
|
minWidth: config.minWidth ?? '20rem',
|
||||||
minHeight: config.minHeight ?? '40rem',
|
minHeight: config.minHeight ?? '10rem',
|
||||||
maxWidth: config.maxWidth ?? '60rem',
|
maxWidth: config.maxWidth ?? '60rem',
|
||||||
maxHeight: config.maxHeight ?? '60rem',
|
maxHeight: config.maxHeight ?? '60rem',
|
||||||
hasBackdrop: true,
|
hasBackdrop: true,
|
||||||
scrollStrategy: this.overlay.scrollStrategies.close(),
|
scrollStrategy: this.overlay.scrollStrategies.block(),
|
||||||
backdropClass: 'cdk-overlay-dark-backdrop',
|
backdropClass: 'cdk-overlay-dark-backdrop',
|
||||||
});
|
});
|
||||||
|
|
||||||
const overlayRef = this.overlay.create(configs);
|
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);
|
const injector = UiDialog._createInjector(uiDialogRef, this.injector, config);
|
||||||
overlayRef.attach(new ComponentPortal(UiDialogComponent, null, injector));
|
overlayRef.attach(new ComponentPortal(UiDialogComponent, null, injector));
|
||||||
|
|||||||
Reference in New Issue
Block a user