/** * Copyright (c) HashiCorp, Inc. * SPDX-License-Identifier: BUSL-1.1 */ import Component from '@glimmer/component'; import Ember from 'ember'; import { action } from '@ember/object'; import { tracked } from '@glimmer/tracking'; import { paginate } from 'core/utils/paginate-list'; /** * @module ClientsTable * ClientsTable renders a paginated table for a passed dataset. HDS table components handle basic sorting * but because this table is paginated, all sorting happens manually. * See https://helios.hashicorp.design/components/table/table?tab=code#component-api * for the full component API and list of supported args. * * @example * */ interface TableColumn { key: string; label: string; isSortable: boolean; } type SortDirection = 'asc' | 'desc'; interface Args { columns: TableColumn[]; data: Record[]; initiallySortBy?: { column?: string; direction?: SortDirection }; setPageSize?: number; showPaginationSizeSelector?: boolean; } export default class ClientsTable extends Component { @tracked currentPage = 1; @tracked pageSize = Ember.testing ? 3 : 10; // lower in tests to test pagination without seeding more data @tracked sortColumn = ''; @tracked sortDirection: SortDirection; constructor(owner: unknown, args: Args) { super(owner, args); const { column = '', direction = 'asc' } = this.args.initiallySortBy || {}; this.sortColumn = column; this.sortDirection = direction; // default is 'asc' for consistency with HDS defaults // Override default page size with a custom amount. // pageSize can be updated by the end user if @showPaginationSizeSelector is true if (this.args.setPageSize) { this.pageSize = this.args.setPageSize; } } get paginatedTableData(): Record[] { const sorted = this.sortTableData(this.args.data); const paginated = paginate(sorted, { page: this.currentPage, pageSize: this.pageSize, }); return paginated; } get columnKeys() { return this.args.columns.map((k: TableColumn) => k['key']); } // This table is paginated so we cannot use any out of the box filtering // from the HDS component and must manually sort data. sortTableData(data: Record[]): Record[] { if (this.sortColumn) { return [...data].sort((a, b) => { const valA = a[this.sortColumn]; const valB = b[this.sortColumn]; if (valA < valB) return this.sortDirection === 'asc' ? -1 : 1; if (valA > valB) return this.sortDirection === 'asc' ? 1 : -1; return 0; }); } return data; } @action handlePaginationChange(action: 'currentPage' | 'pageSize', value: number) { this[action] = value; } @action updateSort(column: string, direction: SortDirection) { // Update tracked variables so paginatedTableData recomputes this.sortColumn = column; this.sortDirection = direction; } }