Merge branch 'next' into develop
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
- **authorization:** Whenever the API throws a "403 Forbidden" error we now show an unauthorized message. [TV-695](https://jira.arbetsformedlingen.se/browse/TV-695)
|
||||
- **avrop:** Now showing spårnamn instead of spårkod inside avrop. [TV-691](https://jira.arbetsformedlingen.se/browse/TV-691)
|
||||
- **avrop:** Fixed error-state on handledare select. [TV-699](https://jira.arbetsformedlingen.se/browse/TV-699)
|
||||
- **avrop:** Several bugfixes related to avrop. [TV-701](https://jira.arbetsformedlingen.se/browse/TV-701)
|
||||
|
||||
## [2.0.0](https://bitbucket.arbetsformedlingen.se/projects/tea/repos/mina-sidor-fa-web/compare/diff?targetBranch=refs%2Ftags%2Fv1.5.0&sourceBranch=refs%2Ftags%2Fv2.0.0) (2021-09-24)
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
@import 'variables/gutters';
|
||||
@import 'variables/z-index';
|
||||
|
||||
.employees-list {
|
||||
position: relative;
|
||||
z-index: $msfa__z-index-default;
|
||||
// &__column-head {
|
||||
// // padding: 0;
|
||||
// }
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
<h2>Personallista</h2>
|
||||
|
||||
<form class="employees__search-wrapper" (ngSubmit)="setSearchFilter()">
|
||||
<form class="employees__search-wrapper" (ngSubmit)="setSearchString()">
|
||||
<digi-form-input-search
|
||||
af-label="Sök på personalens namn"
|
||||
(afOnInput)="setSearchValue($event)"
|
||||
|
||||
@@ -26,8 +26,8 @@ export class EmployeesComponent {
|
||||
return this._searchValue$.getValue();
|
||||
}
|
||||
|
||||
setSearchFilter(): void {
|
||||
this.employeeService.setSearchFilter(this.searchValue);
|
||||
setSearchString(): void {
|
||||
this.employeeService.setSearchString(this.searchValue);
|
||||
}
|
||||
|
||||
setSearchValue($event: CustomEvent<{ target: { value: string } }>): void {
|
||||
|
||||
@@ -5,11 +5,22 @@
|
||||
<section class="avrop" *ngIf="currentStep$ | async as currentStep">
|
||||
<header class="avrop__header">
|
||||
<h1>Nya deltagare</h1>
|
||||
<p>
|
||||
Här ser du alla nya deltagare. Deltagarna ska tilldelas en handledare innan tjänstens start. Kryssa för de
|
||||
deltagare du vill tilldela en handledare. Du kan välja en, eller flera personer samtidigt, genom att
|
||||
<ng-container [ngSwitch]="currentStep">
|
||||
<p *ngSwitchCase="1">
|
||||
Här ser du alla nya deltagare. Deltagarna ska tilldelas en handledare innan tjänstens start. Kryssa för
|
||||
de deltagare du vill tilldela en handledare. Du kan välja en, eller flera personer samtidigt, genom att
|
||||
kryssa i boxarna nedan.
|
||||
</p>
|
||||
<p *ngSwitchCase="2">
|
||||
Välj vilken handledare du vill tilldela till deltagarna. Gå vidare genom att klicka på Nästa. I nästa
|
||||
steg kommer du att kunna granska tilldelningen innan du bekräftar. Återgå till föregående steg genom att
|
||||
klicka på tillbaka.
|
||||
</p>
|
||||
<p *ngSwitchCase="3">
|
||||
Bekräfta valet av tilldelad handledare genom att klicka på bekräfta tilldelning. Återgå till föregående
|
||||
steg genom att klicka på tillbaka.
|
||||
</p>
|
||||
</ng-container>
|
||||
|
||||
<digi-notification-alert
|
||||
*ngIf="currentStep === 4 && selectedHandledare$ | async as selectedHandledare"
|
||||
@@ -26,8 +37,8 @@
|
||||
<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 *ngSwitchCase="3">Förhandsgranska och tilldela</ng-container>
|
||||
<ng-container *ngSwitchCase="4">Tilldelade deltagare</ng-container>
|
||||
</ng-container>
|
||||
</h2>
|
||||
|
||||
@@ -100,7 +111,7 @@
|
||||
<digi-button af-variation="secondary" af-size="m" (afOnClick)="unlockSelectedAvrop()"
|
||||
>Tillbaka
|
||||
</digi-button>
|
||||
<digi-button af-size="m" (afOnClick)="confirmHandledare()">Tilldela</digi-button>
|
||||
<digi-button af-size="m" (afOnClick)="confirmHandledare()">Nästa</digi-button>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="3">
|
||||
<digi-button af-variation="secondary" af-size="m" (afOnClick)="unconfirmHandledare()"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, OnDestroy } from '@angular/core';
|
||||
import { AvropCompact, AvropCompactData } from '@msfa-models/avrop.model';
|
||||
import { Handledare } from '@msfa-models/handledare.model';
|
||||
import { AvropService } from '@msfa-services/avrop.service';
|
||||
@@ -10,7 +10,7 @@ import { Observable } from 'rxjs';
|
||||
styleUrls: ['./avrop.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class AvropComponent {
|
||||
export class AvropComponent implements OnDestroy {
|
||||
readonly totalAmountOfSteps = 3;
|
||||
currentStep$: Observable<number> = this.avropService.currentStep$;
|
||||
error$: Observable<string> = this.avropService.error$;
|
||||
@@ -26,6 +26,10 @@ export class AvropComponent {
|
||||
|
||||
constructor(private avropService: AvropService) {}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.returnToStep1();
|
||||
}
|
||||
|
||||
updateSelectedAvrop(deltagareList: AvropCompact[], currentStep: number): void {
|
||||
if (currentStep !== 1 && !deltagareList.length) {
|
||||
this.avropService.goToStep1();
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
<digi-ng-skeleton-base *ngIf="avropLoading" [afCount]="3" afText="Laddar nya deltagare"></digi-ng-skeleton-base>
|
||||
<div *ngIf="availableAvrop?.length" 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
|
||||
@@ -27,6 +19,7 @@
|
||||
*ngIf="totalPage > 1 && !isLocked"
|
||||
class="avrop-list__pagination"
|
||||
[afTotalPages]="totalPage"
|
||||
[afInitActivePage]="currentPage"
|
||||
[afCurrentResultStart]="currentResultStart"
|
||||
[afCurrentResultEnd]="currentResultEnd"
|
||||
[afTotalResults]="count"
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
@import 'mixins/list';
|
||||
|
||||
.avrop-list {
|
||||
&__select-all {
|
||||
padding: var(--digi--layout--gutter);
|
||||
}
|
||||
|
||||
&__list {
|
||||
@include msfa__reset-list;
|
||||
display: flex;
|
||||
|
||||
@@ -24,10 +24,6 @@ export class AvropListComponent {
|
||||
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;
|
||||
}
|
||||
@@ -53,14 +49,6 @@ export class AvropListComponent {
|
||||
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);
|
||||
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
<tr>
|
||||
<th scope="col" class="deltagare-list-handelser__heading-row">Inkom</th>
|
||||
<th scope="col" class="deltagare-list-handelser__heading-row">Händelse</th>
|
||||
<th scope="col" class="deltagare-list-handelser__heading-row">Datum för händelse</th>
|
||||
<th scope="col" class="deltagare-list-handelser__heading-row">Datum förklaring</th>
|
||||
<th scope="col" class="deltagare-list-handelser__heading-row">Effekt</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -23,8 +22,11 @@
|
||||
<td class="deltagare-list-handelser__table-cell">{{handelse.receivedDate | date}}</td>
|
||||
<td class="deltagare-list-handelser__table-cell" *ngIf="!handelse.isAvbrott; else isAvbrottCell">
|
||||
{{handelse.description}}</td>
|
||||
<td class="deltagare-list-handelser__table-cell">{{handelse.tidpunkt | date }}</td>
|
||||
<td class="deltagare-list-handelser__table-cell">{{handelse.tidpunktDescription}}</td>
|
||||
<td class="deltagare-list-handelser__table-cell">
|
||||
<ng-container *ngIf="handelse.effectDescription && handelse.effectDate">
|
||||
{{handelse.effectDescription}}: {{handelse.effectDate | date }}
|
||||
</ng-container>
|
||||
</td>
|
||||
<ng-template #isAvbrottCell>
|
||||
<td class="deltagare-list-handelser__avbrott-cell">
|
||||
<msfa-icon [icon]="iconType.WARNING" size="l"></msfa-icon>
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
(afOnChange)="setOnlyMyDeltagare($event.detail.target.checked)"
|
||||
></digi-form-checkbox>
|
||||
</div>
|
||||
{{showUnauthorizedError$ | async}}
|
||||
<ng-container *ngIf="(deltagareLoading$ | async) === false; else loadingRef">
|
||||
<msfa-deltagare-list
|
||||
*ngIf="allDeltagareData.data.length; else noDeltagare"
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
grid-area: content;
|
||||
max-width: $digi--layout--breakpoint--l;
|
||||
padding: $digi--layout--gutter--l $digi--layout--gutter--l $digi--layout--gutter--xxl;
|
||||
z-index: $msfa__z-index-default;
|
||||
}
|
||||
|
||||
&__breadcrumbs {
|
||||
|
||||
@@ -13,7 +13,7 @@ export interface AvropCompact {
|
||||
sprakstod: string; // sprakstod
|
||||
utforandeAdress: string; // adress
|
||||
trackCode: string; // sparkod
|
||||
trackName: string; // sparNamn
|
||||
trackName: TrackName; // sparNamn
|
||||
}
|
||||
|
||||
export interface Avrop extends AvropCompact {
|
||||
@@ -60,11 +60,11 @@ export function mapAvropResponseToAvrop(data: AvropResponse): Avrop {
|
||||
sprakstod: sprakstod,
|
||||
utforandeAdress: adress,
|
||||
trackCode: sparkod,
|
||||
trackName: TrackName[sparkod] || TrackName.UNKNOWN,
|
||||
trackName: (TrackName[sparkod] || TrackName.UNKNOWN) as TrackName,
|
||||
genomforandeReferens,
|
||||
participationFrequency: deltagandeGrad,
|
||||
utforandeVerksamhet: utforandeverksamhet,
|
||||
handledareCiamUserId,
|
||||
handledareCiamUserId: handledareCiamUserId,
|
||||
handledare,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,13 +15,18 @@ export interface ContactInformation {
|
||||
|
||||
export function mapResponseToContactInformation(data: ContactInformationResponse): ContactInformation {
|
||||
const { fornamn, efternamn, personnummer, epost, telekomadresser, adresser } = data;
|
||||
|
||||
return {
|
||||
firstName: fornamn || '',
|
||||
lastName: efternamn || '',
|
||||
fullName: fornamn && efternamn ? `${fornamn} ${efternamn}` : '',
|
||||
ssn: personnummer ? mapStringToSsn(personnummer) : '',
|
||||
email: epost || '',
|
||||
phoneNumbers: telekomadresser ? telekomadresser.map(phoneNumber => mapResponseToPhoneNumber(phoneNumber)) : [],
|
||||
phoneNumbers: telekomadresser
|
||||
? telekomadresser
|
||||
.filter(phoneNumber => phoneNumber.landskod && phoneNumber.nummer_utan_inledande_nolla)
|
||||
.map(phoneNumber => mapResponseToPhoneNumber(phoneNumber))
|
||||
: [],
|
||||
addresses: adresser ? adresser.map(address => mapResponseToAddress(address)) : null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,27 @@
|
||||
const GENOMFORANDEHANDELSE_EFFECT_MAP = {
|
||||
Inrapporteringsdatum_GP: 'Inskickad datum',
|
||||
Godkannandedatum_GP: 'Godkänd datum',
|
||||
Avvisatdatum_GP: 'Ej godkänd datum',
|
||||
Inrapporteringsdatum_PR: 'Inrapporterad datum',
|
||||
Godkannandedatum_PR: 'Godkänd datum',
|
||||
Avvisatdatum_PR: 'Ej godkänd datum',
|
||||
Inrapporteringsdatum_SR: 'Inskickad datum',
|
||||
Godkannandedatum_SR: 'Godkänd datum',
|
||||
Avvisatdatum_SR: 'Ej godkänd datum',
|
||||
Handlaggning_startad: 'Handläggning startad',
|
||||
Andringsbeslutdatum: 'Ändringsbeslut datum',
|
||||
Slut_avropsperiod: 'Nytt slutdatum',
|
||||
};
|
||||
|
||||
export interface DeltagareHandelse {
|
||||
description: string;
|
||||
receivedDate: Date;
|
||||
isAvbrott: boolean;
|
||||
effectDate: Date;
|
||||
effectDescription: string;
|
||||
}
|
||||
|
||||
interface DeltagareHandelseApiResponse {
|
||||
description: string;
|
||||
receivedDate: Date;
|
||||
isAvbrott: boolean;
|
||||
@@ -6,6 +29,18 @@ export interface DeltagareHandelse {
|
||||
tidpunktDescription: string;
|
||||
}
|
||||
|
||||
export interface DeltagareHandelseApiResponse {
|
||||
data: DeltagareHandelse[];
|
||||
export interface DeltagareHandelserApiResponse {
|
||||
data: DeltagareHandelseApiResponse[];
|
||||
}
|
||||
|
||||
export function mapDeltagareHandelseApiResponse(
|
||||
deltagareHandelseApiResponse: DeltagareHandelseApiResponse
|
||||
): DeltagareHandelse {
|
||||
const { description, receivedDate, isAvbrott } = deltagareHandelseApiResponse;
|
||||
const effectDate = deltagareHandelseApiResponse.tidpunkt;
|
||||
const effectDescription =
|
||||
GENOMFORANDEHANDELSE_EFFECT_MAP[deltagareHandelseApiResponse.tidpunktDescription] ??
|
||||
deltagareHandelseApiResponse.tidpunktDescription ??
|
||||
'';
|
||||
return { description, receivedDate, isAvbrott, effectDate, effectDescription };
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { environment } from '@msfa-environment';
|
||||
import { DeltagareHandelse, DeltagareHandelseApiResponse } from '@msfa-models/deltagare-handelse.model';
|
||||
import {
|
||||
DeltagareHandelse,
|
||||
DeltagareHandelserApiResponse,
|
||||
mapDeltagareHandelseApiResponse,
|
||||
} from '@msfa-models/deltagare-handelse.model';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@@ -18,11 +22,11 @@ export class DeltagareHandelserApiService {
|
||||
}
|
||||
|
||||
return this.httpClient
|
||||
.get<DeltagareHandelseApiResponse>(`${this._apiBaseUrl}/deltagare/${genomforandeReferens}/handelser`)
|
||||
.get<DeltagareHandelserApiResponse>(`${this._apiBaseUrl}/deltagare/${genomforandeReferens}/handelser`)
|
||||
.pipe(
|
||||
map(({ data }) => {
|
||||
if (data) {
|
||||
return data;
|
||||
return data.map(genomforandeHandelse => mapDeltagareHandelseApiResponse(genomforandeHandelse));
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
@@ -23,19 +23,35 @@ import { ErrorService } from '@msfa-services/error.service';
|
||||
import { BehaviorSubject, combineLatest, Observable, of, throwError } from 'rxjs';
|
||||
import { catchError, distinctUntilChanged, filter, map, switchMap, take, tap } from 'rxjs/operators';
|
||||
|
||||
interface EmployeeParams {
|
||||
page: number;
|
||||
limit: number;
|
||||
sort: keyof EmployeeCompactResponse;
|
||||
order: SortOrder;
|
||||
search: string;
|
||||
onlyEmployeesWithoutAuthorization: boolean;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class EmployeeService extends UnsubscribeDirective {
|
||||
private _apiBaseUrl = `${environment.api.url}/users`;
|
||||
private _currentEmployeeId$ = new BehaviorSubject<string>(null);
|
||||
private _limit$ = new BehaviorSubject<number>(10);
|
||||
private _page$ = new BehaviorSubject<number>(1);
|
||||
private _sort$ = new BehaviorSubject<Sort<keyof EmployeeCompactResponse>>({ key: 'name', order: SortOrder.ASC });
|
||||
public sort$: Observable<Sort<keyof EmployeeCompactResponse>> = this._sort$.asObservable();
|
||||
private _searchFilter$ = new BehaviorSubject<string>('');
|
||||
private _onlyEmployeesWithoutAuthorization$ = new BehaviorSubject<boolean>(false);
|
||||
public onlyEmployeesWithoutAuthorization$: Observable<boolean> = this._onlyEmployeesWithoutAuthorization$.asObservable();
|
||||
private _params$ = new BehaviorSubject<EmployeeParams>({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
sort: 'name',
|
||||
order: SortOrder.ASC,
|
||||
search: '',
|
||||
onlyEmployeesWithoutAuthorization: false,
|
||||
});
|
||||
public sort$: Observable<Sort<keyof EmployeeCompactResponse>> = this._params$.pipe(
|
||||
map(({ sort, order }) => ({ key: sort, order }))
|
||||
);
|
||||
public onlyEmployeesWithoutAuthorization$: Observable<boolean> = this._params$.pipe(
|
||||
map(({ onlyEmployeesWithoutAuthorization }) => onlyEmployeesWithoutAuthorization)
|
||||
);
|
||||
private _employee$ = new BehaviorSubject<Employee>(null);
|
||||
public employee$: Observable<Employee> = this._employee$.asObservable();
|
||||
private _lastUpdatedEmployeeId$ = new BehaviorSubject<string>(null);
|
||||
@@ -67,17 +83,8 @@ export class EmployeeService extends UnsubscribeDirective {
|
||||
);
|
||||
}
|
||||
|
||||
public employeesData$: Observable<EmployeesData> = combineLatest([
|
||||
this._limit$,
|
||||
this._page$,
|
||||
this._sort$,
|
||||
this._searchFilter$,
|
||||
this._onlyEmployeesWithoutAuthorization$,
|
||||
this._lastDeletedEmployee$,
|
||||
]).pipe(
|
||||
switchMap(([limit, page, sort, searchFilter, onlyEmployeesWithoutAuthorization]) =>
|
||||
this._fetchEmployees$(limit, page, sort, searchFilter, onlyEmployeesWithoutAuthorization)
|
||||
)
|
||||
public employeesData$: Observable<EmployeesData> = combineLatest([this._params$, this._lastDeletedEmployee$]).pipe(
|
||||
switchMap(([params]) => this._fetchEmployees$(params))
|
||||
);
|
||||
|
||||
public setCurrentEmployeeId(currentEmployeeId: string): void {
|
||||
@@ -91,26 +98,21 @@ export class EmployeeService extends UnsubscribeDirective {
|
||||
this._lastUpdatedEmployeeId$.next(null);
|
||||
}
|
||||
|
||||
private _fetchEmployees$(
|
||||
limit: number,
|
||||
page: number,
|
||||
sort: Sort<keyof EmployeeCompactResponse>,
|
||||
searchFilter: string,
|
||||
onlyEmployeesWithoutAuthorization?: boolean
|
||||
): Observable<EmployeesData> {
|
||||
private _fetchEmployees$(employeeParams: EmployeeParams): Observable<EmployeesData> {
|
||||
const { sort, order, limit, page, search, onlyEmployeesWithoutAuthorization } = employeeParams;
|
||||
const params: Params = {
|
||||
sort: sort.key as string,
|
||||
order: sort.order as string,
|
||||
sort,
|
||||
order,
|
||||
limit: limit.toString(),
|
||||
page: page.toString(),
|
||||
};
|
||||
|
||||
if (searchFilter) {
|
||||
params.search = searchFilter;
|
||||
if (search) {
|
||||
params.search = search;
|
||||
}
|
||||
|
||||
if (onlyEmployeesWithoutAuthorization) {
|
||||
params.onlyEmployeesWithoutAuthorization = onlyEmployeesWithoutAuthorization?.toString();
|
||||
params.onlyEmployeesWithoutAuthorization = onlyEmployeesWithoutAuthorization.toString();
|
||||
}
|
||||
this._employeesLoading$.next(true);
|
||||
|
||||
@@ -134,12 +136,20 @@ export class EmployeeService extends UnsubscribeDirective {
|
||||
);
|
||||
}
|
||||
|
||||
public setSearchFilter(value: string): void {
|
||||
this._searchFilter$.next(value);
|
||||
public setSearchString(value: string): void {
|
||||
this._params$.next({
|
||||
...this._params$.getValue(),
|
||||
search: value,
|
||||
page: 1,
|
||||
});
|
||||
}
|
||||
|
||||
public setOnlyEmployeesWithoutAuthorization(value: boolean): void {
|
||||
this._onlyEmployeesWithoutAuthorization$.next(value);
|
||||
this._params$.next({
|
||||
...this._params$.getValue(),
|
||||
onlyEmployeesWithoutAuthorization: value,
|
||||
page: 1,
|
||||
});
|
||||
}
|
||||
|
||||
public setEmployeeToDelete(employee: Employee): void {
|
||||
@@ -156,16 +166,17 @@ export class EmployeeService extends UnsubscribeDirective {
|
||||
);
|
||||
}
|
||||
|
||||
public setSort(newSortKey: keyof EmployeeCompactResponse): void {
|
||||
const currentSort = this._sort$.getValue();
|
||||
const order =
|
||||
currentSort.key === newSortKey && currentSort.order === SortOrder.ASC ? SortOrder.DESC : SortOrder.ASC;
|
||||
public setSort(sort: keyof EmployeeCompactResponse): void {
|
||||
const currentParams = this._params$.getValue();
|
||||
const currentSort = currentParams.sort;
|
||||
const currentOrder = currentParams.order;
|
||||
const order = currentSort === sort && currentOrder === SortOrder.ASC ? SortOrder.DESC : SortOrder.ASC;
|
||||
|
||||
this._sort$.next({ key: newSortKey, order });
|
||||
this._params$.next({ ...this._params$.getValue(), sort, order });
|
||||
}
|
||||
|
||||
public setPage(page: number): void {
|
||||
this._page$.next(page);
|
||||
this._params$.next({ ...this._params$.getValue(), page });
|
||||
}
|
||||
|
||||
public postEmployeeInvitation(emails: string[]): Observable<EmployeeInviteResponse | null> {
|
||||
|
||||
@@ -95,8 +95,11 @@ export class AvropService {
|
||||
this._avropIsLocked$,
|
||||
this._avropIsSubmitted$,
|
||||
]).pipe(
|
||||
map(([confirmedHandledare, avropIsLocked, avropIsSubmitted]) => {
|
||||
return AvropService.calculateStep(confirmedHandledare, avropIsLocked, avropIsSubmitted);
|
||||
map(([confirmedHandledare, avropIsLocked, avropIsSubmitted]) =>
|
||||
AvropService.calculateStep(confirmedHandledare, avropIsLocked, avropIsSubmitted)
|
||||
),
|
||||
tap(() => {
|
||||
window.scrollTo(0, 0);
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
- **authorization:** Whenever the API throws a "403 Forbidden" error we now show an unauthorized message. [TV-695](https://jira.arbetsformedlingen.se/browse/TV-695)
|
||||
- **avrop:** Now showing spårnamn instead of spårkod inside avrop. [TV-691](https://jira.arbetsformedlingen.se/browse/TV-691)
|
||||
- **avrop:** Fixed error-state on handledare select. [TV-699](https://jira.arbetsformedlingen.se/browse/TV-699)
|
||||
- **avrop:** Several bugfixes related to avrop. [TV-701](https://jira.arbetsformedlingen.se/browse/TV-701)
|
||||
|
||||
## [2.0.0](https://bitbucket.arbetsformedlingen.se/projects/tea/repos/mina-sidor-fa-web/compare/diff?targetBranch=refs%2Ftags%2Fv1.5.0&sourceBranch=refs%2Ftags%2Fv2.0.0) (2021-09-24)
|
||||
|
||||
|
||||
@@ -24,13 +24,31 @@ Den här webbplatsen är delvis förenlig med lagen om tillgänglighet till digi
|
||||
|
||||
Vi är medvetna om följande brister som inte följer lagkraven:
|
||||
|
||||
- Inga brister hittades
|
||||
- Användare kan inte hoppa över innehåll som upprepas på flera sidor (till exempel menyer) genom en skip-länk som leder till huvudinnehållet. (WCAG 2.4.1 Hoppa över grupperat innehåll)
|
||||
- Tabeller ihar inte en överskrift i form av en *caption* som kort beskriver vilken information tabellen innehåller. Tex tabellen för personallistan ska ha ett namn.(WCAG Tabeller har överskrifter1.3.1 Information och relationer)
|
||||
- Alla obligatoriska fält är inte uppmärkta med (obligatoriskt). Finns fält som inte är uppmärkta tex personal. Dvs där det inte står att dem fälten är obligatoriska fast dem är obligatoriska att fylla. (WCAG 3.3.2 Etiketter och instruktioner)
|
||||
- Inmatningsfel upptäcks inte automatiskt så att fältet markeras och felet beskrivs inte för användaren med text. Fältet får inte attributet aria-invalid. (WCAG 3.3.1 Identifiering av fel).
|
||||
- Meddelande visas inte om en användare skickar in ett formulär som innehåller fel, kommuniceras inte heller till användare med skärmläsare och får fokus. Behöver stämmas av med tillgänglighetstestare gällande implementering av felmeddelande med fokus.(WCAG 3.3.1 Identifiering av fel)
|
||||
- Ändra text mellanrum har vissa brister som kommer kollas på framöver under 2021.(WCAG 1.4.12 Textmellanrum)
|
||||
- Brister gällande förutsägbarhet vid inmatning. Förklarande text för skärmläsare i filtersökfältet behöver adderas.Lägga till area attribut.Skärmläsare behöver få notifieringar på vad som händer , dvs gällande resultat och vad som söks på (WCAG 3.2.2 Förutsägbarhet vid inmatning).
|
||||
- Läs ordning för hjälpmedel har testats och fungerar, men behöver testas mer strukturerat och fokuserat tillsammans med tillgänglighetstestare (WCAG 1.3.2 Meningsfull ordning)
|
||||
- Brister gällande dölj dekorativa bilder. Bild behöver döljas med attribut "area hidden" så att det inte läses upp för skärmläsaren (WCAG 1.1.1 Innehåll som inte är text).
|
||||
- Brister gällande semantiska länkar tex länkar länkar till samma sidor, pga navigeringen ligger fast (WCAG 1.3.1 Information och relationer).
|
||||
- Brister gällande tydliga länktexter vissa knappar är oklara gällande sin betydelse tex står avbryt på en knapp men det behöver förtydligas vad man avbryter . Det står på en annan knapp "Redigera" men det behöver förtydligas vad man redigerar (WCAG 2.4.4 / 2.4.9 Länksyfte).
|
||||
- Beskrivande etiketter behöver testas en gång till tillsammans med tillgänglighetstestare (WCAG 2.4.6 Rubriker och etiketter).
|
||||
- Brist gällande felmeddelande kommuniceras till användare med skärmläsare utan att felmeddelandet får fokus. Behöver lägga in area-liv i felmeddelande och det behöver även testas en gång till tillsammans med tillgänglighetstestare (WCAG 4.1.3 Statusmeddelande).
|
||||
- Brist gällande innehåll som förändras dynamiskt tex man får inte positiv feedback att man genomfört en sökning i personallistan. Tex att sökningen genomförts, inte heller sökträffar. Samt när man filtrerar sökningen så får man inte feedback på att filtreringen genomförts. (WCAG 4.1.3 Statusmeddelande).
|
||||
- Brist gällande dölj innehåll som inte ska visas för skärmläsare, tex dekorativ välkomstbild bör döljas (WCAG 1.1.1 Innehåll som inte är text).
|
||||
|
||||
Områden som behöver testas framöver:
|
||||
- Ytterligare områden som behöver testas är gällande kodkvalitet bl.a. gällande rätt html-markup, att alla HTML-element har fullständiga start & slut-taggar och är nästlade enligt deras specifikationer (WCAG 4.1.1 Se till att koden validerar). Behöver även testas att inga dubbla attribut dvs inga HTML-element innehåller dubbla attributangivelser (WCAG 4.1.1 Se till att koden validerar). Behöver även testas att alla HTML-element har unika id, dvs ett id förekommer endast en gång på sidan (WCAG 4.1.1 Se till att koden validerar).
|
||||
- Ytterligare test behöver även göras kring konsekvent identifiering i tjänsten och konsekvent identifiering på AF (3.2.4 Konsekvent identifiering). Dvs test med tillgänglighetstestare bör göras kring funktioner som finns på flera sidor i tjänsten identifieras på ett konsekvent sätt. Samma termer används t.ex för knappar som gör samma sak (både synlig text och textalternativ). Gäller funktioner i tjänsten. Även test med tillgänglighetstestare bör göras gällande funktioner i tjänsten identifieras på samma sätt som på andra ställen där de förekommer på webbplatsen. Samma termer används t.ex för knappar som gör samma sak.
|
||||
|
||||
## Hur vi har testat webbplatsen
|
||||
|
||||
Vi har gjort en självskattning (intern testning) av webbplatsen. Senaste bedömningen gjordes 2021-09-10.
|
||||
Vi har gjort en självskattning (intern testning) av webbplatsen. Senaste bedömningen gjordes 2021-09-27.
|
||||
|
||||
Redogörelsen uppdaterades den 2021-09-10.
|
||||
Redogörelsen uppdaterades den 2021-09-28.
|
||||
|
||||
## Hur vi jobbar med digital tillgänglighet
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ function generateAvrop(amount = 10, deltagare, handledare) {
|
||||
fornamn: currentDeltagare.contact.fornamn,
|
||||
efternamn: currentDeltagare.contact.efternamn,
|
||||
deltagare: `${currentDeltagare.contact.fornamn} ${currentDeltagare.contact.efternamn}`,
|
||||
genomforandeReferens: faker.datatype.number({ min: 100000000, max: 999999999 }),
|
||||
genomforandeReferens: currentDeltagare.genomforandeReferens,
|
||||
orgId: faker.datatype.uuid(),
|
||||
leverantorId: faker.datatype.number({ min: 1000, max: 99999 }),
|
||||
organisationsnummer: organization.organizationNumber,
|
||||
|
||||
@@ -13,7 +13,21 @@ const HANDELSER = [
|
||||
'Byte av leverantör bifall',
|
||||
];
|
||||
|
||||
const TIDPUNKT_DESCRIPTION = ['Handläggning startad', 'Inrapporteringsdatum slutredovisning'];
|
||||
const TIDPUNKT_DESCRIPTION = [
|
||||
'Inrapporteringsdatum_GP',
|
||||
'Godkannandedatum_GP',
|
||||
'Avvisatdatum_GP',
|
||||
'Inrapporteringsdatum_PR',
|
||||
'Godkannandedatum_PR',
|
||||
'Avvisatdatum_PR',
|
||||
'Inrapporteringsdatum_SR',
|
||||
'Godkannandedatum_SR',
|
||||
'Avvisatdatum_SR',
|
||||
'Handlaggning_startad',
|
||||
'Andringsbeslutdatum',
|
||||
'Slut_avropsperiod',
|
||||
'',
|
||||
];
|
||||
|
||||
function generateHandelser(amount = 10) {
|
||||
const handelser = [];
|
||||
|
||||
@@ -44,9 +44,12 @@ function generateDeltagare(amount = 10) {
|
||||
const educationLevel = EDUCATION_LEVELS[Math.floor(Math.random() * EDUCATION_LEVELS.length)];
|
||||
const sunKod = SUN_KODER[Math.floor(Math.random() * SUN_KODER.length)];
|
||||
|
||||
const genomforandeReferens = faker.datatype.number({ min: 100000000, max: 999999999 });
|
||||
|
||||
const deltagare = {
|
||||
id,
|
||||
id: genomforandeReferens,
|
||||
sokandeId: id,
|
||||
genomforandeReferens,
|
||||
contact: {
|
||||
fornamn,
|
||||
efternamn,
|
||||
|
||||
@@ -147,7 +147,7 @@ router.render = (req, res) => {
|
||||
startdatumAvrop,
|
||||
slutdatumAvrop,
|
||||
hasAvbrott,
|
||||
genomforandeReferens,
|
||||
genomforandeReferens: genomforandeReferens.toString(),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user