Fixed some issues with invites mock-data and response from api
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
<section class="employee-invite">
|
<section class="employee-invite">
|
||||||
<digi-typography>
|
<digi-typography>
|
||||||
<h1>Skapa nytt personalkonto</h1>
|
<h1>Skapa nytt personalkonto</h1>
|
||||||
<p>Såhär skapar du ett nytt personalkonto:</p>
|
<p>Så här skapar du ett nytt personalkonto:</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li>Skicka en inbjudningslänk till personalens e-postadress.</li>
|
<li>Skicka en inbjudningslänk till personalens e-postadress.</li>
|
||||||
<li>Personalen öppnar inbjudningslänken via sin e-post och skapar ett personalkonto med sitt Bank-ID.</li>
|
<li>Personalen öppnar inbjudningslänken via sin e-post och skapar ett personalkonto med sitt Bank-ID.</li>
|
||||||
@@ -32,9 +32,9 @@
|
|||||||
afLabel="E-postadress"
|
afLabel="E-postadress"
|
||||||
afType="email"
|
afType="email"
|
||||||
[afRequired]="true"
|
[afRequired]="true"
|
||||||
[afInvalidMessage]="email.errors?.message || 'Ogiltig e-postadress'"
|
[afInvalidMessage]="emailControl.errors?.message || 'Ogiltig e-postadress'"
|
||||||
[afDisableValidStyle]="true"
|
[afDisableValidStyle]="true"
|
||||||
[afInvalid]="email.invalid && email.dirty"
|
[afInvalid]="emailControl.invalid && emailControl.dirty"
|
||||||
></digi-ng-form-input>
|
></digi-ng-form-input>
|
||||||
<digi-button af-size="m" af-type="submit" class="employee-invite__invitation-btn"
|
<digi-button af-size="m" af-type="submit" class="employee-invite__invitation-btn"
|
||||||
>Skicka inbjudningslänk</digi-button
|
>Skicka inbjudningslänk</digi-button
|
||||||
@@ -42,14 +42,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<digi-notification-alert
|
<digi-notification-alert
|
||||||
*ngIf="(latestSubmittedInvite$ | async) as latestSubmittedInvite"
|
*ngIf="(lastInvite$ | async) as lastInvite"
|
||||||
af-variation="success"
|
af-variation="success"
|
||||||
af-heading="Allt gick bra"
|
af-heading="Allt gick bra"
|
||||||
af-heading-level="h3"
|
af-heading-level="h3"
|
||||||
af-closeable="true"
|
af-closeable="true"
|
||||||
(click)="onCloseAlert()"
|
(click)="onCloseAlert()"
|
||||||
>
|
>
|
||||||
<p>Inbjudan har skickats till {{latestSubmittedInvite.email}}</p>
|
<p *ngIf="lastInvitedNewUsers?.length">Inbjudan har skickats till {{lastInvitedNewUsers.join(', ')}}.</p>
|
||||||
|
<p *ngIf="lastInvitedExistingUsers?.length">
|
||||||
|
Följande personal är redan registrerat: {{lastInvitedExistingUsers.join(', ')}}.
|
||||||
|
</p>
|
||||||
</digi-notification-alert>
|
</digi-notification-alert>
|
||||||
|
|
||||||
<footer class="employee-invite__footer">
|
<footer class="employee-invite__footer">
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
|
||||||
|
import { EmployeeInviteResponse } from '@msfa-models/api/employee-invite.response.model';
|
||||||
import { EmployeeService } from '@msfa-services/api/employee.service';
|
import { EmployeeService } from '@msfa-services/api/employee.service';
|
||||||
import { RequiredValidator } from '@msfa-utils/validators/required.validator';
|
import { RequiredValidator } from '@msfa-utils/validators/required.validator';
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
@@ -10,46 +11,57 @@ import { BehaviorSubject, Observable } from 'rxjs';
|
|||||||
styleUrls: ['./employee-invite.component.scss'],
|
styleUrls: ['./employee-invite.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class EmployeeInviteComponent implements OnInit {
|
export class EmployeeInviteComponent {
|
||||||
form: FormGroup;
|
form: FormGroup = new FormGroup({
|
||||||
private latestSubmittedInvite_ = new BehaviorSubject<string>('');
|
email: new FormControl('', [
|
||||||
latestSubmittedInvite$: Observable<string> = this.latestSubmittedInvite_.asObservable();
|
RequiredValidator('E-postadress'),
|
||||||
|
Validators.pattern('^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$'),
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
private _lastInvite$ = new BehaviorSubject<EmployeeInviteResponse>(null);
|
||||||
|
lastInvite$: Observable<EmployeeInviteResponse> = this._lastInvite$.asObservable();
|
||||||
|
|
||||||
constructor(private employeeService: EmployeeService) {}
|
constructor(private employeeService: EmployeeService) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
get emailControl(): AbstractControl {
|
||||||
this.form = new FormGroup({
|
|
||||||
email: new FormControl('', [
|
|
||||||
RequiredValidator('E-postadress'),
|
|
||||||
Validators.pattern('^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$'),
|
|
||||||
]),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get email() {
|
|
||||||
return this.form.get('email');
|
return this.form.get('email');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get lastInvite(): EmployeeInviteResponse {
|
||||||
|
return this._lastInvite$.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
get lastInvitedNewUsers(): string[] {
|
||||||
|
const invitedUsers = this.lastInvite?.invitedUsers || [];
|
||||||
|
const assignedUsers = this.lastInvite?.assignedUsers || [];
|
||||||
|
return [...invitedUsers, ...assignedUsers.map(assigned => assigned.email)];
|
||||||
|
}
|
||||||
|
|
||||||
|
get lastInvitedExistingUsers(): string[] {
|
||||||
|
const existingUsersInCurrentOrg = this.lastInvite?.existingUsersInCurrentOrg || [];
|
||||||
|
return existingUsersInCurrentOrg.map(existing => existing.email);
|
||||||
|
}
|
||||||
|
|
||||||
submitForm(): void {
|
submitForm(): void {
|
||||||
|
this._lastInvite$.next(null);
|
||||||
if (this.form.invalid) {
|
if (this.form.invalid) {
|
||||||
this.email.markAsDirty();
|
this.emailControl.markAsDirty();
|
||||||
this.email.markAsTouched();
|
this.emailControl.markAsTouched();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const post = this.employeeService.postEmployeeInvitation(this.form.value).subscribe({
|
const post = this.employeeService.postEmployeeInvitation(this.emailControl.value).subscribe({
|
||||||
next: () => {
|
next: data => {
|
||||||
this.latestSubmittedInvite_.next(this.form.value);
|
this._lastInvite$.next(data);
|
||||||
this.form.reset();
|
this.form.reset();
|
||||||
},
|
},
|
||||||
complete: () => {
|
complete: () => {
|
||||||
post.unsubscribe();
|
post.unsubscribe();
|
||||||
},
|
},
|
||||||
error: (err) => console.log(err)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onCloseAlert(): void {
|
onCloseAlert(): void {
|
||||||
this.latestSubmittedInvite_.next('');
|
this._lastInvite$.next(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,18 @@
|
|||||||
export interface EmployeeInviteMockApiResponse {
|
interface ExistingUser {
|
||||||
id: number,
|
ciamUserId: string;
|
||||||
createdAt: number
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
email: string;
|
||||||
|
status: string;
|
||||||
|
roles: string[];
|
||||||
|
tjansteKoder: string[];
|
||||||
|
allaUtforandeVerksamheter: boolean;
|
||||||
|
utforandeVerksamhetIds: number[];
|
||||||
|
adressIds: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EmployeeInviteResponse {
|
||||||
|
assignedUsers: ExistingUser[];
|
||||||
|
invitedUsers: string[];
|
||||||
|
existingUsersInCurrentOrg: ExistingUser[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,12 +42,16 @@ export interface EmployeeRequestData {
|
|||||||
adressIds: number[];
|
adressIds: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EmployeeInviteRequestData {
|
|
||||||
emails: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function mapEmployeeToRequestData(data: Employee): EmployeeRequestData {
|
export function mapEmployeeToRequestData(data: Employee): EmployeeRequestData {
|
||||||
const { email, roles, tjanstCodes, allaUtforandeVerksamheter, utforandeVerksamhet, utforandeVerksamhetIds, utforandeAdressIds } = data;
|
const {
|
||||||
|
email,
|
||||||
|
roles,
|
||||||
|
tjanstCodes,
|
||||||
|
allaUtforandeVerksamheter,
|
||||||
|
utforandeVerksamhet,
|
||||||
|
utforandeVerksamhetIds,
|
||||||
|
utforandeAdressIds,
|
||||||
|
} = data;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
email,
|
email,
|
||||||
@@ -56,7 +60,7 @@ export function mapEmployeeToRequestData(data: Employee): EmployeeRequestData {
|
|||||||
utforandeVerksamhetIds,
|
utforandeVerksamhetIds,
|
||||||
adressIds: utforandeAdressIds,
|
adressIds: utforandeAdressIds,
|
||||||
allaUtforandeVerksamheter: allaUtforandeVerksamheter,
|
allaUtforandeVerksamheter: allaUtforandeVerksamheter,
|
||||||
utforandeVerksamhet: utforandeVerksamhet
|
utforandeVerksamhet: utforandeVerksamhet,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { RoleEnum } from '@msfa-enums/role.enum';
|
|||||||
import { SortOrder } from '@msfa-enums/sort-order.enum';
|
import { SortOrder } from '@msfa-enums/sort-order.enum';
|
||||||
import { environment } from '@msfa-environment';
|
import { environment } from '@msfa-environment';
|
||||||
import { DeleteEmployeeMockApiResponse } from '@msfa-models/api/delete-employee.response.model';
|
import { DeleteEmployeeMockApiResponse } from '@msfa-models/api/delete-employee.response.model';
|
||||||
|
import { EmployeeInviteResponse } from '@msfa-models/api/employee-invite.response.model';
|
||||||
import {
|
import {
|
||||||
EmployeeCompactResponse,
|
EmployeeCompactResponse,
|
||||||
EmployeeResponse,
|
EmployeeResponse,
|
||||||
@@ -14,7 +15,6 @@ import {
|
|||||||
import { Params } from '@msfa-models/api/params.model';
|
import { Params } from '@msfa-models/api/params.model';
|
||||||
import {
|
import {
|
||||||
Employee,
|
Employee,
|
||||||
EmployeeInviteRequestData,
|
|
||||||
EmployeesData,
|
EmployeesData,
|
||||||
mapEmployeeToRequestData,
|
mapEmployeeToRequestData,
|
||||||
mapResponseToEmployee,
|
mapResponseToEmployee,
|
||||||
@@ -25,7 +25,7 @@ import { mapRoleResponseToRoleObject, Role } from '@msfa-models/role.model';
|
|||||||
import { Sort } from '@msfa-models/sort.model';
|
import { Sort } from '@msfa-models/sort.model';
|
||||||
import { ErrorService } from '@msfa-services/error.service';
|
import { ErrorService } from '@msfa-services/error.service';
|
||||||
import { BehaviorSubject, combineLatest, Observable, of, throwError } from 'rxjs';
|
import { BehaviorSubject, combineLatest, Observable, of, throwError } from 'rxjs';
|
||||||
import { catchError, filter, map, switchMap, take } from 'rxjs/operators';
|
import { catchError, filter, map, switchMap, take, tap } from 'rxjs/operators';
|
||||||
import { TjanstService } from './tjanst.service';
|
import { TjanstService } from './tjanst.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
@@ -177,14 +177,15 @@ export class EmployeeService extends UnsubscribeDirective {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public postEmployeeInvitation(email: string): Observable<string[]> {
|
public postEmployeeInvitation(email: string): Observable<EmployeeInviteResponse> {
|
||||||
return this.httpClient
|
return this.httpClient
|
||||||
.patch<{ data: EmployeeInviteRequestData }>(`${this._apiBaseUrl}/invite`, {
|
.patch<{ data: EmployeeInviteResponse }>(`${this._apiBaseUrl}/invite`, {
|
||||||
emails: Object.values(email),
|
emails: [email],
|
||||||
})
|
})
|
||||||
.pipe(
|
.pipe(
|
||||||
take(1),
|
take(1),
|
||||||
map(res => res.data.emails),
|
tap(res => console.log(res)),
|
||||||
|
map(res => res.data),
|
||||||
catchError(error => throwError({ message: error as string, type: ErrorType.API }))
|
catchError(error => throwError({ message: error as string, type: ErrorType.API }))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,18 +11,17 @@ server.use(
|
|||||||
'/api/*': '/$1',
|
'/api/*': '/$1',
|
||||||
'*sort=utforandeVerksamhet*': '$1sort=utforandeVerksamhet[0]$2',
|
'*sort=utforandeVerksamhet*': '$1sort=utforandeVerksamhet[0]$2',
|
||||||
'*sort=tjanst*': '$1sort=tjanst[0]$2',
|
'*sort=tjanst*': '$1sort=tjanst[0]$2',
|
||||||
|
'/users/invite*': '/invites$1',
|
||||||
'/users/:id': '/employees?ciamUserId=:id',
|
'/users/:id': '/employees?ciamUserId=:id',
|
||||||
'/users*': '/employees$1',
|
'/users*': '/employees$1',
|
||||||
'/employees*search=*': '/employees$1fullName_like=$2',
|
'/employees*search=*': '/employees$1fullName_like=$2',
|
||||||
'/employees*onlyEmployeesWithoutAuthorization=*': '/employees$1roles.length_lte=1',
|
'/employees*onlyEmployeesWithoutAuthorization=*': '/employees$1roles.length_lte=1',
|
||||||
'/employees/invite': '/invites',
|
|
||||||
'/employees*': '/employees$1',
|
'/employees*': '/employees$1',
|
||||||
'/services*': '/tjanster$1',
|
'/services*': '/tjanster$1',
|
||||||
'/participants': '/participants?_embed=employees',
|
'/participants': '/participants?_embed=employees',
|
||||||
'/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/handledare*': '/handledare$1',
|
'/avrop/handledare*': '/handledare$1',
|
||||||
'/avrop/utforandeverksamheter*': '/utforandeVerksamheter$1',
|
'/avrop/utforandeverksamheter*': '/utforandeVerksamheter$1',
|
||||||
@@ -33,7 +32,6 @@ server.use(
|
|||||||
'/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',
|
||||||
'/employees/invite': '/invites',
|
|
||||||
'*page=*': '$1_page=$2',
|
'*page=*': '$1_page=$2',
|
||||||
'*limit=*': '$1_limit=$2',
|
'*limit=*': '$1_limit=$2',
|
||||||
'*sort=*': '$1_sort=$2',
|
'*sort=*': '$1_sort=$2',
|
||||||
@@ -55,8 +53,19 @@ router.render = (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (method === 'PATCH') {
|
if (method === 'PATCH') {
|
||||||
// Returning status 204 as this is the same as in the API, BUT we're not actually updating the mock-api
|
if (pathname === '/handledare/assign') {
|
||||||
return res.status(204).jsonp();
|
// 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();
|
||||||
|
}
|
||||||
|
if (pathname === '/invites' && req.body?.emails) {
|
||||||
|
return res.status(200).jsonp({
|
||||||
|
data: {
|
||||||
|
invitedUsers: req.body.emails,
|
||||||
|
assignedUsers: [],
|
||||||
|
existingUsersInCurrentOrg: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return custom error when status is 404.
|
// Return custom error when status is 404.
|
||||||
|
|||||||
Reference in New Issue
Block a user