Skip to content

Commit

Permalink
Merge pull request #2661 from epam/feature/rc-version
Browse files Browse the repository at this point in the history
[DataTable]: Added support of column groups in table header
  • Loading branch information
AlekseyManetov authored Nov 26, 2024
2 parents eb89838 + 4ae6132 commit 94ece70
Show file tree
Hide file tree
Showing 24 changed files with 767 additions and 50 deletions.
116 changes: 116 additions & 0 deletions app/src/docs/_examples/tables/TableGroupedHeader.example.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import React, { useState } from 'react';
import { DataSourceState, DataColumnProps, useUuiContext, useLazyDataSource, DataColumnGroupProps } from '@epam/uui-core';
import { Text, DataTable, Panel, FlexRow, Badge, BadgeProps } from '@epam/uui';
import { Person } from '@epam/uui-docs';

import css from './TablesExamples.module.scss';
import { TApi } from '../../../data';

export default function TableGroupedHeaderExample() {
const svc = useUuiContext<TApi>();
const [tableState, setTableState] = useState<DataSourceState>({});

// Define columns groups array
const columnGroups: DataColumnGroupProps[] = [
{
key: 'location',
caption: 'Location',
textAlign: 'center',
},
{
key: 'position',
caption: 'Position',
textAlign: 'center',
},
];

// Define columns config array
const personColumns: DataColumnProps<Person, number>[] = [
{
key: 'name',
caption: 'Name',
render: (p) => <Text>{p.name}</Text>,
width: 130,
isSortable: true,
},
{
key: 'profileStatus',
caption: 'Status',
render: (p) => (
<FlexRow>
<Badge size="24" indicator fill="outline" color={ p.profileStatus.toLowerCase() as BadgeProps['color'] } caption={ p.profileStatus } />
</FlexRow>
),
grow: 0,
width: 100,
minWidth: 90,
isSortable: true,
},
{
key: 'countryName',
caption: 'Country',
group: 'location', // Specify group key
render: (p) => <Text>{p.countryName}</Text>,
grow: 0,
width: 110,
isSortable: true,
},
{
key: 'cityName',
caption: 'City',
group: 'location', // Specify group key
render: (p) => <Text>{p.cityName}</Text>,
grow: 0,
width: 110,
isSortable: true,
},
{
key: 'officeAddress',
caption: 'Office',
group: 'location', // Specify group key
render: (p) => <Text>{p.officeAddress}</Text>,
grow: 0,
width: 150,
isSortable: true,
},
{
key: 'jobTitle',
caption: 'Title',
group: 'position', // Specify group key
render: (r) => <Text>{r.jobTitle}</Text>,
width: 180,
isSortable: true,
},
{
key: 'titleLevel',
caption: 'Track & Level',
group: 'position', // Specify group key
render: (p) => <Text>{p.titleLevel}</Text>,
grow: 1,
width: 100,
isSortable: true,
},
];

const citiesDS = useLazyDataSource<Person, number, unknown>({
api: svc.api.demo.persons,
backgroundReload: true,
}, []);

const view = citiesDS.useView(tableState, setTableState);

return (
<Panel background="surface-main" shadow cx={ css.container }>
<DataTable
value={ tableState }
onValueChange={ setTableState }
{ ...view.getListProps() }
getRows={ view.getVisibleRows }
showColumnsConfig={ false }
columnGroups={ columnGroups }
columns={ personColumns }
headerTextCase="upper"
/>
</Panel>
);
}
6 changes: 4 additions & 2 deletions app/src/docs/tables/Advanced.doc.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ export class AdvancedTablesDoc extends BaseDocsBlock {

<DocExample cx={ css.appBg } title="Columns Configuration" path="./_examples/tables/ColumnsConfig.example.tsx" />

<DocExample cx={ css.appBg } title="Table with rows Drag&Drop" path="./_examples/tables/TableWithDnD.example.tsx" />

<DocExample cx={ css.appBg } title="Table with paging and select page" path="./_examples/tables/PagedTable.example.tsx" />
<DocExample cx={ css.appBg } title="Table with paging and select all rows" path="./_examples/tables/PagedTableWithSelectAll.example.tsx" />

<DocExample cx={ css.appBg } title="Table with column filters" path="./_examples/tables/ColumnFiltersTable.example.tsx" />

<DocExample cx={ css.appBg } title="Table with pinned rows" path="./_examples/tables/TableWithPinnedRows.example.tsx" />
<DocExample cx={ css.appBg } title="Table with expandable rows" path="./_examples/tables/TableWithExpandableRows.example.tsx" />

<DocExample cx={ css.appBg } title="Table with rows Drag&Drop" path="./_examples/tables/TableWithDnD.example.tsx" />

<DocExample cx={ css.appBg } title="Table with header groups" path="./_examples/tables/TableGroupedHeader.example.tsx" />
</>
);
}
Expand Down
5 changes: 3 additions & 2 deletions app/src/sandbox/tables/PersonsTableDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const formatCurrency = (value: number) => {
};

export function PersonsTableDemo() {
const { personColumns, summaryColumns } = React.useMemo(() => getColumns(), []);
const { personColumns, summaryColumns, personColumnsGroups } = React.useMemo(() => getColumns(), []);

const [summary, setSummary] = React.useState<PersonsSummary & Pick<PersonsApiResponse, 'totalCount'>>({
totalCount: undefined,
Expand Down Expand Up @@ -161,7 +161,7 @@ export function PersonsTableDemo() {
[value.filter?.groupBy],
);
const { rows, listProps } = useDataRows(tree);

return (
<div className={ cx(css.container, css.uuiThemeLoveship) }>
<FlexRow spacing="12" padding="24" vPadding="12" borderBottom={ true }>
Expand Down Expand Up @@ -189,6 +189,7 @@ export function PersonsTableDemo() {
<DataTable
rows={ rows }
columns={ personColumns as DataColumnProps<PersonTableRecord, PersonTableRecordId, any>[] }
columnGroups={ personColumnsGroups }
value={ value }
onValueChange={ onValueChange }
filters={ getFilters() }
Expand Down
50 changes: 41 additions & 9 deletions app/src/sandbox/tables/columns.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,93 @@
import * as React from 'react';
import { Text, FlexRow } from '@epam/loveship';
import { DataQueryFilter, DataColumnProps } from '@epam/uui-core';
import { DataQueryFilter, DataColumnProps, DataColumnGroupProps } from '@epam/uui-core';
import type { Person } from '@epam/uui-docs';
import type { PersonTableRecordId } from './types';
import type { PersonsSummary } from './types';

export function getColumns() {
const personColumnsGroups: DataColumnGroupProps[] = [
{
key: 'name',
caption: 'Name',
},
{
key: 'position',
caption: 'Position',
},
{
key: 'amounts',
caption: 'Amounts',
textAlign: 'right',
},
];

const personColumns: DataColumnProps<Person, PersonTableRecordId, DataQueryFilter<Person>>[] = [
{
key: 'name',
group: 'name',
caption: 'Name',
render: (p) => <Text>{p.name}</Text>,
width: 250,
grow: 1,
fix: 'left',
allowResizing: true,
isSortable: true,
}, {
key: 'name2',
group: 'name',
caption: 'Name2',
render: (p) => <Text>{p.name}</Text>,
width: 250,
fix: 'left',
allowResizing: true,
isSortable: true,
}, {
key: 'jobTitle',
group: 'position',
caption: 'Job Title',
render: (r) => <Text>{r.jobTitle}</Text>,
width: 200,
grow: 1,
allowResizing: true,
isSortable: true,
isFilterActive: (f) => !!f.jobTitle,
}, {
key: 'departmentName',
group: 'position',
caption: 'Department',
render: (p) => <Text>{p.departmentName}</Text>,
width: 200,
grow: 1,
allowResizing: true,
isSortable: true,
isFilterActive: (f) => !!f.departmentId,
}, {
key: 'birthDate',
group: 'position',
caption: 'Birth Date',
render: (p) => p?.birthDate && <Text>{new Date(p.birthDate).toLocaleDateString()}</Text>,
width: 120,
allowResizing: true,
isSortable: true,
}, {
key: 'hireDate',
caption: 'Hire Date',
render: (p) => p?.hireDate && <Text>{new Date(p.hireDate).toLocaleDateString()}</Text>,
width: 120,
allowResizing: true,
isSortable: true,
}, {
key: 'locationName',
caption: 'Location',
render: (p) => <Text>{p.locationName}</Text>,
width: 180,
grow: 1,
allowResizing: true,
isSortable: true,
}, {
key: 'salary',
group: 'amounts',
caption: 'Salary',
render: (p) => <Text color="night900">{p.salary}</Text>,
width: 150,
allowResizing: true,
isSortable: true,
textAlign: 'right',
}, {
Expand All @@ -72,7 +105,6 @@ export function getColumns() {
fix: 'left',
textAlign: 'right',
width: 250,
grow: 1,
render: (p) => (
<FlexRow background="night50">
<Text fontSize="14">
Expand All @@ -87,13 +119,13 @@ export function getColumns() {
),
}, {
key: 'jobTitle',
group: 'position',
width: 200,
grow: 1,
render: () => <Text fontSize="14">-</Text>,
}, {
key: 'departmentName',
group: 'position',
width: 200,
grow: 1,
render: () => (
<Text fontSize="14">
-
Expand All @@ -111,7 +143,6 @@ export function getColumns() {
key: 'locationName',
render: () => <Text fontSize="14">-</Text>,
width: 180,
grow: 1,
}, {
key: 'salary',
caption: 'Total Salary',
Expand All @@ -133,5 +164,6 @@ export function getColumns() {
return {
personColumns,
summaryColumns,
personColumnsGroups,
};
}
3 changes: 2 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# 5.xx.xx - xx.xx.2024

**What's New**
* [ErrorPage]: Added field for additional message with support link (it works with `500, 503, default` errors), added support link for the site
* [DataTable]: added support of column groups in table header. Read more - https://uui.epam.com/documents?id=advancedTables&mode=doc&category=tables&theme=electric#table_with_header_groups
* [ErrorPage]: added field for additional message with support link (it works with `500, 503, default` errors), added support link for the site

**What's Fixed**
* [PickerInput]: fixed unnecessary api calls on body open with `minCharsToSearch` prop and search in body
Expand Down
32 changes: 32 additions & 0 deletions public/docs/content/examples-tables-TableGroupedHeader.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[
{
"type": "paragraph",
"children": [
{
"text": "To create column groups in the table header, provide the group configuration using the "
},
{
"text": "columnGroups",
"uui-richTextEditor-code": true
},
{
"text": " prop. For each column to be grouped, specify the "
},
{
"text": "group",
"uui-richTextEditor-code": true
},
{
"text": " field with the corresponding group key."
}
]
},
{
"type": "note-warning",
"children": [
{
"text": "This is preview version of header groups functionality with limited support of some DataTable features, like columns reordering, resizing and columns configuration via modal."
}
]
}
]
6 changes: 3 additions & 3 deletions uui-components/src/table/DataTableCellContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { DataColumnProps, IClickable, IHasCX, IHasRawProps } from '@epam/uui-core';
import { DataColumnGroupProps, DataColumnProps, IClickable, IHasCX, IHasRawProps } from '@epam/uui-core';
import { FlexCell } from '../layout';

import css from './DataTableCellContainer.module.scss';
Expand All @@ -15,7 +15,7 @@ export interface DataTableCellContainerProps extends
/**
* DataTable column configuration.
*/
column: DataColumnProps;
column: DataColumnProps | DataColumnGroupProps;
/**
* CSS text-align property.
*/
Expand All @@ -38,7 +38,7 @@ export const DataTableCellContainer = React.forwardRef<HTMLDivElement, DataTable
return (
<FlexCell
{ ...props.column }
minWidth={ props.column.width }
minWidth={ 'width' in props.column ? props.column.width : undefined }
rawProps={ props.rawProps }
cx={ ['uui-dt-vars', css.root, props.column.cx, props.cx] }
onClick={ props.onClick }
Expand Down
Loading

0 comments on commit 94ece70

Please sign in to comment.