From 68b49e34330132daf44f1aeb97b4bb7deba349f4 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 4 Apr 2025 08:02:41 +0100 Subject: [PATCH] First pass at pagination Signed-off-by: Charles de Dreuille --- packages/canon/package.json | 1 + .../src/components/DataTable/DataTable.tsx | 20 + .../canon/src/components/DataTable/index.ts | 17 + .../src/components/Table/Table.stories.tsx | 184 ++-- packages/canon/src/components/Table/Table.tsx | 34 +- packages/canon/src/components/Table/index.ts | 12 +- .../components/Table/mocked-data/columns.tsx | 71 ++ .../Table/mocked-data/components.ts | 818 ++++++++++++++++++ .../canon/src/components/Table/styles.css | 10 + packages/canon/src/components/Table/types.ts | 50 ++ .../TablePagination/TablePagination.tsx | 81 ++ .../src/components/TablePagination/index.ts | 18 + .../src/components/TablePagination/types.ts | 50 ++ yarn.lock | 20 + 14 files changed, 1265 insertions(+), 121 deletions(-) create mode 100644 packages/canon/src/components/DataTable/DataTable.tsx create mode 100644 packages/canon/src/components/DataTable/index.ts create mode 100644 packages/canon/src/components/Table/mocked-data/columns.tsx create mode 100644 packages/canon/src/components/Table/mocked-data/components.ts create mode 100644 packages/canon/src/components/Table/types.ts create mode 100644 packages/canon/src/components/TablePagination/TablePagination.tsx create mode 100644 packages/canon/src/components/TablePagination/index.ts create mode 100644 packages/canon/src/components/TablePagination/types.ts diff --git a/packages/canon/package.json b/packages/canon/package.json index b5d2d715f6..fc47bd89d4 100644 --- a/packages/canon/package.json +++ b/packages/canon/package.json @@ -56,6 +56,7 @@ "@storybook/react": "^8.6.8", "@storybook/react-webpack5": "^8.6.8", "@storybook/test": "^8.6.8", + "@tanstack/react-table": "^8.21.2", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "chalk": "^5.4.1", diff --git a/packages/canon/src/components/DataTable/DataTable.tsx b/packages/canon/src/components/DataTable/DataTable.tsx new file mode 100644 index 0000000000..335e4d73e4 --- /dev/null +++ b/packages/canon/src/components/DataTable/DataTable.tsx @@ -0,0 +1,20 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; + +export const DataTable = () => { + return
DataTable
; +}; diff --git a/packages/canon/src/components/DataTable/index.ts b/packages/canon/src/components/DataTable/index.ts new file mode 100644 index 0000000000..cbbb2babe5 --- /dev/null +++ b/packages/canon/src/components/DataTable/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './DataTable'; diff --git a/packages/canon/src/components/Table/Table.stories.tsx b/packages/canon/src/components/Table/Table.stories.tsx index c4c08be527..8c94249a79 100644 --- a/packages/canon/src/components/Table/Table.stories.tsx +++ b/packages/canon/src/components/Table/Table.stories.tsx @@ -14,73 +14,34 @@ * limitations under the License. */ -const invoices = [ - { - invoice: 'INV001', - paymentStatus: 'Paid', - totalAmount: '$250.00', - paymentMethod: 'Credit Card', - }, - { - invoice: 'INV002', - paymentStatus: 'Pending', - totalAmount: '$150.00', - paymentMethod: 'PayPal', - }, - { - invoice: 'INV003', - paymentStatus: 'Unpaid', - totalAmount: '$350.00', - paymentMethod: 'Bank Transfer', - }, - { - invoice: 'INV004', - paymentStatus: 'Paid', - totalAmount: '$450.00', - paymentMethod: 'Credit Card', - }, - { - invoice: 'INV005', - paymentStatus: 'Paid', - totalAmount: '$550.00', - paymentMethod: 'PayPal', - }, - { - invoice: 'INV006', - paymentStatus: 'Pending', - totalAmount: '$200.00', - paymentMethod: 'Bank Transfer', - }, - { - invoice: 'INV007', - paymentStatus: 'Unpaid', - totalAmount: '$300.00', - paymentMethod: 'Credit Card', - }, -]; - import React from 'react'; import type { Meta, StoryObj } from '@storybook/react'; +import { Table } from '../Table'; +import { components } from './mocked-data/components'; import { - Table, - TableBody, - TableCell, - TableFooter, - TableHead, - TableHeader, - TableRow, -} from '../Table'; + // ColumnFiltersState, + // SortingState, + // VisibilityState, + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable, +} from '@tanstack/react-table'; +import { columns } from './mocked-data/columns'; +import { TablePagination } from '../TablePagination'; const meta = { title: 'Components/Table', - component: Table, + component: Table.Root, subcomponents: { - TableBody: TableBody as React.ComponentType, - TableCell: TableCell as React.ComponentType, - TableFooter: TableFooter as React.ComponentType, - TableHead: TableHead as React.ComponentType, - TableHeader: TableHeader as React.ComponentType, - TableRow: TableRow as React.ComponentType, + Body: Table.Body as React.ComponentType, + Cell: Table.Cell as React.ComponentType, + Pagination: TablePagination as React.ComponentType, + Head: Table.Head as React.ComponentType, + Header: Table.Header as React.ComponentType, + Row: Table.Row as React.ComponentType, }, } satisfies Meta; @@ -88,32 +49,79 @@ export default meta; type Story = StoryObj; export const Default: Story = { - render: () => ( - - - - Invoice - Status - Method - Amount - - - - {invoices.map(invoice => ( - - {invoice.invoice} - {invoice.paymentStatus} - {invoice.paymentMethod} - {invoice.totalAmount} - - ))} - - - - Total - $2,500.00 - - -
- ), + render: () => { + const table = useReactTable({ + data: components, + columns, + // onSortingChange: setSorting, + // onColumnFiltersChange: setColumnFilters, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getSortedRowModel: getSortedRowModel(), + getFilteredRowModel: getFilteredRowModel(), + // onColumnVisibilityChange: setColumnVisibility, + // onRowSelectionChange: setRowSelection, + // state: { + // sorting, + // columnFilters, + // columnVisibility, + // rowSelection, + // }, + }); + + return ( + + + {table.getHeaderGroups().map(headerGroup => ( + + {headerGroup.headers.map(header => { + return ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext(), + )} + + ); + })} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map(row => ( + + {row.getVisibleCells().map(cell => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + + )) + ) : ( + + + No results. + + + )} + + table.previousPage()} + onClickNext={() => table.nextPage()} + canPrevious={table.getCanPreviousPage()} + canNext={table.getCanNextPage()} + setPageSize={pageSize => table.setPageSize(pageSize)} + /> + + ); + }, }; diff --git a/packages/canon/src/components/Table/Table.tsx b/packages/canon/src/components/Table/Table.tsx index efd5181036..f67f74883d 100644 --- a/packages/canon/src/components/Table/Table.tsx +++ b/packages/canon/src/components/Table/Table.tsx @@ -16,7 +16,7 @@ import * as React from 'react'; /** @public */ -const Table = React.forwardRef< +const TableRoot = React.forwardRef< HTMLTableElement, React.HTMLAttributes >(({ className, ...props }, ref) => ( @@ -24,7 +24,7 @@ const Table = React.forwardRef< )); -Table.displayName = 'Table'; +TableRoot.displayName = 'TableRoot'; /** @public */ const TableHeader = React.forwardRef< @@ -48,19 +48,6 @@ const TableBody = React.forwardRef< )); TableBody.displayName = 'TableBody'; -/** @public */ -const TableFooter = React.forwardRef< - HTMLTableSectionElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( - -)); -TableFooter.displayName = 'TableFooter'; - /** @public */ const TableRow = React.forwardRef< HTMLTableRowElement, @@ -103,13 +90,12 @@ const TableCaption = React.forwardRef< )); TableCaption.displayName = 'TableCaption'; -export { - Table, - TableHeader, - TableBody, - TableFooter, - TableHead, - TableRow, - TableCell, - TableCaption, +export const Table = { + Root: TableRoot, + Header: TableHeader, + Body: TableBody, + Head: TableHead, + Row: TableRow, + Cell: TableCell, + Caption: TableCaption, }; diff --git a/packages/canon/src/components/Table/index.ts b/packages/canon/src/components/Table/index.ts index cf88de2b1a..1b13d8b85e 100644 --- a/packages/canon/src/components/Table/index.ts +++ b/packages/canon/src/components/Table/index.ts @@ -13,12 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { - Table, - TableHead, - TableRow, - TableHeader, - TableCell, - TableBody, - TableFooter, -} from './Table'; + +export * from './Table'; +export * from './types'; diff --git a/packages/canon/src/components/Table/mocked-data/columns.tsx b/packages/canon/src/components/Table/mocked-data/columns.tsx new file mode 100644 index 0000000000..3ef63c59bb --- /dev/null +++ b/packages/canon/src/components/Table/mocked-data/columns.tsx @@ -0,0 +1,71 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { ColumnDef } from '@tanstack/react-table'; +import { Component } from './components'; +import { Checkbox } from '../../Checkbox'; +import { Text } from '../../Text'; + +export const columns: ColumnDef[] = [ + { + id: 'select', + header: ({ table }) => ( + + table.toggleAllPageRowsSelected(checked) + } + aria-label="Select all" + /> + ), + cell: ({ row }) => ( + row.toggleSelected(checked)} + aria-label="Select row" + /> + ), + enableSorting: false, + enableHiding: false, + }, + { + accessorKey: 'name', + header: 'Name', + cell: ({ row }) => ( +
+ {row.getValue('name')} + + {row.original.description} + +
+ ), + }, + { + accessorKey: 'owner', + header: 'Owner', + cell: ({ row }) => {row.getValue('owner')}, + }, + { + accessorKey: 'type', + header: 'Type', + cell: ({ row }) => {row.getValue('type')}, + }, + { + accessorKey: 'tags', + header: 'Tags', + cell: ({ row }) => {row.getValue('tags')}, + }, +]; diff --git a/packages/canon/src/components/Table/mocked-data/components.ts b/packages/canon/src/components/Table/mocked-data/components.ts new file mode 100644 index 0000000000..f7861023d3 --- /dev/null +++ b/packages/canon/src/components/Table/mocked-data/components.ts @@ -0,0 +1,818 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export interface Component { + name: string; + owner: string; + type: 'documentation' | 'library' | 'service' | 'website' | 'other'; + description?: string; + tags?: string[]; +} + +export const components: Component[] = [ + { + name: 'authentication-and-authorization-service', + owner: 'security-team', + type: 'service', + description: + 'A comprehensive service handling user authentication and role-based access control across all applications.', + tags: ['security', 'authentication', 'authorization'], + }, + { + name: 'user-interface-dashboard-and-analytics-platform', + owner: 'frontend-team', + type: 'website', + description: + 'Interactive dashboard providing real-time analytics and data visualization for business metrics.', + tags: ['analytics', 'visualization', 'dashboard'], + }, + { + name: 'payment-gateway', + owner: 'finance-team', + type: 'service', + description: + 'Secure payment processing system supporting multiple payment methods and currencies.', + tags: ['payments', 'security', 'finance'], + }, + { + name: 'real-time-analytics-processing-and-visualization-engine', + owner: 'data-team', + type: 'service', + description: + 'High-performance engine for processing and visualizing streaming data analytics.', + tags: ['analytics', 'real-time', 'data-processing'], + }, + { + name: 'notification-center', + owner: 'platform-team', + type: 'service', + description: + 'Centralized system for managing and delivering notifications across multiple channels.', + tags: ['notifications', 'messaging'], + }, + { + name: 'administrative-control-panel-and-user-management-interface', + owner: 'frontend-team', + type: 'website', + description: + 'Admin interface for managing users, permissions, and system configurations.', + tags: ['admin', 'user-management', 'configuration'], + }, + { + name: 'search-indexer', + owner: 'search-team', + type: 'service', + description: + 'Service responsible for indexing and updating searchable content across the platform.', + tags: ['search', 'indexing'], + }, + { + name: 'cross-platform-mobile-application-framework', + owner: 'mobile-team', + type: 'website', + description: + 'Framework enabling development of cross-platform mobile applications with shared codebase.', + tags: ['mobile', 'framework', 'cross-platform'], + }, + { + name: 'database-migration', + owner: 'devops-team', + type: 'other', + description: + 'Tools and scripts for managing database schema migrations and data transformations.', + tags: ['database', 'migration', 'devops'], + }, + { + name: 'api-gateway', + owner: 'platform-team', + type: 'service', + description: + 'Central entry point for all API requests, handling routing, authentication, and rate limiting.', + tags: ['api', 'gateway', 'security', 'routing'], + }, + { + name: 'content-management', + owner: 'content-team', + type: 'service', + description: + 'System for managing and delivering digital content across multiple channels.', + tags: ['content', 'management', 'delivery'], + }, + { + name: 'enterprise-reporting-and-analytics-dashboard', + owner: 'analytics-team', + type: 'website', + description: + 'Comprehensive business intelligence platform for enterprise-wide reporting and analytics.', + tags: ['analytics', 'reporting', 'business-intelligence'], + }, + { + name: 'image-processing-and-optimization-service', + owner: 'media-team', + type: 'service', + description: + 'Service for processing, optimizing, and delivering images across different devices and networks.', + tags: ['media', 'optimization', 'processing'], + }, + { + name: 'customer-portal', + owner: 'frontend-team', + type: 'website', + description: + 'Self-service portal for customers to manage their accounts and access services.', + tags: ['customer', 'self-service'], + }, + { + name: 'log-aggregator', + owner: 'devops-team', + type: 'service', + description: + 'Centralized logging system for collecting, processing, and analyzing application logs.', + tags: ['logging', 'monitoring', 'devops'], + }, + { + name: 'identity-provider', + owner: 'security-team', + type: 'service', + description: + 'Service managing user identities and authentication across the organization.', + tags: ['identity', 'security', 'authentication'], + }, + { + name: 'document-storage', + owner: 'storage-team', + type: 'service', + description: + 'Secure and scalable document storage system with version control and access management.', + tags: ['storage', 'documents', 'version-control'], + }, + { + name: 'workflow-engine', + owner: 'platform-team', + type: 'service', + description: + 'Engine for defining and executing business processes and workflows.', + tags: ['workflow', 'automation'], + }, + { + name: 'mobile-backend', + owner: 'mobile-team', + type: 'service', + description: + 'Backend services supporting mobile applications with optimized APIs and data synchronization.', + tags: ['mobile', 'backend', 'api'], + }, + { + name: 'system-monitoring-and-alerting-dashboard', + owner: 'devops-team', + type: 'website', + description: + 'Real-time monitoring and alerting system for infrastructure and application health.', + tags: ['monitoring', 'alerting', 'devops', 'infrastructure'], + }, + { + name: 'email-service', + owner: 'communication-team', + type: 'service', + description: + 'Reliable email delivery service with templates and tracking capabilities.', + tags: ['email', 'communication'], + }, + { + name: 'data-pipeline', + owner: 'data-team', + type: 'service', + description: + 'ETL pipeline for processing and transforming large volumes of data.', + tags: ['data', 'etl', 'pipeline'], + }, + { + name: 'configuration-manager', + owner: 'platform-team', + type: 'service', + description: + 'Centralized system for managing application configurations across environments.', + tags: ['configuration', 'management'], + }, + { + name: 'testing-framework', + owner: 'qa-team', + type: 'library', + description: + 'Comprehensive testing framework supporting various types of automated tests.', + tags: ['testing', 'automation', 'qa'], + }, + { + name: 'cache-service', + owner: 'platform-team', + type: 'service', + description: + 'Distributed caching service for improving application performance.', + tags: ['caching', 'performance'], + }, + { + name: 'billing-system', + owner: 'finance-team', + type: 'service', + description: + 'System for managing customer billing, invoicing, and payment processing.', + tags: ['billing', 'finance', 'payments'], + }, + { + name: 'comprehensive-product-documentation-and-api-reference', + owner: 'docs-team', + type: 'documentation', + description: + 'Complete documentation covering product features, APIs, and integration guides.', + tags: ['documentation', 'api', 'reference'], + }, + { + name: 'queue-manager', + owner: 'platform-team', + type: 'service', + description: + 'Message queue system for asynchronous processing and event handling.', + tags: ['queue', 'messaging', 'async'], + }, + { + name: 'security-scanner', + owner: 'security-team', + type: 'other', + description: + 'Automated security scanning tool for identifying vulnerabilities in code and infrastructure.', + tags: ['security', 'scanning', 'vulnerability'], + }, + { + name: 'user-profile', + owner: 'frontend-team', + type: 'website', + description: + 'User profile management interface with personalization features.', + tags: ['user', 'profile', 'personalization'], + }, + { + name: 'data-warehouse', + owner: 'data-team', + type: 'service', + description: + 'Centralized data repository for business intelligence and analytics.', + tags: ['data', 'warehouse', 'analytics'], + }, + { + name: 'deployment-automation', + owner: 'devops-team', + type: 'other', + description: + 'Automated deployment pipeline for continuous integration and delivery.', + tags: ['deployment', 'automation', 'ci-cd', 'devops'], + }, + { + name: 'chat-service', + owner: 'communication-team', + type: 'service', + description: + 'Real-time chat service supporting text, file sharing, and group conversations.', + tags: ['chat', 'communication', 'real-time'], + }, + { + name: 'analytics-dashboard', + owner: 'analytics-team', + type: 'website', + description: + 'Interactive dashboard for visualizing and analyzing business metrics.', + tags: ['analytics', 'dashboard', 'visualization'], + }, + { + name: 'file-uploader', + owner: 'storage-team', + type: 'service', + description: + 'Service for handling secure file uploads with progress tracking and validation.', + tags: ['storage', 'upload', 'files'], + }, + { + name: 'search-service', + owner: 'search-team', + type: 'service', + description: + 'Full-text search service with advanced filtering and ranking capabilities.', + tags: ['search', 'full-text'], + }, + { + name: 'mobile-sdk', + owner: 'mobile-team', + type: 'library', + description: + 'Software development kit for building mobile applications with native features.', + tags: ['mobile', 'sdk', 'development'], + }, + { + name: 'performance-monitor', + owner: 'devops-team', + type: 'service', + description: + 'System for monitoring and analyzing application performance metrics.', + tags: ['performance', 'monitoring', 'metrics'], + }, + { + name: 'content-delivery', + owner: 'media-team', + type: 'service', + description: + 'CDN service for optimized content delivery across global networks.', + tags: ['cdn', 'content', 'delivery'], + }, + { + name: 'user-authentication', + owner: 'security-team', + type: 'service', + description: + 'Service handling user login, session management, and authentication flows.', + tags: ['authentication', 'security', 'user'], + }, + { + name: 'data-export', + owner: 'data-team', + type: 'service', + description: + 'Service for exporting data in various formats with scheduling capabilities.', + tags: ['data', 'export', 'scheduling'], + }, + { + name: 'admin-api', + owner: 'platform-team', + type: 'service', + description: + 'API endpoints for administrative functions and system management.', + tags: ['api', 'admin', 'management'], + }, + { + name: 'testing-dashboard', + owner: 'qa-team', + type: 'website', + description: 'Dashboard for monitoring test results and quality metrics.', + tags: ['testing', 'dashboard', 'qa'], + }, + { + name: 'message-broker', + owner: 'platform-team', + type: 'service', + description: + 'Message broker service for reliable event-driven communication between services.', + tags: ['messaging', 'broker', 'event-driven'], + }, + { + name: 'payment-processor', + owner: 'finance-team', + type: 'service', + description: + 'Service for processing financial transactions and payment methods.', + tags: ['payments', 'finance', 'processing'], + }, + { + name: 'document-viewer', + owner: 'frontend-team', + type: 'website', + description: 'Web-based document viewer supporting multiple file formats.', + tags: ['documents', 'viewer'], + }, + { + name: 'load-balancer', + owner: 'devops-team', + type: 'service', + description: + 'Service for distributing network traffic across multiple servers.', + tags: ['load-balancing', 'networking', 'infrastructure'], + }, + { + name: 'security-audit', + owner: 'security-team', + type: 'other', + description: + 'Tools and processes for conducting security audits and compliance checks.', + tags: ['security', 'audit', 'compliance'], + }, + { + name: 'user-settings', + owner: 'frontend-team', + type: 'website', + description: + 'Interface for users to manage their preferences and account settings.', + tags: ['user', 'settings', 'preferences'], + }, + { + name: 'data-import', + owner: 'data-team', + type: 'service', + description: + 'Service for importing and validating data from external sources.', + tags: ['data', 'import', 'validation'], + }, + { + name: 'infrastructure-monitor', + owner: 'devops-team', + type: 'service', + description: + 'Monitoring system for infrastructure components and resources.', + tags: ['monitoring', 'infrastructure', 'devops'], + }, + { + name: 'notification-manager', + owner: 'communication-team', + type: 'service', + description: + 'Service for managing and delivering notifications across multiple channels.', + tags: ['notifications', 'management'], + }, + { + name: 'analytics-processor', + owner: 'analytics-team', + type: 'service', + description: + 'Service for processing and analyzing business data and metrics.', + tags: ['analytics', 'processing', 'metrics'], + }, + { + name: 'file-manager', + owner: 'storage-team', + type: 'website', + description: 'Web interface for managing files and storage resources.', + tags: ['files', 'storage', 'management'], + }, + { + name: 'search-index', + owner: 'search-team', + type: 'service', + description: 'Service for maintaining and updating search indices.', + tags: ['search', 'indexing'], + }, + { + name: 'mobile-authentication', + owner: 'mobile-team', + type: 'service', + description: + 'Authentication service specifically designed for mobile applications.', + tags: ['mobile', 'authentication', 'security'], + }, + { + name: 'system-monitor', + owner: 'devops-team', + type: 'service', + description: + 'Monitoring service for system health and performance metrics.', + tags: ['monitoring', 'system', 'metrics'], + }, + { + name: 'media-processor', + owner: 'media-team', + type: 'service', + description: 'Service for processing and optimizing media files.', + tags: ['media', 'processing', 'optimization'], + }, + { + name: 'user-management', + owner: 'security-team', + type: 'service', + description: 'Service for managing user accounts and permissions.', + tags: ['user', 'management', 'security'], + }, + { + name: 'data-transformer', + owner: 'data-team', + type: 'service', + description: + 'Service for transforming data between different formats and structures.', + tags: ['data', 'transformation'], + }, + { + name: 'admin-dashboard', + owner: 'platform-team', + type: 'website', + description: + 'Administrative interface for system management and monitoring.', + tags: ['admin', 'dashboard', 'management'], + }, + { + name: 'test-automation', + owner: 'qa-team', + type: 'other', + description: 'Tools and frameworks for automating testing processes.', + tags: ['testing', 'automation', 'qa'], + }, + { + name: 'event-bus', + owner: 'platform-team', + type: 'service', + description: 'Event-driven communication system between services.', + tags: ['events', 'messaging', 'communication'], + }, + { + name: 'invoice-generator', + owner: 'finance-team', + type: 'service', + description: 'Service for generating and managing invoices.', + tags: ['invoices', 'finance'], + }, + { + name: 'document-editor', + owner: 'frontend-team', + type: 'website', + description: 'Web-based document editing interface.', + tags: ['documents', 'editor'], + }, + { + name: 'service-discovery', + owner: 'devops-team', + type: 'service', + description: 'Service for discovering and registering available services.', + tags: ['discovery', 'services', 'devops'], + }, + { + name: 'security-monitor', + owner: 'security-team', + type: 'service', + description: 'Service for monitoring security events and threats.', + tags: ['security', 'monitoring', 'threats'], + }, + { + name: 'user-preferences', + owner: 'frontend-team', + type: 'website', + description: 'Interface for managing user preferences and settings.', + tags: ['user', 'preferences'], + }, + { + name: 'data-validator', + owner: 'data-team', + type: 'service', + description: 'Service for validating data integrity and format.', + tags: ['data', 'validation'], + }, + { + name: 'infrastructure-automation', + owner: 'devops-team', + type: 'other', + description: + 'Tools for automating infrastructure provisioning and management.', + tags: ['infrastructure', 'automation', 'devops'], + }, + { + name: 'notification-dispatcher', + owner: 'communication-team', + type: 'service', + description: + 'Service for dispatching notifications to appropriate channels.', + tags: ['notifications', 'dispatch'], + }, + { + name: 'analytics-collector', + owner: 'analytics-team', + type: 'service', + description: 'Service for collecting and aggregating analytics data.', + tags: ['analytics', 'collection', 'aggregation'], + }, + { + name: 'file-processor', + owner: 'storage-team', + type: 'service', + description: 'Service for processing and managing files.', + tags: ['files', 'processing'], + }, + { + name: 'search-analyzer', + owner: 'search-team', + type: 'service', + description: 'Service for analyzing search queries and results.', + tags: ['search', 'analysis'], + }, + { + name: 'mobile-notifications', + owner: 'mobile-team', + type: 'service', + description: 'Service for sending notifications to mobile devices.', + tags: ['mobile', 'notifications'], + }, + { + name: 'system-alerts', + owner: 'devops-team', + type: 'service', + description: 'Service for managing and dispatching system alerts.', + tags: ['alerts', 'system', 'monitoring'], + }, + { + name: 'media-encoder', + owner: 'media-team', + type: 'service', + description: 'Service for encoding and processing media files.', + tags: ['media', 'encoding'], + }, + { + name: 'user-authorization', + owner: 'security-team', + type: 'service', + description: 'Service for managing user permissions and access control.', + tags: ['authorization', 'security', 'user'], + }, + { + name: 'data-aggregator', + owner: 'data-team', + type: 'service', + description: 'Service for aggregating data from multiple sources.', + tags: ['data', 'aggregation'], + }, + { + name: 'admin-authentication', + owner: 'platform-team', + type: 'service', + description: 'Authentication service for administrative access.', + tags: ['admin', 'authentication', 'security'], + }, + { + name: 'test-coverage', + owner: 'qa-team', + type: 'other', + description: 'Tools for measuring and reporting test coverage.', + tags: ['testing', 'coverage', 'qa'], + }, + { + name: 'event-processor', + owner: 'platform-team', + type: 'service', + description: 'Service for processing and handling events.', + tags: ['events', 'processing'], + }, + { + name: 'payment-validator', + owner: 'finance-team', + type: 'service', + description: 'Service for validating payment transactions.', + tags: ['payments', 'validation', 'finance'], + }, + { + name: 'document-converter', + owner: 'frontend-team', + type: 'service', + description: 'Service for converting documents between different formats.', + tags: ['documents', 'conversion'], + }, + { + name: 'service-health', + owner: 'devops-team', + type: 'service', + description: 'Service for monitoring and reporting service health status.', + tags: ['health', 'monitoring', 'services'], + }, + { + name: 'security-logger', + owner: 'security-team', + type: 'service', + description: 'Service for logging security-related events and activities.', + tags: ['security', 'logging'], + }, + { + name: 'user-analytics', + owner: 'frontend-team', + type: 'website', + description: + 'Analytics dashboard for user behavior and engagement metrics.', + tags: ['analytics', 'user', 'metrics'], + }, + { + name: 'data-cleaner', + owner: 'data-team', + type: 'service', + description: 'Service for cleaning and standardizing data.', + tags: ['data', 'cleaning'], + }, + { + name: 'infrastructure-deployer', + owner: 'devops-team', + type: 'other', + description: 'Tools for deploying and managing infrastructure resources.', + tags: ['infrastructure', 'deployment', 'devops'], + }, + { + name: 'notification-queue', + owner: 'communication-team', + type: 'service', + description: 'Queue system for managing notification delivery.', + tags: ['notifications', 'queue'], + }, + { + name: 'analytics-exporter', + owner: 'analytics-team', + type: 'service', + description: 'Service for exporting analytics data in various formats.', + tags: ['analytics', 'export'], + }, + { + name: 'file-validator', + owner: 'storage-team', + type: 'service', + description: 'Service for validating file integrity and format.', + tags: ['files', 'validation'], + }, + { + name: 'search-optimizer', + owner: 'search-team', + type: 'service', + description: 'Service for optimizing search performance and relevance.', + tags: ['search', 'optimization'], + }, + { + name: 'mobile-analytics', + owner: 'mobile-team', + type: 'service', + description: 'Analytics service specifically for mobile applications.', + tags: ['mobile', 'analytics'], + }, + { + name: 'system-logger', + owner: 'devops-team', + type: 'service', + description: 'Service for logging system events and activities.', + tags: ['logging', 'system'], + }, + { + name: 'media-validator', + owner: 'media-team', + type: 'service', + description: 'Service for validating media files and formats.', + tags: ['media', 'validation'], + }, + { + name: 'user-audit', + owner: 'security-team', + type: 'service', + description: 'Service for auditing user activities and access.', + tags: ['audit', 'user', 'security'], + }, + { + name: 'data-normalizer', + owner: 'data-team', + type: 'service', + description: 'Service for normalizing data formats and structures.', + tags: ['data', 'normalization'], + }, + { + name: 'admin-authorization', + owner: 'platform-team', + type: 'service', + description: 'Authorization service for administrative functions.', + tags: ['admin', 'authorization', 'security'], + }, + { + name: 'test-reporting', + owner: 'qa-team', + type: 'other', + description: 'Tools for generating and managing test reports.', + tags: ['testing', 'reporting', 'qa'], + }, + { + name: 'event-aggregator', + owner: 'platform-team', + type: 'service', + description: 'Service for aggregating and processing events.', + tags: ['events', 'aggregation'], + }, + { + name: 'payment-reconciler', + owner: 'finance-team', + type: 'service', + description: 'Service for reconciling payment transactions.', + tags: ['payments', 'reconciliation', 'finance'], + }, + { + name: 'document-validator', + owner: 'frontend-team', + type: 'service', + description: 'Service for validating document formats and content.', + tags: ['documents', 'validation'], + }, + { + name: 'service-monitor', + owner: 'devops-team', + type: 'service', + description: 'Service for monitoring service health and performance.', + tags: ['monitoring', 'services', 'health'], + }, + { + name: 'security-validator', + owner: 'security-team', + type: 'service', + description: 'Service for validating security configurations and policies.', + tags: ['security', 'validation'], + }, +]; diff --git a/packages/canon/src/components/Table/styles.css b/packages/canon/src/components/Table/styles.css index 7d3cb35e3d..93a7de3259 100644 --- a/packages/canon/src/components/Table/styles.css +++ b/packages/canon/src/components/Table/styles.css @@ -59,3 +59,13 @@ box-shadow: inset 0px 2px 0 0 var(--canon-bg-surface-1), inset 0px -2px 0 0 var(--canon-bg-surface-1); } + +.canon-TablePagination { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--canon-space-3); + background-color: var(--canon-bg-surface-1); + border-top: 1px solid var(--canon-border); +} diff --git a/packages/canon/src/components/Table/types.ts b/packages/canon/src/components/Table/types.ts new file mode 100644 index 0000000000..79628de2bd --- /dev/null +++ b/packages/canon/src/components/Table/types.ts @@ -0,0 +1,50 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export interface TablePaginationProps + extends React.HTMLAttributes { + /** + * The current page index. + */ + pageIndex: number; + /** + * The current page size. + */ + pageSize: number; + /** + * The total number of rows. + */ + totalRows: number; + /** + * The function to call when the previous button is clicked. + */ + onClickPrevious: () => void; + /** + * The function to call when the next button is clicked. + */ + onClickNext: () => void; + /** + * Whether the previous button is disabled. + */ + canPrevious: boolean; + /** + * Whether the next button is disabled. + */ + canNext: boolean; + /** + * The function to call when the page size is changed. + */ + setPageSize: (pageSize: number) => void; +} diff --git a/packages/canon/src/components/TablePagination/TablePagination.tsx b/packages/canon/src/components/TablePagination/TablePagination.tsx new file mode 100644 index 0000000000..b04fd69f28 --- /dev/null +++ b/packages/canon/src/components/TablePagination/TablePagination.tsx @@ -0,0 +1,81 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import * as React from 'react'; +import { Text } from '../Text'; +import { TablePaginationProps } from './types'; +import { Button } from '../Button'; + +/** @public */ +const TablePagination = React.forwardRef( + ({ className, ...props }, ref) => { + const { + pageIndex, + pageSize, + onClickPrevious, + onClickNext, + canPrevious, + canNext, + totalRows, + setPageSize, + } = props; + return ( +
+ +
+ {`${pageIndex * pageSize + 1} - ${ + (pageIndex + 1) * pageSize + } of ${totalRows}`} +
+
+ + +
+
+ ); + }, +); +TablePagination.displayName = 'TablePagination'; + +export { TablePagination }; diff --git a/packages/canon/src/components/TablePagination/index.ts b/packages/canon/src/components/TablePagination/index.ts new file mode 100644 index 0000000000..2a2d462f84 --- /dev/null +++ b/packages/canon/src/components/TablePagination/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './TablePagination'; +export * from './types'; diff --git a/packages/canon/src/components/TablePagination/types.ts b/packages/canon/src/components/TablePagination/types.ts new file mode 100644 index 0000000000..79628de2bd --- /dev/null +++ b/packages/canon/src/components/TablePagination/types.ts @@ -0,0 +1,50 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export interface TablePaginationProps + extends React.HTMLAttributes { + /** + * The current page index. + */ + pageIndex: number; + /** + * The current page size. + */ + pageSize: number; + /** + * The total number of rows. + */ + totalRows: number; + /** + * The function to call when the previous button is clicked. + */ + onClickPrevious: () => void; + /** + * The function to call when the next button is clicked. + */ + onClickNext: () => void; + /** + * Whether the previous button is disabled. + */ + canPrevious: boolean; + /** + * Whether the next button is disabled. + */ + canNext: boolean; + /** + * The function to call when the page size is changed. + */ + setPageSize: (pageSize: number) => void; +} diff --git a/yarn.lock b/yarn.lock index baf0dd3925..9e19cc722f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3789,6 +3789,7 @@ __metadata: "@storybook/react": ^8.6.8 "@storybook/react-webpack5": ^8.6.8 "@storybook/test": ^8.6.8 + "@tanstack/react-table": ^8.21.2 "@types/react": ^18.0.0 "@types/react-dom": ^18.0.0 chalk: ^5.4.1 @@ -19117,6 +19118,25 @@ __metadata: languageName: node linkType: hard +"@tanstack/react-table@npm:^8.21.2": + version: 8.21.2 + resolution: "@tanstack/react-table@npm:8.21.2" + dependencies: + "@tanstack/table-core": 8.21.2 + peerDependencies: + react: ">=16.8" + react-dom: ">=16.8" + checksum: 3cda97794c10777d48d01de29d087a33edd8af153b3096ac9798c7ebddd31bd34f2b7838ecf4bddaf469d661a777556bd8021e15a41f692eb2e3dd79dd0e5c3b + languageName: node + linkType: hard + +"@tanstack/table-core@npm:8.21.2": + version: 8.21.2 + resolution: "@tanstack/table-core@npm:8.21.2" + checksum: 21573388b26cef9c6fcabe3785640c470ea072a6d6ec34543e7eaf54ee742bf5fb12f8a04b172d7e08bd828a35afd7133add5adb4729dd4f94eaf4745b1cab14 + languageName: node + linkType: hard + "@techdocs/cli@workspace:*, @techdocs/cli@workspace:packages/techdocs-cli": version: 0.0.0-use.local resolution: "@techdocs/cli@workspace:packages/techdocs-cli"