feat: ✨ Aggiunta paginazione custom
This commit is contained in:
parent
eaf6884609
commit
b808fa50f0
|
@ -1,5 +1,6 @@
|
|||
import '@maicol07/material-web-additions/data-table/data-table.js';
|
||||
|
||||
import {DataTable as MdDataTable} from '@maicol07/material-web-additions/data-table/lib/data-table';
|
||||
import {
|
||||
mdiChevronLeft,
|
||||
mdiChevronRight,
|
||||
|
@ -15,19 +16,19 @@ import {
|
|||
Attributes,
|
||||
Component
|
||||
} from 'mithril-utilities';
|
||||
import {KebabCase} from 'type-fest';
|
||||
|
||||
export interface DataTableAttributes extends Attributes {
|
||||
inProgress?: boolean;
|
||||
paginated?: boolean;
|
||||
currentPageSize?: number;
|
||||
pageSizesLabel?: string;
|
||||
paginationTotalLabel?: string;
|
||||
type MdDataTableAttributes = {
|
||||
[K in keyof MdDataTable as KebabCase<K>]: MdDataTable[K];
|
||||
};
|
||||
|
||||
export interface DataTableAttributes extends Attributes, Partial<MdDataTableAttributes> {
|
||||
}
|
||||
|
||||
export default class DataTable<A extends DataTableAttributes = DataTableAttributes> extends Component<A> {
|
||||
view(vnode: Vnode<A>) {
|
||||
return (
|
||||
<md-data-table pageSizesLabel={__('Righe per pagina:')} paginationTotalLabel={__(':firstRow-:lastRow di :totalRows')} {...vnode.attrs}>
|
||||
<md-data-table page-sizes-label={__('Righe per pagina:')} pagination-total-label={__(':firstRow-:lastRow di :totalRows')} {...vnode.attrs}>
|
||||
{this.contents(vnode)}
|
||||
<MdIcon icon={mdiPageFirst} slot="pagination-first-button-icon"/>
|
||||
<MdIcon icon={mdiChevronLeft} slot="pagination-previous-button-icon"/>
|
||||
|
|
|
@ -5,6 +5,7 @@ import '@maicol07/material-web-additions/data-table/data-table-row.js';
|
|||
|
||||
import {
|
||||
DataTable as MdDataTable,
|
||||
PaginateDetail,
|
||||
RowSelectionChangedDetail
|
||||
} from '@maicol07/material-web-additions/data-table/lib/data-table';
|
||||
import {DataTableCell} from '@maicol07/material-web-additions/data-table/lib/data-table-cell';
|
||||
|
@ -31,18 +32,14 @@ export interface RecordsTableAttributes<M extends Model<any, any>> extends DataT
|
|||
cols: Collection<Children> | Collection<RecordsTableColumnAttributes> | Collection<Children | RecordsTableColumnAttributes>;
|
||||
records: Map<string, M>;
|
||||
readonly?: boolean;
|
||||
selectable?: boolean;
|
||||
|
||||
onTableRowClick?(recordId: string, event: MouseEvent): void;
|
||||
|
||||
onDeleteRecordButtonClick?(recordId: string, event: MouseEvent): void;
|
||||
|
||||
onDeleteSelectedRecordsButtonClick?(recordsIds: string[], event: MouseEvent): void;
|
||||
|
||||
onRowSelectionChanged?(selectedRecordsIds: string[], event: CustomEventInit<RowSelectionChangedDetail>): void;
|
||||
|
||||
onPageChange?(event: CustomEventInit<PaginateDetail>): void;
|
||||
valueModifier?(value: any, attribute: string, record: M): any;
|
||||
|
||||
selectable?: boolean;
|
||||
}
|
||||
|
||||
export default class RecordsTable<M extends Model<any, any>, A extends RecordsTableAttributes<M> = RecordsTableAttributes<M>> extends DataTable<A> {
|
||||
|
@ -51,9 +48,12 @@ export default class RecordsTable<M extends Model<any, any>, A extends RecordsTa
|
|||
|
||||
oninit(vnode: Vnode<A, this>) {
|
||||
super.oninit(vnode);
|
||||
this.setDefaultAttributes(vnode);
|
||||
}
|
||||
|
||||
vnode.attrs.paginated ??= true;
|
||||
vnode.attrs.currentPageSize ??= 10;
|
||||
onbeforeupdate(vnode: VnodeDOM<A, this>) {
|
||||
super.onbeforeupdate(vnode);
|
||||
this.setDefaultAttributes(vnode);
|
||||
}
|
||||
|
||||
onupdate(vnode: VnodeDOM<A, this>) {
|
||||
|
@ -67,6 +67,12 @@ export default class RecordsTable<M extends Model<any, any>, A extends RecordsTa
|
|||
}
|
||||
}
|
||||
|
||||
setDefaultAttributes(vnode: Vnode<A, this>) {
|
||||
vnode.attrs.paginated ??= true;
|
||||
vnode.attrs['current-page-size'] ??= 10;
|
||||
vnode.attrs['custom-pagination'] ??= true;
|
||||
}
|
||||
|
||||
contents(vnode: Vnode<A>) {
|
||||
return [
|
||||
this.tableColumns(vnode).values<Children>().all(),
|
||||
|
@ -199,7 +205,8 @@ export default class RecordsTable<M extends Model<any, any>, A extends RecordsTa
|
|||
oncreate(vnode: VnodeDOM<A, this>) {
|
||||
super.oncreate(vnode);
|
||||
|
||||
this.element.addEventListener('rowSelectionChanged', this.onRowSelectionChanged.bind(this, vnode));
|
||||
this.element.addEventListener('row-selection-changed', this.onRowSelectionChanged.bind(this, vnode));
|
||||
this.element.addEventListener('paginate', this.onTablePaginate.bind(this, vnode));
|
||||
}
|
||||
|
||||
protected onRowSelectionChanged(vnode: Vnode<A>, event: CustomEventInit<RowSelectionChangedDetail>) {
|
||||
|
@ -224,6 +231,10 @@ export default class RecordsTable<M extends Model<any, any>, A extends RecordsTa
|
|||
vnode.attrs.onTableRowClick?.(recordId, event);
|
||||
}
|
||||
|
||||
protected onTablePaginate(vnode: Vnode<A>, event: CustomEventInit<PaginateDetail>) {
|
||||
vnode.attrs.onPageChange?.(event);
|
||||
}
|
||||
|
||||
protected onDeleteRecordButtonClicked(vnode: Vnode<A>, record: M, event: MouseEvent) {
|
||||
event.stopPropagation();
|
||||
vnode.attrs.onDeleteRecordButtonClick?.(record.getId()!, event);
|
||||
|
|
|
@ -6,6 +6,7 @@ import '@material/web/fab/fab.js';
|
|||
import '@material/web/iconbutton/standard-icon-button.js';
|
||||
|
||||
import {router} from '@maicol07/inertia-mithril';
|
||||
import {PaginateDetail} from '@maicol07/material-web-additions/data-table/lib/data-table';
|
||||
import {
|
||||
FilterTextFieldInputEventDetail,
|
||||
SortButtonClickedEventDetail
|
||||
|
@ -34,6 +35,21 @@ import {match} from 'ts-pattern';
|
|||
import {Match} from 'ts-pattern/dist/types/Match';
|
||||
import type {Class} from 'type-fest';
|
||||
|
||||
export interface Meta {
|
||||
current_page: number;
|
||||
from: number;
|
||||
last_page: number;
|
||||
path: string;
|
||||
per_page: number;
|
||||
to: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface JSONAPIResponse {
|
||||
meta: Meta;
|
||||
}
|
||||
|
||||
|
||||
type RecordDialogVnode<M extends Model<any, any>, D extends RecordDialog<M>> = Vnode<RecordDialogAttributes<M>, D>;
|
||||
type DeleteRecordDialogVnode<M extends Model<any, any>, D extends DeleteRecordDialog<M>> = Vnode<DeleteRecordDialogAttributes<M>, D>;
|
||||
|
||||
|
@ -63,6 +79,11 @@ export default abstract class RecordsPage<
|
|||
|
||||
protected currentPageSize = 50;
|
||||
protected pageSizes = [10, 25, 50, 100];
|
||||
protected currentPage = 1;
|
||||
protected lastPage = 1;
|
||||
protected firstRowOfPage = 1;
|
||||
protected totalRecords = 0;
|
||||
protected lastRowOfPage = this.totalRecords;
|
||||
|
||||
protected filters: Map<string, string> = new Map();
|
||||
protected sort: Map<string, SortDirection> = new Map([['id', SortDirection.ASC]]);
|
||||
|
@ -72,6 +93,8 @@ export default abstract class RecordsPage<
|
|||
|
||||
oninit(vnode: Vnode<PageAttributes, this>) {
|
||||
super.oninit(vnode);
|
||||
// @ts-ignore
|
||||
this.modelType.pageSize = this.currentPageSize;
|
||||
// Redraw on a first load to call onbeforeupdate
|
||||
m.redraw();
|
||||
}
|
||||
|
@ -93,7 +116,13 @@ export default abstract class RecordsPage<
|
|||
// Fix Restify when filtering relations
|
||||
query = query.option('related', query.getQuery().getInclude().join(','));
|
||||
|
||||
const response = await query.get();
|
||||
const response = await query.get(this.currentPage);
|
||||
const rawResponse = response.getHttpClientResponse().getData() as JSONAPIResponse;
|
||||
this.lastPage = rawResponse.meta.last_page;
|
||||
this.firstRowOfPage = rawResponse.meta.from;
|
||||
this.lastRowOfPage = rawResponse.meta.to;
|
||||
this.currentPageSize = rawResponse.meta.per_page;
|
||||
this.totalRecords = rawResponse.meta.total;
|
||||
const data = response.getData();
|
||||
|
||||
this.records.clear();
|
||||
|
@ -187,14 +216,18 @@ export default abstract class RecordsPage<
|
|||
records={this.records}
|
||||
paginated
|
||||
selectable
|
||||
currentPageSize={this.currentPageSize}
|
||||
pageSizes={JSON.stringify(this.pageSizes)}
|
||||
cols={this.tableColumns()}
|
||||
inProgress={this.isTableLoading}
|
||||
in-progress={this.isTableLoading}
|
||||
readonly={this.readonlyRecords}
|
||||
current-first-row={this.firstRowOfPage}
|
||||
current-last-row={this.lastRowOfPage}
|
||||
current-page-size={this.currentPageSize}
|
||||
page-sizes={JSON.stringify(this.pageSizes)}
|
||||
total-rows={this.totalRecords}
|
||||
onTableRowClick={this.onTableRowClick.bind(this)}
|
||||
onDeleteRecordButtonClick={this.onDeleteRecordButtonClicked.bind(this)}
|
||||
onDeleteSelectedRecordsButtonClick={this.onDeleteSelectedRecordsButtonClicked.bind(this)}
|
||||
readonly={this.readonlyRecords}
|
||||
onPageChange={this.onTablePageChange.bind(this)}
|
||||
valueModifier={(value: unknown, attribute: string, record: M) => this.cellValueModifier(value, attribute, record)
|
||||
.otherwise(() => value)}/>
|
||||
);
|
||||
|
@ -267,6 +300,24 @@ export default abstract class RecordsPage<
|
|||
this.openDeleteRecordsDialog(recordsIds.map((recordId) => this.records.get(recordId)!));
|
||||
}
|
||||
|
||||
onTablePageChange(event: CustomEvent<PaginateDetail>) {
|
||||
const {pageSize, action} = event.detail;
|
||||
this.currentPageSize = pageSize;
|
||||
const currentPage = this.currentPage;
|
||||
match(action)
|
||||
.with('first', () => (this.currentPage = 1))
|
||||
.with('previous', () => (this.currentPage--))
|
||||
.with('next', () => (this.currentPage++))
|
||||
.with('last', () => (this.currentPage = this.lastPage))
|
||||
.with('current', () => {})
|
||||
.run();
|
||||
console.log('onTablePageChange', event.detail);
|
||||
if (currentPage !== this.currentPage) {
|
||||
this.refreshRecords = true;
|
||||
m.redraw();
|
||||
}
|
||||
}
|
||||
|
||||
onupdate(vnode: VnodeDOM<PageAttributes, this>) {
|
||||
super.onupdate(vnode);
|
||||
|
||||
|
|
Loading…
Reference in New Issue