Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Expand Up @@ -5,6 +5,39 @@ exports[`common initial render should be successfull 1`] = `
class="dx-widget dx-cardview"
>

<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-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>

</div>
Expand Down
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 "
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 "
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 "
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 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 "
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
@@ -0,0 +1,144 @@
import $ from '@js/core/renderer';
import type * as SortableTypes from '@js/ui/sortable_types';
import type { ComponentType, InfernoNode } from 'inferno';
import { Component, render } from 'inferno';

import type { Column } from '../../grid_core/columns_controller/types';
import type { Props as SortableProps } from '../../grid_core/inferno_wrappers/sortable';
import { Sortable } from '../../grid_core/inferno_wrappers/sortable';

export type Status = 'forbid' | 'show' | 'moving' | 'none';

export interface Props extends Omit<SortableProps, 'onAdd' | 'onReorder' | 'dragTemplate'> {
source: string;

visibleColumns: Column[];

allowColumnReordering: boolean;

onMove: (column: Column, toIndex: number, source: string) => void;

dragTemplate?: ComponentType<{ column: Column; status: Status }>;
}

interface State {
status: Status;
}

export class ColumnSortable extends Component<Props, State> {
status: Status = 'moving';

dragItemProps?: {
container: HTMLElement;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
props: any;
};

private readonly onDragStart = (e: SortableTypes.DragStartEvent): void => {
const column = this.props.visibleColumns[e.fromIndex];

if (!column.allowReordering) {
e.cancel = true;
return;
}

e.itemData = {
column,
source: this.props.source,
};
};

private readonly onDragMove = (e: SortableTypes.DragMoveEvent): void => {
const containerCoords = $(e.element).get(0).getBoundingClientRect();
const dragCoords = {
// @ts-expect-error
x: e.event.clientX,
// @ts-expect-error
y: e.event.clientY,
};

const yDistance = Math.min(
Math.abs(dragCoords.y - containerCoords.y),
Math.abs(dragCoords.y - containerCoords.y + containerCoords.height),
);

// TODO: move to scss variable
this.status = yDistance <= 64
? 'moving'
: 'forbid';

this.renderDragTemplate();
};

private readonly onDragChange = (e: SortableTypes.DragChangeEvent): void => {
if (this.status === 'forbid') {
e.cancel = true;
}
};

private readonly onMove = (e: SortableTypes.AddEvent | SortableTypes.ReorderEvent): void => {
this.props.onMove(
e.itemData.column,
e.toIndex,
e.itemData.source,
);
};

// TODO: move all none-native approaches to sortable wrapper
private readonly renderDragTemplate = (): void => {
if (!this.dragItemProps) {
return;
}

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const DragTemplate = this.props.dragTemplate!;
render(
// @ts-expect-error
<DragTemplate
column={this.dragItemProps.props.itemData.column}
status={this.status}
/>,
this.dragItemProps.container,
);
};

render(): InfernoNode {
if (!this.props.allowColumnReordering) {
// @ts-expect-error
return this.props.children;
}

const {
source,
visibleColumns,
dragTemplate,
dropFeedbackMode,
...restProps
} = this.props;

const sortableDragTemplate = dragTemplate ? (e, container): void => {
this.dragItemProps = {
props: e,
// @ts-expect-error
container: $(container).get(0),
};
this.renderDragTemplate();
} : undefined;

return (
<Sortable
{...restProps}
dropFeedbackMode={dropFeedbackMode ?? 'indicate'}
onDragStart={this.onDragStart}
group='dx-cardview-columns'
onAdd={this.onMove}
onReorder={this.onMove}
onDragMove={this.onDragMove}
onDragChange={this.onDragChange}
dragTemplate={sortableDragTemplate}
>
{this.props.children}
</Sortable>
);
}
}
Loading
Loading