feat(informativ-rapport): Implemented Informativ rapport. (TV-782)

Squashed commit of the following:

commit 5206466fd53275ed16d5a529abafc41db3fc09a5
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Fri Oct 22 15:11:45 2021 +0200

    Merge pull request #218 in TEA/mina-sidor-fa-web from feature/TV-813 to feature/TV-782-informativ-rapport

    Squashed commit of the following:

    commit ba53ee6e2a4e7835a84b67f9ea80336a6ddc6b4f
    Merge: 36f8676c cfde226f
    Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
    Date:   Fri Oct 22 14:23:58 2021 +0200

        Merge branch 'develop' into feature/TV-813

    commit 36f8676cd80899937a27fd4c7873ec2adf908d67
    Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
    Date:   Fri Oct 22 14:19:01 2021 +0200

        Removed unused module inside reportviews

    commit 31f6a26747bbd75d16c887674464f40d015da7a2
    Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
    Date:   Fri Oct 22 14:14:46 2021 +0200

        Added component for report-description-list

commit 2d7406fd64abcb1936f3a2145bbfb98da7f0ac7c
Merge: 2e35a67d cfde226f
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Fri Oct 22 14:23:43 2021 +0200

    Merge branch 'develop' into feature/TV-782-informativ-rapport

commit 2e35a67db54609a00e167198648e46c25a94eea8
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Fri Oct 22 12:16:22 2021 +0200

    Changed type to category

commit 000c2b966a697b724a1bc58ea5ba9503b8782f42
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Fri Oct 22 12:05:57 2021 +0200

    Updated with information texts

commit 275f18a094ed03319ac4a6668b08a697f0202fee
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Fri Oct 22 10:24:42 2021 +0200

    Implemented informativ rapport

commit 4544e7c180994a009f0a93b2645965ae725ec901
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Fri Oct 22 08:10:03 2021 +0200

    Added base for informativ rapport

commit 36329210f4dffa2a3d8bed2a571fa880fe3b75fc
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Thu Oct 21 14:55:09 2021 +0200

    WIP
This commit is contained in:
Erik Tiekstra
2021-10-25 07:24:53 +02:00
parent 6611784427
commit 612e099737
42 changed files with 661 additions and 202 deletions

View File

@@ -0,0 +1,19 @@
<dl *ngIf="avrop">
<dt>Namn</dt>
<dd>{{avrop.fullName}}</dd>
<dt>Personnummer</dt>
<dd>
<msfa-hide-text symbols="********-****" [changingText]="avrop.ssn" ariaLabelType="Personnummer"></msfa-hide-text>
</dd>
<dt>Tjänst</dt>
<dd>{{avrop.tjanst}}</dd>
<dt>Startdatum</dt>
<dd>
<digi-typography-time [afDateTime]="avrop.startDate"></digi-typography-time>
</dd>
<dt>Slutdatum</dt>
<dd>
<digi-typography-time [afDateTime]="avrop.endDate"></digi-typography-time>
</dd>
<ng-content></ng-content>
</dl>

View File

@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ReportDescriptionListComponent } from './report-description-list.component';
import { ReportDescriptionListModule } from './report-description-list.module';
describe('ReportDescriptionListComponent', () => {
let component: ReportDescriptionListComponent;
let fixture: ComponentFixture<ReportDescriptionListComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ReportDescriptionListModule],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ReportDescriptionListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,12 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { Avrop } from '@msfa-models/avrop.model';
@Component({
selector: 'msfa-report-description-list',
templateUrl: './report-description-list.component.html',
styleUrls: ['./report-description-list.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ReportDescriptionListComponent {
@Input() avrop: Avrop;
}

View File

@@ -0,0 +1,12 @@
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.module';
import { ReportDescriptionListComponent } from './report-description-list.component';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [ReportDescriptionListComponent],
imports: [CommonModule, HideTextModule],
exports: [ReportDescriptionListComponent],
})
export class ReportDescriptionListModule {}

View File

@@ -2,50 +2,7 @@
<digi-typography>
<h1>{{ reportTitle }}</h1>
<p class="report-layout__description" *ngIf="description">{{description}}</p>
<div class="report-layout__deltagare-info" *ngIf="avrop">
<h2 *ngIf="reportSubTitle">{{reportSubTitle}}</h2>
<dl>
<dt>Namn</dt>
<dd>{{avrop.fullName}}</dd>
<dt>Personnummer</dt>
<dd>
<msfa-hide-text
symbols="********-****"
[changingText]="avrop.ssn"
ariaLabelType="Personnummer"
></msfa-hide-text>
</dd>
<dt>Tjänst</dt>
<dd>{{avrop.tjanst}}</dd>
<ng-container *ngIf="!isPeriodDate; else periodDateRef">
<dt>Startdatum</dt>
<dd>
<digi-typography-time [afDateTime]="avrop.startDate"></digi-typography-time>
</dd>
<dt>Slutdatum</dt>
<dd>
<digi-typography-time [afDateTime]="avrop.endDate"></digi-typography-time>
</dd>
</ng-container>
<ng-template #periodDateRef>
<dt>Avser period</dt>
<dd>
<digi-typography-time [afDateTime]="avrop.startDate"></digi-typography-time>
-
<digi-typography-time [afDateTime]="avrop.endDate"></digi-typography-time>
</dd>
</ng-template>
</dl>
</div>
<div class="report-layout__progress-bar" *ngIf="!!totalAmountOfSteps && !!currentStep">
<digi-progressbar
[afTotalSteps]="totalAmountOfSteps"
[afCompletedSteps]="currentStep - 1"
af-steps-label="steg avklarade"
></digi-progressbar>
</div>
<msfa-report-description-list [avrop]="avrop"></msfa-report-description-list>
<div class="report-layout__main-content">
<ng-content></ng-content>
</div>

View File

@@ -1,16 +0,0 @@
@import 'variables/z-index';
@import 'apps/mina-sidor-fa/src/styles/variables/gutters';
.report-layout {
&__notification-alert {
margin-bottom: $digi--layout--gutter--xl;
}
&__progress-bar {
margin: $digi--layout--gutter--xl 0;
}
&__progress-bar {
z-index: $msfa__z-index-default;
}
}

View File

@@ -1,8 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ReportLayoutComponent } from './report-layout.component';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ReportLayoutModule } from './report-layout.module';
import { RouterTestingModule } from '@angular/router/testing';
describe('ReportLayoutComponent', () => {
let component: ReportLayoutComponent;
@@ -10,7 +8,7 @@ describe('ReportLayoutComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ReportLayoutModule, RouterTestingModule, HttpClientTestingModule],
imports: [ReportLayoutModule],
}).compileComponents();
});

View File

@@ -13,11 +13,5 @@ export class ReportLayoutComponent {
@Input() description: string;
@Input() startDate: string;
@Input() endDate: string;
@Input() service: string;
@Input() isPeriodDate = false;
@Input() avrop: Avrop;
@Input() totalAmountOfSteps: number;
@Input() currentStep: number;
@Input() showSuccessNotification = false;
@Input() showDangerNotification = false;
}

View File

@@ -1,15 +1,13 @@
import { DigiNgProgressProgressbarModule } from '@af/digi-ng/_progress/progressbar';
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.module';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { ReportDescriptionListModule } from '../report-description-list/report-description-list.module';
import { ReportLayoutComponent } from './report-layout.component';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [ReportLayoutComponent],
imports: [CommonModule, RouterModule, LayoutModule, DigiNgProgressProgressbarModule, HideTextModule],
imports: [CommonModule, LayoutModule, ReportDescriptionListModule],
exports: [ReportLayoutComponent],
})
export class ReportLayoutModule {}

View File

@@ -90,6 +90,16 @@ activeFeatures.forEach(feature => {
loadChildren: () => import('./pages/report-forms/signal-form/signal-form.module').then(m => m.SignalFormModule),
});
break;
case Feature.REPORTING_INFORMATIV_RAPPORT:
routes.push({
path: 'informativ-rapport',
data: { title: 'Skapa Informativ rapport' },
loadChildren: () =>
import('./pages/report-forms/informativ-rapport-form/informativ-rapport-form.module').then(
m => m.InformativRapportFormModule
),
});
break;
default:
break;
}

View File

@@ -38,6 +38,13 @@
afText="Signal om arbete eller studier"
></digi-ng-link-button>
</li>
<li *ngIf="informativRapportButtonVisible">
<digi-ng-link-button
class="deltagare-tab-reports__button"
afRoute="./informativ-rapport"
afText="Informativ rapport"
></digi-ng-link-button>
</li>
</ul>
<ng-container *ngIf="reportsData; else loadingRef">

View File

@@ -21,6 +21,9 @@ export class DeltagareTabReportsComponent {
get periodiskRedovisningButtonVisible(): boolean {
return this._activeFeatures.includes(Feature.REPORTING_PERIODISK_REDOVISNING);
}
get informativRapportButtonVisible(): boolean {
return this._activeFeatures.includes(Feature.REPORTING_INFORMATIV_RAPPORT);
}
emitNewPage(page: number): void {
this.reportsPaginated.emit(page);

View File

@@ -96,27 +96,7 @@
id="confirmAvvikelserapport"
>
<msfa-loader *ngIf="submitIsLoading$ | async" type="absolute"></msfa-loader>
<dl>
<dt>Namn</dt>
<dd>{{avrop.fullName}}</dd>
<dt>Personnummer</dt>
<dd>
<msfa-hide-text
symbols="********-****"
[changingText]="avrop.ssn"
ariaLabelType="Personnummer"
></msfa-hide-text>
</dd>
<dt>Tjänst</dt>
<dd>{{avrop.tjanst}}</dd>
<dt>Startdatum</dt>
<dd>
<digi-typography-time [afDateTime]="avrop.startDate"></digi-typography-time>
</dd>
<dt>Slutdatum</dt>
<dd>
<digi-typography-time [afDateTime]="avrop.endDate"></digi-typography-time>
</dd>
<msfa-report-description-list [avrop]="avrop">
<dt>Orsak till avvikelse:</dt>
<dd>{{(chosenReason$ | async)?.name }}</dd>
<ng-container *ngIf="avvikelseSubmitData$ | async; let avvikelseSubmitData; else loadingRef">
@@ -127,7 +107,7 @@
<dt>Dag för avvikelse:</dt>
<dd>{{avvikelseSubmitData.avvikelseAlternativ.rapporteringsdatum }}</dd>
</ng-container>
</dl>
</msfa-report-description-list>
<digi-notification-alert
*ngIf="submitError$ | async as error"
af-variation="danger"

View File

@@ -12,9 +12,9 @@ import { ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module';
import { ConfirmDialogModule } from '@msfa-shared/components/confirm-dialog/confirm-dialog.module';
import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.module';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { LoaderModule } from '@msfa-shared/components/loader/loader.module';
import { ReportDescriptionListModule } from '../../../components/report-description-list/report-description-list.module';
import { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
import { AvvikelseReportFormComponent } from './avvikelse-report-form.component';
import { AvvikelseReportFormService } from './avvikelse-report-form.service';
@@ -37,7 +37,7 @@ import { AvvikelseReportFormService } from './avvikelse-report-form.service';
DigiNgSkeletonBaseModule,
DigiNgFormSelectModule,
LoaderModule,
HideTextModule,
ReportDescriptionListModule,
DigiNgFormInputModule,
DigiNgDialogModule,
],

View File

@@ -271,52 +271,34 @@
id="confirm-franvaro-report"
>
<msfa-loader *ngIf="submitLoading$ | async" type="absolute"></msfa-loader>
<dl *ngIf="reasons$ | async as reasons">
<dt>Namn</dt>
<dd>{{avrop.fullName}}</dd>
<dt>Personnummer</dt>
<dd>
<msfa-hide-text
symbols="********-****"
[changingText]="avrop.ssn"
ariaLabelType="Personnummer"
></msfa-hide-text>
</dd>
<dt>Tjänst</dt>
<dd>{{avrop.tjanst}}</dd>
<dt>Startdatum</dt>
<dd>
<digi-typography-time [afDateTime]="avrop.startDate"></digi-typography-time>
</dd>
<dt>Slutdatum</dt>
<dd>
<digi-typography-time [afDateTime]="avrop.endDate"></digi-typography-time>
</dd>
<dt>Orsak till frånvaro</dt>
<dd>{{getReasonNameFromValue(reasons, reasonFormControl.value)}}</dd>
<ng-container *ngIf="showOtherKnownReasonsSelect">
<ng-container *ngIf="otherKnownReasons$ | async as otherKnownReasons">
<dt>Annan känd orsak</dt>
<dd>{{getReasonNameFromValue(otherKnownReasons, otherKnownReasonFormControl.value)}}</dd>
<msfa-report-description-list [avrop]="avrop">
<ng-container *ngIf="reasons$ | async as reasons">
<dt>Orsak till frånvaro</dt>
<dd>{{getReasonNameFromValue(reasons, reasonFormControl.value)}}</dd>
<ng-container *ngIf="showOtherKnownReasonsSelect">
<ng-container *ngIf="otherKnownReasons$ | async as otherKnownReasons">
<dt>Annan känd orsak</dt>
<dd>{{getReasonNameFromValue(otherKnownReasons, otherKnownReasonFormControl.value)}}</dd>
</ng-container>
<ng-container *ngIf="showKnownReasonTextArea">
<dt>Beskrivning för frånvaro</dt>
<dd>{{knownReasonCommentFormControl.value}}</dd>
</ng-container>
</ng-container>
<ng-container *ngIf="showKnownReasonTextArea">
<dt>Beskrivning för frånvaro</dt>
<dd>{{knownReasonCommentFormControl.value}}</dd>
<dt>Dag för frånvaro</dt>
<dd>
<digi-typography-time [afDateTime]="dateFormValueAsDate"></digi-typography-time>
</dd>
<dt>Heldag eller del av dag</dt>
<dd>{{dayOrPartOfDayFromValue}}</dd>
<ng-container *ngIf="showTimePickers">
<dt>Tid för frånvaro</dt>
<dd>{{startTimeFormControl.value}} - {{endTimeFormControl.value}}</dd>
</ng-container>
<dt>Tid för förväntad närvaro</dt>
<dd>{{expectedPresenceStartTimeFormControl.value}} - {{expectedPresenceEndTimeFormControl.value}}</dd>
</ng-container>
<dt>Dag för frånvaro</dt>
<dd>
<digi-typography-time [afDateTime]="dateFormValueAsDate"></digi-typography-time>
</dd>
<dt>Heldag eller del av dag</dt>
<dd>{{dayOrPartOfDayFromValue}}</dd>
<ng-container *ngIf="showTimePickers">
<dt>Tid för frånvaro</dt>
<dd>{{startTimeFormControl.value}} - {{endTimeFormControl.value}}</dd>
</ng-container>
<dt>Tid för förväntad närvaro</dt>
<dd>{{expectedPresenceStartTimeFormControl.value}} - {{expectedPresenceEndTimeFormControl.value}}</dd>
</dl>
</msfa-report-description-list>
<digi-notification-alert
*ngIf="submitError$ | async as error"
class="franvaro-report-form__alert"

View File

@@ -11,9 +11,9 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module';
import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.module';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { LoaderModule } from '@msfa-shared/components/loader/loader.module';
import { ReportDescriptionListModule } from '../../../components/report-description-list/report-description-list.module';
import { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
import { FranvaroReportFormComponent } from './franvaro-report-form.component';
import { FranvaroReportFormService } from './franvaro-report-form.service';
@@ -29,7 +29,7 @@ import { FranvaroReportFormService } from './franvaro-report-form.service';
ReportLayoutModule,
LoaderModule,
BackLinkModule,
HideTextModule,
ReportDescriptionListModule,
DigiNgFormSelectModule,
DigiNgFormDatepickerModule,
DigiNgFormRadiobuttonGroupModule,

View File

@@ -100,27 +100,7 @@
id="confirm-gemensam-planering-form"
>
<msfa-loader *ngIf="submitLoading$ | async" type="absolute"></msfa-loader>
<dl>
<dt>Namn</dt>
<dd>{{avrop.fullName}}</dd>
<dt>Personnummer</dt>
<dd>
<msfa-hide-text
symbols="********-****"
[changingText]="avrop.ssn"
ariaLabelType="Personnummer"
></msfa-hide-text>
</dd>
<dt>Tjänst</dt>
<dd>{{avrop.tjanst}}</dd>
<dt>Startdatum</dt>
<dd>
<digi-typography-time [afDateTime]="avrop.startDate"></digi-typography-time>
</dd>
<dt>Slutdatum</dt>
<dd>
<digi-typography-time [afDateTime]="avrop.endDate"></digi-typography-time>
</dd>
<msfa-report-description-list [avrop]="avrop">
<dt>Deltar arbetssökande på distans?</dt>
<dd>{{gpFormGroup.value.distance ? 'Ja' : 'Nej'}}</dd>
<dt>Aktiviteter</dt>
@@ -138,7 +118,7 @@
</li>
</ul>
</dd>
</dl>
</msfa-report-description-list>
<digi-notification-alert
*ngIf="error$ | async as error"
class="gemensam-planering-form__alert"

View File

@@ -8,9 +8,9 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module';
import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.module';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { LoaderModule } from '@msfa-shared/components/loader/loader.module';
import { ReportDescriptionListModule } from '../../../components/report-description-list/report-description-list.module';
import { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
import { GemensamPlaneringFormComponent } from './gemensam-planering-form.component';
import { GemensamPlaneringFormService } from './gemensam-planering-form.service';
@@ -28,7 +28,7 @@ import { GemensamPlaneringFormService } from './gemensam-planering-form.service'
ReportLayoutModule,
BackLinkModule,
LoaderModule,
HideTextModule,
ReportDescriptionListModule,
DigiNgSkeletonBaseModule,
DigiNgFormCheckboxModule,
DigiNgDialogModule,

View File

@@ -0,0 +1,163 @@
<msfa-layout>
<msfa-report-layout
*ngIf="avrop$ | async as avrop, else skeletonRef"
[avrop]="avrop"
reportTitle="Skapa Informativ rapport"
>
<div class="informativ-rapport-form" *ngIf="genomforandeReferens$ | async as genomforandeReferens">
<div
class="informativ-rapport-form__confirmation"
*ngIf="lastSubmittedInformativRapport$ | async as lastSubmittedInformativRapport; else formRef"
>
<digi-notification-alert af-variation="success" af-heading="Allt gick bra" af-heading-level="h3">
<p>Informativ rapport för deltagare {{avrop.fullName}} är nu inskickad till Arbetsförmedlingen.</p>
<dl>
<dt>Datum</dt>
<dd>
{{lastSubmittedInformativRapport | date:'longDate'}} kl {{lastSubmittedInformativRapport |
date:'shortTime'}}
</dd>
</dl>
</digi-notification-alert>
<msfa-back-link route="../">Tillbaka till deltagaren</msfa-back-link>
</div>
<ng-template #formRef>
<form
class="informativ-rapport-form__form"
[formGroup]="informativRapportFormGroup"
id="informativ-rapport-form"
(ngSubmit)="openConfirmDialog()"
>
<div class="informativ-rapport-form__form-item">
<div class="informativ-rapport-form__label-wrapper">
<label for="informativ-rapport-form-category">Vad gäller ärendet</label>
<digi-button
class="informativ-rapport-form__category-information-button"
af-variation="tertiary"
(afOnClick)="openCategoryInformationDialog()"
>
<digi-icon-info-circle-solid
class="msfa__digi-icon informativ-rapport-form__category-information-icon"
slot="icon"
aria-hidden="true"
></digi-icon-info-circle-solid>
Info
<span class="msfa__a11y-sr-only"> om kategorierna</span>
</digi-button>
</div>
<digi-ng-form-select
class="informativ-rapport-form__category-select"
[formControl]="categoryFormControl"
afLabel=""
afPlaceholder="Välj kategori"
afId="informativ-rapport-form-category"
[afSelectItems]="categorySelectItems"
[afRequired]="true"
[afAnnounceIfOptional]="true"
[afInvalidMessage]="categoryFormControl.errors?.required"
[afDisableValidStyle]="true"
[afInvalid]="formControlIsInvalid('category')"
></digi-ng-form-select>
</div>
<div class="informativ-rapport-form__form-item">
<digi-ng-form-textarea
[formControl]="commentFormControl"
afLabel="Kompletterande information"
afDescription="Undvik att skriva in information som känsliga personuppgifter, skyddad identitet eller deltagarens mående. Skriv i sådant fall in det telefonnummer du vill bli kontaktad på, vi bedömer om återkoppling är relevant."
[afDisableValidStyle]="true"
[afRequired]="true"
[afInvalidMessage]="commentFormControl.errors?.required"
[afAnnounceIfOptional]="true"
[afMaxLength]="2000"
[afInvalid]="formControlIsInvalid('comment')"
></digi-ng-form-textarea>
</div>
<footer class="informativ-rapport-form__footer">
<div class="informativ-rapport-form__cta-wrapper">
<digi-button af-type="submit" af-size="m">Förhandsgranska</digi-button>
<msfa-back-link [showIcon]="false" [asButton]="true" route="../">
<span>Avbryt</span>
<span class="msfa__a11y-sr-only">&nbsp;och gå tillbaka till deltagaren</span>
</msfa-back-link>
</div>
</footer>
<digi-ng-dialog
[afActive]="confirmDialogOpen$ | async"
(afOnPrimaryClick)="submitAndCloseConfirmDialog()"
(afOnInactive)="cancelConfirmDialog()"
afHeadingLevel="h2"
afPrimaryButtonText="Skicka in"
afSecondaryButtonText="Avbryt"
(afOnSecondaryClick)="cancelConfirmDialog()"
afHeading="Vill du skicka in Informativ rapport"
afAriaLabel="Förhandsgranska och skicka in Informativ rapport"
id="confirm-informativ-rapport"
>
<msfa-loader *ngIf="submitLoading$ | async" type="absolute"></msfa-loader>
<msfa-report-description-list [avrop]="avrop">
<ng-container *ngIf="submitData$ | async; let submitData; else loadingRef">
<dt>Vad gäller ärendet</dt>
<dd>{{getInformativRapportCategory(submitData.category)}}</dd>
<dt>Kompletterande information</dt>
<dd>{{submitData.comment}}</dd>
</ng-container>
</msfa-report-description-list>
<digi-notification-alert
*ngIf="submitError$ | async as error"
class="informativ-rapport-form__alert"
af-variation="danger"
af-heading="Någonting gick fel"
>
<p>Kunde inte spara Informativ rapport. 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>
<digi-ng-dialog
[afActive]="categoryInformationDialogOpen$ | async"
(afOnPrimaryClick)="closeCategoryInformationDialog()"
(afOnInactive)="closeCategoryInformationDialog()"
afHeadingLevel="h2"
afPrimaryButtonText="Stäng"
afHeading="Deltaljerad information om de olika kategorier"
afAriaLabel="Här står det mer detaljerad information för vad kategorierna innebär"
id="category-information"
>
<!-- <h3>Skicka dokumentation till Arbetsförmedlingen</h3>
<p>Skicka in dokumentation som Arbetsförmedlingen begärt.</p> -->
<h3>Behov av annan insats</h3>
<p>
Informera om att deltagaren kan behöva en arbetsmarknadspolitisk insats, exempelvis utbildning,
yrkessvenska, karriärvägledning, studiemotiverande folkhögskoleutbildning, praktik med mera.
</p>
<h3>Behov av hjälpmedel</h3>
<p>
Informera om att deltagare med funktionsnedsättning har behov av hjälpmedel under tjänsten, som vi som
leverantör inte kan tillhandahålla.
</p>
<h3>Behov av teckenspråkstolk</h3>
<p>Informera om att deltagare har behov av teckenspråkstolk.</p>
<h3>Behov av dialog med Arbetsförmedlingen</h3>
<p>
Informera om att det behövs dialog gällande deltagarens ärende, exempelvis inför eventuellt
stöd/anpassning eller hälsa.
</p>
</digi-ng-dialog>
</form>
</ng-template>
</div>
</msfa-report-layout>
</msfa-layout>
<ng-template #skeletonRef>
<digi-ng-skeleton-base
[afCount]="3"
afText="Laddar data för att kunna skapa Informativ rapport"
></digi-ng-skeleton-base>
</ng-template>
<ng-template #loadingRef>
<msfa-loader type="padded"></msfa-loader>
</ng-template>

View File

@@ -0,0 +1,64 @@
@import 'variables/gutters';
@import 'variables/z-index';
.informativ-rapport-form {
max-width: var(--digi--typography--text--max-width);
&__confirmation,
&__warning,
&__form {
display: flex;
flex-direction: column;
gap: $digi--layout--gutter--l;
}
&__label-wrapper {
display: flex;
gap: var(--digi--layout--gutter);
padding-bottom: var(--digi--layout--gutter--s);
label {
font-weight: var(--digi--typography--font-weight--semibold);
cursor: pointer;
}
}
&__category-information-button {
::ng-deep .digi-button {
padding: 0;
&__icon {
margin-right: var(--digi--layout--gutter--xs);
}
}
}
&__category-information-icon {
width: 1.25em;
}
&__category-select {
::ng-deep .digi-ng-form-select__label {
display: none;
}
}
&__footer {
display: flex;
flex-direction: column;
gap: var(--digi--layout--gutter);
}
&__cta-wrapper {
display: flex;
gap: var(--digi--layout--gutter);
}
&__validation-message {
margin-top: var(--digi--layout--gutter--s);
}
&__percent-range {
max-width: 20rem;
display: block;
}
}

View File

@@ -0,0 +1,33 @@
import { DigiNgFormRadiobuttonGroupModule } from '@af/digi-ng/_form/form-radiobutton-group';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { RouterTestingModule } from '@angular/router/testing';
import { LayoutComponent } from '@msfa-shared/components/layout/layout.component';
import { InformativRapportFormComponent } from './informativ-rapport-form.component';
import { InformativRapportFormService } from './informativ-rapport-form.service';
describe('InformativRapportFormComponent', () => {
let component: InformativRapportFormComponent;
let fixture: ComponentFixture<InformativRapportFormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [InformativRapportFormComponent, LayoutComponent],
imports: [RouterTestingModule, HttpClientTestingModule, ReactiveFormsModule, DigiNgFormRadiobuttonGroupModule],
providers: [InformativRapportFormService],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(InformativRapportFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,130 @@
import { FormSelectItem } from '@af/digi-ng/_form/form-select';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { InformativRapportCategory, InformativRapportCategoryKey } from '@msfa-enums/informativ-rapport-category.enum';
import { InformativRapportRequest } from '@msfa-models/api/informativ-rapport.request.model';
import { Avrop } from '@msfa-models/avrop.model';
import { CustomError } from '@msfa-models/error/custom-error';
import { RequiredValidator } from '@msfa-utils/validators/required.validator';
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
import { map, shareReplay, switchMap, take } from 'rxjs/operators';
import { InformativRapportFormData } from './informativ-rapport-form.model';
import { InformativRapportFormService } from './informativ-rapport-form.service';
@Component({
selector: 'msfa-informativ-rapport-form',
templateUrl: './informativ-rapport-form.component.html',
styleUrls: ['./informativ-rapport-form.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class InformativRapportFormComponent {
shouldValidate$ = new BehaviorSubject<boolean>(false);
confirmDialogOpen$ = new BehaviorSubject<boolean>(false);
categoryInformationDialogOpen$ = new BehaviorSubject<boolean>(false);
submitLoading$ = new BehaviorSubject<boolean>(false);
lastSubmittedInformativRapport$ = new BehaviorSubject<Date>(null);
submitError$ = new BehaviorSubject<CustomError>(null);
genomforandeReferens$: Observable<number> = this.activatedRoute.params.pipe(
map(params => +params.genomforandeReferens)
);
avrop$: Observable<Avrop> = this.genomforandeReferens$.pipe(
switchMap(genomforandeReferens => this.informativRapportFormService.fetchAvropInformation$(genomforandeReferens)),
shareReplay(1)
);
informativRapportFormGroup = new FormGroup({
category: new FormControl(null, [RequiredValidator('Ett ärende måste väljas')]),
comment: new FormControl('', [RequiredValidator('Kompletterande information är obligatoriskt')]),
});
categorySelectItems: FormSelectItem[] = Object.entries(InformativRapportCategory).map(([value, name]) => ({
name,
value,
}));
formData$: Observable<InformativRapportFormData> = this.informativRapportFormGroup
.valueChanges as Observable<InformativRapportFormData>;
submitData$ = combineLatest([this.genomforandeReferens$, this.formData$]).pipe(
map(([genomforandeReferens, formData]) => this._formDataToSubmitData(genomforandeReferens, formData)),
shareReplay(1)
);
constructor(
private informativRapportFormService: InformativRapportFormService,
private activatedRoute: ActivatedRoute
) {}
get categoryFormControl(): FormControl {
return this.informativRapportFormGroup.get('category') as FormControl;
}
get commentFormControl(): FormControl {
return this.informativRapportFormGroup.get('comment') as FormControl;
}
private _formDataToSubmitData(
genomforandeReferens: number,
formData: InformativRapportFormData
): InformativRapportRequest {
const { category, comment } = formData;
return {
genomforandeReferens,
category,
comment,
};
}
private _markFormAsTouchedAndDirty(): void {
this.informativRapportFormGroup.markAllAsTouched();
this.commentFormControl.markAsDirty();
this.categoryFormControl.markAsDirty();
}
getInformativRapportCategory(category: InformativRapportCategoryKey): InformativRapportCategory {
return InformativRapportCategory[category] as InformativRapportCategory;
}
formControlIsInvalid(formControlName: string): boolean {
return this.informativRapportFormGroup.get(formControlName).errors && this.shouldValidate$.getValue();
}
openCategoryInformationDialog(): void {
this.categoryInformationDialogOpen$.next(true);
}
closeCategoryInformationDialog(): void {
this.categoryInformationDialogOpen$.next(false);
}
openConfirmDialog(): void {
this.shouldValidate$.next(true);
this._markFormAsTouchedAndDirty();
if (this.informativRapportFormGroup.invalid) {
return;
}
this.confirmDialogOpen$.next(true);
}
cancelConfirmDialog(): void {
this.confirmDialogOpen$.next(false);
this.submitError$.next(null);
}
submitAndCloseConfirmDialog(): void {
this.submitLoading$.next(true);
this.submitData$.pipe(take(1)).subscribe(submitData =>
this.informativRapportFormService.postInformativRapport$(submitData).subscribe({
next: () => {
this.submitLoading$.next(false);
this.lastSubmittedInformativRapport$.next(new Date());
this.confirmDialogOpen$.next(false);
},
error: (customError: CustomError) => {
this.submitError$.next({ ...customError, message: customError.error.message });
this.submitLoading$.next(false);
throw { ...customError, avoidToast: true };
},
})
);
}
}

View File

@@ -0,0 +1,6 @@
import { InformativRapportCategoryKey } from '@msfa-enums/informativ-rapport-category.enum';
export interface InformativRapportFormData {
category: InformativRapportCategoryKey;
comment: string;
}

View File

@@ -0,0 +1,37 @@
import { DigiNgDialogModule } from '@af/digi-ng/_dialog/dialog';
import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select';
import { DigiNgFormTextareaModule } from '@af/digi-ng/_form/form-textarea';
import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base';
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module';
import { ConfirmDialogModule } from '@msfa-shared/components/confirm-dialog/confirm-dialog.module';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { ReportDescriptionListModule } from '../../../components/report-description-list/report-description-list.module';
import { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
import { InformativRapportFormComponent } from './informativ-rapport-form.component';
import { InformativRapportFormService } from './informativ-rapport-form.service';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [InformativRapportFormComponent],
imports: [
CommonModule,
RouterModule.forChild([{ path: '', component: InformativRapportFormComponent }]),
LayoutModule,
ReactiveFormsModule,
ReportLayoutModule,
ConfirmDialogModule,
ReportDescriptionListModule,
BackLinkModule,
DigiNgSkeletonBaseModule,
DigiNgDialogModule,
DigiNgFormSelectModule,
DigiNgFormTextareaModule,
],
providers: [InformativRapportFormService],
exports: [InformativRapportFormComponent],
})
export class InformativRapportFormModule {}

View File

@@ -0,0 +1,22 @@
import { Injectable } from '@angular/core';
import { InformativRapportRequest } from '@msfa-models/api/informativ-rapport.request.model';
import { Avrop } from '@msfa-models/avrop.model';
import { DeltagareApiService } from '@msfa-services/api/deltagare.api.service';
import { InformativRapportApiService } from '@msfa-services/api/informativ-rapport.api.service';
import { Observable } from 'rxjs';
@Injectable()
export class InformativRapportFormService {
constructor(
private informativRapportApiService: InformativRapportApiService,
private deltagareApiService: DeltagareApiService
) {}
public postInformativRapport$(requestData: InformativRapportRequest): Observable<void> {
return this.informativRapportApiService.postInformativRapport$(requestData);
}
public fetchAvropInformation$(genomforandeReferens: number): Observable<Avrop> {
return this.deltagareApiService.fetchAvropInformation$(genomforandeReferens);
}
}

View File

@@ -36,6 +36,7 @@
[afSelectItems]="periodsToFormselectItems(periods)"
[afDisableValidStyle]="true"
[afRequired]="true"
[afAnnounceIfOptional]="true"
[formControl]="periodFormControl"
[afInvalid]="formControlIsInvalid(periodFormControl)"
(afOnChange)="openChangePeriodDialogIfValuesExist()"
@@ -182,27 +183,7 @@
id="confirm-periodisk-redovisning-form"
>
<msfa-loader *ngIf="submitIsLoading$ | async" type="absolute"></msfa-loader>
<dl>
<dt>Namn</dt>
<dd>{{avrop.fullName}}</dd>
<dt>Personnummer</dt>
<dd>
<msfa-hide-text
symbols="********-****"
[changingText]="avrop.ssn"
ariaLabelType="Personnummer"
></msfa-hide-text>
</dd>
<dt>Tjänst</dt>
<dd>{{avrop.tjanst}}</dd>
<dt>Startdatum</dt>
<dd>
<digi-typography-time [afDateTime]="avrop.startDate"></digi-typography-time>
</dd>
<dt>Slutdatum</dt>
<dd>
<digi-typography-time [afDateTime]="avrop.endDate"></digi-typography-time>
</dd>
<msfa-report-description-list [avrop]="avrop">
<ng-container *ngIf="submitData$ | async; let submitData; else loadingRef">
<dt>Har ni under perioden tillhandahållit språkstöd till deltagaren:</dt>
<dd>{{submitData.hasOfferedLanguageSupport ? 'Ja' : 'Nej' }}</dd>
@@ -228,7 +209,7 @@
</dd>
</ng-template>
</ng-container>
</dl>
</msfa-report-description-list>
<digi-notification-alert
*ngIf="submitError$ | async as error"
af-variation="danger"

View File

@@ -1,4 +1,7 @@
import { DigiNgDialogModule } from '@af/digi-ng/_dialog/dialog';
import { DigiNgFormCheckboxModule } from '@af/digi-ng/_form/form-checkbox';
import { DigiNgFormRadiobuttonGroupModule } from '@af/digi-ng/_form/form-radiobutton-group';
import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select';
import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base';
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
@@ -7,13 +10,10 @@ import { RouterModule } from '@angular/router';
import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { LoaderModule } from '@msfa-shared/components/loader/loader.module';
import { ReportDescriptionListModule } from '../../../components/report-description-list/report-description-list.module';
import { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
import { PeriodiskRedovisningFormComponent } from './periodisk-redovisning-form.component';
import { PeriodiskRedovisningFormService } from './periodisk-redovisning-form.service';
import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select';
import { DigiNgFormRadiobuttonGroupModule } from '@af/digi-ng/_form/form-radiobutton-group';
import { DigiNgFormCheckboxModule } from '@af/digi-ng/_form/form-checkbox';
import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.module';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
@@ -24,6 +24,7 @@ import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.modu
LayoutModule,
ReactiveFormsModule,
ReportLayoutModule,
ReportDescriptionListModule,
BackLinkModule,
LoaderModule,
DigiNgSkeletonBaseModule,
@@ -31,7 +32,6 @@ import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.modu
DigiNgFormSelectModule,
DigiNgFormRadiobuttonGroupModule,
DigiNgFormCheckboxModule,
HideTextModule,
],
providers: [PeriodiskRedovisningFormService],
exports: [PeriodiskRedovisningFormComponent],

View File

@@ -123,7 +123,7 @@
id="confirm-signal"
>
<msfa-loader *ngIf="submitLoading$ | async" type="absolute"></msfa-loader>
<dl>
<msfa-report-description-list [avrop]="avrop">
<dt>Typ av sysselsättning</dt>
<dd>{{typeFormControl.value}}</dd>
<dt>Omfattning</dt>
@@ -134,7 +134,7 @@
</ng-container>
<dt>Startdatum</dt>
<dd><digi-typography-time [afDateTime]="startDateFormValueAsDate"></digi-typography-time></dd>
</dl>
</msfa-report-description-list>
<digi-notification-alert
*ngIf="error$ | async as error"
class="signal-form__alert"

View File

@@ -3,7 +3,6 @@ import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module';
import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.module';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { LoaderModule } from '@msfa-shared/components/loader/loader.module';
import { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
@@ -20,7 +19,6 @@ import { AvvikelseReportViewService } from './avvikelse-report-view.service';
ReportLayoutModule,
BackLinkModule,
LoaderModule,
HideTextModule,
DigiNgSkeletonBaseModule,
],
providers: [AvvikelseReportViewService],

View File

@@ -3,7 +3,6 @@ import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module';
import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.module';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { LoaderModule } from '@msfa-shared/components/loader/loader.module';
import { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
@@ -20,7 +19,6 @@ import { FranvaroReportViewService } from './franvaro-report-view.service';
ReportLayoutModule,
BackLinkModule,
LoaderModule,
HideTextModule,
DigiNgSkeletonBaseModule,
],
providers: [FranvaroReportViewService],

View File

@@ -3,7 +3,6 @@ import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module';
import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.module';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { LoaderModule } from '@msfa-shared/components/loader/loader.module';
import { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
@@ -20,7 +19,6 @@ import { GemensamPlaneringViewService } from './gemensam-planering-view.service'
ReportLayoutModule,
BackLinkModule,
LoaderModule,
HideTextModule,
DigiNgSkeletonBaseModule,
],
providers: [GemensamPlaneringViewService],

View File

@@ -3,7 +3,7 @@
<a
class="navigation__logo-link"
[routerLink]="['/']"
aria-label="Till startsidan för mina sidor för fristående aktörer"
aria-label="Till startsidan för Mina sidor för fristående aktörer"
>
<digi-logo af-system-name="Mina sidor för fristående aktörer" af-color="secondary"></digi-logo>
</a>

View File

@@ -4,6 +4,7 @@ export const DELTAGARE_REPORTING_ROUTES = {
franvarorapport: 'Avvikelserapport (frånvaro)',
avvikelserapport: 'Avvikelserapport (avvikelse)',
signal: 'Signal om arbete eller studier',
'informativ-rapport': 'Informativ rapport',
};
export const NAVIGATION = {

View File

@@ -14,4 +14,5 @@ export enum Feature {
REPORTING,
REPORTING_SIGNAL,
REPORTING_PERIODISK_REDOVISNING,
REPORTING_INFORMATIV_RAPPORT,
}

View File

@@ -0,0 +1,8 @@
export enum InformativRapportCategory {
annan_insats = 'Behov av annan insats',
hjalpmedel = 'Behov av hjälpmedel',
teckensprakstolk = 'Behov av teckenspråkstolk',
dialog = 'Behov av dialog med Arbetsförmedlingen',
}
export type InformativRapportCategoryKey = keyof InformativRapportCategory;

View File

@@ -0,0 +1,6 @@
import { InformativRapportCategoryKey } from '@msfa-enums/informativ-rapport-category.enum';
export interface InformativRapportRequest {
genomforandeReferens: number;
category: InformativRapportCategoryKey;
comment: string;
}

View File

@@ -0,0 +1,6 @@
import { InformativRapportCategoryKey } from '@msfa-enums/informativ-rapport-category.enum';
export interface InformativRapportResponse {
category: InformativRapportCategoryKey;
comment: string;
}

View File

@@ -0,0 +1,16 @@
import { InformativRapportCategory } from '@msfa-enums/informativ-rapport-category.enum';
import { InformativRapportResponse } from './api/informativ-rapport.response.model';
export interface InformativRapport {
category: InformativRapportCategory;
comment: string;
}
export function mapResponseToInformativRapport(data: InformativRapportResponse): InformativRapport {
const { category, comment } = data;
return {
category: InformativRapportCategory[category] as InformativRapportCategory,
comment: comment,
};
}

View File

@@ -0,0 +1,29 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ErrorType } from '@msfa-enums/error-type.enum';
import { environment } from '@msfa-environment';
import { InformativRapportRequest } from '@msfa-models/api/informativ-rapport.request.model';
import { CustomError } from '@msfa-models/error/custom-error';
import { Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';
@Injectable({
providedIn: 'root',
})
export class InformativRapportApiService {
private _apiBaseUrl = `${environment.api.url}/rapporter/informativ-rapport`;
public postInformativRapport$(requestData: InformativRapportRequest): Observable<void> {
return this.httpClient.post<void>(this._apiBaseUrl, requestData).pipe(
catchError((error: Error) => {
throw new CustomError({
error,
message: `Kunde inte spara Informativ rapport.\n\n${error.message}`,
type: ErrorType.API,
});
})
);
}
constructor(private httpClient: HttpClient) {}
}

View File

@@ -7,6 +7,7 @@ export function RequiredValidator(message = 'Fältet är obligatoriskt'): Valida
if (
control.value === null ||
control.value === undefined ||
control.value === '' ||
(Array.isArray(control.value) && !control.value.length)
) {
return { required: message };

View File

@@ -24,4 +24,5 @@ export const ACTIVE_FEATURES_TEST: Feature[] = [
Feature.RELEASES,
Feature.VERSION_INFO,
Feature.REPORTING_PERIODISK_REDOVISNING,
Feature.REPORTING_INFORMATIV_RAPPORT,
];