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:
@@ -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),
|
||||
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
@@ -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('');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 { }
|
||||
@@ -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>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface EmployeeInviteMockApiResponse {
|
||||
id: number,
|
||||
createdAt: number
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export interface EmployeeInviteMockaData {
|
||||
id: number
|
||||
}
|
||||
@@ -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 }))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user