table sorting working
This commit is contained in:
parent
c3f0ffe190
commit
46065fc745
@ -1,6 +0,0 @@
|
|||||||
import { IPerson } from './person'
|
|
||||||
|
|
||||||
export interface IAPIResponse {
|
|
||||||
stats: any;
|
|
||||||
list: IPerson[];
|
|
||||||
}
|
|
@ -11,6 +11,7 @@ import { ListComponent } from './list/list.component';
|
|||||||
import { ListPaginateComponent } from './list-paginate/list-paginate.component';
|
import { ListPaginateComponent } from './list-paginate/list-paginate.component';
|
||||||
import { ListService } from './list.service';
|
import { ListService } from './list.service';
|
||||||
import { GenderPipe } from './gender.pipe';
|
import { GenderPipe } from './gender.pipe';
|
||||||
|
import { CustomSortPipe } from './custom-sort.pipe';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -20,12 +21,13 @@ import { GenderPipe } from './gender.pipe';
|
|||||||
ListPageComponent,
|
ListPageComponent,
|
||||||
ListComponent,
|
ListComponent,
|
||||||
ListPaginateComponent,
|
ListPaginateComponent,
|
||||||
GenderPipe
|
GenderPipe,
|
||||||
|
CustomSortPipe,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
AppRoutingModule,
|
AppRoutingModule,
|
||||||
HttpClientModule
|
HttpClientModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
],
|
],
|
||||||
|
@ -1 +1 @@
|
|||||||
<p>article-page works!</p>
|
<app-article></app-article>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
// This is a router component for the article.
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-article-page',
|
selector: 'app-article-page',
|
||||||
templateUrl: './article-page.component.html',
|
templateUrl: './article-page.component.html',
|
||||||
|
8
src/app/custom-sort.pipe.spec.ts
Normal file
8
src/app/custom-sort.pipe.spec.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { CustomSortPipe } from './custom-sort.pipe';
|
||||||
|
|
||||||
|
describe('CustomSortPipe', () => {
|
||||||
|
it('create an instance', () => {
|
||||||
|
const pipe = new CustomSortPipe();
|
||||||
|
expect(pipe).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
19
src/app/custom-sort.pipe.ts
Normal file
19
src/app/custom-sort.pipe.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
import { Sort } from './sort'
|
||||||
|
|
||||||
|
const sorter = new Sort();
|
||||||
|
|
||||||
|
// This is a sorting pipe for the list of people.
|
||||||
|
// I couldn't come up with a better way of doing it at the moment.
|
||||||
|
|
||||||
|
@Pipe({
|
||||||
|
name: 'customSort'
|
||||||
|
})
|
||||||
|
export class CustomSortPipe implements PipeTransform {
|
||||||
|
transform(value: Array<any>, field: string, direction: number): Array<any> {
|
||||||
|
if (direction === 0 || field == null) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return sorter.sort(value.slice(), field, direction);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
import { Pipe, PipeTransform } from '@angular/core';
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
|
||||||
|
// This is a simple pipe for formatting the gender
|
||||||
|
|
||||||
@Pipe({
|
@Pipe({
|
||||||
name: 'gender'
|
name: 'gender'
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
|
// This is a router component for the list of people.
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-list-page',
|
selector: 'app-list-page',
|
||||||
templateUrl: './list-page.component.html',
|
templateUrl: './list-page.component.html',
|
||||||
|
@ -16,11 +16,17 @@ export class ListPaginateComponent {
|
|||||||
constructor(private router: Router) { }
|
constructor(private router: Router) { }
|
||||||
|
|
||||||
public get pageNums(): number[] {
|
public get pageNums(): number[] {
|
||||||
|
// This function calculates the buttons for the pagination so that the
|
||||||
|
// current page number is always in the center unless it is near the beginning
|
||||||
|
// or the end.
|
||||||
const starti = Math.min(Math.max(this.page - 2, 1), this.pages - 4);
|
const starti = Math.min(Math.max(this.page - 2, 1), this.pages - 4);
|
||||||
return [...Array(5)].map((p, i) => starti + i);
|
return [...Array(5)].map((p, i) => starti + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
public navigate(num: number): void {
|
public navigate(num: number): void {
|
||||||
this.router.navigate(['/list'], { queryParams: { page: Math.min(Math.max(num, 1), this.pages) }});
|
// This function navigates to a page number that is clamped
|
||||||
|
this.router.navigate(['/list'], { queryParams: {
|
||||||
|
page: Math.min(Math.max(num, 1), this.pages),
|
||||||
|
} });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Observable } from 'rxjs'
|
import { Observable } from 'rxjs'
|
||||||
import { IAPIResponse } from './api-response'
|
|
||||||
|
// This is the service file for the API request
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class ListService {
|
export class ListService {
|
||||||
private listUrl = 'http://midaiganes.irw.ee/api/list';
|
private listUrl = 'http://midaiganes.irw.ee/api/list?limit=100';
|
||||||
|
|
||||||
constructor(private http: HttpClient) { }
|
constructor(private http: HttpClient) { }
|
||||||
|
|
||||||
public getList(limit: number = 10, offset: number = 0): Observable<IAPIResponse> {
|
public getList(): Observable<any> {
|
||||||
const url = `${this.listUrl}?offset=${offset}&limit=${limit}`;
|
return this.http.get<any>(this.listUrl);
|
||||||
return this.http.get<IAPIResponse>(url);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,57 @@
|
|||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<th>Eesnimi</th>
|
<th (click)="setSort('firstname')" class="clickable">Eesnimi
|
||||||
<th>Perekonnanimi</th>
|
<ng-container *ngIf="sortBy === 'firstname';else default_sort">
|
||||||
<th>Sugu</th>
|
<ng-container [ngSwitch]="sortDir">
|
||||||
<th>Sünnikuupäev</th>
|
<i *ngSwitchCase=-1>^</i>
|
||||||
<th>Telefon</th>
|
<i *ngSwitchCase=1>v</i>
|
||||||
|
<i *ngSwitchDefault>|</i>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #default_sort><i>|</i></ng-template>
|
||||||
|
</th>
|
||||||
|
<th (click)="setSort('surname')" class="clickable">Perekonnanimi
|
||||||
|
<ng-container *ngIf="sortBy === 'surname';else default_sort">
|
||||||
|
<ng-container [ngSwitch]="sortDir">
|
||||||
|
<i *ngSwitchCase=-1>^</i>
|
||||||
|
<i *ngSwitchCase=1>v</i>
|
||||||
|
<i *ngSwitchDefault>|</i>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #default_sort><i>|</i></ng-template>
|
||||||
|
</th>
|
||||||
|
<th (click)="setSort('sex')" class="clickable">Sugu
|
||||||
|
<ng-container *ngIf="sortBy === 'sex';else default_sort">
|
||||||
|
<ng-container [ngSwitch]="sortDir">
|
||||||
|
<i *ngSwitchCase=-1>^</i>
|
||||||
|
<i *ngSwitchCase=1>v</i>
|
||||||
|
<i *ngSwitchDefault>|</i>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #default_sort><i>|</i></ng-template>
|
||||||
|
</th>
|
||||||
|
<th (click)="setSort('date')" class="clickable">Sünnikuupäev
|
||||||
|
<ng-container *ngIf="sortBy === 'date';else default_sort">
|
||||||
|
<ng-container [ngSwitch]="sortDir">
|
||||||
|
<i *ngSwitchCase=-1>^</i>
|
||||||
|
<i *ngSwitchCase=1>v</i>
|
||||||
|
<i *ngSwitchDefault>|</i>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #default_sort><i>|</i></ng-template>
|
||||||
|
</th>
|
||||||
|
<th (click)="setSort('phone')" class="clickable">Telefon
|
||||||
|
<ng-container *ngIf="sortBy === 'phone';else default_sort">
|
||||||
|
<ng-container [ngSwitch]="sortDir">
|
||||||
|
<i *ngSwitchCase=-1>^</i>
|
||||||
|
<i *ngSwitchCase=1>v</i>
|
||||||
|
<i *ngSwitchDefault>|</i>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #default_sort><i>|</i></ng-template>
|
||||||
|
</th>
|
||||||
</thead>
|
</thead>
|
||||||
<ng-container *ngFor="let person of people">
|
<ng-container *ngFor="let person of people | customSort:sortBy:sortDir | slice:startIndex:endIndex;">
|
||||||
<tr (click)="selectPerson(person)">
|
<tr (click)="selectPerson(person)">
|
||||||
<td>{{ person.firstname }}</td>
|
<td>{{ person.firstname }}</td>
|
||||||
<td>{{ person.surname }}</td>
|
<td>{{ person.surname }}</td>
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
import { Component, OnInit, OnChanges, SimpleChanges, Input } from '@angular/core';
|
import { Component, OnInit, SimpleChanges, Input } from '@angular/core';
|
||||||
import { ListService } from '../list.service'
|
import { ListService } from '../list.service'
|
||||||
|
|
||||||
import { IPerson } from '../person'
|
import { IPerson } from '../person'
|
||||||
import { IAPIResponse } from '../api-response'
|
|
||||||
|
// This component is for listing the people
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-list',
|
selector: 'app-list',
|
||||||
templateUrl: './list.component.html',
|
templateUrl: './list.component.html',
|
||||||
styleUrls: ['./list.component.styl']
|
styleUrls: ['./list.component.styl']
|
||||||
})
|
})
|
||||||
export class ListComponent implements OnInit, OnChanges {
|
export class ListComponent implements OnInit {
|
||||||
public people: IPerson[];
|
public people: IPerson[];
|
||||||
private selected: IPerson;
|
private selected: IPerson;
|
||||||
|
|
||||||
private sortBy: string;
|
public sortBy: string;
|
||||||
private sortDir: number;
|
public sortDir = 0;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
public page = 1;
|
public page = 1;
|
||||||
@ -23,28 +24,42 @@ export class ListComponent implements OnInit, OnChanges {
|
|||||||
|
|
||||||
constructor(private listService: ListService) { }
|
constructor(private listService: ListService) { }
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges): void {
|
|
||||||
if (changes.page) {
|
|
||||||
this.getList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.getList();
|
this.getList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getList(): void {
|
public get startIndex(): number {
|
||||||
const offset = this.perPage * this.page;
|
// First argument to array slicer
|
||||||
this.listService.getList(this.perPage, offset).subscribe(
|
return (this.page - 1) * this.perPage;
|
||||||
(data) => this.updateList(data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateList(data: IAPIResponse): void {
|
public get endIndex(): number {
|
||||||
this.people = data.list;
|
// Second argument to array slicer
|
||||||
// this.pages = data.stats.total / this.perPage
|
return this.startIndex + this.perPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setSort(field: string): void {
|
||||||
|
// Reset the sorting if it is a new field
|
||||||
|
if (this.sortBy !== field) {
|
||||||
|
this.sortDir = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sortBy = field;
|
||||||
|
this.sortDir++;
|
||||||
|
|
||||||
|
// Loop back to descending sort
|
||||||
|
if (this.sortDir === 2) {
|
||||||
|
this.sortDir = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getList(): void {
|
||||||
|
this.listService.getList().subscribe(
|
||||||
|
(data) => this.people = data.list);
|
||||||
}
|
}
|
||||||
|
|
||||||
private selectPerson(person: IPerson): void {
|
private selectPerson(person: IPerson): void {
|
||||||
|
// Select a person to show the details of
|
||||||
if (this.selected === person) {
|
if (this.selected === person) {
|
||||||
this.selected = null;
|
this.selected = null;
|
||||||
return;
|
return;
|
||||||
|
@ -7,4 +7,4 @@ export interface IPerson {
|
|||||||
phone: string;
|
phone: string;
|
||||||
image: string[];
|
image: string[];
|
||||||
intro: string;
|
intro: string;
|
||||||
};
|
}
|
||||||
|
15
src/app/sort.ts
Normal file
15
src/app/sort.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
// This is a simple encapsulation class for the Collator used in sorting.
|
||||||
|
|
||||||
|
export class Sort {
|
||||||
|
private collator = new Intl.Collator('et', {
|
||||||
|
numeric: true,
|
||||||
|
sensitivity: 'base',
|
||||||
|
});
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
public sort(value: Array<any>, property: string, order: number, type = ''): Array<any> {
|
||||||
|
return value.sort((a, b) => this.collator.compare(a[property], b[property]) * order);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user