Merge pull request #4 in TEA/dafa-web-monorepo from TV-107 to develop

* commit '5f10baae0c438b079f2620ea9b9c0088194561c3':
  more changes
  more changes according to PR comments
  changed code according to comments from pull request
  updated startpage from flex to grid, and other minor changes
  startpage added and employee, administration page updated
This commit is contained in:
Erik Tiekstra
2021-05-04 11:21:36 +02:00
16 changed files with 246 additions and 187 deletions

View File

@@ -6,7 +6,7 @@ export interface Staff {
staffId: string;
firstName: string;
lastName: string;
kommun: string;
utforandeverksamhet: string;
active: boolean;
service: string;
fullName?: string;

View File

@@ -10,25 +10,22 @@
<form [formGroup]="formGroup" (ngSubmit)="submitForm()">
<div class="create-account__block">
<h2>Personuppgifter</h2>
<div class="create-account__combined-inputs">
<digi-ng-form-input
class="create-account__input"
formControlName="firstName"
afLabel="Förnamn"
afInvalidMessage="Förnamn är obligatoriskt"
[afDisableValidStyle]="true"
[afInvalid]="firstNameControl.invalid && firstNameControl.dirty"
></digi-ng-form-input>
<digi-ng-form-input
class="create-account__input"
formControlName="lastName"
afLabel="Efternamn"
afInvalidMessage="Efternamn är obligatoriskt"
[afDisableValidStyle]="true"
[afInvalid]="lastNameControl.invalid && lastNameControl.dirty"
></digi-ng-form-input>
</div>
<digi-ng-form-input
class="create-account__input"
formControlName="firstName"
afLabel="Förnamn"
afInvalidMessage="Förnamn är obligatoriskt"
[afDisableValidStyle]="true"
[afInvalid]="firstNameControl.invalid && firstNameControl.dirty"
></digi-ng-form-input>
<digi-ng-form-input
class="create-account__input"
formControlName="lastName"
afLabel="Efternamn"
afInvalidMessage="Efternamn är obligatoriskt"
[afDisableValidStyle]="true"
[afInvalid]="lastNameControl.invalid && lastNameControl.dirty"
></digi-ng-form-input>
<digi-ng-form-input
class="create-account__input"
formControlName="ssn"
@@ -37,72 +34,54 @@
[afDisableValidStyle]="true"
[afInvalid]="ssnControl.invalid && ssnControl.dirty"
></digi-ng-form-input>
<digi-ng-form-input
class="create-account__input"
formControlName="staffId"
afLabel="Personal-ID"
[afInvalidMessage]="staffIdControl.errors?.message || ''"
[afDisableValidStyle]="true"
[afInvalid]="staffIdControl.invalid && staffIdControl.dirty"
></digi-ng-form-input>
<digi-ng-form-input
class="create-account__input"
formControlName="email"
afLabel="Arbetsmejl"
afType="email"
[afInvalidMessage]="emailControl.errors?.message || ''"
[afDisableValidStyle]="true"
[afInvalid]="emailControl.invalid && emailControl.dirty"
></digi-ng-form-input>
<digi-ng-form-input
class="create-account__input"
formControlName="phone"
afLabel="Telefonnummer arbete"
afType="tel"
[afInvalidMessage]="phoneControl.errors?.message || ''"
[afDisableValidStyle]="true"
[afInvalid]="phoneControl.invalid && phoneControl.dirty"
></digi-ng-form-input>
</div>
<div class="create-account__block">
<h2>Bemanning av personal</h2>
<h2>Tjänst</h2>
<fieldset class="create-account__fieldset">
<legend>Är {{ firstNameControl.value || 'medarbetaren' }} i aktiv tjänst?</legend>
<digi-ng-form-radiobutton-group
[afRadiobuttons]="activeRadioButtons"
formControlName="active"
></digi-ng-form-radiobutton-group>
</fieldset>
<fieldset class="create-account__fieldset">
<legend>Planerad frånvaroperiod</legend>
<div class="create-account__combined-inputs">
<digi-ng-form-datepicker
formControlName="outOfOfficeStart"
afLabel="Från"
[afMinDate]="todaysDate"
></digi-ng-form-datepicker>
<digi-ng-form-datepicker
formControlName="outOfOfficeEnd"
afLabel="Till"
[afMinDate]="todaysDate"
></digi-ng-form-datepicker>
</div>
<digi-button (afOnClick)="addOutOfOfficeDate()">Lägg till</digi-button>
<ul class="create-account__pending-out-of-office-list" *ngIf="pendingOutOfOfficeDates.length">
<li *ngFor="let date of pendingOutOfOfficeDates">
Från {{ date.start | localDate }} till {{ date.end | localDate }}
<digi-button af-variation="secondary" af-size="s" (afOnClick)="removeOutOfOfficeDate(date.id)">
<digi-icon-x slot="icon"></digi-icon-x>
<span>Ta bort</span>
</digi-button>
</li>
</ul>
</fieldset>
<digi-ng-form-select afPlaceholder=" " afLabel="Välj tjänst" formControlName="service" [afSelectItems]="list">
</digi-ng-form-select>
</div>
<fieldset class="create-account__fieldset">
<legend>Tilldela behörigheter</legend>
<div class="create-account__permission-checkbox">
<digi-ng-form-checkbox formControlName="permissions" afLabel="Välj administrera behörigheter">
</digi-ng-form-checkbox>
<digi-ng-popover afDirection="block-start">
<p>Jag har tillräckligt med utrymme för att öppnas till höger (inline-start).</p>
<a href="#">Tab to me</a>
</digi-ng-popover>
</div>
<div class="create-account__permission-checkbox">
<digi-ng-form-checkbox formControlName="participant" afLabel="Välj ta emot deltagare"></digi-ng-form-checkbox>
<digi-ng-popover afDirection="block-start">
<p>Jag har tillräckligt med utrymme för att öppnas till höger (inline-start).</p>
<a href="#">Tab to me</a>
</digi-ng-popover>
</div>
<div class="create-account__permission-checkbox">
<digi-ng-form-checkbox
formControlName="infoParticipant"
afLabel="Välj rapportering, planering och infomration om deltagare"
>
</digi-ng-form-checkbox>
<digi-ng-popover afDirection="block-start">
<p>Jag har tillräckligt med utrymme för att öppnas till höger (inline-start).</p>
<a href="#">Tab to me</a>
</digi-ng-popover>
</div>
<div class="create-account__permission-checkbox">
<digi-ng-form-checkbox formControlName="orderBills" afLabel="Välj administrera ordrar och fakturor">
</digi-ng-form-checkbox>
<digi-ng-popover afDirection="block-start">
<p>Jag har tillräckligt med utrymme för att öppnas till höger (inline-start).</p>
<a href="#">Tab to me</a>
</digi-ng-popover>
</div>
</fieldset>
<div class="create-account__footer">
<digi-button af-type="reset" af-variation="secondary">Avbryt</digi-button>

View File

@@ -4,7 +4,6 @@
&__block {
max-width: var(--digi--typography--text--max-width);
}
&__combined-inputs {
display: flex;
gap: var(--digi--layout--gutter);
@@ -16,11 +15,16 @@
margin-bottom: var(--digi--layout--gutter);
}
&__permission-checkbox {
display: flex;
height: 5rem;
align-items: center;
}
&__fieldset {
margin: 0;
margin-bottom: var(--digi--layout--gutter);
padding: 0;
border-width: 0;
border: 0;
margin-top: var(--digi--layout--gutter);
legend {
width: 100%;
@@ -28,7 +32,7 @@
align-items: center;
margin: 0;
font-weight: var(--digi--typography--font-weight--bold);
font-size: var(--digi--typography--font-size);
font-size: 1.5rem;
padding-bottom: var(--digi--layout--gutter--s);
}
}
@@ -51,7 +55,16 @@
}
&__footer {
margin-top: var(--digi--layout--gutter);
display: flex;
gap: var(--digi--layout--gutter);
}
}
.search-address {
width: 30%;
}
digi-ng-popover {
margin-left: var(--digi--layout--gutter);
}

View File

@@ -1,7 +1,10 @@
import { RadiobuttonModel } from '@af/digi-ng/_form/form-radiobutton-group';
import { FormSelectBaseItem } from '@af/digi-ng/_form/form-select-base';
import { PopoverDirection, PopoverOrientation } from '@af/digi-ng/_popover/popover';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { AbstractControl, FormBuilder, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';
import { Service } from '@dafa-enums/service.enum';
import { OutOfOfficeDate } from '@dafa-models/out-of-office-date.model';
import { StaffService } from '@dafa-services/api/staff.service';
import { RequiredValidator } from '@dafa-validators/required.validator';
@@ -15,47 +18,61 @@ import { BehaviorSubject } from 'rxjs';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CreateAccountComponent {
private _pendingOutOfOfficeDates$ = new BehaviorSubject<OutOfOfficeDate[]>([
{
id: 123456789,
start: new Date(),
end: new Date(),
},
{
id: 987654321,
start: new Date(),
end: new Date(),
},
]);
private _searchValue$ = new BehaviorSubject<string>('');
formGroup: FormGroup;
todaysDate = new Date();
list: FormSelectBaseItem[] = [
{
name: Service.STOM,
value: '1',
},
{
name: Service.KVL,
value: '2',
},
{
name: Service.KROM,
value: '3',
},
];
constructor(private formBuilder: FormBuilder, private staffService: StaffService, private router: Router) {
this.formGroup = this.formBuilder.group({
firstName: this.formBuilder.control('', [RequiredValidator('Förnamn')]),
lastName: this.formBuilder.control('', [RequiredValidator('Efternamn')]),
ssn: this.formBuilder.control('', [RequiredValidator('Personnummer'), SocialSecurityNumberValidator()]),
staffId: this.formBuilder.control('', [RequiredValidator('Personal-ID')]),
email: this.formBuilder.control('', [RequiredValidator('Arbetsmejl')]),
phone: this.formBuilder.control('', [RequiredValidator('Telefonnummer arbete')]),
active: this.formBuilder.control(true),
outOfOfficeStart: this.formBuilder.control(''),
outOfOfficeEnd: this.formBuilder.control(''),
service: this.formBuilder.control(''),
permissions: this.formBuilder.control(false),
participant: this.formBuilder.control(false),
infoParticipant: this.formBuilder.control(false),
orderBills: this.formBuilder.control(false),
});
}
get pendingOutOfOfficeDates(): OutOfOfficeDate[] {
return this._pendingOutOfOfficeDates$.getValue();
handleSearchSubmit(): void {
// skicka searchvalue till en service och filtrera
}
get activeRadioButtons(): RadiobuttonModel[] {
handleSearchInput($event: CustomEvent): void {
this._searchValue$.next($event.detail.target.value);
}
get formselectItem(): FormSelectBaseItem[] {
return [
{
label: 'Ja',
value: true,
name: Service.STOM,
value: '1',
},
{
label: 'Nej',
value: false,
name: Service.KVL,
value: '2',
},
{
name: Service.KROM,
value: '3',
},
];
}
@@ -69,41 +86,6 @@ export class CreateAccountComponent {
get ssnControl(): AbstractControl {
return this.formGroup.get('ssn');
}
get staffIdControl(): AbstractControl {
return this.formGroup.get('staffId');
}
get emailControl(): AbstractControl {
return this.formGroup.get('email');
}
get phoneControl(): AbstractControl {
return this.formGroup.get('phone');
}
get outOfOfficeStartControl(): AbstractControl {
return this.formGroup.get('outOfOfficeStart');
}
get outOfOfficeEndControl(): AbstractControl {
return this.formGroup.get('outOfOfficeEnd');
}
addOutOfOfficeDate(): void {
if (this.outOfOfficeStartControl.value && this.outOfOfficeEndControl.value) {
this._pendingOutOfOfficeDates$.next([
...this.pendingOutOfOfficeDates,
{
id: Date.now(),
start: new Date(this.outOfOfficeStartControl.value),
end: new Date(this.outOfOfficeEndControl.value),
},
]);
this.outOfOfficeStartControl.patchValue('');
this.outOfOfficeEndControl.patchValue('');
}
}
removeOutOfOfficeDate(id: number): void {
this._pendingOutOfOfficeDates$.next(this.pendingOutOfOfficeDates.filter(date => date.id !== id));
}
private _markFormAsDirty(): void {
Object.keys(this.formGroup.controls).forEach(control => {
@@ -117,7 +99,6 @@ export class CreateAccountComponent {
const submittableValues = {
...this.formGroup.value,
fullName: `${this.firstNameControl.value} ${this.lastNameControl.value}`,
outOfOffice: this.pendingOutOfOfficeDates,
};
delete submittableValues.outOfOfficeStart;

View File

@@ -7,6 +7,9 @@ import { ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { LocalDatePipeModule } from '@dafa-shared/pipes/local-date/local-date.module';
import { CreateAccountComponent } from './create-account.component';
import { DigiNgPopoverModule } from '@af/digi-ng/_popover/popover';
import { DigiNgFormCheckboxModule } from '@af/digi-ng/_form/form-checkbox';
import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
@@ -19,6 +22,9 @@ import { CreateAccountComponent } from './create-account.component';
DigiNgFormInputModule,
DigiNgFormRadiobuttonGroupModule,
DigiNgFormDatepickerModule,
DigiNgFormSelectModule,
DigiNgPopoverModule,
DigiNgFormCheckboxModule,
],
})
export class CreateAccountModule {}

View File

@@ -11,33 +11,6 @@
</ng-container>
</button>
</th>
<th scope="col" class="staff-list__column-head">
<button class="staff-list__sort-button" (click)="handleSort('staffId')">
Personal-ID
<ng-container *ngIf="sortBy?.key === 'staffId'">
<digi-icon-caret-up class="staff-list__sort-icon" *ngIf="!sortBy.reverse"></digi-icon-caret-up>
<digi-icon-caret-down class="staff-list__sort-icon" *ngIf="sortBy.reverse"></digi-icon-caret-down>
</ng-container>
</button>
</th>
<th scope="col" class="staff-list__column-head">
<button class="staff-list__sort-button" (click)="handleSort('kommun')">
Kommun
<ng-container *ngIf="sortBy?.key === 'kommun'">
<digi-icon-caret-up class="staff-list__sort-icon" *ngIf="!sortBy.reverse"></digi-icon-caret-up>
<digi-icon-caret-down class="staff-list__sort-icon" *ngIf="sortBy.reverse"></digi-icon-caret-down>
</ng-container>
</button>
</th>
<th scope="col" class="staff-list__column-head">
<button class="staff-list__sort-button" (click)="handleSort('active')">
Aktiv i tjänst
<ng-container *ngIf="sortBy?.key === 'active'">
<digi-icon-caret-up class="staff-list__sort-icon" *ngIf="!sortBy.reverse"></digi-icon-caret-up>
<digi-icon-caret-down class="staff-list__sort-icon" *ngIf="sortBy.reverse"></digi-icon-caret-down>
</ng-container>
</button>
</th>
<th scope="col" class="staff-list__column-head">
<button class="staff-list__sort-button" (click)="handleSort('service')">
Tjänst
@@ -47,6 +20,15 @@
</ng-container>
</button>
</th>
<th scope="col" class="staff-list__column-head">
<button class="staff-list__sort-button" (click)="handleSort('utforandeverksamhet')">
Utförandeverksamhet
<ng-container *ngIf="sortBy?.key === 'utforandeverksamhet'">
<digi-icon-caret-up class="staff-list__sort-icon" *ngIf="!sortBy.reverse"></digi-icon-caret-up>
<digi-icon-caret-down class="staff-list__sort-icon" *ngIf="sortBy.reverse"></digi-icon-caret-down>
</ng-container>
</button>
</th>
</tr>
</thead>
<tbody>
@@ -54,10 +36,8 @@
<th scope="row">
<a [routerLink]="staff.id" class="staff-list__link">{{ staff.fullName }}</a>
</th>
<td>{{ staff.staffId }}</td>
<td>{{ staff.kommun }}</td>
<td>{{ staff.active ? 'Ja' : 'Nej' }}</td>
<td>{{ staff.service }}</td>
<td>{{ staff.kommun }}</td>
</tr>
</tbody>
</table>
@@ -72,4 +52,5 @@
[afTotalResults]="staff.length"
(afOnPageChange)="handlePagination($event.detail)"
af-result-name="deltagare"
></digi-navigation-pagination>
>
</digi-navigation-pagination>

View File

@@ -17,6 +17,8 @@ export class StaffListComponent {
private _currentPage$ = new BehaviorSubject<number>(1);
private _staffPerPage = 10;
private _searchValue$ = new BehaviorSubject<string>('');
get currentPage(): number {
return this._currentPage$.getValue();
}

View File

@@ -4,6 +4,7 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { StaffListComponent } from './staff-list.component';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [StaffListComponent],

View File

@@ -8,14 +8,18 @@
</p>
<div class="staff__cta-wrapper">
<digi-ng-link-internal afText="Skapa nytt konto" afRoute="/administration/skapa-konto"></digi-ng-link-internal>
<digi-ng-link-button afText="Skapa nytt konto" afRoute="/administration/skapa-konto"></digi-ng-link-button>
</div>
<h2>Personallista</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Earum, officia perferendis? Excepturi animi rem culpa
facere, laboriosam vel, quia eos eligendi, cupiditate doloribus aspernatur unde nihil iste earum corrupti illo.
</p>
<form class="staff__search-wrapper" (ngSubmit)="handleSearchSubmit()">
<digi-form-input-search
af-label="Sök kunder"
af-label-description="Sök på namn eller ärendenummer"
(afOnInput)="handleSearchInput($event)"
></digi-form-input-search>
</form>
<dafa-staff-list
*ngIf="filteredStaff$ | async as staff; else loadingRef"

View File

@@ -1,3 +1,4 @@
@import 'variables/gutters';
.staff {
&__cta-wrapper {
margin-top: var(--digi--layout--gutter);
@@ -8,4 +9,10 @@
align-items: center;
gap: var(--digi--layout--gutter--s);
}
&__search-wrapper {
display: flex;
max-width: var(--digi--typography--text--max-width);
margin-top: $digi--layout--gutter--l;
margin-bottom: $digi--layout--gutter--xl;
}
}

View File

@@ -5,6 +5,8 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { StaffListModule } from './components/staff-list/staff-list.module';
import { StaffComponent } from './staff.component';
import { DigiNgLinkButtonModule } from '@af/digi-ng/_link/link-button';
import { FormsModule } from '@angular/forms';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
@@ -15,6 +17,8 @@ import { StaffComponent } from './staff.component';
DigiNgLinkInternalModule,
DigiNgSkeletonBaseModule,
StaffListModule,
DigiNgLinkButtonModule,
FormsModule,
],
})
export class StaffModule {}

View File

@@ -1 +1,40 @@
<section class="start">Start funkar!</section>
<section class="start">
<digi-typography>
<h1>Välkommen till DAFA 2.0</h1>
<p>Här finner du de senaste nyheterna om uppdateringar, notiser och mer.</p>
</digi-typography>
<div class="start__wrapper">
<div class="start__main">
<digi-info-card af-heading="Notiser" af-heading-level="h1" af-type="info" af-link-text="Deltagare">
<p>
Det har kommit in nya avrop med deltagare, länken nedan tar dig till fliken Nya deltagare. Du finner den också
i vänster menyn på sidan
</p>
<digi-ng-link-internal afText="Deltagare" afRoute="/mina-deltagare"></digi-ng-link-internal>
</digi-info-card>
</div>
<div class="start__sidebar">
<digi-ng-notification-alert afVariation="info" afSize="l" afHeading="Viktig information" afHeadingLevel="h3">
<p>Large alert! Check the knobs section and play around!</p>
</digi-ng-notification-alert>
<div class="start__sidebar-alert">
<digi-ng-notification-alert
afVariation="success"
afSize="l"
afCloseable="true"
afHeading="Allt gick bra"
afHeadingLevel="h3"
>
<p>Dina skickade tilldelningar har nått fram till handledare som godkänt och arbetat vidare med deltagarna</p>
</digi-ng-notification-alert>
</div>
</div>
<div class="start__footer">
<digi-info-card af-heading="Statistik" af-heading-level="h1" af-type="info">
<p><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></p>
</digi-info-card>
</div>
</div>
</section>

View File

@@ -0,0 +1,24 @@
@import 'variables/gutters';
.start {
&__wrapper {
display: grid;
grid-template-rows: auto;
grid-template-areas:
'header header '
'main sidebar'
'footer footer ';
grid-gap: var(--digi--layout--gutter);
}
&__main {
grid-area: main;
}
&__sidebar {
grid-area: sidebar;
}
&__sidebar-alert {
margin-top: var(--digi--layout--gutter);
}
&__footer {
grid-area: footer;
}
}

View File

@@ -1,4 +1,12 @@
import { CardHeadingLevel, CardVariation } from '@af/digi-ng/_card/card';
import {
NotificationAlertHeadingLevel,
NotificationAlertSize,
NotificationAlertVariation,
} from '@af/digi-ng/_notification/notification-alert';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { InfoCardHeadingLevel } from '@digi/core/dist/types/components/_info-card/info-card/info-card-heading-level.enum';
import { InfoCardType } from '@digi/core/dist/types/components/_info-card/info-card/info-card-type.enum';
@Component({
selector: 'dafa-start',

View File

@@ -1,10 +1,20 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { StartComponent } from './start.component';
import { DigiNgCardModule } from '@af/digi-ng/_card/card';
import { DigiNgNotificationAlertModule } from '@af/digi-ng/_notification/notification-alert';
import { DigiNgLinkInternalModule } from '@af/digi-ng/_link/link-internal';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [StartComponent],
imports: [CommonModule, RouterModule.forChild([{ path: '', component: StartComponent }])],
imports: [
CommonModule,
RouterModule.forChild([{ path: '', component: StartComponent }]),
DigiNgCardModule,
DigiNgNotificationAlertModule,
DigiNgLinkInternalModule,
],
})
export class StartModule {}

View File

@@ -4,7 +4,7 @@
"license": "MIT",
"repository": "https://bitbucket.arbetsformedlingen.se/projects/TEA/repos/dafa-web-monorepo",
"engines": {
"node": "15.11.0"
"node": "14.16.1"
},
"scripts": {
"ng": "nx",