feat(avrop): Added additional functionality to avrop-flow. (TV-411)
Squashed commit of the following: commit b174dd7480baa5e5e4b7f4bea4c9fc674d344c0c Merge: e1f9d2d0661d22Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Thu Aug 26 11:50:11 2021 +0200 Merged develop and resolved conflicts commit e1f9d2d49e279e704b760a3cbe45941cdcfb81d9 Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Thu Aug 26 11:41:45 2021 +0200 Now fetching handledare and patching through API commit cc017fdc6eb5d9620399eee011341a0307fe5658 Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Wed Aug 25 16:02:20 2021 +0200 Updated some functionality commit 345712842c12af08dd4a956d0d2fdfd2592ab3de Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Wed Aug 25 15:32:22 2021 +0200 Implmented pagination and select all commit 95f9be3fae6d3f3b258897be9b78f49442ee0747 Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Wed Aug 25 13:03:41 2021 +0200 Renamed avrop-table instances to avrop-list and avrop-table-row to avrop-row commit 5f1e11bff74c942e2c8b9e62892f043dc299f612 Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Wed Aug 25 12:54:56 2021 +0200 Added some changes to mock-api related to parameter changes inside avrop commit 71b199744a31b2a4b8bcaa6870094fd900851030 Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Wed Aug 25 12:23:57 2021 +0200 added qp to avrop requests commit dc0e34b4971ddfd3d683d482502439b961df8852 Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Tue Aug 24 16:02:31 2021 +0200 Renamed multiple variablenames inside avrop-api commit 8a4d5471cf637db7d90c6659c893f6841ec9c961 Merge: be9e9b350a83f7Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Tue Aug 24 13:57:50 2021 +0200 Merged develop and fixed conflicts commit be9e9b323aee76493b5035cd79f6058781ae4c1a Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Tue Aug 24 13:27:16 2021 +0200 Moved around elements inside avrop component commit 7ede2d00cd7ed105ef12be88e2ab788841329f00 Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Tue Aug 24 09:34:57 2021 +0200 Moved around some components and other files to match project-structure commit 7d1396216de643388a5690f2fa2733f127623b6c Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Tue Aug 24 09:04:28 2021 +0200 Fixed issues with utforande verksamheter model and mock-data commit 22baca18c25bd4ce8dcc713e91126214882cf017 Merge: 4ba3c1c59ce393Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Tue Aug 24 08:56:02 2021 +0200 Merged develop and fixed conflicts commit 4ba3c1ce9dac206602de9651a98aecfd5857a0e5 Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Tue Aug 24 08:48:21 2021 +0200 Fixed issues with tjanst model and mock-data commit 50d8c698778fa64cedd4249f6852715d038b450c Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Tue Aug 24 08:40:25 2021 +0200 Fixed issues with kommun-model and mock-data
This commit is contained in:
@@ -39,7 +39,9 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ng-container *ngIf="employee.utforandeVerksamheter.length">
|
<ng-container *ngIf="employee.utforandeVerksamheter.length">
|
||||||
{{ employee.utforandeVerksamheter[0]['namn'] }}<ng-container *ngIf="employee.utforandeVerksamheter.length > 1">
|
{{ employee.utforandeVerksamheter[0]['namn'] }}<ng-container
|
||||||
|
*ngIf="employee.utforandeVerksamheter.length > 1"
|
||||||
|
>
|
||||||
(+{{employee.utforandeVerksamheter.length - 1}})</ng-container
|
(+{{employee.utforandeVerksamheter.length - 1}})</ng-container
|
||||||
>
|
>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
@@ -74,9 +76,9 @@
|
|||||||
</digi-ng-dialog>
|
</digi-ng-dialog>
|
||||||
|
|
||||||
<digi-navigation-pagination
|
<digi-navigation-pagination
|
||||||
*ngIf="totalPages > 1"
|
*ngIf="totalPage > 1"
|
||||||
class="employees-list__pagination"
|
class="employees-list__pagination"
|
||||||
[afTotalPages]="totalPages"
|
[afTotalPages]="totalPage"
|
||||||
[afCurrentResultStart]="currentResultStart"
|
[afCurrentResultStart]="currentResultStart"
|
||||||
[afCurrentResultEnd]="currentResultEnd"
|
[afCurrentResultEnd]="currentResultEnd"
|
||||||
[afTotalResults]="count"
|
[afTotalResults]="count"
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ describe('EmployeesListComponent', () => {
|
|||||||
describe('20 employees sorted by Full name Ascending', () => {
|
describe('20 employees sorted by Full name Ascending', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
component.employees = employeesMock;
|
component.employees = employeesMock;
|
||||||
component.paginationMeta = { count: employeesMock.length, limit: 50, page: 1, totalPages: 3 };
|
component.paginationMeta = { count: employeesMock.length, limit: 50, page: 1, totalPage: 3 };
|
||||||
component.sort = { key: <keyof EmployeeCompactResponse>'fullName', order: SortOrder.ASC };
|
component.sort = { key: <keyof EmployeeCompactResponse>'fullName', order: SortOrder.ASC };
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export class EmployeesListComponent implements OnDestroy {
|
|||||||
employeeSelected$: Observable<EmployeeCompact> = this._employeeSelected$.asObservable();
|
employeeSelected$: Observable<EmployeeCompact> = this._employeeSelected$.asObservable();
|
||||||
showDialog: boolean;
|
showDialog: boolean;
|
||||||
|
|
||||||
constructor(private employeeService: EmployeeService) { }
|
constructor(private employeeService: EmployeeService) {}
|
||||||
|
|
||||||
columnHeaders: { label: string; key: keyof EmployeeCompactResponse }[] = [
|
columnHeaders: { label: string; key: keyof EmployeeCompactResponse }[] = [
|
||||||
{ label: 'Namn', key: 'name' },
|
{ label: 'Namn', key: 'name' },
|
||||||
@@ -47,8 +47,8 @@ export class EmployeesListComponent implements OnDestroy {
|
|||||||
return this.paginationMeta.page;
|
return this.paginationMeta.page;
|
||||||
}
|
}
|
||||||
|
|
||||||
get totalPages(): number {
|
get totalPage(): number {
|
||||||
return this.paginationMeta?.totalPages;
|
return this.paginationMeta?.totalPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
get count(): number {
|
get count(): number {
|
||||||
@@ -73,7 +73,8 @@ export class EmployeesListComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onDeleteEmployee(employee: EmployeeCompact): void {
|
onDeleteEmployee(employee: EmployeeCompact): void {
|
||||||
this.employeeService.deleteEmployee(employee.id)
|
this.employeeService
|
||||||
|
.deleteEmployee(employee.id)
|
||||||
.pipe(takeUntil(this.componentDestroyed$))
|
.pipe(takeUntil(this.componentDestroyed$))
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: (res: DeleteEmployeeMockApiResponse) => {
|
next: (res: DeleteEmployeeMockApiResponse) => {
|
||||||
@@ -87,11 +88,10 @@ export class EmployeesListComponent implements OnDestroy {
|
|||||||
},
|
},
|
||||||
error: err => {
|
error: err => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
openDialog(val: boolean, employee: EmployeeCompact): void {
|
openDialog(val: boolean, employee: EmployeeCompact): void {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
this.showDialog = false;
|
this.showDialog = false;
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
|
||||||
import { TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { AvropService } from './avrop.service';
|
|
||||||
|
|
||||||
describe('AvropServiceService', () => {
|
|
||||||
let service: AvropService;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({ imports: [HttpClientTestingModule] });
|
|
||||||
service = TestBed.inject(AvropService);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be created', () => {
|
|
||||||
expect(service).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,98 +1,120 @@
|
|||||||
<msfa-layout>
|
<msfa-layout>
|
||||||
<section class="call-off" *ngIf="currentStep$ | async; let currentStep; else: loadingRef">
|
<section class="avrop" *ngIf="currentStep$ | async as currentStep; else: loadingRef">
|
||||||
<digi-typography>
|
<digi-typography>
|
||||||
<h2>Välj deltagare att tilldela</h2>
|
<header class="avrop__header">
|
||||||
<p>Steg {{ currentStep }} av {{ steps }}:</p>
|
<h1>Nya deltagare</h1>
|
||||||
|
<p>
|
||||||
|
Inkomna deltagare kan hanteras enskilt eller gemensamt. Genom att klicka i boxarna för en eller flera
|
||||||
|
deltagare kan du gå vidare och tilldela ansvarig handledare och skicka välkomstbrev.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<digi-notification-alert
|
||||||
|
*ngIf="currentStep === 4 && selectedHandledare$ | async as selectedHandledare"
|
||||||
|
af-heading="Allt gick bra"
|
||||||
|
af-variation="success"
|
||||||
|
>
|
||||||
|
<p>Tilldelningen är nu skickad till {{selectedHandledare.fullName}}.</p>
|
||||||
|
</digi-notification-alert>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="avrop__steps">
|
||||||
|
<div class="avrop__step-header">
|
||||||
|
<h2 class="avrop__sub-heading">
|
||||||
|
<ng-container [ngSwitch]="currentStep">
|
||||||
|
<ng-container *ngSwitchCase="1">Välj deltagare att tilldela</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="2">Tilldela handledare</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="3">Förehandsgranska och tilldela</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="4">Tilldelade delgare</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div class="avrop__progress-bar" *ngIf="currentStep < 4">
|
||||||
|
<span>Steg {{ currentStep }} av {{ totalAmountOfSteps }}:</span>
|
||||||
|
<digi-ng-progress-progressbar
|
||||||
|
[afSteps]="totalAmountOfSteps"
|
||||||
|
[afActiveStep]="currentStep"
|
||||||
|
></digi-ng-progress-progressbar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="avrop__content">
|
||||||
|
<div class="avrop__filter" *ngIf="currentStep === 1">
|
||||||
|
<h3>Filter</h3>
|
||||||
|
<msfa-avrop-filters></msfa-avrop-filters>
|
||||||
|
</div>
|
||||||
|
<div class="avrop__select-handledare" *ngIf="currentStep === 2">
|
||||||
|
<ng-container *ngIf="availableHandledare$ | async as availableHandledare; else loadingRef">
|
||||||
|
<digi-form-select
|
||||||
|
*ngIf="availableHandledare?.length; else noAvailabeHandledare"
|
||||||
|
af-label="Välj handledare att tilldela"
|
||||||
|
af-placeholder="Välj handledare"
|
||||||
|
[afRequired]="true"
|
||||||
|
(afOnChange)="changeHandledare($event.detail)"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
*ngFor="let availableHandledare of availableHandledare"
|
||||||
|
[value]="availableHandledare.ciamUserId"
|
||||||
|
>
|
||||||
|
{{ availableHandledare.fullName }}
|
||||||
|
</option>
|
||||||
|
</digi-form-select>
|
||||||
|
|
||||||
|
<ng-template #noAvailableHandledare>
|
||||||
|
<p>Inga handledare har behörighet till markerade deltagare</p>
|
||||||
|
</ng-template>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>Välj deltagare att tilldela handledare</h3>
|
||||||
|
<msfa-avrop-list
|
||||||
|
*ngIf="avropData$ | async as avropData"
|
||||||
|
[availableAvrop]="avropData.data"
|
||||||
|
[paginationMeta]="avropData.meta"
|
||||||
|
[selectedAvrop]="selectedAvrop$ | async"
|
||||||
|
[isLocked]="avropIsLocked$ | async"
|
||||||
|
[isSubmitted]="avropIsSubmitted$ | async"
|
||||||
|
[handledare]="selectedHandledare$ | async"
|
||||||
|
[handledareConfirmed]="handledareConfirmed$ | async"
|
||||||
|
(selectionChanged)="updateSelectedAvrop($event)"
|
||||||
|
(paginated)="setNewPage($event)"
|
||||||
|
></msfa-avrop-list>
|
||||||
|
</div>
|
||||||
|
<div class="avrop__footer" [ngSwitch]="currentStep">
|
||||||
|
<digi-notification-alert
|
||||||
|
*ngIf="error$ | async as error"
|
||||||
|
af-heading="Felmeddelande"
|
||||||
|
af-variation="danger"
|
||||||
|
af-closeable="true"
|
||||||
|
(afOnClose)="resetError()"
|
||||||
|
>
|
||||||
|
<p>{{error}}</p>
|
||||||
|
</digi-notification-alert>
|
||||||
|
|
||||||
|
<div class="avrop__cta-wrapper">
|
||||||
|
<ng-container *ngSwitchCase="1">
|
||||||
|
<digi-button af-size="m" (afOnClick)="lockSelectedAvrop()">Nästa</digi-button>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="2">
|
||||||
|
<digi-button af-variation="secondary" af-size="m" (afOnClick)="unlockSelectedAvrop()"
|
||||||
|
>Tillbaka</digi-button
|
||||||
|
>
|
||||||
|
<digi-button af-size="m" (afOnClick)="confirmHandledare()">Tilldela</digi-button>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="3">
|
||||||
|
<digi-button af-variation="secondary" af-size="m" (afOnClick)="unconfirmHandledare()"
|
||||||
|
>Tillbaka</digi-button
|
||||||
|
>
|
||||||
|
<digi-button af-size="m" (afOnClick)="save()">Bekräfta tilldelning</digi-button>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="4">
|
||||||
|
<digi-button af-size="m" (afOnClick)="returnToStep1()">Tillbaka till nya deltagare</digi-button>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
</digi-typography>
|
</digi-typography>
|
||||||
<digi-ng-progress-progressbar [afSteps]="steps" afAriaLabel="An aria label" [afActiveStep]="currentStep">
|
|
||||||
</digi-ng-progress-progressbar>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<ng-container *ngIf="currentStep == 4">
|
|
||||||
<h2>Avropet är sparat</h2>
|
|
||||||
<digi-button af-size="m" class="employee-form__read-more" (afOnClick)="goToStep1()">
|
|
||||||
Tillbaka till nya deltagare
|
|
||||||
</digi-button>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container *ngIf="currentStep == 1">
|
|
||||||
<msfa-avrop-filters></msfa-avrop-filters>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngIf="currentStep == 3">
|
|
||||||
<h2>Vänligen bekräfta</h2>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngIf="currentStep < 4">
|
|
||||||
<msfa-avrop-table
|
|
||||||
[selectableDeltagareList]="selectableDeltagareList$ | async"
|
|
||||||
[selectedDeltagareListInput]="selectedDeltagareList$ | async"
|
|
||||||
[isLocked]="deltagareListIsLocked$ | async"
|
|
||||||
(changedSelectedDeltagareList)="updateSelectedDeltagareList($event)"
|
|
||||||
[handledare]="selectedHandledare$ | async"
|
|
||||||
[handledareConfirmed]="handledareConfirmed$ | async"
|
|
||||||
></msfa-avrop-table>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container *ngIf="currentStep == 1">
|
|
||||||
<digi-button af-size="m" class="employee-form__read-more" (afOnClick)="lockSelectedDeltagare()">
|
|
||||||
Lås deltagare
|
|
||||||
</digi-button>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container *ngIf="currentStep == 2">
|
|
||||||
<h2>Välj handledare</h2>
|
|
||||||
<ng-container *ngIf="selectableHandledareList$ | async; let selectableHandledareList; else loadingRefSmall">
|
|
||||||
<select
|
|
||||||
[value]="(selectedHandledare$ | async)?.id ? (selectedHandledare$ | async)?.id : ''"
|
|
||||||
(change)="changeHandledare($event)"
|
|
||||||
>
|
|
||||||
<option disabled value="">Välj handledare</option>
|
|
||||||
|
|
||||||
<option *ngFor="let selectableHandledare of selectableHandledareList" [value]="selectableHandledare?.id">
|
|
||||||
{{ selectableHandledare?.fullName }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<span *ngIf="selectableHandledareList.length === 0"
|
|
||||||
>Inga handledare har behörighet till alla markerade deltagare</span
|
|
||||||
>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<br /><br />
|
|
||||||
<digi-button
|
|
||||||
af-variation="secondary"
|
|
||||||
af-size="m"
|
|
||||||
class="employee-form__read-more"
|
|
||||||
(afOnClick)="unlockSelectedDeltagare()"
|
|
||||||
>
|
|
||||||
Tillbaka
|
|
||||||
</digi-button>
|
|
||||||
<digi-button af-size="m" class="employee-form__read-more" (afOnClick)="confirmHandledare()">
|
|
||||||
Tilldela
|
|
||||||
</digi-button>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<div *ngIf="currentStep == 3">
|
|
||||||
<br /><br />
|
|
||||||
<digi-button
|
|
||||||
af-variation="secondary"
|
|
||||||
af-size="m"
|
|
||||||
class="employee-form__read-more"
|
|
||||||
(afOnClick)="unconfirmHandledare()"
|
|
||||||
>
|
|
||||||
Tillbaka
|
|
||||||
</digi-button>
|
|
||||||
<digi-button af-size="m" class="employee-form__read-more" (afOnClick)="save()"> Spara avrop </digi-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<ng-template #loadingRef>
|
<ng-template #loadingRef>
|
||||||
<digi-ng-skeleton-base [afCount]="3" afText="Laddar personal"></digi-ng-skeleton-base>
|
<digi-icon-spinner class="msfa__spinner" af-title="Laddar innehåll"></digi-icon-spinner>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template #loadingRefSmall>
|
|
||||||
<digi-icon-spinner af-title="Laddar innehåll"></digi-icon-spinner>
|
|
||||||
</ng-template>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
</msfa-layout>
|
</msfa-layout>
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
@import 'variables/gutters';
|
||||||
|
|
||||||
|
.avrop {
|
||||||
|
&__header {
|
||||||
|
margin-bottom: $digi--layout--gutter--xxl;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__sub-heading {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__step-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: start;
|
||||||
|
margin-bottom: $digi--layout--gutter--xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__select-handledare {
|
||||||
|
max-width: var(--digi--typography--text--max-width);
|
||||||
|
margin-bottom: $digi--layout--gutter--xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__footer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $digi--layout--gutter--xl;
|
||||||
|
max-width: var(--digi--typography--text--max-width);
|
||||||
|
margin-top: $digi--layout--gutter--xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__cta-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--digi--layout--gutter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,20 +3,27 @@ import { HttpClientTestingModule } from '@angular/common/http/testing';
|
|||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { LayoutComponent } from '@msfa-shared/components/layout/layout.component';
|
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
|
||||||
import { AvropComponent } from './avrop.component';
|
import { AvropComponent } from './avrop.component';
|
||||||
import { AvropFiltersComponent } from './components/avrop-filters/avrop-filters.component';
|
import { AvropFiltersModule } from './components/avrop-filters/avrop-filters.module';
|
||||||
import { AvropTableComponent } from './components/avrop-table/avrop-table.component';
|
import { AvropListModule } from './components/avrop-list/avrop-list.module';
|
||||||
|
|
||||||
describe('CallOffComponent', () => {
|
describe('AvropComponent', () => {
|
||||||
let component: AvropComponent;
|
let component: AvropComponent;
|
||||||
let fixture: ComponentFixture<AvropComponent>;
|
let fixture: ComponentFixture<AvropComponent>;
|
||||||
|
|
||||||
beforeEach(
|
beforeEach(
|
||||||
waitForAsync(() => {
|
waitForAsync(() => {
|
||||||
void TestBed.configureTestingModule({
|
void TestBed.configureTestingModule({
|
||||||
declarations: [AvropComponent, LayoutComponent, AvropFiltersComponent, AvropTableComponent],
|
declarations: [AvropComponent],
|
||||||
imports: [RouterTestingModule, HttpClientTestingModule, DigiNgProgressProgressbarModule],
|
imports: [
|
||||||
|
RouterTestingModule,
|
||||||
|
HttpClientTestingModule,
|
||||||
|
DigiNgProgressProgressbarModule,
|
||||||
|
LayoutModule,
|
||||||
|
AvropFiltersModule,
|
||||||
|
AvropListModule,
|
||||||
|
],
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||||
import { Avrop } from '@msfa-models/avrop.model';
|
import { Avrop, AvropCompactData } from '@msfa-models/avrop.model';
|
||||||
|
import { Handledare } from '@msfa-models/handledare.model';
|
||||||
import { MultiselectFilterOption } from '@msfa-models/multiselect-filter-option';
|
import { MultiselectFilterOption } from '@msfa-models/multiselect-filter-option';
|
||||||
|
import { AvropService } from '@msfa-services/avrop.service';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { AvropService } from './avrop.service';
|
|
||||||
import { HandledareAvrop } from './models/handledare-avrop';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'msfa-avrop',
|
selector: 'msfa-avrop',
|
||||||
@@ -12,31 +12,32 @@ import { HandledareAvrop } from './models/handledare-avrop';
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class AvropComponent {
|
export class AvropComponent {
|
||||||
steps = 3;
|
readonly totalAmountOfSteps = 3;
|
||||||
|
currentStep$: Observable<number> = this.avropService.currentStep$;
|
||||||
|
|
||||||
currentStep$ = this.avropService.currentStep$;
|
error$: Observable<string> = this.avropService.error$;
|
||||||
|
filteredUtforandeVerksamheter$: Observable<MultiselectFilterOption[]> = this.avropService
|
||||||
selectedUtforandeVerksamheter$: Observable<MultiselectFilterOption[]> = this.avropService
|
.filteredUtforandeVerksamheter$;
|
||||||
.selectedUtforandeVerksamheter$;
|
avropData$: Observable<AvropCompactData> = this.avropService.avropData$;
|
||||||
selectableDeltagareList$: Observable<Avrop[]> = this.avropService.selectableDeltagareList$;
|
selectedAvrop$: Observable<Avrop[]> = this.avropService.selectedAvrop$;
|
||||||
selectedDeltagareList$: Observable<Avrop[]> = this.avropService.selectedDeltagareList$;
|
availableHandledare$: Observable<Handledare[]> = this.avropService.availableHandledare$;
|
||||||
selectableHandledareList$: Observable<HandledareAvrop[]> = this.avropService.selectableHandledareList$;
|
selectedHandledare$: Observable<Handledare> = this.avropService.selectedHandledare$;
|
||||||
selectedHandledare$: Observable<HandledareAvrop> = this.avropService.selectedHandledare$;
|
avropIsLocked$: Observable<boolean> = this.avropService.avropIsLocked$;
|
||||||
deltagareListIsLocked$: Observable<boolean> = this.avropService.deltagareListIsLocked$;
|
|
||||||
handledareConfirmed$: Observable<boolean> = this.avropService.handledareIsConfirmed$;
|
handledareConfirmed$: Observable<boolean> = this.avropService.handledareIsConfirmed$;
|
||||||
|
avropIsSubmitted$: Observable<boolean> = this.avropService.avropIsSubmitted$;
|
||||||
|
|
||||||
constructor(private avropService: AvropService) {}
|
constructor(private avropService: AvropService) {}
|
||||||
|
|
||||||
updateSelectedDeltagareList(deltagareList: Avrop[]): void {
|
updateSelectedAvrop(deltagareList: Avrop[]): void {
|
||||||
this.avropService.setSelectedDeltagare(deltagareList);
|
this.avropService.setSelectedAvrop(deltagareList);
|
||||||
}
|
}
|
||||||
|
|
||||||
lockSelectedDeltagare(): void {
|
lockSelectedAvrop(): void {
|
||||||
this.avropService.lockSelectedDeltagare();
|
this.avropService.lockSelectedAvrop();
|
||||||
}
|
}
|
||||||
|
|
||||||
unlockSelectedDeltagare(): void {
|
unlockSelectedAvrop(): void {
|
||||||
this.avropService.unlockSelectedDeltagare();
|
this.avropService.unlockSelectedAvrop();
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmHandledare(): void {
|
confirmHandledare(): void {
|
||||||
@@ -51,13 +52,19 @@ export class AvropComponent {
|
|||||||
return this.avropService.save();
|
return this.avropService.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
changeHandledare(newHandledare: { target: HTMLInputElement }): void {
|
changeHandledare(handledareId: string): void {
|
||||||
const handledareId = newHandledare.target.value;
|
this.avropService.assignHandledare(handledareId);
|
||||||
|
|
||||||
this.avropService.setHandledareState(handledareId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
goToStep1(): void {
|
returnToStep1(): void {
|
||||||
this.avropService.goToStep1();
|
this.avropService.goToStep1();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetError(): void {
|
||||||
|
this.avropService.resetError();
|
||||||
|
}
|
||||||
|
|
||||||
|
setNewPage(page: number): void {
|
||||||
|
this.avropService.setPage(page);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,24 +5,18 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
|||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
|
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
|
||||||
import { AvropComponent } from './avrop.component';
|
import { AvropComponent } from './avrop.component';
|
||||||
import { AvropFiltersComponent } from './components/avrop-filters/avrop-filters.component';
|
import { AvropFiltersModule } from './components/avrop-filters/avrop-filters.module';
|
||||||
import { TemporaryFilterComponent } from './components/avrop-filters/temporary-filter/temporary-filter.component';
|
import { AvropListModule } from './components/avrop-list/avrop-list.module';
|
||||||
import { AvropTableRowComponent } from './components/avrop-table/avrop-table-row/avrop-table-row.component';
|
|
||||||
import { AvropTableComponent } from './components/avrop-table/avrop-table.component';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
declarations: [
|
declarations: [AvropComponent],
|
||||||
AvropComponent,
|
|
||||||
AvropFiltersComponent,
|
|
||||||
AvropTableComponent,
|
|
||||||
AvropTableRowComponent,
|
|
||||||
TemporaryFilterComponent,
|
|
||||||
],
|
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
RouterModule.forChild([{ path: '', component: AvropComponent }]),
|
RouterModule.forChild([{ path: '', component: AvropComponent }]),
|
||||||
LayoutModule,
|
LayoutModule,
|
||||||
|
AvropListModule,
|
||||||
|
AvropFiltersModule,
|
||||||
DigiNgProgressProgressbarModule,
|
DigiNgProgressProgressbarModule,
|
||||||
DigiNgSkeletonBaseModule,
|
DigiNgSkeletonBaseModule,
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,194 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { Avrop } from '@msfa-models/avrop.model';
|
|
||||||
import { MultiselectFilterOption } from '@msfa-models/multiselect-filter-option';
|
|
||||||
import { AvropApiService } from '@msfa-services/api/avrop-api.service';
|
|
||||||
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
|
|
||||||
import { first, map, switchMap } from 'rxjs/operators';
|
|
||||||
import { HandledareAvrop } from './models/handledare-avrop';
|
|
||||||
|
|
||||||
type Step = 1 | 2 | 3 | 4;
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root',
|
|
||||||
})
|
|
||||||
export class AvropService {
|
|
||||||
private _selectedTjanster$ = new BehaviorSubject<MultiselectFilterOption[]>(null);
|
|
||||||
private _selectedUtforandeVerksamheter$ = new BehaviorSubject<MultiselectFilterOption[]>(null);
|
|
||||||
private _selectedKommuner$ = new BehaviorSubject<MultiselectFilterOption[]>(null);
|
|
||||||
private _selectedDeltagareList$ = new BehaviorSubject<Avrop[]>([]);
|
|
||||||
private _deltagareListIsLocked$ = new BehaviorSubject<boolean>(null);
|
|
||||||
private _selectedHandledare$ = new BehaviorSubject<HandledareAvrop>(null);
|
|
||||||
private _handledareIsConfirmed$ = new BehaviorSubject<boolean>(false);
|
|
||||||
private _avropIsSaved$ = new BehaviorSubject<boolean>(false);
|
|
||||||
|
|
||||||
selectedTjanster$: Observable<MultiselectFilterOption[]> = this._selectedTjanster$.asObservable();
|
|
||||||
selectedUtforandeVerksamheter$: Observable<
|
|
||||||
MultiselectFilterOption[]
|
|
||||||
> = this._selectedUtforandeVerksamheter$.asObservable();
|
|
||||||
selectedKommuner$: Observable<MultiselectFilterOption[]> = this._selectedKommuner$.asObservable();
|
|
||||||
|
|
||||||
selectableDeltagareList$: Observable<Avrop[]> = combineLatest([
|
|
||||||
this.selectedTjanster$,
|
|
||||||
this.selectedUtforandeVerksamheter$,
|
|
||||||
this.selectedKommuner$,
|
|
||||||
]).pipe(
|
|
||||||
switchMap(([selectedTjanster, selectedUtforandeVerksamheter, selectedKommuner]) =>
|
|
||||||
this.avropApiService.getNyaAvrop$(selectedTjanster, selectedKommuner, selectedUtforandeVerksamheter)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
selectableTjanster$: Observable<MultiselectFilterOption[]> = combineLatest([
|
|
||||||
this.selectedUtforandeVerksamheter$,
|
|
||||||
this.selectedKommuner$,
|
|
||||||
]).pipe(
|
|
||||||
switchMap(([selectedUtforandeVerksamheter, selectedKommuner]) =>
|
|
||||||
this.avropApiService.getSelectableTjanster$(selectedKommuner, selectedUtforandeVerksamheter)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
selectableUtforandeVerksamheter$: Observable<MultiselectFilterOption[]> = combineLatest([
|
|
||||||
this.selectedTjanster$,
|
|
||||||
this.selectedKommuner$,
|
|
||||||
]).pipe(
|
|
||||||
switchMap(([selectedTjanster, selectedKommuner]) =>
|
|
||||||
this.avropApiService.getSelectableUtforandeVerksamheter$(selectedTjanster, selectedKommuner)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
selectableKommuner$: Observable<MultiselectFilterOption[]> = combineLatest([
|
|
||||||
this.selectedTjanster$,
|
|
||||||
this.selectedUtforandeVerksamheter$,
|
|
||||||
]).pipe(
|
|
||||||
switchMap(([selectedTjanster, selectedUtforandeVerksamheter]) =>
|
|
||||||
this.avropApiService.getSelectableKommuner$(selectedTjanster, selectedUtforandeVerksamheter)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
selectedDeltagareList$: Observable<Avrop[]> = this._selectedDeltagareList$.asObservable();
|
|
||||||
|
|
||||||
deltagareListIsLocked$: Observable<boolean> = this._deltagareListIsLocked$.asObservable();
|
|
||||||
lockedDeltagareList$: Observable<Avrop[]> = combineLatest([
|
|
||||||
this.selectedDeltagareList$,
|
|
||||||
this.deltagareListIsLocked$,
|
|
||||||
]).pipe(map(([selectedDeltagareList, isLocked]) => (isLocked ? selectedDeltagareList : null)));
|
|
||||||
|
|
||||||
selectableHandledareList$: Observable<HandledareAvrop[]> = this.lockedDeltagareList$.pipe(
|
|
||||||
switchMap(lockedDeltagare => this.avropApiService.getSelectableHandledare$(lockedDeltagare))
|
|
||||||
);
|
|
||||||
|
|
||||||
selectedHandledare$: Observable<HandledareAvrop> = this._selectedHandledare$.asObservable();
|
|
||||||
|
|
||||||
handledareIsConfirmed$: Observable<boolean> = this._handledareIsConfirmed$.asObservable();
|
|
||||||
avropIsSaved$: Observable<boolean> = this._handledareIsConfirmed$.asObservable();
|
|
||||||
|
|
||||||
currentStep$: Observable<Step> = combineLatest([
|
|
||||||
this.handledareIsConfirmed$,
|
|
||||||
this._deltagareListIsLocked$,
|
|
||||||
this.avropIsSaved$,
|
|
||||||
]).pipe(
|
|
||||||
map(([confirmedHandledare, lockedDeltagareList, avropIsSaved]) =>
|
|
||||||
AvropService.calculateStep(confirmedHandledare, lockedDeltagareList, avropIsSaved)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
private static calculateStep(
|
|
||||||
confirmedHandledare: boolean,
|
|
||||||
deltagareListIsLocked: boolean,
|
|
||||||
avropIsSaved: boolean
|
|
||||||
): Step {
|
|
||||||
if (avropIsSaved && confirmedHandledare && deltagareListIsLocked) {
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (confirmedHandledare && deltagareListIsLocked) {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deltagareListIsLocked) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
setSelectedDeltagare(deltagare: Avrop[]): void {
|
|
||||||
this._selectedDeltagareList$.next(deltagare);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(private avropApiService: AvropApiService) {}
|
|
||||||
|
|
||||||
lockSelectedDeltagare(): void {
|
|
||||||
if ((this._selectedDeltagareList$?.value?.length ?? -1) <= 0) {
|
|
||||||
throw new Error('För att låsa deltagare behöver några ha markerats först.');
|
|
||||||
}
|
|
||||||
this._deltagareListIsLocked$.next(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
unlockSelectedDeltagare(): void {
|
|
||||||
this._deltagareListIsLocked$.next(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
confirmHandledare(): void {
|
|
||||||
if (!this._selectedHandledare$?.value) {
|
|
||||||
throw new Error('För att kunna tilldela behövs en handledare väljas först.');
|
|
||||||
}
|
|
||||||
this._handledareIsConfirmed$.next(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
unconfirmHandledare(): void {
|
|
||||||
this._handledareIsConfirmed$.next(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
async save(): Promise<void> {
|
|
||||||
if (!this._handledareIsConfirmed$) {
|
|
||||||
throw new Error('Handledaren måste bekräftas innan avropet kan sparas');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._deltagareListIsLocked$) {
|
|
||||||
throw new Error('Deltagarlistan måste låsas innan avropet kan sparas');
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.avropApiService.tilldelaHandledare(this._selectedDeltagareList$.value, this._selectedHandledare$.value);
|
|
||||||
this._avropIsSaved$.next(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setHandledareState(handledareId: string): void {
|
|
||||||
this.selectableHandledareList$.pipe(first()).subscribe(handledareList => {
|
|
||||||
this._selectedHandledare$.next(handledareList.find(handledare => handledare.id === handledareId));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setSelectedTjanster(selectedFilterOptions: MultiselectFilterOption[]): void {
|
|
||||||
this._selectedTjanster$.next(selectedFilterOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
setSelectedUtforandeVerksamheter(selectedFilterOptions: MultiselectFilterOption[]): void {
|
|
||||||
this._selectedUtforandeVerksamheter$.next(selectedFilterOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
setSelectedKommuner(selectedFilterOptions: MultiselectFilterOption[]): void {
|
|
||||||
this._selectedKommuner$.next(selectedFilterOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
goToStep1(): void {
|
|
||||||
this._selectedHandledare$.next(null);
|
|
||||||
this._selectedDeltagareList$.next([]);
|
|
||||||
this._deltagareListIsLocked$.next(false);
|
|
||||||
this._handledareIsConfirmed$.next(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeKommun(kommunToRemove: MultiselectFilterOption) {
|
|
||||||
this.setSelectedKommuner(this._selectedKommuner$.value.filter(selectedKommun => selectedKommun !== kommunToRemove));
|
|
||||||
}
|
|
||||||
|
|
||||||
removeUtforandeVerksamhet(utforandeVerksamhetToRemove: MultiselectFilterOption) {
|
|
||||||
this.setSelectedUtforandeVerksamheter(
|
|
||||||
this._selectedUtforandeVerksamheter$.value.filter(
|
|
||||||
selectedUtforandeVerksamhet => selectedUtforandeVerksamhet !== utforandeVerksamhetToRemove
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeTjanst(tjanstToRemove: MultiselectFilterOption) {
|
|
||||||
this.setSelectedTjanster(this._selectedTjanster$.value.filter(selectedTjanst => selectedTjanst !== tjanstToRemove));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +1,36 @@
|
|||||||
<div style="display: flex">
|
<div style="display: flex">
|
||||||
<ng-container *ngIf="selectableTjanster$ | async; let selectableTjanster; else loadingRef">
|
<ng-container *ngIf="availableTjanster$ | async; let availableTjanster; else loadingRef">
|
||||||
<msfa-temporary-filter
|
<msfa-temporary-filter
|
||||||
[filterLabel]="'Tjänster'"
|
[filterLabel]="'Tjänster'"
|
||||||
[filterOptions]="selectableTjanster"
|
[filterOptions]="availableTjanster"
|
||||||
[selectedOptions]="selectedTjanster$ | async"
|
[selectedOptions]="filteredTjanster$ | async"
|
||||||
(selectedOptionsChange)="updateSelectedTjanster($event)"
|
(selectedOptionsChange)="updateSelectedTjanster($event)"
|
||||||
></msfa-temporary-filter>
|
></msfa-temporary-filter>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="selectableUtforandeVerksamheter$ | async; let selectableUtforandeVerksamheter; else loadingRef">
|
<ng-container *ngIf="availableUtforandeVerksamheter$ | async; let availableUtforandeVerksamheter; else loadingRef">
|
||||||
<msfa-temporary-filter
|
<msfa-temporary-filter
|
||||||
[filterLabel]="'Utförande verksamheter'"
|
[filterLabel]="'Utförande verksamheter'"
|
||||||
[filterOptions]="selectableUtforandeVerksamheter"
|
[filterOptions]="availableUtforandeVerksamheter"
|
||||||
[selectedOptions]="selectedUtforandeVerksamheter$ | async"
|
[selectedOptions]="filteredUtforandeVerksamheter$ | async"
|
||||||
(selectedOptionsChange)="updateSelectedUtforandeVerksamheter($event)"
|
(selectedOptionsChange)="updateSelectedUtforandeVerksamheter($event)"
|
||||||
></msfa-temporary-filter>
|
></msfa-temporary-filter>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngIf="selectableKommuner$ | async; let selectableKommuner; else loadingRef">
|
<ng-container *ngIf="availableKommuner$ | async; let availableKommuner; else loadingRef">
|
||||||
<msfa-temporary-filter
|
<msfa-temporary-filter
|
||||||
[filterLabel]="'Kommuner'"
|
[filterLabel]="'Kommuner'"
|
||||||
[filterOptions]="selectableKommuner"
|
[filterOptions]="availableKommuner"
|
||||||
[selectedOptions]="selectedKommuner$ | async"
|
[selectedOptions]="filteredKommuner$ | async"
|
||||||
(selectedOptionsChange)="updateSelectedKommuner($event)"
|
(selectedOptionsChange)="updateSelectedKommuner($event)"
|
||||||
></msfa-temporary-filter>
|
></msfa-temporary-filter>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<div class="avrop-filters__tags">
|
<div class="avrop-filters__tags">
|
||||||
<div class="avrop-filters__tag" *ngFor="let kommun of selectedKommuner$ | async">
|
<div class="avrop-filters__tag" *ngFor="let kommun of filteredKommuner$ | async">
|
||||||
<digi-tag [afText]="kommun.label" (click)="removeKommun(kommun)" af-no-icon="false" af-size="s"></digi-tag>
|
<digi-tag [afText]="kommun.label" (click)="removeKommun(kommun)" af-no-icon="false" af-size="s"></digi-tag>
|
||||||
</div>
|
</div>
|
||||||
<div class="avrop-filters__tag" *ngFor="let kommun of selectedUtforandeVerksamheter$ | async">
|
<div class="avrop-filters__tag" *ngFor="let kommun of filteredUtforandeVerksamheter$ | async">
|
||||||
<digi-tag
|
<digi-tag
|
||||||
[afText]="kommun.label"
|
[afText]="kommun.label"
|
||||||
(click)="removeUtforandeVerksamhet(kommun)"
|
(click)="removeUtforandeVerksamhet(kommun)"
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
af-size="s"
|
af-size="s"
|
||||||
></digi-tag>
|
></digi-tag>
|
||||||
</div>
|
</div>
|
||||||
<div class="avrop-filters__tag" *ngFor="let kommun of selectedTjanster$ | async">
|
<div class="avrop-filters__tag" *ngFor="let kommun of filteredTjanster$ | async">
|
||||||
<digi-tag [afText]="kommun.label" (click)="removeTjanst(kommun)" af-no-icon="false" af-size="s"></digi-tag>
|
<digi-tag [afText]="kommun.label" (click)="removeTjanst(kommun)" af-no-icon="false" af-size="s"></digi-tag>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
|
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||||
|
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||||
import { ComponentFixture, discardPeriodicTasks, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
import { ComponentFixture, discardPeriodicTasks, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { AvropService } from '../../avrop.service';
|
||||||
import { AvropFiltersComponent } from './avrop-filters.component';
|
import { AvropFiltersComponent } from './avrop-filters.component';
|
||||||
import { TemporaryFilterComponent } from './temporary-filter/temporary-filter.component';
|
import { TemporaryFilterComponent } from './temporary-filter/temporary-filter.component';
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
||||||
import { AvropService } from '../../avrop.service';
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { By } from '@angular/platform-browser';
|
|
||||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
|
||||||
|
|
||||||
describe('AvropFiltersComponent', () => {
|
describe('AvropFiltersComponent', () => {
|
||||||
let component: AvropFiltersComponent;
|
let component: AvropFiltersComponent;
|
||||||
@@ -30,8 +29,8 @@ describe('AvropFiltersComponent', () => {
|
|||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show 1 tag if selectedKommuner$ is an observable with one value', () => {
|
it('should show 1 tag if filteredKommuner$ is an observable with one value', () => {
|
||||||
component.selectedKommuner$ = of([{ id: '1', label: 'Stockholm', count: 1 }]);
|
component.filteredKommuner$ = of([{ id: '1', label: 'Stockholm', count: 1 }]);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const tags = fixture.debugElement.queryAll(By.css('.avrop-filters__tag'));
|
const tags = fixture.debugElement.queryAll(By.css('.avrop-filters__tag'));
|
||||||
expect(tags.length).toBe(1);
|
expect(tags.length).toBe(1);
|
||||||
@@ -39,7 +38,7 @@ describe('AvropFiltersComponent', () => {
|
|||||||
|
|
||||||
it('clicking a kommun-tag should trigger removeKommun()', fakeAsync(() => {
|
it('clicking a kommun-tag should trigger removeKommun()', fakeAsync(() => {
|
||||||
jest.spyOn(component, 'removeKommun').mockReturnThis();
|
jest.spyOn(component, 'removeKommun').mockReturnThis();
|
||||||
component.selectedKommuner$ = of([{ id: '1', label: 'Stockholm', count: 1 }]);
|
component.filteredKommuner$ = of([{ id: '1', label: 'Stockholm', count: 1 }]);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const tags = fixture.debugElement.query(By.css('digi-tag'));
|
const tags = fixture.debugElement.query(By.css('digi-tag'));
|
||||||
tags.nativeElement.click();
|
tags.nativeElement.click();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||||
import { MultiselectFilterOption } from '@msfa-models/multiselect-filter-option';
|
import { MultiselectFilterOption } from '@msfa-models/multiselect-filter-option';
|
||||||
|
import { AvropService } from '@msfa-services/avrop.service';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { AvropService } from '../../avrop.service';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'msfa-avrop-filters',
|
selector: 'msfa-avrop-filters',
|
||||||
@@ -10,14 +10,14 @@ import { AvropService } from '../../avrop.service';
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class AvropFiltersComponent {
|
export class AvropFiltersComponent {
|
||||||
selectableTjanster$: Observable<MultiselectFilterOption[]> = this.avropService.selectableTjanster$;
|
availableTjanster$: Observable<MultiselectFilterOption[]> = this.avropService.availableTjanster$;
|
||||||
selectableUtforandeVerksamheter$: Observable<MultiselectFilterOption[]> = this.avropService
|
availableUtforandeVerksamheter$: Observable<MultiselectFilterOption[]> = this.avropService
|
||||||
.selectableUtforandeVerksamheter$;
|
.availableUtforandeVerksamheter$;
|
||||||
selectableKommuner$: Observable<MultiselectFilterOption[]> = this.avropService.selectableKommuner$;
|
availableKommuner$: Observable<MultiselectFilterOption[]> = this.avropService.availableKommuner$;
|
||||||
selectedTjanster$: Observable<MultiselectFilterOption[]> = this.avropService.selectedTjanster$;
|
filteredTjanster$: Observable<MultiselectFilterOption[]> = this.avropService.filteredTjanster$;
|
||||||
selectedUtforandeVerksamheter$: Observable<MultiselectFilterOption[]> = this.avropService
|
filteredUtforandeVerksamheter$: Observable<MultiselectFilterOption[]> = this.avropService
|
||||||
.selectedUtforandeVerksamheter$;
|
.filteredUtforandeVerksamheter$;
|
||||||
selectedKommuner$: Observable<MultiselectFilterOption[]> = this.avropService.selectedKommuner$;
|
filteredKommuner$: Observable<MultiselectFilterOption[]> = this.avropService.filteredKommuner$;
|
||||||
|
|
||||||
constructor(private avropService: AvropService) {}
|
constructor(private avropService: AvropService) {}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
|
import { TemporaryFilterModule } from '../temporary-filter/temporary-filter.module';
|
||||||
|
import { AvropFiltersComponent } from './avrop-filters.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
|
declarations: [AvropFiltersComponent],
|
||||||
|
imports: [CommonModule, TemporaryFilterModule],
|
||||||
|
exports: [AvropFiltersComponent],
|
||||||
|
})
|
||||||
|
export class AvropFiltersModule {}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<div class="avrop-list">
|
||||||
|
<div class="avrop-list__select-all">
|
||||||
|
<digi-form-checkbox
|
||||||
|
*ngIf="!isLocked"
|
||||||
|
af-label="Välj alla deltagare"
|
||||||
|
[afChecked]="isAllSelected"
|
||||||
|
(change)="toggleAllAvrop($event.target.checked)"
|
||||||
|
></digi-form-checkbox>
|
||||||
|
</div>
|
||||||
|
<ul class="avrop-list__list">
|
||||||
|
<li *ngFor="let avrop of avropRows">
|
||||||
|
<msfa-avrop-row
|
||||||
|
[avrop]="avrop"
|
||||||
|
[isSelected]="isSelected(avrop)"
|
||||||
|
[isLocked]="isLocked"
|
||||||
|
[isSubmitted]="isSubmitted"
|
||||||
|
[handledare]="handledare"
|
||||||
|
[handledareConfirmed]="handledareConfirmed"
|
||||||
|
(toggled)="toggleSelectedAvrop(avrop, $event)"
|
||||||
|
(deleted)="toggleSelectedAvrop(avrop, false)"
|
||||||
|
></msfa-avrop-row>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<digi-navigation-pagination
|
||||||
|
*ngIf="totalPage > 1 && !isLocked"
|
||||||
|
class="avrop-list__pagination"
|
||||||
|
[afTotalPages]="totalPage"
|
||||||
|
[afCurrentResultStart]="currentResultStart"
|
||||||
|
[afCurrentResultEnd]="currentResultEnd"
|
||||||
|
[afTotalResults]="count"
|
||||||
|
(afOnPageChange)="emitNewPage($event.detail)"
|
||||||
|
af-result-name="deltagare"
|
||||||
|
>
|
||||||
|
</digi-navigation-pagination>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
@import 'mixins/list';
|
||||||
|
|
||||||
|
.avrop-list {
|
||||||
|
&__select-all {
|
||||||
|
padding: var(--digi--layout--gutter);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__list {
|
||||||
|
@include msfa__reset-list;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__pagination {
|
||||||
|
display: block;
|
||||||
|
margin-top: var(--digi--layout--gutter);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { AvropListComponent } from './avrop-list.component';
|
||||||
|
|
||||||
|
describe('AvropListComponent', () => {
|
||||||
|
let component: AvropListComponent;
|
||||||
|
let fixture: ComponentFixture<AvropListComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [AvropListComponent],
|
||||||
|
}).compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(AvropListComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
|
import { Avrop, AvropCompact } from '@msfa-models/avrop.model';
|
||||||
|
import { Handledare } from '@msfa-models/handledare.model';
|
||||||
|
import { PaginationMeta } from '@msfa-models/pagination-meta.model';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'msfa-avrop-list',
|
||||||
|
templateUrl: './avrop-list.component.html',
|
||||||
|
styleUrls: ['./avrop-list.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class AvropListComponent {
|
||||||
|
@Input() availableAvrop: AvropCompact[];
|
||||||
|
@Input() paginationMeta: PaginationMeta;
|
||||||
|
@Input() selectedAvrop: AvropCompact[];
|
||||||
|
@Input() handledare: Handledare;
|
||||||
|
@Input() isLocked: boolean;
|
||||||
|
@Input() isSubmitted: boolean;
|
||||||
|
@Input() handledareConfirmed: boolean;
|
||||||
|
@Output() selectionChanged = new EventEmitter<AvropCompact[]>();
|
||||||
|
@Output() paginated = new EventEmitter<number>();
|
||||||
|
|
||||||
|
get avropRows(): AvropCompact[] {
|
||||||
|
return this.isLocked ? this.selectedAvrop : this.availableAvrop;
|
||||||
|
}
|
||||||
|
get isAllSelected(): boolean {
|
||||||
|
return this.selectedAvrop?.length === this.availableAvrop?.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
get currentPage(): number {
|
||||||
|
return this.paginationMeta.page;
|
||||||
|
}
|
||||||
|
|
||||||
|
get totalPage(): number {
|
||||||
|
return this.paginationMeta?.totalPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
get count(): number {
|
||||||
|
return this.paginationMeta.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
get currentResultStart(): number {
|
||||||
|
return (this.currentPage - 1) * this.paginationMeta.limit + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
get currentResultEnd(): number {
|
||||||
|
const end = this.currentResultStart + this.paginationMeta.limit - 1;
|
||||||
|
return end < this.count ? end : this.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
isSelected(avrop: Avrop): boolean {
|
||||||
|
return !!this.selectedAvrop?.find(selectedAvrop => selectedAvrop.id === avrop.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleAllAvrop(selected: boolean): void {
|
||||||
|
if (selected && this.selectedAvrop?.length !== this.availableAvrop?.length) {
|
||||||
|
this.selectionChanged.emit(this.availableAvrop);
|
||||||
|
} else if (!selected && this.selectedAvrop.length) {
|
||||||
|
this.selectionChanged.emit([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleSelectedAvrop(avrop: Avrop, selected: boolean): void {
|
||||||
|
const avropIsSelected = !!this.selectedAvrop?.find(selectedAvrop => selectedAvrop.id === avrop.id);
|
||||||
|
|
||||||
|
if (selected && !avropIsSelected) {
|
||||||
|
this.selectionChanged.emit([...this.selectedAvrop, avrop]);
|
||||||
|
} else if (!selected && avropIsSelected) {
|
||||||
|
this.selectionChanged.emit(this.selectedAvrop.filter(selectedAvrop => selectedAvrop.id !== avrop.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emitNewPage(page: number): void {
|
||||||
|
this.paginated.emit(page);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
|
import { AvropRowModule } from '../avrop-row/avrop-row.module';
|
||||||
|
import { AvropListComponent } from './avrop-list.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
|
declarations: [AvropListComponent],
|
||||||
|
imports: [CommonModule, AvropRowModule],
|
||||||
|
exports: [AvropListComponent],
|
||||||
|
})
|
||||||
|
export class AvropListModule {}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<digi-typography>
|
||||||
|
<div
|
||||||
|
class="avrop-row"
|
||||||
|
[ngClass]="{'avrop-row--locked': isLocked, 'avrop-row--deletable': handledareConfirmed && !isSubmitted}"
|
||||||
|
>
|
||||||
|
<div class="avrop-row__select" *ngIf="!isLocked">
|
||||||
|
<digi-form-checkbox
|
||||||
|
af-label="Välj deltagare"
|
||||||
|
[afChecked]="isSelected"
|
||||||
|
(change)="emitToggle($event.target.checked)"
|
||||||
|
></digi-form-checkbox>
|
||||||
|
</div>
|
||||||
|
<dl class="avrop-row__name">
|
||||||
|
<dt class="avrop-table__label">Namn:</dt>
|
||||||
|
<dd *ngIf="avrop.fullName; else emptyText">{{avrop.fullName}}</dd>
|
||||||
|
</dl>
|
||||||
|
<dl class="avrop-row__tjanst">
|
||||||
|
<dt class="avrop-table__label">Tjänst:</dt>
|
||||||
|
<dd *ngIf="avrop.tjanst; else emptyText">{{avrop.tjanst}}</dd>
|
||||||
|
</dl>
|
||||||
|
<dl class="avrop-row__start">
|
||||||
|
<dt class="avrop-table__label">Startdatum:</dt>
|
||||||
|
<dd>
|
||||||
|
<digi-typography-time
|
||||||
|
*ngIf="avrop.startDate; else emptyText"
|
||||||
|
[afDateTime]="avrop.startDate"
|
||||||
|
></digi-typography-time>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<dl class="avrop-row__end">
|
||||||
|
<dt class="avrop-table__label">Slutdatum:</dt>
|
||||||
|
<dd>
|
||||||
|
<digi-typography-time *ngIf="avrop.endDate; else emptyText" [afDateTime]="avrop.endDate"></digi-typography-time>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<dl class="avrop-row__translator">
|
||||||
|
<dt class="avrop-table__label">Språkstöd/Tolk:</dt>
|
||||||
|
<dd>{{avrop.sprakstod || '- '}}/{{avrop.tolkbehov || ' -'}}</dd>
|
||||||
|
</dl>
|
||||||
|
<dl class="avrop-row__address">
|
||||||
|
<dt class="avrop-table__label">Utförande adress:</dt>
|
||||||
|
<dd *ngIf="avrop.utforandeAdress; else emptyText">{{avrop.utforandeAdress}}</dd>
|
||||||
|
</dl>
|
||||||
|
<dl class="avrop-row__level">
|
||||||
|
<dt class="avrop-table__label">Spår/nivå:</dt>
|
||||||
|
<dd *ngIf="avrop.trackCode; else emptyText">{{avrop.trackCode}}</dd>
|
||||||
|
</dl>
|
||||||
|
<dl class="avrop-row__handledare" *ngIf="isLocked">
|
||||||
|
<dt class="avrop-table__label">Vald handledare:</dt>
|
||||||
|
<dd *ngIf="handledare?.fullName; else emptyText">{{handledare.fullName}}</dd>
|
||||||
|
</dl>
|
||||||
|
<div *ngIf="isLocked" class="avrop-row__delete">
|
||||||
|
<digi-button
|
||||||
|
*ngIf="handledareConfirmed && !isSubmitted"
|
||||||
|
[attr.af-variation]="ButtonVariation.TERTIARY"
|
||||||
|
(afOnClick)="emitDelete()"
|
||||||
|
>
|
||||||
|
Ta bort
|
||||||
|
<digi-icon-x slot="icon"></digi-icon-x>
|
||||||
|
</digi-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-template #emptyText>
|
||||||
|
<span aria-hidden="true">-</span>
|
||||||
|
<span class="msfa__a11y-sr-only">Info saknas</span>
|
||||||
|
</ng-template>
|
||||||
|
</digi-typography>
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
@import 'variables/gutters';
|
||||||
|
|
||||||
|
.avrop-row {
|
||||||
|
position: relative;
|
||||||
|
display: grid;
|
||||||
|
padding: var(--digi--layout--gutter);
|
||||||
|
background-color: var(--digi--ui--color--background--secondary);
|
||||||
|
grid-template-columns: auto repeat(4, 1fr);
|
||||||
|
gap: var(--digi--layout--gutter) $digi--layout--gutter--l;
|
||||||
|
grid-template-areas:
|
||||||
|
'select name start translator level'
|
||||||
|
'select tjanst end address handledare';
|
||||||
|
|
||||||
|
&--locked {
|
||||||
|
grid-template-columns: repeat(4, 1fr) 7.5rem;
|
||||||
|
grid-template-areas:
|
||||||
|
'name start translator level delete'
|
||||||
|
'tjanst end address handledare delete';
|
||||||
|
}
|
||||||
|
|
||||||
|
&__select {
|
||||||
|
grid-area: select;
|
||||||
|
margin-right: var(--digi--layout--gutter);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__name {
|
||||||
|
grid-area: name;
|
||||||
|
}
|
||||||
|
&__tjanst {
|
||||||
|
grid-area: tjanst;
|
||||||
|
}
|
||||||
|
&__start {
|
||||||
|
grid-area: start;
|
||||||
|
}
|
||||||
|
&__end {
|
||||||
|
grid-area: end;
|
||||||
|
}
|
||||||
|
&__translator {
|
||||||
|
grid-area: translator;
|
||||||
|
}
|
||||||
|
&__address {
|
||||||
|
grid-area: address;
|
||||||
|
}
|
||||||
|
&__level {
|
||||||
|
grid-area: level;
|
||||||
|
}
|
||||||
|
&__handledare {
|
||||||
|
grid-area: handledare;
|
||||||
|
}
|
||||||
|
&__delete {
|
||||||
|
grid-area: delete;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avrop-row__close-btn {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
::ng-deep {
|
||||||
|
button {
|
||||||
|
padding: 0.5rem 0.75rem !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avrop-row__checkbox {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avrop-row__data-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: $digi--layout--gutter--xl $digi--layout--gutter--l;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avrop-row__data-column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $digi--layout--gutter--l 0;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avrop-row__data-column--bottom-align {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avrop-table__label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
@@ -1,21 +1,20 @@
|
|||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { AvropRowComponent } from './avrop-row.component';
|
||||||
|
|
||||||
import { AvropTableRowComponent } from './avrop-table-row.component';
|
describe('AvropRowComponent', () => {
|
||||||
|
let component: AvropRowComponent;
|
||||||
describe('AvropTableRowComponent', () => {
|
let fixture: ComponentFixture<AvropRowComponent>;
|
||||||
let component: AvropTableRowComponent;
|
|
||||||
let fixture: ComponentFixture<AvropTableRowComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [AvropTableRowComponent],
|
declarations: [AvropRowComponent],
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(AvropTableRowComponent);
|
fixture = TestBed.createComponent(AvropRowComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { ButtonVariation } from '@af/digi-ng/_button/button';
|
||||||
|
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
|
import { AvropCompact } from '@msfa-models/avrop.model';
|
||||||
|
import { Handledare } from '@msfa-models/handledare.model';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'msfa-avrop-row',
|
||||||
|
templateUrl: './avrop-row.component.html',
|
||||||
|
styleUrls: ['./avrop-row.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class AvropRowComponent {
|
||||||
|
@Input() avrop: AvropCompact;
|
||||||
|
@Input() isSelected: boolean;
|
||||||
|
@Input() isLocked: boolean;
|
||||||
|
@Input() isSubmitted: boolean;
|
||||||
|
@Input() handledare: Handledare;
|
||||||
|
@Input() handledareConfirmed: boolean;
|
||||||
|
@Output() toggled = new EventEmitter<boolean>();
|
||||||
|
@Output() deleted = new EventEmitter<void>();
|
||||||
|
|
||||||
|
readonly ButtonVariation = ButtonVariation;
|
||||||
|
|
||||||
|
emitToggle(isSelected: boolean): void {
|
||||||
|
this.toggled.emit(isSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
emitDelete(): void {
|
||||||
|
this.deleted.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
|
import { AvropRowComponent } from './avrop-row.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
|
declarations: [AvropRowComponent],
|
||||||
|
imports: [CommonModule],
|
||||||
|
exports: [AvropRowComponent],
|
||||||
|
})
|
||||||
|
export class AvropRowModule {}
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
<div class="avrop-table-row">
|
|
||||||
<div class="avrop-table-row__data-row">
|
|
||||||
<div class="avrop-table-row__data-column">
|
|
||||||
<digi-form-checkbox
|
|
||||||
*ngIf="!isLocked"
|
|
||||||
class="avrop-table-row__checkbox"
|
|
||||||
[afLabel]="'Välj sökande'"
|
|
||||||
[afChecked]="isSelected"
|
|
||||||
(change)="emitSelectionChange($event.target.checked)"
|
|
||||||
>
|
|
||||||
</digi-form-checkbox>
|
|
||||||
</div>
|
|
||||||
<div class="avrop-table-row__data-column">
|
|
||||||
<div class="avrop-table__cell">
|
|
||||||
<digi-typography>
|
|
||||||
<strong class="avrop-table__label">Namn:</strong>
|
|
||||||
<span>{{deltagare?.fullName}}</span>
|
|
||||||
</digi-typography>
|
|
||||||
</div>
|
|
||||||
<div class="avrop-table__cell">
|
|
||||||
<digi-typography>
|
|
||||||
<strong class="avrop-table__label">Tjänst:</strong>
|
|
||||||
<span>{{deltagare?.tjanst}}</span>
|
|
||||||
</digi-typography>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="avrop-table-row__data-column">
|
|
||||||
<div class="avrop-table__cell">
|
|
||||||
<digi-typography>
|
|
||||||
<strong class="avrop-table__label">Startdatum:</strong>
|
|
||||||
<digi-typography-time *ngIf="deltagare?.startDate" [afDateTime]="deltagare?.startDate"></digi-typography-time>
|
|
||||||
</digi-typography>
|
|
||||||
</div>
|
|
||||||
<div class="avrop-table__cell">
|
|
||||||
<digi-typography>
|
|
||||||
<strong class="avrop-table__label">Slutdatum:</strong>
|
|
||||||
<digi-typography-time *ngIf="deltagare?.endDate" [afDateTime]="deltagare?.endDate"></digi-typography-time>
|
|
||||||
</digi-typography>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="avrop-table-row__data-column">
|
|
||||||
<div class="avrop-table__cell">
|
|
||||||
<digi-typography>
|
|
||||||
<strong class="avrop-table__label">Språkstöd/Tolk:</strong>
|
|
||||||
<span>{{deltagare?.sprakstod + '/' + deltagare?.tolkbehov}}</span>
|
|
||||||
</digi-typography>
|
|
||||||
</div>
|
|
||||||
<div class="avrop-table__cell">
|
|
||||||
<digi-typography>
|
|
||||||
<strong class="avrop-table__label">Utförande adress:</strong>
|
|
||||||
<span>{{deltagare?.utforandeAdress}}</span>
|
|
||||||
</digi-typography>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="avrop-table-row__data-column avrop-table-row__data-column--bottom-align">
|
|
||||||
<div class="avrop-table__cell">
|
|
||||||
<digi-typography>
|
|
||||||
<strong class="avrop-table__label">Spår/nivå:</strong>
|
|
||||||
<span>{{deltagare?.trackCode}}</span>
|
|
||||||
</digi-typography>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="handledare" class="avrop-table-row__data-column avrop-table-row__data-column--bottom-align">
|
|
||||||
<div class="avrop-table__cell">
|
|
||||||
<digi-typography>
|
|
||||||
<strong class="avrop-table__label">Vald handledare:</strong>
|
|
||||||
<span>{{handledare?.fullName}}</span>
|
|
||||||
</digi-typography>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<digi-button
|
|
||||||
class="avrop-table-row__close-btn"
|
|
||||||
*ngIf="handledareConfirmed"
|
|
||||||
[attr.af-variation]="ButtonVariation.TERTIARY"
|
|
||||||
(afOnClick)="emitDeltagareDeleted()"
|
|
||||||
>
|
|
||||||
Ta bort
|
|
||||||
<digi-icon-x slot="icon"></digi-icon-x>
|
|
||||||
</digi-button>
|
|
||||||
</div>
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
@import 'variables/gutters';
|
|
||||||
|
|
||||||
.avrop-table-row {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
padding: var(--digi--layout--gutter) var(--digi--layout--gutter);
|
|
||||||
background-color: var(--digi--ui--color--background--secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.avrop-table-row__close-btn {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
|
|
||||||
::ng-deep {
|
|
||||||
button {
|
|
||||||
padding: 0.5rem 0.75rem !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.avrop-table-row__checkbox {
|
|
||||||
margin-top: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avrop-table-row__data-row {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: $digi--layout--gutter--xl $digi--layout--gutter--l;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avrop-table-row__data-column {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: $digi--layout--gutter--l 0;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avrop-table-row__data-column--bottom-align {
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avrop-table__label {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
|
|
||||||
import { Avrop } from '@msfa-models/avrop.model';
|
|
||||||
import { ButtonVariation } from '../../../enums/button-vatiation.enum';
|
|
||||||
import { HandledareAvrop } from '../../../models/handledare-avrop';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'msfa-avrop-table-row',
|
|
||||||
templateUrl: './avrop-table-row.component.html',
|
|
||||||
styleUrls: ['./avrop-table-row.component.scss'],
|
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
||||||
})
|
|
||||||
export class AvropTableRowComponent {
|
|
||||||
@Input() deltagare: Avrop;
|
|
||||||
@Input() isSelected: boolean;
|
|
||||||
@Input() isLocked: boolean;
|
|
||||||
@Input() handledare: HandledareAvrop;
|
|
||||||
@Input() handledareConfirmed: boolean;
|
|
||||||
@Output() isSelectedChange = new EventEmitter<boolean>();
|
|
||||||
@Output() deleteDeltagareClicked = new EventEmitter<void>();
|
|
||||||
|
|
||||||
ButtonVariation = ButtonVariation;
|
|
||||||
|
|
||||||
emitSelectionChange(isSelected: boolean): void {
|
|
||||||
this.isSelectedChange.emit(isSelected);
|
|
||||||
}
|
|
||||||
|
|
||||||
emitDeltagareDeleted(): void {
|
|
||||||
this.deleteDeltagareClicked.emit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<div class="avrop-table">
|
|
||||||
<msfa-avrop-table-row
|
|
||||||
*ngFor="let deltagare of deltagareRows"
|
|
||||||
[deltagare]="deltagare"
|
|
||||||
[isSelected]="isSelected(deltagare)"
|
|
||||||
[isLocked]="isLocked"
|
|
||||||
(isSelectedChange)="isSelectedChange(deltagare, $event)"
|
|
||||||
[handledare]="handledare"
|
|
||||||
[handledareConfirmed]="handledareConfirmed"
|
|
||||||
></msfa-avrop-table-row>
|
|
||||||
</div>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
.avrop-table {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { AvropTableComponent } from './avrop-table.component';
|
|
||||||
|
|
||||||
describe('AvropTableComponent', () => {
|
|
||||||
let component: AvropTableComponent;
|
|
||||||
let fixture: ComponentFixture<AvropTableComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
declarations: [ AvropTableComponent ]
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(AvropTableComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
|
||||||
import { Avrop } from '@msfa-models/avrop.model';
|
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
|
||||||
import { filter } from 'rxjs/operators';
|
|
||||||
import { HandledareAvrop } from '../../models/handledare-avrop';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'msfa-avrop-table',
|
|
||||||
templateUrl: './avrop-table.component.html',
|
|
||||||
styleUrls: ['./avrop-table.component.scss'],
|
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
||||||
})
|
|
||||||
export class AvropTableComponent implements OnInit {
|
|
||||||
private _selectedDeltagare$ = new BehaviorSubject<Avrop[]>(null);
|
|
||||||
selectedDeltagareState$: Observable<Avrop[]> = this._selectedDeltagare$.asObservable();
|
|
||||||
|
|
||||||
@Input() selectableDeltagareList: Avrop[];
|
|
||||||
@Input() selectedDeltagareListInput: Avrop[];
|
|
||||||
@Input() handledare: HandledareAvrop;
|
|
||||||
@Input() isLocked: boolean;
|
|
||||||
@Input() handledareConfirmed: boolean;
|
|
||||||
@Output() changedSelectedDeltagareList = new EventEmitter<Avrop[]>();
|
|
||||||
|
|
||||||
get deltagareRows(): Avrop[] {
|
|
||||||
return this.isLocked ? this.selectedDeltagareListInput : this.selectableDeltagareList;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
this._selectedDeltagare$
|
|
||||||
.pipe(filter(x => !!x))
|
|
||||||
.subscribe(selectedDeltagare => this.changedSelectedDeltagareList.emit(selectedDeltagare));
|
|
||||||
// TODO lägg till unusubscribeOnDestroy
|
|
||||||
}
|
|
||||||
|
|
||||||
isSelected(deltagare: Avrop): boolean {
|
|
||||||
return this.selectedDeltagareListInput?.includes(deltagare) ?? false;
|
|
||||||
}
|
|
||||||
|
|
||||||
isSelectedChange(deltagare: Avrop, isSelected: boolean): void {
|
|
||||||
if (isSelected) {
|
|
||||||
return this._selectedDeltagare$.next([
|
|
||||||
...(this._selectedDeltagare$.value?.filter(deltagareInList => deltagareInList != deltagare) ?? []),
|
|
||||||
deltagare,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
return this._selectedDeltagare$.next(
|
|
||||||
this._selectedDeltagare$.value?.filter(deltagareInList => deltagareInList != deltagare) ?? []
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
|
import { TemporaryFilterComponent } from './temporary-filter.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
|
declarations: [TemporaryFilterComponent],
|
||||||
|
imports: [CommonModule],
|
||||||
|
exports: [TemporaryFilterComponent],
|
||||||
|
})
|
||||||
|
export class TemporaryFilterModule {}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
export enum ButtonSize {
|
|
||||||
S = 's',
|
|
||||||
M = 'm',
|
|
||||||
L = 'l',
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
export enum ButtonVariation {
|
|
||||||
PRIMARY = 'primary',
|
|
||||||
SECONDARY = 'secondary',
|
|
||||||
TERTIARY = 'tertiary',
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export interface HandledareAvrop {
|
|
||||||
fullName: string;
|
|
||||||
id: string;
|
|
||||||
}
|
|
||||||
@@ -37,9 +37,9 @@
|
|||||||
</digi-table>
|
</digi-table>
|
||||||
|
|
||||||
<digi-navigation-pagination
|
<digi-navigation-pagination
|
||||||
*ngIf="totalPages > 1"
|
*ngIf="totalPage > 1"
|
||||||
class="deltagare-list__pagination"
|
class="deltagare-list__pagination"
|
||||||
[afTotalPages]="totalPages"
|
[afTotalPages]="totalPage"
|
||||||
[afCurrentResultStart]="currentResultStart"
|
[afCurrentResultStart]="currentResultStart"
|
||||||
[afCurrentResultEnd]="currentResultEnd"
|
[afCurrentResultEnd]="currentResultEnd"
|
||||||
[afTotalResults]="count"
|
[afTotalResults]="count"
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ export class DeltagareListComponent {
|
|||||||
return this.paginationMeta.page;
|
return this.paginationMeta.page;
|
||||||
}
|
}
|
||||||
|
|
||||||
get totalPages(): number {
|
get totalPage(): number {
|
||||||
return this.paginationMeta?.totalPages;
|
return this.paginationMeta?.totalPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
get count(): number {
|
get count(): number {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export interface AvropTjanstResponse {
|
export interface AvropTjanstResponse {
|
||||||
code: string;
|
id: string;
|
||||||
name: string;
|
label: string;
|
||||||
|
count: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { PaginationMeta } from '@msfa-models/pagination-meta.model';
|
||||||
|
|
||||||
export interface AvropResponse {
|
export interface AvropResponse {
|
||||||
id: string;
|
id: string;
|
||||||
deltagare: string;
|
deltagare: string;
|
||||||
@@ -28,3 +30,8 @@ export interface AvropResponse {
|
|||||||
supervisorId: number;
|
supervisorId: number;
|
||||||
recievedTimestamp: string;
|
recievedTimestamp: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AvropApiResponse {
|
||||||
|
data: AvropResponse[];
|
||||||
|
meta: PaginationMeta;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export interface HandledareResponse {
|
export interface HandledareResponse {
|
||||||
id: number;
|
ciamUserId: string;
|
||||||
name: string
|
namn: string;
|
||||||
|
count: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export interface KommunResponse {
|
export interface KommunResponse {
|
||||||
kommunCode: number;
|
id: string;
|
||||||
kommun: string;
|
label: string;
|
||||||
|
count: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export interface Params {
|
||||||
|
[param: string]: string | string[];
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export interface UtforandeVerksamhetResponse {
|
export interface UtforandeVerksamhetResponse {
|
||||||
id: number;
|
id: string;
|
||||||
name: string;
|
label: string;
|
||||||
|
count: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
import { AvropTjanstResponse } from './api/avrop-tjanst.response.model';
|
import { AvropTjanstResponse } from './api/avrop-tjanst.response.model';
|
||||||
|
|
||||||
export interface AvropTjanst {
|
export interface AvropTjanst {
|
||||||
code: string;
|
id: string;
|
||||||
name: string;
|
label: string;
|
||||||
|
count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mapResponseToAvropTjanst(data: AvropTjanstResponse): AvropTjanst {
|
export function mapResponseToAvropTjanst(data: AvropTjanstResponse): AvropTjanst {
|
||||||
const { code, name } = data;
|
const { id, label, count } = data;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code,
|
id,
|
||||||
name,
|
label,
|
||||||
|
count,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { AvropResponse } from './api/avrop.response.model';
|
import { AvropResponse } from './api/avrop.response.model';
|
||||||
|
import { PaginationMeta } from './pagination-meta.model';
|
||||||
|
|
||||||
export interface AvropCompact {
|
export interface AvropCompact {
|
||||||
id: string; // id
|
id: string; // id
|
||||||
@@ -20,6 +21,11 @@ export interface Avrop extends AvropCompact {
|
|||||||
utforandeVerksamhet: string; // utforandeverksamhet
|
utforandeVerksamhet: string; // utforandeverksamhet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AvropCompactData {
|
||||||
|
data: AvropCompact[];
|
||||||
|
meta: PaginationMeta;
|
||||||
|
}
|
||||||
|
|
||||||
export function mapAvropResponseToAvrop(data: AvropResponse): Avrop {
|
export function mapAvropResponseToAvrop(data: AvropResponse): Avrop {
|
||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import { HandledareResponse } from './api/handledare.response.model';
|
import { HandledareResponse } from './api/handledare.response.model';
|
||||||
|
|
||||||
export interface Handledare {
|
export interface Handledare {
|
||||||
id: number;
|
ciamUserId: string;
|
||||||
name: string;
|
fullName: string;
|
||||||
|
count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mapHandledareResponseToHandledare(
|
export function mapHandledareResponseToHandledare(data: HandledareResponse): Handledare {
|
||||||
data: HandledareResponse
|
const { ciamUserId, namn, count } = data;
|
||||||
): Handledare {
|
|
||||||
const { id, name } = data;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
ciamUserId,
|
||||||
name
|
fullName: namn,
|
||||||
}
|
count,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
import { KommunResponse } from './api/kommun.response.model';
|
import { KommunResponse } from './api/kommun.response.model';
|
||||||
|
|
||||||
export interface Kommun {
|
export interface Kommun {
|
||||||
id: number;
|
id: string;
|
||||||
name: string;
|
label: string;
|
||||||
|
count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mapKommunResponseToKommun(data: KommunResponse): Kommun {
|
export function mapKommunResponseToKommun(data: KommunResponse): Kommun {
|
||||||
const { kommunCode, kommun } = data;
|
const { id, label, count } = data;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: kommunCode,
|
id,
|
||||||
name: kommun
|
label,
|
||||||
|
count,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ export interface PaginationMeta {
|
|||||||
count: number;
|
count: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
page: number;
|
page: number;
|
||||||
totalPages: number;
|
totalPage: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
import { UtforandeVerksamhetResponse } from './api/utforande-verksamhet.response.model';
|
import { UtforandeVerksamhetResponse } from './api/utforande-verksamhet.response.model';
|
||||||
|
|
||||||
export interface UtforandeVerksamhet {
|
export interface UtforandeVerksamhet {
|
||||||
id: number;
|
id: string;
|
||||||
name: string;
|
label: string;
|
||||||
|
count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mapUtforandeVerksamhetResponseToUtforandeVerksamhet(
|
export function mapUtforandeVerksamhetResponseToUtforandeVerksamhet(
|
||||||
data: UtforandeVerksamhetResponse
|
data: UtforandeVerksamhetResponse
|
||||||
): UtforandeVerksamhet {
|
): UtforandeVerksamhet {
|
||||||
const { id, name } = data;
|
const { id, label, count } = data;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
name,
|
label,
|
||||||
|
count,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,92 +2,98 @@ import { HttpClient } from '@angular/common/http';
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { environment } from '@msfa-environment';
|
import { environment } from '@msfa-environment';
|
||||||
import { AvropTjanstResponse } from '@msfa-models/api/avrop-tjanst.response.model';
|
import { AvropTjanstResponse } from '@msfa-models/api/avrop-tjanst.response.model';
|
||||||
import { AvropResponse } from '@msfa-models/api/avrop.response.model';
|
import { AvropApiResponse } from '@msfa-models/api/avrop.response.model';
|
||||||
|
import { HandledareResponse } from '@msfa-models/api/handledare.response.model';
|
||||||
import { KommunResponse } from '@msfa-models/api/kommun.response.model';
|
import { KommunResponse } from '@msfa-models/api/kommun.response.model';
|
||||||
|
import { Params } from '@msfa-models/api/params.model';
|
||||||
import { UtforandeVerksamhetResponse } from '@msfa-models/api/utforande-verksamhet.response.model';
|
import { UtforandeVerksamhetResponse } from '@msfa-models/api/utforande-verksamhet.response.model';
|
||||||
import { mapResponseToAvropTjanst } from '@msfa-models/avrop-tjanst.model';
|
import { AvropTjanst, mapResponseToAvropTjanst } from '@msfa-models/avrop-tjanst.model';
|
||||||
import { Avrop, mapAvropResponseToAvrop } from '@msfa-models/avrop.model';
|
import { AvropCompact, AvropCompactData, mapAvropResponseToAvrop } from '@msfa-models/avrop.model';
|
||||||
import { mapKommunResponseToKommun } from '@msfa-models/kommun.model';
|
import { Handledare, mapHandledareResponseToHandledare } from '@msfa-models/handledare.model';
|
||||||
import { MultiselectFilterOption } from '@msfa-models/multiselect-filter-option';
|
import { Kommun, mapKommunResponseToKommun } from '@msfa-models/kommun.model';
|
||||||
import { mapUtforandeVerksamhetResponseToUtforandeVerksamhet } from '@msfa-models/utforande-verksamhet.model';
|
import {
|
||||||
import { Observable, of } from 'rxjs';
|
mapUtforandeVerksamhetResponseToUtforandeVerksamhet,
|
||||||
import { delay, filter, map } from 'rxjs/operators';
|
UtforandeVerksamhet,
|
||||||
import { HandledareAvrop } from '../../../pages/avrop/models/handledare-avrop';
|
} from '@msfa-models/utforande-verksamhet.model';
|
||||||
|
import { BehaviorSubject, Observable, of } from 'rxjs';
|
||||||
const tempHandledareMock: HandledareAvrop[] = [
|
import { filter, map, tap } from 'rxjs/operators';
|
||||||
{ id: '1', fullName: 'Göran Persson' },
|
|
||||||
{ id: '2', fullName: 'Stefan Löfven' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const tempMockDelay = 300;
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class AvropApiService {
|
export class AvropApiService {
|
||||||
private _apiBaseUrl = `${environment.api.url}/avrop`;
|
private _apiBaseUrl = `${environment.api.url}/avrop`;
|
||||||
|
private _lockedAvropSnapshot$ = new BehaviorSubject<AvropCompact[]>(null);
|
||||||
|
private _availableHandledareSnapshot$ = new BehaviorSubject<Handledare[]>(null);
|
||||||
|
|
||||||
constructor(private httpClient: HttpClient) {}
|
constructor(private httpClient: HttpClient) {}
|
||||||
|
|
||||||
getNyaAvrop$(
|
get lockedAvropValue(): AvropCompact[] {
|
||||||
tjanstIds: MultiselectFilterOption[],
|
return this._lockedAvropSnapshot$.getValue();
|
||||||
kommunIds: MultiselectFilterOption[],
|
|
||||||
utforandeVerksamhetIds: MultiselectFilterOption[],
|
|
||||||
offset = 0,
|
|
||||||
limit = 20
|
|
||||||
): Observable<Avrop[]> {
|
|
||||||
return this.httpClient.get<{ data: AvropResponse[] }>(`${this._apiBaseUrl}`).pipe(
|
|
||||||
filter(response => !!response?.data),
|
|
||||||
map(({ data }) => data.map(avrop => mapAvropResponseToAvrop(avrop)))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getSelectableHandledare$(deltagare: Avrop[]): Observable<HandledareAvrop[]> {
|
fetchAvrop$(params: Params): Observable<AvropCompactData> {
|
||||||
// TODO replace with API-call
|
|
||||||
console.log('[API call] getSelectableHandledare$. Inputs: deltagare', deltagare);
|
|
||||||
return of(tempHandledareMock).pipe(delay(tempMockDelay));
|
|
||||||
}
|
|
||||||
|
|
||||||
getSelectableTjanster$(
|
|
||||||
selectedKommuner: MultiselectFilterOption[],
|
|
||||||
selectedUtforandeVerksamheter: MultiselectFilterOption[]
|
|
||||||
): Observable<MultiselectFilterOption[]> {
|
|
||||||
return this.httpClient.get<{ data: AvropTjanstResponse[] }>(`${this._apiBaseUrl}/tjanster`).pipe(
|
|
||||||
filter(response => !!response?.data),
|
|
||||||
map(({ data }) => data.map(tjanster => ({ label: mapResponseToAvropTjanst(tjanster).name })))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getSelectableUtforandeVerksamheter$(
|
|
||||||
selectedTjanster: MultiselectFilterOption[],
|
|
||||||
selectedKommuner: MultiselectFilterOption[]
|
|
||||||
): Observable<MultiselectFilterOption[]> {
|
|
||||||
return this.httpClient
|
return this.httpClient
|
||||||
.get<{ data: UtforandeVerksamhetResponse[] }>(`${this._apiBaseUrl}/utforandeverksamheter`)
|
.get<AvropApiResponse>(`${this._apiBaseUrl}`, { params })
|
||||||
|
.pipe(map(({ data, meta }) => ({ data: data.map(avrop => mapAvropResponseToAvrop(avrop)), meta })));
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchAvailableHandledare$(avrop: AvropCompact[]): Observable<Handledare[]> {
|
||||||
|
const lockedAvropIsEqual = this.lockedAvropValue?.every(
|
||||||
|
(lockedAvrop, index) => lockedAvrop.id === avrop[index]?.id
|
||||||
|
);
|
||||||
|
|
||||||
|
// Checking to see if we really need to make a new api-request
|
||||||
|
if (lockedAvropIsEqual) {
|
||||||
|
return of(this._availableHandledareSnapshot$.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
this._lockedAvropSnapshot$.next(avrop);
|
||||||
|
|
||||||
|
return this.httpClient.get<{ data: HandledareResponse[] }>(`${this._apiBaseUrl}/handledare`).pipe(
|
||||||
|
map(({ data }) => data.map(handledare => mapHandledareResponseToHandledare(handledare))),
|
||||||
|
tap(handledare => {
|
||||||
|
this._availableHandledareSnapshot$.next(handledare);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchAvailableTjanster$(params: Params): Observable<AvropTjanst[]> {
|
||||||
|
return this.httpClient
|
||||||
|
.get<{ data: AvropTjanstResponse[] }>(`${this._apiBaseUrl}/tjanster`, { params })
|
||||||
|
.pipe(
|
||||||
|
filter(response => !!response?.data),
|
||||||
|
map(({ data }) => data.map(tjanster => mapResponseToAvropTjanst(tjanster)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchAvailableUtforandeVerksamheter$(params: Params): Observable<UtforandeVerksamhet[]> {
|
||||||
|
return this.httpClient
|
||||||
|
.get<{ data: UtforandeVerksamhetResponse[] }>(`${this._apiBaseUrl}/utforandeverksamheter`, { params })
|
||||||
.pipe(
|
.pipe(
|
||||||
filter(response => !!response?.data),
|
filter(response => !!response?.data),
|
||||||
map(({ data }) =>
|
map(({ data }) =>
|
||||||
data.map(utforandeverksamheter => ({
|
data.map(utforandeverksamheter => mapUtforandeVerksamhetResponseToUtforandeVerksamhet(utforandeverksamheter))
|
||||||
label: mapUtforandeVerksamhetResponseToUtforandeVerksamhet(utforandeverksamheter).name,
|
|
||||||
}))
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSelectableKommuner$(
|
fetchAvailableKommuner$(params: Params): Observable<Kommun[]> {
|
||||||
selectedTjanster: MultiselectFilterOption[],
|
return this.httpClient
|
||||||
selectedUtforandeVerksamheter: MultiselectFilterOption[]
|
.get<{ data: KommunResponse[] }>(`${this._apiBaseUrl}/kommuner`, { params })
|
||||||
): Observable<MultiselectFilterOption[]> {
|
.pipe(
|
||||||
return this.httpClient.get<{ data: KommunResponse[] }>(`${this._apiBaseUrl}/kommuner`).pipe(
|
filter(response => !!response?.data),
|
||||||
filter(response => !!response?.data),
|
map(({ data }) => data.map(kommun => mapKommunResponseToKommun(kommun)))
|
||||||
map(({ data }) => data.map(kommun => ({ label: mapKommunResponseToKommun(kommun).name })))
|
);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async tilldelaHandledare(deltagare: Avrop[], handledare: HandledareAvrop): Promise<void> {
|
async assignHandledare(avrop: AvropCompact[], handledareId: string): Promise<void> {
|
||||||
console.log('[API call] SAVE avrop. Inputs: deltagare, handledare', deltagare, handledare);
|
const params: Params = {
|
||||||
await of(null).pipe(delay(200)).toPromise();
|
avropIds: avrop.map(deltagare => deltagare.id),
|
||||||
// TODO anropa API
|
ciamUserId: handledareId,
|
||||||
return;
|
};
|
||||||
|
return this.httpClient
|
||||||
|
.patch<void>(`${this._apiBaseUrl}/handledare/assign`, null, { params })
|
||||||
|
.toPromise();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { DisabilityResponse } from '@msfa-models/api/disability.response.model';
|
|||||||
import { DriversLicenseResponse } from '@msfa-models/api/drivers-license.response.model';
|
import { DriversLicenseResponse } from '@msfa-models/api/drivers-license.response.model';
|
||||||
import { EducationsResponse } from '@msfa-models/api/educations.response.model';
|
import { EducationsResponse } from '@msfa-models/api/educations.response.model';
|
||||||
import { HighestEducationResponse } from '@msfa-models/api/highest-education.response.model';
|
import { HighestEducationResponse } from '@msfa-models/api/highest-education.response.model';
|
||||||
|
import { Params } from '@msfa-models/api/params.model';
|
||||||
import { TranslatorResponse } from '@msfa-models/api/translator.response.model';
|
import { TranslatorResponse } from '@msfa-models/api/translator.response.model';
|
||||||
import { WorkExperiencesResponse } from '@msfa-models/api/work-experiences.response.model';
|
import { WorkExperiencesResponse } from '@msfa-models/api/work-experiences.response.model';
|
||||||
import { WorkLanguagesResponse } from '@msfa-models/api/work-languages.response.model';
|
import { WorkLanguagesResponse } from '@msfa-models/api/work-languages.response.model';
|
||||||
@@ -84,14 +85,13 @@ export class DeltagareService extends UnsubscribeDirective {
|
|||||||
page: number,
|
page: number,
|
||||||
sort: Sort<keyof DeltagareCompact>
|
sort: Sort<keyof DeltagareCompact>
|
||||||
): Observable<DeltagareCompactData> {
|
): Observable<DeltagareCompactData> {
|
||||||
const params: { [param: string]: string | string[] } = {
|
const params: Params = {
|
||||||
sort: sort.key as string,
|
sort: sort.key as string,
|
||||||
order: sort.order as string,
|
order: sort.order as string,
|
||||||
limit: limit.toString(),
|
limit: limit.toString(),
|
||||||
page: page.toString(),
|
page: page.toString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(params);
|
|
||||||
return this.httpClient
|
return this.httpClient
|
||||||
.get<DeltagareCompactApiResponse>(this._apiBaseUrl, {
|
.get<DeltagareCompactApiResponse>(this._apiBaseUrl, {
|
||||||
params,
|
params,
|
||||||
|
|||||||
@@ -8,12 +8,16 @@ import { DeleteEmployeeMockApiResponse } from '@msfa-models/api/delete-employee.
|
|||||||
import {
|
import {
|
||||||
EmployeeCompactResponse,
|
EmployeeCompactResponse,
|
||||||
EmployeeResponse,
|
EmployeeResponse,
|
||||||
EmployeesApiResponse
|
EmployeesApiResponse,
|
||||||
} from '@msfa-models/api/employee.response.model';
|
} from '@msfa-models/api/employee.response.model';
|
||||||
|
import { Params } from '@msfa-models/api/params.model';
|
||||||
import {
|
import {
|
||||||
Employee, EmployeeInviteRequestData, EmployeesData, mapEmployeeToRequestData,
|
Employee,
|
||||||
|
EmployeeInviteRequestData,
|
||||||
|
EmployeesData,
|
||||||
|
mapEmployeeToRequestData,
|
||||||
mapResponseToEmployee,
|
mapResponseToEmployee,
|
||||||
mapResponseToEmployeeCompact
|
mapResponseToEmployeeCompact,
|
||||||
} from '@msfa-models/employee.model';
|
} from '@msfa-models/employee.model';
|
||||||
import { errorToCustomError } from '@msfa-models/error/custom-error';
|
import { errorToCustomError } from '@msfa-models/error/custom-error';
|
||||||
import { Sort } from '@msfa-models/sort.model';
|
import { Sort } from '@msfa-models/sort.model';
|
||||||
@@ -97,7 +101,7 @@ export class EmployeeService extends UnsubscribeDirective {
|
|||||||
searchFilter: string,
|
searchFilter: string,
|
||||||
onlyEmployeesWithoutAuthorization?: boolean
|
onlyEmployeesWithoutAuthorization?: boolean
|
||||||
): Observable<EmployeesData> {
|
): Observable<EmployeesData> {
|
||||||
const params: { [param: string]: string | string[] } = {
|
const params: Params = {
|
||||||
sort: sort.key as string,
|
sort: sort.key as string,
|
||||||
order: sort.order as string,
|
order: sort.order as string,
|
||||||
limit: limit.toString(),
|
limit: limit.toString(),
|
||||||
@@ -175,7 +179,7 @@ export class EmployeeService extends UnsubscribeDirective {
|
|||||||
public postEmployeeInvitation(email: string): Observable<string[]> {
|
public postEmployeeInvitation(email: string): Observable<string[]> {
|
||||||
return this.httpClient
|
return this.httpClient
|
||||||
.post<{ data: EmployeeInviteRequestData }>(`${this._apiBaseUrl}/invite`, {
|
.post<{ data: EmployeeInviteRequestData }>(`${this._apiBaseUrl}/invite`, {
|
||||||
emails: Object.values(email)
|
emails: Object.values(email),
|
||||||
})
|
})
|
||||||
.pipe(
|
.pipe(
|
||||||
take(1),
|
take(1),
|
||||||
|
|||||||
245
apps/mina-sidor-fa/src/app/shared/services/avrop.service.ts
Normal file
245
apps/mina-sidor-fa/src/app/shared/services/avrop.service.ts
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Params } from '@msfa-models/api/params.model';
|
||||||
|
import { Avrop, AvropCompactData } from '@msfa-models/avrop.model';
|
||||||
|
import { Handledare } from '@msfa-models/handledare.model';
|
||||||
|
import { MultiselectFilterOption } from '@msfa-models/multiselect-filter-option';
|
||||||
|
import { AvropApiService } from '@msfa-services/api/avrop-api.service';
|
||||||
|
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
|
||||||
|
import { filter, map, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
|
type Step = 1 | 2 | 3 | 4;
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class AvropService {
|
||||||
|
private _limit$ = new BehaviorSubject<number>(5);
|
||||||
|
private _page$ = new BehaviorSubject<number>(1);
|
||||||
|
private _filteredTjanster$ = new BehaviorSubject<MultiselectFilterOption[]>(null);
|
||||||
|
private _filteredUtforandeVerksamheter$ = new BehaviorSubject<MultiselectFilterOption[]>(null);
|
||||||
|
private _filteredKommuner$ = new BehaviorSubject<MultiselectFilterOption[]>(null);
|
||||||
|
private _selectedAvrop$ = new BehaviorSubject<Avrop[]>([]);
|
||||||
|
private _avropIsLocked$ = new BehaviorSubject<boolean>(null);
|
||||||
|
private _selectedHandledareId$ = new BehaviorSubject<string>(null);
|
||||||
|
private _handledareIsConfirmed$ = new BehaviorSubject<boolean>(false);
|
||||||
|
private _avropIsSubmitted$ = new BehaviorSubject<boolean>(false);
|
||||||
|
private _error$ = new BehaviorSubject<string>(null);
|
||||||
|
|
||||||
|
public filteredTjanster$: Observable<MultiselectFilterOption[]> = this._filteredTjanster$.asObservable();
|
||||||
|
public filteredUtforandeVerksamheter$: Observable<
|
||||||
|
MultiselectFilterOption[]
|
||||||
|
> = this._filteredUtforandeVerksamheter$.asObservable();
|
||||||
|
public filteredKommuner$: Observable<MultiselectFilterOption[]> = this._filteredKommuner$.asObservable();
|
||||||
|
public selectedAvrop$: Observable<Avrop[]> = this._selectedAvrop$.asObservable();
|
||||||
|
public avropIsLocked$: Observable<boolean> = this._avropIsLocked$.asObservable();
|
||||||
|
public selectedHandledare$: Observable<Handledare> = this._selectedHandledareId$.pipe(
|
||||||
|
filter(selectedHandledare => !!selectedHandledare),
|
||||||
|
switchMap(handledareId =>
|
||||||
|
this.availableHandledare$.pipe(
|
||||||
|
map(availableHandledare => availableHandledare.find(handledare => handledare.ciamUserId === handledareId))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
public handledareIsConfirmed$: Observable<boolean> = this._handledareIsConfirmed$.asObservable();
|
||||||
|
public avropIsSubmitted$: Observable<boolean> = this._avropIsSubmitted$.asObservable();
|
||||||
|
public error$: Observable<string> = this._error$.asObservable();
|
||||||
|
|
||||||
|
public avropData$: Observable<AvropCompactData> = combineLatest([
|
||||||
|
this._filteredTjanster$,
|
||||||
|
this._filteredUtforandeVerksamheter$,
|
||||||
|
this._filteredKommuner$,
|
||||||
|
this._page$,
|
||||||
|
this._limit$,
|
||||||
|
]).pipe(switchMap(() => this.avropApiService.fetchAvrop$(this._getParams('avrop'))));
|
||||||
|
|
||||||
|
public availableTjanster$: Observable<MultiselectFilterOption[]> = combineLatest([
|
||||||
|
this._filteredUtforandeVerksamheter$,
|
||||||
|
this._filteredKommuner$,
|
||||||
|
]).pipe(switchMap(() => this.avropApiService.fetchAvailableTjanster$(this._getParams('tjanster'))));
|
||||||
|
|
||||||
|
public availableUtforandeVerksamheter$: Observable<MultiselectFilterOption[]> = combineLatest([
|
||||||
|
this._filteredTjanster$,
|
||||||
|
this._filteredKommuner$,
|
||||||
|
]).pipe(
|
||||||
|
switchMap(() => this.avropApiService.fetchAvailableUtforandeVerksamheter$(this._getParams('utforandeVerksamheter')))
|
||||||
|
);
|
||||||
|
|
||||||
|
public availableKommuner$: Observable<MultiselectFilterOption[]> = combineLatest([
|
||||||
|
this._filteredTjanster$,
|
||||||
|
this._filteredUtforandeVerksamheter$,
|
||||||
|
]).pipe(switchMap(() => this.avropApiService.fetchAvailableKommuner$(this._getParams('kommuner'))));
|
||||||
|
|
||||||
|
private _lockedAvrop$: Observable<Avrop[]> = combineLatest([this.selectedAvrop$, this.avropIsLocked$]).pipe(
|
||||||
|
map(([selectedAvrop, isLocked]) => (isLocked ? selectedAvrop : null))
|
||||||
|
);
|
||||||
|
|
||||||
|
public availableHandledare$: Observable<Handledare[]> = this._lockedAvrop$.pipe(
|
||||||
|
filter(lockedAvrop => !!lockedAvrop),
|
||||||
|
switchMap(lockedAvrop => this.avropApiService.fetchAvailableHandledare$(lockedAvrop))
|
||||||
|
);
|
||||||
|
|
||||||
|
public currentStep$: Observable<Step> = combineLatest([
|
||||||
|
this._handledareIsConfirmed$,
|
||||||
|
this._avropIsLocked$,
|
||||||
|
this._avropIsSubmitted$,
|
||||||
|
]).pipe(
|
||||||
|
map(([confirmedHandledare, avropIsLocked, avropIsSubmitted]) => {
|
||||||
|
return AvropService.calculateStep(confirmedHandledare, avropIsLocked, avropIsSubmitted);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
private static calculateStep(confirmedHandledare: boolean, avropIsLocked: boolean, avropIsSubmitted: boolean): Step {
|
||||||
|
if (avropIsLocked) {
|
||||||
|
if (confirmedHandledare) {
|
||||||
|
if (avropIsSubmitted) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getParams(type: 'avrop' | 'kommuner' | 'tjanster' | 'utforandeVerksamheter'): Params {
|
||||||
|
const tjanstKod = this._filteredTjanster$.getValue()?.length
|
||||||
|
? { tjanstKod: this._filteredTjanster$.getValue().map(tjanst => tjanst.id) }
|
||||||
|
: null;
|
||||||
|
const kommunKod = this._filteredKommuner$.getValue()?.length
|
||||||
|
? { kommunKod: this._filteredKommuner$.getValue().map(kommun => kommun.id) }
|
||||||
|
: null;
|
||||||
|
const utforandeverksamhetId = this._filteredUtforandeVerksamheter$.getValue()?.length
|
||||||
|
? {
|
||||||
|
utforandeverksamhetId: this._filteredUtforandeVerksamheter$
|
||||||
|
.getValue()
|
||||||
|
.map(utforandeVerksamhet => utforandeVerksamhet.id),
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'avrop':
|
||||||
|
return {
|
||||||
|
...tjanstKod,
|
||||||
|
...kommunKod,
|
||||||
|
...utforandeverksamhetId,
|
||||||
|
page: this._page$.getValue().toString(),
|
||||||
|
limit: this._limit$.getValue().toString(),
|
||||||
|
};
|
||||||
|
case 'kommuner':
|
||||||
|
return {
|
||||||
|
...tjanstKod,
|
||||||
|
...utforandeverksamhetId,
|
||||||
|
};
|
||||||
|
case 'tjanster':
|
||||||
|
return {
|
||||||
|
...kommunKod,
|
||||||
|
...utforandeverksamhetId,
|
||||||
|
};
|
||||||
|
case 'utforandeVerksamheter':
|
||||||
|
return {
|
||||||
|
...tjanstKod,
|
||||||
|
...kommunKod,
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public setSelectedAvrop(deltagare: Avrop[]): void {
|
||||||
|
this._selectedAvrop$.next(deltagare);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private avropApiService: AvropApiService) {}
|
||||||
|
|
||||||
|
public resetError(): void {
|
||||||
|
this._error$.next(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public lockSelectedAvrop(): void {
|
||||||
|
this.resetError();
|
||||||
|
if ((this._selectedAvrop$?.value?.length ?? -1) <= 0) {
|
||||||
|
this._error$.next('För att låsa deltagare behöver några ha markerats först.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._avropIsLocked$.next(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public unlockSelectedAvrop(): void {
|
||||||
|
this.resetError();
|
||||||
|
this._avropIsLocked$.next(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public confirmHandledare(): void {
|
||||||
|
this.resetError();
|
||||||
|
if (!this._selectedHandledareId$?.value) {
|
||||||
|
this._error$.next('För att kunna tilldela behövs en handledare väljas först.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._handledareIsConfirmed$.next(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public unconfirmHandledare(): void {
|
||||||
|
this.resetError();
|
||||||
|
this._handledareIsConfirmed$.next(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async save(): Promise<void> {
|
||||||
|
this.resetError();
|
||||||
|
if (!this._handledareIsConfirmed$) {
|
||||||
|
this._error$.next('Handledaren måste bekräftas innan avropet kan sparas');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._avropIsLocked$) {
|
||||||
|
this._error$.next('Deltagarlistan måste låsas innan avropet kan sparas');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.avropApiService.assignHandledare(this._selectedAvrop$.value, this._selectedHandledareId$.value);
|
||||||
|
this._avropIsSubmitted$.next(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public assignHandledare(handledareId: string): void {
|
||||||
|
this._selectedHandledareId$.next(handledareId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setSelectedTjanster(selectedFilterOptions: MultiselectFilterOption[]): void {
|
||||||
|
this._filteredTjanster$.next(selectedFilterOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setSelectedUtforandeVerksamheter(selectedFilterOptions: MultiselectFilterOption[]): void {
|
||||||
|
this._filteredUtforandeVerksamheter$.next(selectedFilterOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setSelectedKommuner(selectedFilterOptions: MultiselectFilterOption[]): void {
|
||||||
|
this._filteredKommuner$.next(selectedFilterOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public goToStep1(): void {
|
||||||
|
this._selectedHandledareId$.next(null);
|
||||||
|
this._selectedAvrop$.next([]);
|
||||||
|
this._avropIsLocked$.next(false);
|
||||||
|
this._handledareIsConfirmed$.next(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeKommun(kommunToRemove: MultiselectFilterOption): void {
|
||||||
|
this.setSelectedKommuner(this._filteredKommuner$.value.filter(selectedKommun => selectedKommun !== kommunToRemove));
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeUtforandeVerksamhet(utforandeVerksamhetToRemove: MultiselectFilterOption): void {
|
||||||
|
this.setSelectedUtforandeVerksamheter(
|
||||||
|
this._filteredUtforandeVerksamheter$.value.filter(
|
||||||
|
selectedUtforandeVerksamhet => selectedUtforandeVerksamhet !== utforandeVerksamhetToRemove
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeTjanst(tjanstToRemove: MultiselectFilterOption): void {
|
||||||
|
this.setSelectedTjanster(this._filteredTjanster$.value.filter(selectedTjanst => selectedTjanst !== tjanstToRemove));
|
||||||
|
}
|
||||||
|
|
||||||
|
public setPage(page: number): void {
|
||||||
|
this._page$.next(page);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,16 @@
|
|||||||
@import 'mixins/a11y';
|
@import 'mixins/a11y';
|
||||||
@import 'mixins/icon';
|
@import 'mixins/icon';
|
||||||
|
|
||||||
|
@keyframes spinning {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
font-family: var(--digi--typography--font-family);
|
font-family: var(--digi--typography--font-family);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -30,6 +40,17 @@ address {
|
|||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dl {
|
||||||
|
dt {
|
||||||
|
font-weight: var(--digi--typography--font-weight--semibold);
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Make all digi icons display inline-flex to make them get the correct height.
|
// Make all digi icons display inline-flex to make them get the correct height.
|
||||||
[class^='sc-digi-icon'],
|
[class^='sc-digi-icon'],
|
||||||
.digi-button__icon {
|
.digi-button__icon {
|
||||||
@@ -41,6 +62,11 @@ address {
|
|||||||
@include msfa__a11y-sr-only;
|
@include msfa__a11y-sr-only;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__spinner {
|
||||||
|
display: inline-flex;
|
||||||
|
animation: spinning infinite 0.6s linear;
|
||||||
|
}
|
||||||
|
|
||||||
&__digi-icon {
|
&__digi-icon {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,20 +2,20 @@ import faker from 'faker';
|
|||||||
import kommuner from './kommuner.js';
|
import kommuner from './kommuner.js';
|
||||||
import languages from './languages.js';
|
import languages from './languages.js';
|
||||||
import organizations from './organizations.js';
|
import organizations from './organizations.js';
|
||||||
import utforandeVerksamheter from './utforande-verksamheter.js';
|
|
||||||
import tjanster from './tjanster.js';
|
import tjanster from './tjanster.js';
|
||||||
|
import utforandeVerksamheter from './utforande-verksamheter.js';
|
||||||
|
|
||||||
faker.locale = 'sv';
|
faker.locale = 'sv';
|
||||||
|
|
||||||
const TJANSTER = tjanster.generate();
|
const TJANSTER = tjanster.generate();
|
||||||
const SUPORTLANGUAGES = languages.generate();
|
const SUPORTLANGUAGES = languages.generate();
|
||||||
const TRACK = ['A', 'B', 'C'];
|
const TRACK = [{ kod: 'A012SP1', name: 'Nivå A: Kundval Rusta och matcha' }];
|
||||||
const ORGANIZATIONS = organizations.generate();
|
const ORGANIZATIONS = organizations.generate();
|
||||||
const UTFORANDEVERKSAMHETER = utforandeVerksamheter.generate();
|
const UTFORANDEVERKSAMHETER = utforandeVerksamheter.generate();
|
||||||
const KOMMUNER = kommuner.generate();
|
const KOMMUNER = kommuner.generate();
|
||||||
const FREKVENSER = ['25%', '50%', '75%', '100%'];
|
const FREKVENSER = ['25%', '50%', '75%', '100%'];
|
||||||
|
|
||||||
function generateAvrop(amount = 10, deltagare) {
|
function generateAvrop(amount = 10, deltagare, handledare) {
|
||||||
const avrop = [];
|
const avrop = [];
|
||||||
|
|
||||||
for (let i = 1; i <= amount; ++i) {
|
for (let i = 1; i <= amount; ++i) {
|
||||||
@@ -25,6 +25,7 @@ function generateAvrop(amount = 10, deltagare) {
|
|||||||
const tjanst = TJANSTER[Math.floor(Math.random() * TJANSTER.length)];
|
const tjanst = TJANSTER[Math.floor(Math.random() * TJANSTER.length)];
|
||||||
const track = TRACK[Math.floor(Math.random() * TRACK.length)];
|
const track = TRACK[Math.floor(Math.random() * TRACK.length)];
|
||||||
const currentDeltagare = deltagare[i - 1];
|
const currentDeltagare = deltagare[i - 1];
|
||||||
|
const utforandeAdress = utforandeVerksamhet.adresser[0];
|
||||||
|
|
||||||
avrop.push({
|
avrop.push({
|
||||||
id: faker.datatype.uuid(),
|
id: faker.datatype.uuid(),
|
||||||
@@ -37,25 +38,25 @@ function generateAvrop(amount = 10, deltagare) {
|
|||||||
organisationsnummer: organization.organizationNumber,
|
organisationsnummer: organization.organizationNumber,
|
||||||
utforandeVerksamhetId: utforandeVerksamhet.utforandeVerksamhetId,
|
utforandeVerksamhetId: utforandeVerksamhet.utforandeVerksamhetId,
|
||||||
utforandeverksamhet: utforandeVerksamhet.namn,
|
utforandeverksamhet: utforandeVerksamhet.namn,
|
||||||
kommunKod: kommun.kommunCode,
|
kommunKod: kommun.id,
|
||||||
kommun: kommun.kommun,
|
kommun: kommun.label,
|
||||||
utforandeAdressId: faker.datatype.number({ min: 10000, max: 99999 }),
|
utforandeAdressId: utforandeAdress.adressId,
|
||||||
adress: `${utforandeVerksamhet.adresser.adressrad}`,
|
adress: utforandeAdress.adressrad,
|
||||||
ordernummer: `AKTTEST-${faker.datatype.number({ min: 10000, max: 99999 })}`,
|
ordernummer: `AKTTEST-${faker.datatype.number({ min: 10000, max: 99999 })}`,
|
||||||
bokningsId: faker.datatype.number({ min: 100000, max: 999999 }),
|
bokningsId: faker.datatype.number({ min: 100000, max: 999999 }),
|
||||||
personnummer: currentDeltagare.personnummer,
|
personnummer: currentDeltagare.personnummer,
|
||||||
sokandeId: currentDeltagare.id,
|
sokandeId: currentDeltagare.id,
|
||||||
tjanstekod: tjanst.code,
|
tjanstekod: tjanst.id,
|
||||||
tjansteNamn: tjanst.name,
|
tjansteNamn: tjanst.label,
|
||||||
deltagandeGrad: FREKVENSER[Math.floor(Math.random() * FREKVENSER.length)],
|
deltagandeGrad: FREKVENSER[Math.floor(Math.random() * FREKVENSER.length)],
|
||||||
startdatumAvrop: faker.date.recent(),
|
startdatumAvrop: faker.date.recent(),
|
||||||
slutdatumAvrop: faker.date.future(),
|
slutdatumAvrop: faker.date.future(),
|
||||||
aktnummerDiariet: `Af-2021/0000 ${faker.datatype.number({ min: 1000, max: 9999 })}`,
|
aktnummerDiariet: `Af-2021/0000 ${faker.datatype.number({ min: 1000, max: 9999 })}`,
|
||||||
tolkbehov: currentDeltagare.translator.sprak.beskrivning,
|
tolkbehov: currentDeltagare.translator.sprak.beskrivning,
|
||||||
sprakstod: SUPORTLANGUAGES[Math.floor(Math.random() * SUPORTLANGUAGES.length)].beskrivning,
|
sprakstod: SUPORTLANGUAGES[Math.floor(Math.random() * SUPORTLANGUAGES.length)].beskrivning,
|
||||||
sparkod: track,
|
sparkod: track.kod,
|
||||||
sparNamn: `Nivå ${track}: ${tjanst.name}`,
|
sparNamn: track.name,
|
||||||
supervisorId: Math.random() > 0.3 && faker.datatype.uuid(),
|
handledareCiamUserId: null,
|
||||||
recievedTimestamp: faker.date.recent(),
|
recievedTimestamp: faker.date.recent(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import faker from 'faker';
|
import faker from 'faker';
|
||||||
import utforandeVerksamheter from './utforande-verksamheter.js';
|
|
||||||
import tjanster from './tjanster.js';
|
import tjanster from './tjanster.js';
|
||||||
|
import utforandeVerksamheter from './utforande-verksamheter.js';
|
||||||
import chooseRandom from './utils/choose-random.util.js';
|
import chooseRandom from './utils/choose-random.util.js';
|
||||||
|
|
||||||
faker.locale = 'sv';
|
faker.locale = 'sv';
|
||||||
@@ -36,14 +36,17 @@ function generateEmployees(amount = 10) {
|
|||||||
roles: hasBehorigheter
|
roles: hasBehorigheter
|
||||||
? ['OrganizationUser', ...chooseRandom(ROLES, faker.datatype.number({ min: 1, max: ROLES.length }))]
|
? ['OrganizationUser', ...chooseRandom(ROLES, faker.datatype.number({ min: 1, max: ROLES.length }))]
|
||||||
: ['OrganizationUser'],
|
: ['OrganizationUser'],
|
||||||
tjanst: hasBehorigheter ? currentTjanster.map(tjanst => tjanst.name) : [],
|
tjanst: hasBehorigheter ? currentTjanster.map(tjanst => tjanst.label) : [],
|
||||||
tjansteKoder: hasBehorigheter ? currentTjanster.map(tjanst => tjanst.tjanstekod) : [],
|
tjansteKoder: hasBehorigheter ? currentTjanster.map(tjanst => tjanst.id) : [],
|
||||||
allaUtforandeVerksamheter: faker.datatype.boolean(),
|
allaUtforandeVerksamheter: faker.datatype.boolean(),
|
||||||
utforandeVerksamhet: hasBehorigheter ? currentUtforandeVerksamheter.map(utforandeVerksamhet => utforandeVerksamhet) : [],
|
utforandeVerksamhet: hasBehorigheter
|
||||||
utforandeVerksamhetIds: hasBehorigheter ? currentUtforandeVerksamheter.map(utforandeVerksamhet => utforandeVerksamhet.utforandeVerksamhetId) : [],
|
? currentUtforandeVerksamheter.map(utforandeVerksamhet => utforandeVerksamhet)
|
||||||
|
: [],
|
||||||
|
utforandeVerksamhetIds: hasBehorigheter
|
||||||
|
? currentUtforandeVerksamheter.map(utforandeVerksamhet => utforandeVerksamhet.utforandeVerksamhetId)
|
||||||
|
: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
employee.email = `${employee.firstName}.${employee.lastName}@private-epost.se`.toLowerCase();
|
|
||||||
employees.push(employee);
|
employees.push(employee);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,66 +4,79 @@ import avrop from './avrop.js';
|
|||||||
import currentUser from './current-user.js';
|
import currentUser from './current-user.js';
|
||||||
import deltagare from './deltagare.js';
|
import deltagare from './deltagare.js';
|
||||||
import employees from './employees.js';
|
import employees from './employees.js';
|
||||||
|
import handledare from './handledare.js';
|
||||||
import languages from './languages.js';
|
import languages from './languages.js';
|
||||||
import participants from './participants.js';
|
import participants from './participants.js';
|
||||||
import tjanster from './tjanster.js';
|
import tjanster from './tjanster.js';
|
||||||
|
|
||||||
const generatedEmployees = employees.generate(50);
|
const generatedEmployees = employees.generate(50);
|
||||||
const generatedDeltagare = deltagare.generate(50);
|
const generatedDeltagare = deltagare.generate(50);
|
||||||
const generatedAvrop = avrop.generate(10, generatedDeltagare.slice(0, 10));
|
const generatedHandledare = handledare.generate(generatedEmployees.slice(0, 6));
|
||||||
|
const generatedAvrop = avrop.generate(10, generatedDeltagare.slice(0, 10), generatedHandledare);
|
||||||
const generatedTjanster = tjanster.generate();
|
const generatedTjanster = tjanster.generate();
|
||||||
const avropTjanster = [];
|
const avropTjanster = [];
|
||||||
const organizations = [];
|
const utforandeVerksamheter = [];
|
||||||
const kommuner = [];
|
const avropKommuner = [];
|
||||||
|
|
||||||
generatedAvrop.forEach(({ tjanstekod, tjansteNamn, utforandeVerksamhetId, utforandeverksamhet, kommunKod, kommun }) => {
|
generatedAvrop.forEach(({ tjanstekod, tjansteNamn, utforandeVerksamhetId, utforandeverksamhet, kommunKod, kommun }) => {
|
||||||
const tjanstExists = avropTjanster.find(tjanst => tjanst.code === tjanstekod);
|
const tjanstExists = avropTjanster.find(tjanst => tjanst.id === tjanstekod);
|
||||||
const organizationExists = organizations.find(organization => organization.id === utforandeVerksamhetId);
|
const utforandeVerksamhetExists = utforandeVerksamheter.find(
|
||||||
const kommunExists = kommuner.find(kommun => kommun.kommunCode === kommunKod);
|
utforandeVerksamhet => utforandeVerksamhet.id === utforandeVerksamhetId
|
||||||
|
);
|
||||||
|
const kommunExists = avropKommuner.find(kommun => kommun.id === kommunKod);
|
||||||
|
|
||||||
if (tjanstExists) {
|
if (tjanstExists) {
|
||||||
if (!tjanstExists.related_utforandeverksamhetIds.includes(utforandeVerksamhetId)) {
|
tjanstExists.count = tjanstExists.count + 1;
|
||||||
tjanstExists.related_utforandeverksamhetIds.push(utforandeVerksamhetId);
|
|
||||||
|
if (!tjanstExists.related_utforandeverksamhetId.includes(utforandeVerksamhetId)) {
|
||||||
|
tjanstExists.related_utforandeverksamhetId.push(utforandeVerksamhetId);
|
||||||
}
|
}
|
||||||
if (!tjanstExists.related_kommunCodes.includes(kommunKod)) {
|
if (!tjanstExists.related_kommunKod.includes(kommunKod)) {
|
||||||
tjanstExists.related_kommunCodes.push(kommunKod);
|
tjanstExists.related_kommunKod.push(kommunKod);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
avropTjanster.push({
|
avropTjanster.push({
|
||||||
code: tjanstekod,
|
id: tjanstekod,
|
||||||
name: tjansteNamn,
|
label: tjansteNamn,
|
||||||
related_utforandeverksamhetIds: [utforandeVerksamhetId],
|
count: 1,
|
||||||
related_kommunCodes: [kommunKod],
|
related_utforandeverksamhetId: [utforandeVerksamhetId],
|
||||||
|
related_kommunKod: [kommunKod],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (organizationExists) {
|
if (utforandeVerksamhetExists) {
|
||||||
if (!organizationExists.related_tjanstIds.includes(tjanstekod)) {
|
utforandeVerksamhetExists.count = utforandeVerksamhetExists.count + 1;
|
||||||
organizationExists.related_tjanstIds.push(tjanstekod);
|
|
||||||
|
if (!utforandeVerksamhetExists.related_tjanstKod.includes(tjanstekod)) {
|
||||||
|
utforandeVerksamhetExists.related_tjanstKod.push(tjanstekod);
|
||||||
}
|
}
|
||||||
if (!organizationExists.related_kommunCodes.includes(kommunKod)) {
|
if (!utforandeVerksamhetExists.related_kommunKod.includes(kommunKod)) {
|
||||||
organizationExists.related_kommunCodes.push(kommunKod);
|
utforandeVerksamhetExists.related_kommunKod.push(kommunKod);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
organizations.push({
|
utforandeVerksamheter.push({
|
||||||
id: utforandeVerksamhetId,
|
id: utforandeVerksamhetId,
|
||||||
name: utforandeverksamhet,
|
label: utforandeverksamhet,
|
||||||
related_tjanstIds: [tjanstekod],
|
count: 1,
|
||||||
related_kommunCodes: [kommunKod],
|
related_tjanstKod: [tjanstekod],
|
||||||
|
related_kommunKod: [kommunKod],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (kommunExists) {
|
if (kommunExists) {
|
||||||
if (!kommunExists.related_tjanstIds.includes(tjanstekod)) {
|
kommunExists.count = kommunExists.count + 1;
|
||||||
kommunExists.related_tjanstIds.push(tjanstekod);
|
|
||||||
|
if (!kommunExists.related_tjanstKod.includes(tjanstekod)) {
|
||||||
|
kommunExists.related_tjanstKod.push(tjanstekod);
|
||||||
}
|
}
|
||||||
if (!kommunExists.related_utforandeverksamhetIds.includes(utforandeVerksamhetId)) {
|
if (!kommunExists.related_utforandeverksamhetId.includes(utforandeVerksamhetId)) {
|
||||||
kommunExists.related_utforandeverksamhetIds.push(utforandeVerksamhetId);
|
kommunExists.related_utforandeverksamhetId.push(utforandeVerksamhetId);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
kommuner.push({
|
avropKommuner.push({
|
||||||
kommunCode: kommunKod,
|
id: kommunKod,
|
||||||
kommun,
|
label: kommun,
|
||||||
related_tjanstIds: [tjanstekod],
|
count: 1,
|
||||||
related_utforandeverksamhetIds: [utforandeVerksamhetId],
|
related_tjanstKod: [tjanstekod],
|
||||||
|
related_utforandeverksamhetId: [utforandeVerksamhetId],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -74,9 +87,10 @@ const apiData = {
|
|||||||
avrop: generatedAvrop,
|
avrop: generatedAvrop,
|
||||||
avropTjanster,
|
avropTjanster,
|
||||||
tjanster: generatedTjanster,
|
tjanster: generatedTjanster,
|
||||||
organizations,
|
utforandeVerksamheter,
|
||||||
kommuner,
|
kommuner: avropKommuner,
|
||||||
deltagare: generatedDeltagare,
|
deltagare: generatedDeltagare,
|
||||||
|
handledare: generatedHandledare,
|
||||||
participants: participants.generate(50).map(participant => ({
|
participants: participants.generate(50).map(participant => ({
|
||||||
...participant,
|
...participant,
|
||||||
employeeId: generatedEmployees[Math.floor(Math.random() * generatedEmployees.length)].id,
|
employeeId: generatedEmployees[Math.floor(Math.random() * generatedEmployees.length)].id,
|
||||||
|
|||||||
21
mock-api/mina-sidor-fa/scripts/handledare.js
Normal file
21
mock-api/mina-sidor-fa/scripts/handledare.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import faker from 'faker';
|
||||||
|
|
||||||
|
faker.locale = 'sv';
|
||||||
|
|
||||||
|
function generateHandledare(employees) {
|
||||||
|
const handledare = [];
|
||||||
|
|
||||||
|
employees.forEach(({ name, ciamUserId }) => {
|
||||||
|
handledare.push({
|
||||||
|
namn: name,
|
||||||
|
ciamUserId,
|
||||||
|
count: faker.datatype.number(20),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return handledare;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
generate: generateHandledare,
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@ import faker from 'faker';
|
|||||||
|
|
||||||
faker.locale = 'sv';
|
faker.locale = 'sv';
|
||||||
|
|
||||||
function generateOrganizations(amount = 10) {
|
function generateOrganizations(amount = 4) {
|
||||||
const organizations = [];
|
const organizations = [];
|
||||||
|
|
||||||
for (let i = 1; i <= amount; ++i) {
|
for (let i = 1; i <= amount; ++i) {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ function generateParticipants(amount = 10) {
|
|||||||
firstName: faker.name.firstName(),
|
firstName: faker.name.firstName(),
|
||||||
lastName: faker.name.lastName(),
|
lastName: faker.name.lastName(),
|
||||||
status: STATUSES[Math.floor(Math.random() * STATUSES.length)],
|
status: STATUSES[Math.floor(Math.random() * STATUSES.length)],
|
||||||
service: TJANSTER[Math.floor(Math.random() * TJANSTER.length)].name,
|
service: TJANSTER[Math.floor(Math.random() * TJANSTER.length)].label,
|
||||||
nextStep: STEPS[Math.floor(Math.random() * STEPS.length)],
|
nextStep: STEPS[Math.floor(Math.random() * STEPS.length)],
|
||||||
errandNumber: faker.datatype.number({ min: 100000, max: 999999 }),
|
errandNumber: faker.datatype.number({ min: 100000, max: 999999 }),
|
||||||
startDate: faker.date.recent(),
|
startDate: faker.date.recent(),
|
||||||
|
|||||||
@@ -6,19 +6,11 @@ function generateTjanster() {
|
|||||||
const tjanster = [
|
const tjanster = [
|
||||||
{
|
{
|
||||||
id: 'A012',
|
id: 'A012',
|
||||||
name: 'Kundval Rusta och matcha',
|
label: 'Kundval Rusta och matcha',
|
||||||
tjanstekod: 'A012',
|
|
||||||
tjanstId: 25,
|
|
||||||
count: 8, // Behövs för avrop-tjanst
|
|
||||||
label: 'Kundval Rusta och matcha', // Behövs för avrop-tjanst
|
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
// id: 'KVL',
|
// id: 'KVL',
|
||||||
// name: 'Karriärvägledning',
|
// label: 'Karriärvägledning',
|
||||||
// tjanstekod: 'KVL',
|
|
||||||
// tjanstId: 33,
|
|
||||||
// count: 8, // Behövs för avrop-tjanst
|
|
||||||
// label: 'Karriärvägledning', // Behövs för avrop-tjanst
|
|
||||||
// },
|
// },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ function generateUtforandeVerksamheter(amount = 10) {
|
|||||||
for (let i = 1; i <= 5; ++i) {
|
for (let i = 1; i <= 5; ++i) {
|
||||||
addresses.push({
|
addresses.push({
|
||||||
adressId: faker.datatype.uuid(),
|
adressId: faker.datatype.uuid(),
|
||||||
adressrad: faker.address.streetName(),
|
adressrad: `${faker.address.streetName()} ${faker.datatype.number({ min: 1, max: 999 })}`,
|
||||||
postort: faker.address.city(),
|
postort: faker.address.city(),
|
||||||
postnummer: faker.address.zipCode(),
|
postnummer: faker.address.zipCode(),
|
||||||
});
|
});
|
||||||
@@ -23,7 +23,7 @@ function generateUtforandeVerksamheter(amount = 10) {
|
|||||||
leverantorNamn: faker.company.companyName(),
|
leverantorNamn: faker.company.companyName(),
|
||||||
tjanstId: faker.datatype.number(10),
|
tjanstId: faker.datatype.number(10),
|
||||||
tjanst: faker.name.jobTitle(),
|
tjanst: faker.name.jobTitle(),
|
||||||
adresser: chooseRandom(addresses, faker.datatype.number(4)),
|
adresser: chooseRandom(addresses, faker.datatype.number({ min: 1, max: addresses.length })),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,9 +22,13 @@ server.use(
|
|||||||
'/participant/:id': '/participants/:id?_embed=employees',
|
'/participant/:id': '/participants/:id?_embed=employees',
|
||||||
'/auth/userinfo': '/currentUser',
|
'/auth/userinfo': '/currentUser',
|
||||||
'/auth/organizations': '/currentUser',
|
'/auth/organizations': '/currentUser',
|
||||||
|
'/avrop/handledare/assign*': '/avrop$1',
|
||||||
'/avrop/tjanster*': '/avropTjanster$1',
|
'/avrop/tjanster*': '/avropTjanster$1',
|
||||||
'/avrop/utforandeverksamheter*': '/organizations$1',
|
'/avrop/handledare*': '/handledare$1',
|
||||||
|
'/avrop/utforandeverksamheter*': '/utforandeVerksamheter$1',
|
||||||
'/avrop/kommuner*': '/kommuner$1',
|
'/avrop/kommuner*': '/kommuner$1',
|
||||||
|
'/avrop*utforandeverksamhetId*': '/avrop$1utforandeVerksamhetId$2',
|
||||||
|
'/avrop*tjanstKod*': '/avrop$1tjanstekod$2',
|
||||||
'/deltagare?*': '/avrop?$1',
|
'/deltagare?*': '/avrop?$1',
|
||||||
'/deltagare/:sokandeId/avrop': '/avrop?sokandeId=:sokandeId',
|
'/deltagare/:sokandeId/avrop': '/avrop?sokandeId=:sokandeId',
|
||||||
'/deltagare/:sokandeId/*': '/deltagare/:sokandeId',
|
'/deltagare/:sokandeId/*': '/deltagare/:sokandeId',
|
||||||
@@ -48,6 +52,11 @@ router.render = (req, res) => {
|
|||||||
return res.status(401).jsonp({ error: 'No valid access-token' });
|
return res.status(401).jsonp({ error: 'No valid access-token' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (method === 'PATCH') {
|
||||||
|
// Returning status 204 as this is the same as in the API, BUT we're not actually updating the mock-api
|
||||||
|
return res.status(204).jsonp();
|
||||||
|
}
|
||||||
|
|
||||||
// Return custom error when status is 404.
|
// Return custom error when status is 404.
|
||||||
if (res.statusCode === 404) {
|
if (res.statusCode === 404) {
|
||||||
return res.status(404).jsonp({ error: `Can't find path: ${pathname}` });
|
return res.status(404).jsonp({ error: `Can't find path: ${pathname}` });
|
||||||
@@ -91,11 +100,15 @@ router.render = (req, res) => {
|
|||||||
if (params) {
|
if (params) {
|
||||||
const newData = [];
|
const newData = [];
|
||||||
params.forEach((value, key) => {
|
params.forEach((value, key) => {
|
||||||
if (key === 'kommunCodes') {
|
// if (key === 'kommunKod') {
|
||||||
value = +value;
|
// value = +value;
|
||||||
}
|
// }
|
||||||
|
|
||||||
newData.push(...data.filter(item => item[`related_${key}`].includes(value)));
|
newData.push(
|
||||||
|
...data.filter(item => {
|
||||||
|
return item[`related_${key}`].includes(value);
|
||||||
|
})
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
data = newData.filter((value, index, arr) => arr.findIndex(item => item.code === value.code) === index);
|
data = newData.filter((value, index, arr) => arr.findIndex(item => item.code === value.code) === index);
|
||||||
@@ -131,13 +144,13 @@ function appendMetaData(params, res) {
|
|||||||
const limit = +params.get('limit');
|
const limit = +params.get('limit');
|
||||||
const page = +params.get('page');
|
const page = +params.get('page');
|
||||||
const count = res.get('X-Total-Count');
|
const count = res.get('X-Total-Count');
|
||||||
const totalPages = Math.ceil(count / limit);
|
const totalPage = Math.ceil(count / limit);
|
||||||
return {
|
return {
|
||||||
meta: {
|
meta: {
|
||||||
count,
|
count,
|
||||||
limit,
|
limit,
|
||||||
page,
|
page,
|
||||||
totalPages,
|
totalPage,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user