Added foundation of a simple mock-api
This commit is contained in:
committed by
Erik Tiekstra
parent
81ac40ef31
commit
e1b8979b99
@@ -5,10 +5,8 @@
|
||||
<dafa-navigation [user]="user"></dafa-navigation>
|
||||
</header>
|
||||
|
||||
<main id="dafa-main-content" class="dafa__main">
|
||||
<dafa-sidebar class="dafa__sidebar"></dafa-sidebar>
|
||||
<div class="dafa__content">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
<dafa-sidebar class="dafa__sidebar"></dafa-sidebar>
|
||||
<main id="dafa-main-content" class="dafa__content">
|
||||
<router-outlet></router-outlet>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -1,24 +1,35 @@
|
||||
@import 'variables/navigation';
|
||||
@import 'variables/breakpoints';
|
||||
@import 'variables/gutters';
|
||||
|
||||
.dafa {
|
||||
&__main {
|
||||
display: grid;
|
||||
grid-template-columns: 15rem 1fr;
|
||||
grid-template-areas: 'sidebar content';
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
display: grid;
|
||||
grid-template-columns: 15rem 1fr;
|
||||
grid-template-rows: $dafa__navigation-height 1fr;
|
||||
grid-template-areas:
|
||||
'header header'
|
||||
'sidebar content';
|
||||
|
||||
@media (min-width: $digi--layout--breakpoint--m) {
|
||||
grid-template-rows: $dafa__navigation-height-large 1fr;
|
||||
}
|
||||
|
||||
&__header {
|
||||
grid-area: header;
|
||||
}
|
||||
|
||||
&__sidebar {
|
||||
grid-area: sidebar;
|
||||
height: calc(100vh - #{$dafa__navigation-height} - 1px);
|
||||
|
||||
@media (min-width: $digi--layout--breakpoint--m) {
|
||||
height: calc(100vh - #{$dafa__navigation-height-large} - 1px);
|
||||
}
|
||||
background-color: var(--digi--ui--color--background--secondary);
|
||||
border-right: 1px solid var(--digi--ui--color--background--off);
|
||||
}
|
||||
|
||||
&__content {
|
||||
grid-area: content;
|
||||
padding: 1.25rem 1.5rem;
|
||||
padding: var(--digi--layout--gutter) $digi--layout--gutter--l $digi--layout--gutter--xxl;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
|
||||
.sidebar {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
background-color: var(--digi--ui--color--background--secondary);
|
||||
border-right: 1px solid var(--digi--ui--color--background--off);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
|
||||
&__list {
|
||||
@include dafa__reset-list;
|
||||
|
||||
5
apps/dafa-web/src/app/data/enums/service.enum.ts
Normal file
5
apps/dafa-web/src/app/data/enums/service.enum.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export enum Service {
|
||||
KVL = 'KVL',
|
||||
KROM = 'KROM',
|
||||
STOM = 'STOM',
|
||||
}
|
||||
9
apps/dafa-web/src/app/data/models/participant.model.ts
Normal file
9
apps/dafa-web/src/app/data/models/participant.model.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Service } from '@dafa-enums/service.enum';
|
||||
|
||||
export interface Participant {
|
||||
id: number;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
service: Service;
|
||||
errandNumber: number;
|
||||
}
|
||||
6
apps/dafa-web/src/app/data/models/sort-by.model.ts
Normal file
6
apps/dafa-web/src/app/data/models/sort-by.model.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { Participant } from './participant.model';
|
||||
|
||||
export interface SortBy {
|
||||
key: keyof Participant;
|
||||
reverse: boolean;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<digi-ng-table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Namn</th>
|
||||
<th scope="col">Ärendenummer</th>
|
||||
<th scope="col">Tjänst</th>
|
||||
<th scope="col">Startdatum</th>
|
||||
<th scope="col">Slutdatum</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let participant of participants">
|
||||
<th scope="row">{{ participant.firstName }} {{ participant.lastName }}</th>
|
||||
<td>{{ participant.errandNumber }}</td>
|
||||
<td>{{ participant.service }}</td>
|
||||
<td>{{ participant.startDate | date: 'yyyy-MM-dd' }}</td>
|
||||
<td>{{ participant.endDate | date: 'yyyy-MM-dd' }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</digi-ng-table>
|
||||
@@ -0,0 +1,26 @@
|
||||
import { DigiNgTableModule } from '@af/digi-ng/_table/table';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { ParticipantsListComponent } from './participants-list.component';
|
||||
|
||||
describe('ParticipantsListComponent', () => {
|
||||
let component: ParticipantsListComponent;
|
||||
let fixture: ComponentFixture<ParticipantsListComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ParticipantsListComponent],
|
||||
imports: [RouterTestingModule, DigiNgTableModule],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ParticipantsListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { Participant } from '@dafa-models/participant.model';
|
||||
|
||||
@Component({
|
||||
selector: 'dafa-participants-list',
|
||||
templateUrl: './participants-list.component.html',
|
||||
styleUrls: ['./participants-list.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ParticipantsListComponent {
|
||||
@Input() participants: Participant[];
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { DigiNgTableModule } from '@af/digi-ng/_table/table';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { ParticipantsListComponent } from './participants-list.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [ParticipantsListComponent],
|
||||
imports: [CommonModule, DigiNgTableModule],
|
||||
exports: [ParticipantsListComponent],
|
||||
})
|
||||
export class ParticipantsListModule {}
|
||||
@@ -1,18 +1,27 @@
|
||||
<digi-typography>
|
||||
<section class="participants">
|
||||
<section class="participants">
|
||||
<digi-typography>
|
||||
<h1>Mina deltagare</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-typography>
|
||||
|
||||
<form class="participants__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>
|
||||
</section>
|
||||
</digi-typography>
|
||||
<form class="participants__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-participants-list
|
||||
*ngIf="participants$ | async as participants; else loadingRef"
|
||||
[participants]="participants"
|
||||
></dafa-participants-list>
|
||||
|
||||
<ng-template #loadingRef>
|
||||
<digi-ng-skeleton-base [afCount]="3" afText="Laddar deltagare"></digi-ng-skeleton-base>
|
||||
</ng-template>
|
||||
</section>
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
@import 'variables/gutters';
|
||||
|
||||
.participants {
|
||||
&__search-wrapper {
|
||||
max-width: var(--digi--typography--text--max-width);
|
||||
margin-top: $digi--layout--gutter--l;
|
||||
margin-bottom: $digi--layout--gutter--xl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base';
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { ParticipantsListModule } from './components/participants-list/participants-list.module';
|
||||
import { ParticipantsComponent } from './participants.component';
|
||||
|
||||
describe('ParticipantsComponent', () => {
|
||||
@@ -10,7 +12,7 @@ describe('ParticipantsComponent', () => {
|
||||
waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ParticipantsComponent],
|
||||
imports: [RouterTestingModule],
|
||||
imports: [RouterTestingModule, DigiNgSkeletonBaseModule, ParticipantsListModule],
|
||||
}).compileComponents();
|
||||
})
|
||||
);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { Participant } from '@dafa-models/participant.model';
|
||||
import { ParticipantsService } from '@dafa-services/api/participants.service';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'dafa-participants',
|
||||
@@ -9,6 +11,9 @@ import { BehaviorSubject } from 'rxjs';
|
||||
})
|
||||
export class ParticipantsComponent {
|
||||
private _searchValue$ = new BehaviorSubject<string>('');
|
||||
participants$: Observable<Participant[]> = this.participantsService.participants$;
|
||||
|
||||
constructor(private participantsService: ParticipantsService) {}
|
||||
|
||||
get searchValue(): string {
|
||||
return this._searchValue$.getValue();
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { ParticipantsListModule } from './components/participants-list/participants-list.module';
|
||||
import { ParticipantsComponent } from './participants.component';
|
||||
|
||||
@NgModule({
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
declarations: [ParticipantsComponent],
|
||||
imports: [CommonModule, RouterModule.forChild([{ path: '', component: ParticipantsComponent }]), FormsModule],
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule.forChild([{ path: '', component: ParticipantsComponent }]),
|
||||
FormsModule,
|
||||
DigiNgSkeletonBaseModule,
|
||||
ParticipantsListModule,
|
||||
],
|
||||
})
|
||||
export class ParticipantsModule {}
|
||||
|
||||
45
apps/dafa-web/src/app/services/api/participants.service.ts
Normal file
45
apps/dafa-web/src/app/services/api/participants.service.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { environment } from '@dafa-environment';
|
||||
import { Participant } from '@dafa-models/participant.model';
|
||||
import { SortBy } from '@dafa-models/sort-by.model';
|
||||
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ParticipantsService {
|
||||
private _participants$: Observable<Participant[]> = this.httpClient.get<Participant[]>(
|
||||
`${environment.apiBase}/participants`
|
||||
);
|
||||
private _sortBy$ = new BehaviorSubject<SortBy | null>({ key: 'service', reverse: false });
|
||||
public sortBy$: Observable<SortBy> = this._sortBy$.asObservable();
|
||||
|
||||
public participants$: Observable<Participant[]> = combineLatest([this._sortBy$, this._participants$]).pipe(
|
||||
map(([sortBy, participants]) => {
|
||||
if (sortBy) {
|
||||
const reverse = sortBy.reverse ? -1 : 1;
|
||||
return [...participants].sort((a, b) => {
|
||||
const first = a[sortBy.key];
|
||||
const second = b[sortBy.key];
|
||||
return reverse * +(first > second) - +(second > first);
|
||||
});
|
||||
}
|
||||
return participants;
|
||||
})
|
||||
);
|
||||
|
||||
public setSortKey(key: keyof Participant) {
|
||||
const currentSortBy = this._sortBy$.getValue();
|
||||
let reverse = false;
|
||||
|
||||
if (currentSortBy?.key === key) {
|
||||
reverse = !currentSortBy.reverse;
|
||||
}
|
||||
|
||||
this._sortBy$.next({ key, reverse });
|
||||
}
|
||||
|
||||
constructor(private httpClient: HttpClient) {}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
export const environment = {
|
||||
production: true,
|
||||
apiBase: '/api',
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
export const environment = {
|
||||
production: false,
|
||||
apiBase: '/api',
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
1
apps/dafa-web/src/styles/functions/_rem.scss
Normal file
1
apps/dafa-web/src/styles/functions/_rem.scss
Normal file
@@ -0,0 +1 @@
|
||||
@import '~@af/digi-core/src/global/styles/base/functions/rem';
|
||||
9
apps/dafa-web/src/styles/variables/_gutters.scss
Normal file
9
apps/dafa-web/src/styles/variables/_gutters.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
@import '~@af/digi-core/src/global/styles/layout/variables/layout__variables';
|
||||
@import 'functions/rem';
|
||||
|
||||
// AF DIGI Variables
|
||||
$digi--layout--gutter--l: rem(25);
|
||||
$digi--layout--gutter--xl: rem(40);
|
||||
$digi--layout--gutter--xxl: rem(60);
|
||||
|
||||
// Local variables
|
||||
Reference in New Issue
Block a user