133 lines
3.3 KiB
TypeScript
133 lines
3.3 KiB
TypeScript
import { CommonModule } from '@angular/common';
|
|
import {
|
|
Component,
|
|
EventEmitter,
|
|
Input,
|
|
OnChanges,
|
|
Output,
|
|
SimpleChanges,
|
|
} from '@angular/core';
|
|
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
|
import {
|
|
faSort,
|
|
faSortDown,
|
|
faSortUp,
|
|
} from '@fortawesome/free-solid-svg-icons';
|
|
import { SORT } from '../../enums/sort';
|
|
import { Header } from '../../models/header';
|
|
import { Page } from '../../models/page';
|
|
import { Result } from '../../models/result';
|
|
|
|
@Component({
|
|
selector: 'fbi-table',
|
|
standalone: true,
|
|
imports: [CommonModule, FontAwesomeModule],
|
|
templateUrl: './table.component.html',
|
|
styleUrl: './table.component.scss',
|
|
})
|
|
export class TableComponent implements OnChanges {
|
|
@Input() data!: Result;
|
|
|
|
@Output() page = new EventEmitter<Page>();
|
|
@Output() sort = new EventEmitter<Header>();
|
|
|
|
Math = Math;
|
|
faSortDown = faSortDown;
|
|
faSortUp = faSortUp;
|
|
faSort = faSort;
|
|
SORT = SORT;
|
|
pagesize: PageButton[] = [];
|
|
pager: PageButton[] = [];
|
|
|
|
ngOnChanges(changes: SimpleChanges): void {
|
|
const data = changes['data']?.currentValue;
|
|
if (data) {
|
|
this.updatePageSize(data);
|
|
this.updatePager(data);
|
|
}
|
|
}
|
|
|
|
onPage(event: MouseEvent, page: number): void {
|
|
event.stopPropagation();
|
|
const current = this.data?.page?.page;
|
|
const size = this.data?.page?.size;
|
|
if (current === page) return;
|
|
this.page.emit(new Page({ page: page, size: size }));
|
|
}
|
|
|
|
onPageSize(event: MouseEvent, size: number): void {
|
|
event.stopPropagation();
|
|
const current = this.data?.page?.size;
|
|
if (current === size) return;
|
|
|
|
const page = this.data?.page ?? { page: 1, size: 100 };
|
|
const start = (page.page - 1) * page.size + 1;
|
|
const newPage = Math.ceil(start / size);
|
|
this.page.emit(new Page({ page: newPage, size: size }));
|
|
}
|
|
|
|
onSort(event: MouseEvent, header: Header): void {
|
|
event.stopPropagation();
|
|
this.sort.emit(header);
|
|
}
|
|
|
|
private updatePageSize(data: Result): void {
|
|
const size = data.page?.size ?? 20;
|
|
const sizes = [10, 20, 50].map(
|
|
(i) => new PageButton({ page: i, current: i === size })
|
|
);
|
|
|
|
this.pagesize = sizes;
|
|
}
|
|
|
|
private updatePager(data: Result): void {
|
|
const page = data.page?.page ?? 1;
|
|
const last = Math.ceil(data.total / (data.page?.size ?? data.total));
|
|
|
|
// get the list of pages
|
|
const pages = [
|
|
1,
|
|
page + 1 > last ? page - 2 : 1,
|
|
page - 1,
|
|
page,
|
|
page + 1,
|
|
page < 3 ? 3 : last,
|
|
last,
|
|
]
|
|
// unique
|
|
.filter((v, i, a) => a.indexOf(v) === i)
|
|
// in range
|
|
.filter((i) => 1 <= i && i <= last);
|
|
|
|
const buttons = pages.map(
|
|
(i) =>
|
|
new PageButton({
|
|
page: i,
|
|
current: i === page,
|
|
})
|
|
);
|
|
if (buttons.length > 2) {
|
|
if (buttons[0].page !== buttons[1].page - 1) {
|
|
buttons.splice(1, 0, new PageButton({ ellipsis: true }));
|
|
}
|
|
const length = buttons.length;
|
|
if (buttons[length - 2].page !== buttons[length - 1].page - 1) {
|
|
buttons.splice(length - 1, 0, new PageButton({ ellipsis: true }));
|
|
}
|
|
}
|
|
this.pager = buttons;
|
|
}
|
|
}
|
|
|
|
export class PageButton {
|
|
page: number;
|
|
current: boolean;
|
|
ellipsis: boolean;
|
|
|
|
constructor(data: Partial<PageButton>) {
|
|
this.page = data?.page ?? -1;
|
|
this.current = data?.current ?? false;
|
|
this.ellipsis = data?.ellipsis ?? false;
|
|
}
|
|
}
|