Merge pull request #48 in TEA/dafa-web-monorepo from feature/TV-335 to develop

Squashed commit of the following:

commit 8135e484f44885875bd28dbb0cb7f89fdb7223fa
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Sat Aug 14 19:32:56 2021 +0200

    TV-335 refactoring validators

commit f85a832f9f3e7161380b4b204639a71129eee2fb
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Sat Aug 14 18:18:30 2021 +0200

    TV-335 refactoring

commit 81e03f9377ae3ea4d1e2a196d1074e2e620472b1
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Fri Aug 13 17:51:33 2021 +0200

    TV-335 spelling

commit 8542d0d20743e6a6d777c083e3559416b96529bc
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Fri Aug 13 17:48:10 2021 +0200

    TV-335 review fixes

commit 07a5da0576d2d42f043b54cb655aac2070ab218c
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Fri Aug 13 13:22:15 2021 +0200

    TV-335 use digi layout gutters for margins

commit 9c99d78b10a4c7414d83005ba1847ddd5420d7f5
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Fri Aug 13 11:47:32 2021 +0200

    TV-335 added ChangeDetectorRef, refactoring submitForm

commit 21b4e3ca5d72b3cedfd0795ef2d924f3380d167b
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Fri Aug 13 11:09:40 2021 +0200

    TV-335 refactoring due to review comments

commit 9e389c7e67e56e9965453822c38c5fce44e99b35
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Fri Aug 13 00:43:57 2021 +0200

    TV-335 refactoring

commit e3c98416bea1ff705b17bd5bdd85112cbff13c91
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Thu Aug 12 18:56:21 2021 +0200

    TV-335 invalidFormMessage

commit f3f54fc8c331b7b00a4ebef72e80e7fb56640985
Merge: e68eb7c 466abd1
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Thu Aug 12 16:55:33 2021 +0200

    Merge branch 'develop' into feature/TV-335

commit e68eb7cb09aecb2252f542bece1228db453d3cf6
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Thu Aug 12 16:49:40 2021 +0200

    TV-335 email validator

commit eee201919eca8186e0864a69e5f80fd696e40b91
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Thu Aug 12 16:23:30 2021 +0200

    TV-335 post mock data api, notification alert

commit 46b185ad82ac5946ccfdf173a960fde7261e51bd
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Thu Aug 12 11:56:43 2021 +0200

    TV-335 prepare method for post request

commit 8b983fbf34ff39b6252cff9bfdc904d6aeeb3a46
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Thu Aug 12 11:54:25 2021 +0200

    TV-335 routing

commit 01bac9359100a22c3fafa482e828e88727c7ab29
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Thu Aug 12 11:53:30 2021 +0200

    TV-335 employee-invite component
This commit is contained in:
Nicolas Fuentes Maturana
2021-08-17 09:35:10 +02:00
parent bfa8ed551f
commit 39cdcff53d
10 changed files with 230 additions and 4 deletions

View File

@@ -19,6 +19,10 @@ const routes: Routes = [
path: 'skapa-konto',
loadChildren: () => import('./pages/employee-form/employee-form.module').then(m => m.EmployeeFormModule),
},
{
path: 'bjuda-in',
loadChildren: () => import('./pages/employee-invite/employee-invite.module').then(m => m.EmployeeInviteModule),
},
{
path: 'redigera-konto/:employeeId',
loadChildren: () => import('./pages/employee-form/employee-form.module').then(m => m.EmployeeFormModule),

View File

@@ -0,0 +1,60 @@
<dafa-layout>
<section class="employee-invite">
<digi-typography>
<h1>Skapa nytt personalkonto</h1>
<p>Såhär skapar du ett nytt personalkonto:</p>
<ol>
<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>
När kontot är skapat ser du det i personallistan. Det nya personalkontot saknar fortfarande behörigheter.
</li>
<li>
Ge personalkontot behörigheter genom att klicka på namnet i personallistan och ange vilka behörigheter
personalen ska ha. Nu kan personalen logga in och arbeta.
</li>
</ol>
</digi-typography>
<form [formGroup]="form" (ngSubmit)="submitForm()">
<div class="employee-invite__block">
<digi-typography>
<h2>Skicka en inbjudningslänk</h2>
<p>
Skicka en inbjudningslänk till personalen du vill lägga till som systemanvändare. Ange personalens
e-postadress nedan och tryck på skicka inbjudningslänk.
</p>
</digi-typography>
<div class="employee-invite__input-section">
<digi-ng-form-input
afId="employee-invite-email"
class="employee-invite__input"
formControlName="email"
afLabel="E-postadress"
afType="email"
[afRequired]="true"
[afInvalidMessage]="email.errors?.message || 'Ogiltig e-postadress'"
[afDisableValidStyle]="true"
[afInvalid]="email.invalid && email.dirty"
></digi-ng-form-input>
<digi-button af-size="m" af-type="submit" class="employee-invite__invitation-btn"
>Skicka inbjudningslänk</digi-button
>
</div>
</div>
<digi-notification-alert
*ngIf="(latestSubmittedInvite$ | async) as latestSubmittedInvite"
af-variation="success"
af-heading="Allt gick bra"
af-heading-level="h3"
af-closeable="true"
(click)="onCloseAlert()"
>
<p>Inbjudan har skickats till {{latestSubmittedInvite.email}}</p>
</digi-notification-alert>
<footer class="employee-invite__footer">
<dafa-back-link [route]="['/administration/personal']">Tillbaka till personallistan</dafa-back-link>
</footer>
</form>
</section>
</dafa-layout>

View File

@@ -0,0 +1,31 @@
@import 'variables/gutters';
.employee-invite {
&__block {
max-width: var(--digi--typography--text--max-width);
margin-top: $digi--layout--gutter--xl;
margin-bottom: $digi--layout--gutter--xl;
}
&__input-section {
display: flex;
margin-top: $digi--layout--gutter--xl;
}
&__input {
display: block;
min-width: 240px;
margin-bottom: var(--digi--layout--gutter);
}
&__invitation-btn {
margin-top: 31px;
margin-left: 16px;
}
&__footer {
margin-top: $digi--layout--gutter--xl;
display: flex;
gap: var(--digi--layout--gutter);
}
}

View File

@@ -0,0 +1,33 @@
import { DigiNgFormInputModule } from '@af/digi-ng/_form/form-input';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { EmployeeInviteComponent } from './employee-invite.component';
describe('EmployeeInviteComponent', () => {
let component: EmployeeInviteComponent;
let fixture: ComponentFixture<EmployeeInviteComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [ EmployeeInviteComponent ],
imports: [
ReactiveFormsModule,
DigiNgFormInputModule
]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(EmployeeInviteComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,56 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { EmployeeService } from '@dafa-services/api/employee.service';
import { RequiredValidator } from '@dafa-utils/validators/required.validator';
import { BehaviorSubject, Observable } from 'rxjs';
@Component({
selector: 'dafa-employee-invite',
templateUrl: './employee-invite.component.html',
styleUrls: ['./employee-invite.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class EmployeeInviteComponent implements OnInit {
form: FormGroup;
private latestSubmittedInvite_ = new BehaviorSubject<string>('');
latestSubmittedInvite$: Observable<string> = this.latestSubmittedInvite_.asObservable();
constructor(private employeeService: EmployeeService) { }
ngOnInit(): void {
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');
}
submitForm(): void {
if (this.form.invalid) {
this.email.markAsDirty();
this.email.markAsTouched();
return;
}
const post = this.employeeService.postEmployeeInvitation(this.form.value).subscribe({
next: () => {
this.latestSubmittedInvite_.next(this.form.value);
this.form.reset();
},
complete: () => {
post.unsubscribe();
}
});
}
onCloseAlert(): void {
this.latestSubmittedInvite_.next('');
}
}

View File

@@ -0,0 +1,22 @@
import { DigiNgFormInputModule } from '@af/digi-ng/_form/form-input';
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { BackLinkModule } from '@dafa-shared/components/back-link/back-link.module';
import { LayoutModule } from '@dafa-shared/components/layout/layout.module';
import { EmployeeInviteComponent } from './employee-invite.component';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [EmployeeInviteComponent],
imports: [
CommonModule,
RouterModule.forChild([{ path: '', component: EmployeeInviteComponent }]),
LayoutModule,
BackLinkModule,
ReactiveFormsModule,
DigiNgFormInputModule
]
})
export class EmployeeInviteModule { }

View File

@@ -9,7 +9,7 @@
</p>
<div class="employees__cta-wrapper">
<digi-ng-link-button afText="Skapa nytt konto" afRoute="/administration/skapa-konto"></digi-ng-link-button>
<digi-ng-link-button afText="Skapa nytt konto" afRoute="/administration/bjuda-in"></digi-ng-link-button>
</div>
<h2>Personallista</h2>

View File

@@ -0,0 +1,4 @@
export interface EmployeeInviteMockApiResponse {
id: number,
createdAt: number
}

View File

@@ -0,0 +1,3 @@
export interface EmployeeInviteMockaData {
id: number
}

View File

@@ -3,20 +3,23 @@ import { Injectable } from '@angular/core';
import { ErrorType } from '@dafa-enums/error-type.enum';
import { SortOrder } from '@dafa-enums/sort-order.enum';
import { environment } from '@dafa-environment';
import { EmployeeInviteMockApiResponse } from '@dafa-models/api/employee-invite.response.model';
import { EmployeeInviteMockaData } from '@dafa-models/employee-invite-mock-data.model';
import {
Employee,
EmployeeApiResponse,
EmployeesApiResponse,
EmployeesData,
mapEmployeeReponseToEmployee,
mapEmployeeToEmployeeApiRequestData,
mapEmployeeToEmployeeApiRequestData
} from '@dafa-models/employee.model';
import { Sort } from '@dafa-models/sort.model';
import { BehaviorSubject, combineLatest, Observable, throwError } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';
import { catchError, map, switchMap, take } from 'rxjs/operators';
const API_HEADERS = { headers: environment.api.headers };
@Injectable({
providedIn: 'root',
})
@@ -81,7 +84,7 @@ export class EmployeeService {
.pipe(map(result => mapEmployeeReponseToEmployee(result.data)));
}
constructor(private httpClient: HttpClient) {}
constructor(private httpClient: HttpClient) { }
public setSearchFilter(value: string): void {
this._searchFilter$.next(value);
@@ -111,4 +114,14 @@ export class EmployeeService {
catchError(error => throwError({ message: error as string, type: ErrorType.API }))
);
}
postEmployeeInvitation(email: string): Observable<EmployeeInviteMockaData> {
return this.httpClient
.post<{ data: EmployeeInviteMockApiResponse }>('http://localhost:8000/invites', { email }, API_HEADERS)
.pipe(
take(1),
map(res => res.data),
catchError(error => throwError({ message: error as string, type: ErrorType.API }))
);
}
}