Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Item should render sort icons 1`] = `
<div>
<div
class="dx-cardview-header-item undefined undefined"
tabindex="0"
>
Column 1
<span
class="dx-cardview-header-item-sorting"
>
<i
class="dx-icon dx-icon-sortup"
/>
</span>
</div>
</div>
`;

exports[`Item should use column caption as text 1`] = `
<div>
<div
class="dx-cardview-header-item undefined undefined"
tabindex="0"
>
my column caption
</div>
</div>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`ColumnProperties headerItemCssClass should override content of headerPanel item 1`] = `
<div
class="test-container"
>
<div
class="dx-cardview-headers"
>
<div
class="dx-scrollable dx-visibility-change-handler dx-scrollable-horizontal dx-scrollable-simulated"
>
<div
class="dx-scrollable-wrapper"
>
<div
class="dx-scrollable-container"
tabindex="0"
>
<div
class="dx-scrollable-content"
style="left: 0px; top: 0px; transform: none;"
>
<div
class="dx-cardview-headers-content"
>
<div
class="dx-cardview-header-item my-css-class undefined"
tabindex="0"
>
Column 1
</div>
</div>
</div>
<div
class="dx-scrollable-scrollbar dx-widget dx-scrollbar-horizontal"
style="display: none;"
>
<div
class="dx-scrollable-scroll dx-state-invisible"
>
<div
class="dx-scrollable-scroll-content"
/>
</div>
</div>
</div>
</div>
</div>

</div>
</div>
`;

exports[`Options headerPanel itemCssClass should add css class to headerPanel item 1`] = `
<div
class="dx-scrollable dx-visibility-change-handler dx-scrollable-horizontal dx-scrollable-simulated"
>
<div
class="dx-scrollable-wrapper"
>
<div
class="dx-scrollable-container"
tabindex="0"
>
<div
class="dx-scrollable-content"
style="left: 0px; top: 0px; transform: none;"
>
<div
class="dx-cardview-headers-content"
>
<div
class="dx-cardview-header-item undefined my-class"
tabindex="0"
>
Column 1
</div>
</div>
</div>
<div
class="dx-scrollable-scrollbar dx-widget dx-scrollbar-horizontal"
style="display: none;"
>
<div
class="dx-scrollable-scroll dx-state-invisible"
>
<div
class="dx-scrollable-scroll-content"
/>
</div>
</div>
</div>
</div>
</div>
`;

exports[`Options headerPanel visible when it is false should hide headerPanel 1`] = `
<div
class="test-container"
>

</div>
`;

exports[`Options headerPanel visible when it is true should show headerPanel 1`] = `
<div
class="test-container"
>
<div
class="dx-cardview-headers"
>
<div
class="dx-scrollable dx-visibility-change-handler dx-scrollable-horizontal dx-scrollable-simulated"
>
<div
class="dx-scrollable-wrapper"
>
<div
class="dx-scrollable-container"
tabindex="0"
>
<div
class="dx-scrollable-content"
style="left: 0px; top: 0px; transform: none;"
>
<div
class="dx-cardview-headers-content"
>
<div
class="dx-cardview-header-item undefined undefined"
tabindex="0"
>
Column 1
</div>
</div>
</div>
<div
class="dx-scrollable-scrollbar dx-widget dx-scrollbar-horizontal"
style="display: none;"
>
<div
class="dx-scrollable-scroll dx-state-invisible"
>
<div
class="dx-scrollable-scroll-content"
/>
</div>
</div>
</div>
</div>
</div>

</div>
</div>
`;
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export class ColumnSortable extends Component<Props, State> {
source,
visibleColumns,
dragTemplate,
dropFeedbackMode,
...restProps
} = this.props;

Expand All @@ -123,7 +124,7 @@ export class ColumnSortable extends Component<Props, State> {
return (
<Sortable
{...restProps}
dropFeedbackMode='indicate'
dropFeedbackMode={dropFeedbackMode ?? 'indicate'}
onDragStart={this.onDragStart}
group='dx-cardview-columns'
onAdd={this.onMove}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
/* eslint-disable max-len */
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import type { Column } from '@ts/grids/new/grid_core/columns_controller/types';
import { Scrollable } from '@ts/grids/new/grid_core/inferno_wrappers/scrollable';
import type { ComponentType } from 'inferno';
import { Component } from 'inferno';

import { ColumnSortable } from './column_sortable';
import { CLASSES as itemClasses, Item } from './item';
import type { DraggingOptions } from './options';

export const CLASSES = {
headers: 'dx-cardview-headers',
Expand All @@ -17,13 +20,30 @@ export interface HeaderPanelProps {
onMove: (column: Column, toIndex: number) => void;

allowColumnReordering: boolean;

showSortIndexes: boolean;

onSortClick: (column: Column) => void;

itemTemplate?: ComponentType<{ column: Column }>;

itemCssClass?: string;

visible: boolean;

draggingOptions?: DraggingOptions;
}

export class HeaderPanel extends Component<HeaderPanelProps> {
public render(): JSX.Element {
if (!this.props.visible) {
return <></>;
}

return (
<div className={CLASSES.headers}>
<ColumnSortable
{...this.props.draggingOptions}
allowColumnReordering={this.props.allowColumnReordering}
source="header-panel-main"
visibleColumns={this.props.columns}
Expand All @@ -41,7 +61,11 @@ export class HeaderPanel extends Component<HeaderPanelProps> {
<div className={CLASSES.content}>
{this.props.columns.map((column) => (
<Item
showSortIndexes={this.props.showSortIndexes}
column={column}
onSortClick={(): void => { this.props.onSortClick(column); }}
template={this.props.itemTemplate}
cssClass={this.props.itemCssClass}
/>
))}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { describe, expect, it } from '@jest/globals';
import { render } from 'inferno';

import { normalizeColumn } from '../../grid_core/columns_controller/columns_controller.mock';
import type { ItemProps } from './item';
import { Item } from './item';

const setup = (props: ItemProps) => {
const rootElement = document.createElement('div');
render(
<Item {...props} />,
rootElement,
);

return rootElement;
};

describe('Item', () => {
it('should use column caption as text', () => {
const el = setup({
column: normalizeColumn({
dataField: 'my column data field',
caption: 'my column caption',
}),
});

expect(el).toMatchSnapshot();
});

it('should render sort icons', () => {
const el = setup({
column: normalizeColumn({
dataField: 'column1',
sortIndex: 0,
sortOrder: 'asc',
}),
});

expect(el).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,81 @@ import type { Status } from './column_sortable';
export const CLASSES = {
item: 'dx-cardview-header-item',
button: 'dx-cardview-header-item-button',
sorting: {
container: 'dx-cardview-header-item-sorting',
order: 'dx-cardview-header-item-sorting-order',
},
};

export interface HeaderItemProps {
column: Pick<Column, 'caption' | 'visible'>;
buttons?: ComponentType;

status?: Status;
}

// TODO: extract icons to separate component
const ICONS = {
// TODO: move to icons
// TODO: move to dx-icon once they are updated
forbid: (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8ZM15 8C15 6.24696 14.3556 4.64442 13.2907 3.41636L3.41636 13.2907C4.64442 14.3556 6.24696 15 8 15C11.866 15 15 11.866 15 8ZM2.70925 12.5836L12.5836 2.70925C11.3556 1.6444 9.75303 1 8 1C4.13401 1 1 4.13401 1 8C1 9.75303 1.6444 11.3556 2.70925 12.5836Z" fill="#242424"/>
</svg>
),
// TODO: move to dx-icon once they are updated
moving: (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.35355 0.146447C8.25978 0.0526784 8.13261 0 8 0C7.86739 0 7.74021 0.0526784 7.64645 0.146447L5.14645 2.64645C4.95118 2.84171 4.95118 3.15829 5.14645 3.35355C5.34171 3.54882 5.65829 3.54882 5.85355 3.35355L7.5 1.70711V5.5C7.5 5.77614 7.72386 6 8 6C8.27614 6 8.5 5.77614 8.5 5.5V1.70711L10.1464 3.35355C10.3417 3.54882 10.6583 3.54882 10.8536 3.35355C11.0488 3.15829 11.0488 2.84171 10.8536 2.64645L8.35355 0.146447ZM0.146447 7.64645C0.0526784 7.74021 0 7.86739 0 8C0 8.13261 0.0526784 8.25979 0.146447 8.35355L2.64645 10.8536C2.84171 11.0488 3.15829 11.0488 3.35355 10.8536C3.54882 10.6583 3.54882 10.3417 3.35355 10.1464L1.70711 8.5H5.5C5.77614 8.5 6 8.27614 6 8C6 7.72386 5.77614 7.5 5.5 7.5H1.70711L3.35355 5.85355C3.54882 5.65829 3.54882 5.34171 3.35355 5.14645C3.15829 4.95118 2.84171 4.95118 2.64645 5.14645L0.146447 7.64645ZM8 16C7.86739 16 7.74021 15.9473 7.64645 15.8536L5.14645 13.3536C4.95118 13.1583 4.95118 12.8417 5.14645 12.6464C5.34171 12.4512 5.65829 12.4512 5.85355 12.6464L7.5 14.2929L7.5 10.5C7.5 10.2239 7.72386 10 8 10C8.27614 10 8.5 10.2239 8.5 10.5V14.2929L10.1464 12.6464C10.3417 12.4512 10.6583 12.4512 10.8536 12.6464C11.0488 12.8417 11.0488 13.1583 10.8536 13.3536L8.35355 15.8536C8.25979 15.9473 8.13261 16 8 16ZM15.8536 8.35355C15.9473 8.25978 16 8.13261 16 8C16 7.86739 15.9473 7.74021 15.8536 7.64645L13.3536 5.14645C13.1583 4.95118 12.8417 4.95118 12.6464 5.14645C12.4512 5.34171 12.4512 5.65829 12.6464 5.85355L14.2929 7.5L10.5 7.5C10.2239 7.5 10 7.72386 10 8C10 8.27614 10.2239 8.5 10.5 8.5L14.2929 8.5L12.6464 10.1464C12.4512 10.3417 12.4512 10.6583 12.6464 10.8536C12.8417 11.0488 13.1583 11.0488 13.3536 10.8536L15.8536 8.35355Z" fill="#242424"/>
</svg>
),
sortUp: <i className='dx-icon dx-icon-sortup'/>,
sortDown: <i className='dx-icon dx-icon-sortdown'/>,
};

export function Item(props: HeaderItemProps): JSX.Element {
interface SortIconProps {
sortOrder: 'asc' | 'desc';
sortIndex: number;
showSortIndex: boolean;
}

function SortIcon(props: SortIconProps): JSX.Element {
return (
<span className={CLASSES.sorting.container}>
{props.sortOrder === 'asc' && ICONS.sortUp}
{props.sortOrder === 'desc' && ICONS.sortDown}
{
props.showSortIndex && (
<span className={CLASSES.sorting.order}>
{props.sortIndex}
</span>
)
}
</span>
);
}

export interface ItemProps {
column: Column;
status?: Status;
showSortIndexes?: boolean;
onSortClick?: () => void;
template?: ComponentType<{ column: Column }>;
cssClass?: string;
}

export function Item(props: ItemProps): JSX.Element {
const Template = props.column.headerItemTemplate ?? props.template;
const cssClass = `${CLASSES.item} ${props.column.headerItemCssClass} ${props.cssClass}`;

return (
<div className={CLASSES.item} tabIndex={0}>
<div className={cssClass} tabIndex={0} onClick={props.onSortClick}>
{ props.status && ICONS[props.status]}
{props.column.caption}
{/* @ts-expect-error */}
{ Template && <Template column={props.column}/>}
{ !Template && props.column.caption }
{
props.column.sortOrder !== undefined && (
<SortIcon
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
sortIndex={props.column.sortIndex!}
sortOrder={props.column.sortOrder}
showSortIndex={props.showSortIndexes ?? false}
/>
)
}
</div>
);
}
Loading
Loading