Added better staff mock data and updated several pages

This commit is contained in:
Erik Tiekstra
2021-04-09 08:48:22 +02:00
committed by Erik Tiekstra
parent cee9168c3c
commit 1ee6ca9251
27 changed files with 385 additions and 56 deletions
+2 -1
View File
@@ -2,6 +2,7 @@ import { NavigationBreadcrumbsItem } from '@af/digi-ng/_navigation/navigation-br
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { User } from '@dafa-models/user.model';
import { mapPathToPageName } from '@dafa-utils/map-path-to-page-name.util';
import { BehaviorSubject } from 'rxjs';
import { filter } from 'rxjs/operators';
import { UnsubscribeDirective } from './directives/unsubscribe.directive';
@@ -41,7 +42,7 @@ export class AppComponent extends UnsubscribeDirective {
...[...paths]
.filter(path => !!path)
.map(path => ({
text: `${path.charAt(0).toUpperCase()}${path.slice(1)}`,
text: mapPathToPageName(path),
routerLink: paths.slice(0, paths.length - 1).join('/'),
})),
]);
@@ -0,0 +1,10 @@
export const Navigation = {
administration: 'Administration',
'skapa-konto': 'Skapa nytt konto',
personal: 'Personal',
'mina-deltagare': 'Mina deltagare',
avrop: 'Avrop',
meddelanden: 'Meddelanden',
statistik: 'Statistik',
installningar: 'Inställningar',
};
@@ -2,7 +2,7 @@ import { ParticipantStatus } from '@dafa-enums/participant-status.enum';
import { Service } from '@dafa-enums/service.enum';
export interface Participant {
id: number;
id: string;
firstName: string;
lastName: string;
status: ParticipantStatus;
@@ -1,6 +1,7 @@
import { Participant } from './participant.model';
import { Staff } from './staff.model';
export interface SortBy {
key: keyof Participant;
key: keyof Participant | keyof Staff;
reverse: boolean;
}
@@ -1,16 +1,10 @@
import { ParticipantStatus } from '@dafa-enums/participant-status.enum';
import { Service } from '@dafa-enums/service.enum';
export interface Participant {
id: number;
export interface Staff {
id: string;
staffId: string;
firstName: string;
lastName: string;
status: ParticipantStatus;
nextStep: string;
service: Service;
errandNumber: number;
startDate: Date;
endDate: Date;
handleBefore: Date;
kommun: string;
active: boolean;
service: string;
fullName?: string;
}
@@ -11,7 +11,7 @@ const routes: Routes = [
},
{
path: 'personal',
loadChildren: () => import('./pages/staff-list/staff-list.module').then(m => m.StaffListModule),
loadChildren: () => import('./pages/staff/staff.module').then(m => m.StaffModule),
},
{
path: 'skapa-konto',
@@ -1,14 +0,0 @@
<section class="staff-list">
<digi-typography>
<h1>Personallista</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam magna neque, interdum vel massa eget, condimentum
rutrum velit. Sed vitae ullamcorper sem. Aliquam malesuada nunc sed purus mollis scelerisque. Curabitur bibendum
leo quis ante porttitor tincidunt. Nam tincidunt imperdiet tortor eu suscipit. Maecenas ut dui est.
</p>
<digi-button>
Skapa nytt konto
<dafa-icon [icon]="iconType.PLUS"></dafa-icon>
</digi-button>
</digi-typography>
</section>
@@ -1,12 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IconType } from '@dafa-enums/icon-type.enum';
@Component({
selector: 'dafa-staff-list',
templateUrl: './staff-list.component.html',
styleUrls: ['./staff-list.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class StaffListComponent {
iconType = IconType;
}
@@ -0,0 +1,73 @@
<digi-ng-table>
<table>
<thead>
<tr>
<th scope="col" class="staff-list__column-head">
<button class="staff-list__sort-button" (click)="handleSort('fullName')">
Namn
<ng-container *ngIf="sortBy?.key === 'fullName'">
<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('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
<ng-container *ngIf="sortBy?.key === 'service'">
<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>
<tr *ngFor="let staff of pagedStaff">
<th scope="row">{{ staff.firstName }} {{ staff.lastName }}</th>
<td>{{ staff.staffId }}</td>
<td>{{ staff.kommun }}</td>
<td>{{ staff.active ? 'Ja' : 'Nej' }}</td>
<td>{{ staff.service }}</td>
</tr>
</tbody>
</table>
</digi-ng-table>
<digi-navigation-pagination
*ngIf="staff.length > pagedStaff.length"
class="staff-list__pagination"
[afTotalPages]="totalPages"
[afCurrentResultStart]="currentResultStart"
[afCurrentResultEnd]="currentResultEnd"
[afTotalResults]="staff.length"
(afOnPageChange)="handlePagination($event.detail)"
af-result-name="deltagare"
></digi-navigation-pagination>
@@ -0,0 +1,35 @@
@import 'variables/gutters';
.staff-list {
&__column-head {
padding: 0;
}
&__sort-button {
position: relative;
background-color: transparent;
border-width: 0;
width: 100%;
text-align: left;
padding: var(--digi--layout--gutter--s) $digi--layout--gutter--l var(--digi--layout--gutter--s)
var(--digi--layout--gutter);
margin: 0;
font-size: inherit;
font-weight: inherit;
display: flex;
align-items: center;
gap: var(--digi--layout--gutter);
cursor: pointer;
}
&__sort-icon {
position: absolute;
display: inline-flex;
right: 0.5rem;
}
&__pagination {
display: block;
margin-top: var(--digi--layout--gutter);
}
}
@@ -0,0 +1,27 @@
import { DigiNgTableModule } from '@af/digi-ng/_table/table';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { StaffListComponent } from './staff-list.component';
describe('StaffListComponent', () => {
let component: StaffListComponent;
let fixture: ComponentFixture<StaffListComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [StaffListComponent],
imports: [RouterTestingModule, DigiNgTableModule],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(StaffListComponent);
component = fixture.componentInstance;
component.staff = [];
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,47 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { SortBy } from '@dafa-models/sort-by.model';
import { Staff } from '@dafa-models/staff.model';
import { BehaviorSubject } from 'rxjs';
@Component({
selector: 'dafa-staff-list',
templateUrl: './staff-list.component.html',
styleUrls: ['./staff-list.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class StaffListComponent {
@Input() staff: Staff[];
@Input() sortBy: SortBy | null;
@Output() sorted = new EventEmitter<keyof Staff>();
private _currentPage$ = new BehaviorSubject<number>(1);
private _staffPerPage = 10;
get currentPage(): number {
return this._currentPage$.getValue();
}
get totalPages(): number {
return Math.ceil(this.staff.length / this._staffPerPage);
}
get pagedStaff(): Staff[] {
return [...this.staff].slice(this.currentResultStart - 1, this.currentResultEnd - 1);
}
get currentResultStart(): number {
return (this.currentPage - 1) * this._staffPerPage + 1;
}
get currentResultEnd(): number {
return this.currentResultStart + this._staffPerPage;
}
handleSort(key: keyof Staff): void {
this.sorted.emit(key);
}
handlePagination(page: number): void {
this._currentPage$.next(page);
}
}
@@ -1,12 +1,12 @@
import { DigiNgTableModule } from '@af/digi-ng/_table/table';
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { IconModule } from '@dafa-shared/components/icon/icon.module';
import { StaffListComponent } from './staff-list.component';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [StaffListComponent],
imports: [CommonModule, RouterModule.forChild([{ path: '', component: StaffListComponent }]), IconModule],
imports: [CommonModule, DigiNgTableModule],
exports: [StaffListComponent],
})
export class StaffListModule {}
@@ -0,0 +1,31 @@
<section class="staff">
<digi-typography>
<h1>Personal</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam magna neque, interdum vel massa eget, condimentum
rutrum velit. Sed vitae ullamcorper sem. Aliquam malesuada nunc sed purus mollis scelerisque. Curabitur bibendum
leo quis ante porttitor tincidunt. Nam tincidunt imperdiet tortor eu suscipit. Maecenas ut dui est.
</p>
<div class="staff__cta-wrapper">
<digi-ng-link-internal afText="Skapa nytt konto" afRoute="/administration/skapa-konto"></digi-ng-link-internal>
</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>
<dafa-staff-list
*ngIf="filteredStaff$ | async as staff; else loadingRef"
[staff]="staff"
[sortBy]="staffSortBy$ | async"
(sorted)="handleStaffSort($event)"
></dafa-staff-list>
</digi-typography>
<ng-template #loadingRef>
<digi-ng-skeleton-base [afCount]="3" afText="Laddar personal"></digi-ng-skeleton-base>
</ng-template>
</section>
@@ -0,0 +1,11 @@
.staff {
&__cta-wrapper {
margin-top: var(--digi--layout--gutter);
}
&__link {
display: inline-flex;
align-items: center;
gap: var(--digi--layout--gutter--s);
}
}
@@ -1,22 +1,22 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { StaffListComponent } from './staff-list.component';
import { StaffComponent } from './staff.component';
describe('StaffListComponent', () => {
let component: StaffListComponent;
let fixture: ComponentFixture<StaffListComponent>;
describe('StaffComponent', () => {
let component: StaffComponent;
let fixture: ComponentFixture<StaffComponent>;
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [StaffListComponent],
declarations: [StaffComponent],
imports: [RouterTestingModule],
}).compileComponents();
})
);
beforeEach(() => {
fixture = TestBed.createComponent(StaffListComponent);
fixture = TestBed.createComponent(StaffComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
@@ -0,0 +1,37 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IconType } from '@dafa-enums/icon-type.enum';
import { SortBy } from '@dafa-models/sort-by.model';
import { Staff } from '@dafa-models/staff.model';
import { StaffService } from '@dafa-services/api/staff.service';
import { BehaviorSubject, Observable } from 'rxjs';
@Component({
selector: 'dafa-staff',
templateUrl: './staff.component.html',
styleUrls: ['./staff.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class StaffComponent {
private _searchValue$ = new BehaviorSubject<string>('');
filteredStaff$: Observable<Staff[]> = this.staffService.filteredStaff$;
staffSortBy$: Observable<SortBy | null> = this.staffService.staffSortBy$;
iconType = IconType;
constructor(private staffService: StaffService) {}
get searchValue(): string {
return this._searchValue$.getValue();
}
handleSearchSubmit(): void {
this.staffService.setSearchFilter(this.searchValue);
}
handleSearchInput($event: CustomEvent): void {
this._searchValue$.next($event.detail.target.value);
}
handleStaffSort(key: keyof Staff): void {
this.staffService.setStaffSortKey(key);
}
}
@@ -0,0 +1,20 @@
import { DigiNgLinkInternalModule } from '@af/digi-ng/_link/link-internal';
import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base';
import { CommonModule } from '@angular/common';
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';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [StaffComponent],
imports: [
CommonModule,
RouterModule.forChild([{ path: '', component: StaffComponent }]),
DigiNgLinkInternalModule,
DigiNgSkeletonBaseModule,
StaffListModule,
],
})
export class StaffModule {}
@@ -0,0 +1,56 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { environment } from '@dafa-environment';
import { SortBy } from '@dafa-models/sort-by.model';
import { Staff } from '@dafa-models/staff.model';
import { sort } from '@dafa-utils/sort.util';
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
function filterStaff(staff: Staff[], searchFilter: string): Staff[] {
return staff.filter(person => {
const searchValueExistsInName = person.fullName.toLowerCase().includes(searchFilter.toLowerCase());
return searchValueExistsInName;
});
}
@Injectable({
providedIn: 'root',
})
export class StaffService {
private _allStaff$: Observable<Staff[]> = this.httpClient.get<Staff[]>(`${environment.apiBase}/staff`).pipe(
map(staff =>
staff.map(person => ({
...person,
fullName: `${person.firstName} ${person.lastName}`,
}))
)
);
private _staffSortBy$ = new BehaviorSubject<SortBy | null>({ key: 'fullName', reverse: false });
public staffSortBy$: Observable<SortBy> = this._staffSortBy$.asObservable();
private _searchFilter$ = new BehaviorSubject<string>('');
public searchFilter$: Observable<string> = this._searchFilter$.asObservable();
private _filteredStaff$: Observable<Staff[]> = combineLatest([this._allStaff$, this._searchFilter$]).pipe(
map(([staff, searchFilter]) => filterStaff(staff, searchFilter))
);
public filteredStaff$: Observable<Staff[]> = combineLatest([this._filteredStaff$, this._staffSortBy$]).pipe(
map(([staff, sortBy]) => {
return sortBy ? sort(staff, sortBy) : staff;
})
);
public setSearchFilter(value: string) {
this._searchFilter$.next(value);
}
public setStaffSortKey(key: keyof Staff) {
const currentSortBy = this._staffSortBy$.getValue();
const reverse = currentSortBy?.key === key ? !currentSortBy.reverse : false;
this._staffSortBy$.next({ key, reverse });
}
constructor(private httpClient: HttpClient) {}
}
@@ -0,0 +1,5 @@
import { Navigation } from '@dafa-constants/navigation';
export function mapPathToPageName(path: string): string {
return Navigation[path] || `${path.charAt(0).toUpperCase()}${path.slice(1)}`;
}
+1
View File
@@ -15,6 +15,7 @@
body {
margin: 0;
font-weight: var(--digi--typography--font-weight);
overflow: hidden;
}
button {