Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DataTable]: reworked isAwaysVisible column configuration prop and isLocked prop #2539

Merged
merged 2 commits into from
Oct 9, 2024
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
1 change: 1 addition & 0 deletions app/src/demo/tables/editableTable/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export function getColumnsTableMode(columnsProps: ColumnsProps) {
caption: 'Name',
width: 300,
fix: 'left',
isLocked: true,
renderCell: (props) => (
<DataTableCell
{ ...props.rowLens.prop('name').toProps() }
Expand Down
3 changes: 2 additions & 1 deletion app/src/demo/tables/filteredTable/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const personColumns: DataColumnProps<Person, number>[] = [
width: 130,
fix: 'left',
isSortable: true,
isAlwaysVisible: true,
isLocked: true,
},
{
key: 'profileStatus',
Expand All @@ -26,6 +26,7 @@ export const personColumns: DataColumnProps<Person, number>[] = [
width: 100,
minWidth: 90,
isSortable: true,
isAlwaysVisible: true,
},
{
key: 'salary',
Expand Down
2 changes: 1 addition & 1 deletion app/src/demo/tables/masterDetailedTable/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const personColumns: DataColumnProps<Person, PersonTableRecordId[], DataQ
fix: 'left',
isSortable: true,
justifyContent: 'space-between',
isAlwaysVisible: true,
isLocked: true,
}, {
key: 'profileStatus',
caption: 'Profile Status',
Expand Down
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# 5.*.* - **.**.****

**What's New**
[DataTable]:
* [Breaking change]: reworked `isAwaysVisible` column configuration prop. Now it's not make column fixed by default and doesn't forbid to unpin or reorder, it's only disallow to hide this column from table. If you need previous behavior, please use `isLocked` prop.
* Added `isLocked` prop for column configuration. If `true` value provided, makes this column locked, which means that you can't hide, unpin or reorder this column. This column should always be pined.
* [PickerInput]:
* Added support of `minCharsToSearch` > 0 with `searchPosition = 'body'`.
* Added renderEmpty prop to render custom empty block for depends on various reasons.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ const mockAcceptDropParams = (params: TAcceptDropParams): TAcceptDropParamsAll =

describe('columnsConfigurationUtils', () => {
describe('canAcceptDrop', () => {
it('should not accept drop before isAlwaysVisible fixed left columns', () => {
it('should not accept drop before isLocked fixed left columns', () => {
const params = mockAcceptDropParams({
dstData: {
column: {
key: '1', fix: 'left', caption: '1', isAlwaysVisible: true, width: 1,
key: '1', fix: 'left', caption: '1', isLocked: true, width: 1,
},
columnConfig: { width: 1, isVisible: true, order: 'a' },
},
Expand All @@ -68,18 +68,18 @@ describe('columnsConfigurationUtils', () => {
columnConfig: { width: 2, isVisible: true, order: 'b' },
},
});
const result = canAcceptDrop(params, { key: '100500', fix: 'left', isAlwaysVisible: true, width: 0 }); // Try to drop between 2 isAlwaysVisible columns
const result = canAcceptDrop(params, { key: '100500', fix: 'left', isLocked: true, width: 0 }); // Try to drop between 2 isLocked columns
expect(result).toEqual({});

const result2 = canAcceptDrop(params, { key: '100500', width: 0 }); // Try to drop at last isAlwaysVisible columns
const result2 = canAcceptDrop(params, { key: '100500', width: 0 }); // Try to drop at last isLocked columns
expect(result2).toEqual({ bottom: true });
});

it('should not accept drop after isAlwaysVisible fixed right columns', () => {
it('should not accept drop after isLocked fixed right columns', () => {
const params = mockAcceptDropParams({
dstData: {
column: {
key: '1', fix: 'right', caption: '1', isAlwaysVisible: true, width: 1,
key: '1', fix: 'right', caption: '1', isLocked: true, width: 1,
},
columnConfig: { width: 1, isVisible: true, order: 'a' },
},
Expand All @@ -90,12 +90,31 @@ describe('columnsConfigurationUtils', () => {
columnConfig: { width: 2, isVisible: true, order: 'b' },
},
});
const result = canAcceptDrop(params, { key: '100500', width: 0 }, { key: '100501', fix: 'right', isAlwaysVisible: true, width: 0 }); // Try to drop between 2 isAlwaysVisible columns
const result = canAcceptDrop(params, { key: '100500', width: 0 }, { key: '100501', fix: 'right', isLocked: true, width: 0 }); // Try to drop between 2 isLocked columns
expect(result).toEqual({});

const result2 = canAcceptDrop(params, { key: '100500', width: 0 }); // Try to drop at first isAlwaysVisible columns
const result2 = canAcceptDrop(params, { key: '100500', width: 0 }); // Try to drop at first isLocked columns
expect(result2).toEqual({ top: true });
});

it('should not accept drop for isAlwaysVisible column in hidden section', () => {
const params = mockAcceptDropParams({
dstData: {
column: {
key: '1', fix: 'right', caption: '1', width: 1,
},
columnConfig: { width: 1, isVisible: false, order: 'a' },
},
srcData: {
column: {
key: '2', caption: '2', width: 2, isAlwaysVisible: true,
},
columnConfig: { width: 2, isVisible: true, order: 'b' },
},
});
const result = canAcceptDrop(params);
expect(result).toEqual({});
});
});
describe('sortColumnsAndAddGroupKey', () => {
it('should sort columns by "order" and should add "groupKey" attribute', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,29 @@ import React from 'react';
import { AcceptDropParams, ColumnsConfig, DataColumnProps, DropPosition, getOrderBetween, IColumnConfig, orderBy } from '@epam/uui-core';
import { ColumnsConfigurationRowProps, DndDataType, GroupedColumnsType, GroupedDataColumnProps } from './types';

export function isColumnAlwaysPinned(column: DataColumnProps) {
return Boolean(column?.isAlwaysVisible);
export function isColumnLocked(column: DataColumnProps) {
return Boolean(column?.isLocked);
}

export function canAcceptDrop(props: AcceptDropParams<DndDataType, DndDataType>, nextColumn?: DataColumnProps, prevColumn?: DataColumnProps) {
const { dstData } = props;
const { dstData, srcData } = props;

if (isColumnAlwaysPinned(dstData.column)) {
if (dstData.column.fix === 'left' && !isColumnAlwaysPinned(nextColumn)) { // If user try to drop column at the last isAlwaysVisible column. Allow to drop only to the end of the fixed list.
if (isColumnLocked(dstData.column)) {
if (dstData.column.fix === 'left' && !isColumnLocked(nextColumn)) { // If user try to drop column at the last isAlwaysVisible column. Allow to drop only to the end of the fixed list.
return { bottom: true };
}

if (dstData.column.fix === 'right' && !isColumnAlwaysPinned(prevColumn)) { // If user try to drop column at the first isAlwaysVisible. Allow to drop only to the start of the fixed list
if (dstData.column.fix === 'right' && !isColumnLocked(prevColumn)) { // If user try to drop column at the first isAlwaysVisible. Allow to drop only to the start of the fixed list
return { top: true };
}

return {}; // Shouldn't drop between 2 isAlwaysVisible columns
}

if (srcData.column.isAlwaysVisible && dstData.columnConfig.isVisible === false) {
return {}; // We shouldn't move isAlwaysVisible column into 'Hidden from table' group
}

return { top: true, bottom: true };
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
import {
canAcceptDrop,
isColumnAlwaysHiddenInTheConfigurationModal,
isColumnAlwaysPinned,
isColumnLocked,
} from '../columnsConfigurationUtils';
import { DndDataType, GroupedDataColumnProps, ColumnsConfigurationRowProps, TColumnPinPosition } from '../types';
import { groupAndFilterSortedColumns, sortColumnsAndAddGroupKey } from '../columnsConfigurationUtils';
Expand Down Expand Up @@ -75,7 +75,7 @@ export function useColumnsConfiguration(props: UseColumnsConfigurationProps<any,
};
});
};
const isPinnedAlways = isColumnAlwaysPinned(column);
const isPinnedAlways = isColumnLocked(column);
const fix = columnConfig.fix || (isPinnedAlways ? 'left' : undefined);
return {
...column,
Expand Down
2 changes: 1 addition & 1 deletion uui-core/src/helpers/applyColumnsConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const getColumnsConfig = <TItem, TId>(columns: DataColumnProps<TItem, TId

resultConfig[column.key] = {
width: column.width,
fix: column.fix ?? (column.isAlwaysVisible ? 'left' : undefined),
fix: column.fix ?? (column.isLocked ? 'left' : undefined),
isVisible: !column.isHiddenByDefault,
order: order,
};
Expand Down
9 changes: 6 additions & 3 deletions uui-core/src/types/tables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,14 @@ export interface DataColumnProps<TItem = any, TId = any, TFilter = any> extends
*/
isSortable?: boolean;

/** Pass true to make this column always visible and forbid to hide it from columns config dialog */
isAlwaysVisible?: boolean;

/** Makes this column locked, which means that you can't hide, unpin or reorder this column. Usually applicable for such column without which table because useless.
* Note, that isAlwaysVisible column should be always fixed to any side of the table, if you didn't specify `column.fix` prop for such column, 'left' value will be used by default.
* Also, if you have a few isAlwaysVisible columns, it's necessary to place it together in the start or end(depends on `fix` prop) of columns array.
* Note, that isLocked column should be always fixed to any side of the table, if you didn't specify `column.fix` prop for such column, 'left' value will be used by default.
* Also, if you have a few isLocked columns, it's necessary to place it together in the start or end(depends on `fix` prop) of columns array.
* */
isAlwaysVisible?: boolean;
isLocked?: boolean;

/** Makes column hidden by default. User can turn it on later, via ColumnsConfiguration */
isHiddenByDefault?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const ColumnRow = React.memo(function ColumnRow(props: ColumnRowProps<any
label={ props.renderItem ? props.renderItem(props.column) : column.caption }
value={ isVisible }
onValueChange={ toggleVisibility }
isReadonly={ column.isAlwaysVisible }
isReadonly={ column.isAlwaysVisible || column.isLocked }
cx={ css.checkbox }
/>
<FlexRow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const mockColumns: DataColumnProps[] = [
caption: 'ID',
render: (product: any) => <div>{product}</div>,
isSortable: true,
isAlwaysVisible: true,
isLocked: true,
grow: 0,
width: 96,
}, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,77 @@ exports[`ColumnsConfigurationModal should be rendered correctly 1`] = `
</button>
</div>
</div>
</div>
</div>
</div>
<div
className="uui-flex-row root hDivider container align-items-center"
style={
Object {
"columnGap": undefined,
"rowGap": undefined,
}
}
/>
<div
aria-expanded={true}
className="uui-accordion-container container uui-opened subgroupAccordion"
>
<div
className="uui-accordion-toggler uui-opened"
onClick={[Function]}
onKeyDown={[Function]}
tabIndex={0}
>
<div
className="uui-accordion-toggle-container"
>
<div
className="uui-flex-row root rowWrapper container align-items-top"
className="uui-flex-row root uui-size-36 subgroup container align-items-center"
style={
Object {
"columnGap": undefined,
"rowGap": undefined,
}
}
>
<div
className="container uui-icon uui-enabled"
style={Object {}}
>
<svg
className=""
height="18"
width="18"
/>
</div>
<div
className="root uui-text uui-size-none uui-color-tertiary uui-font-weight-400 uui-font-style-normal uui-typography subgroupTitle container"
>
Not pinned
</div>
</div>
<div
className="container uui-icon uui-enabled arrow"
style={Object {}}
/>
</div>
</div>
<div
className="uui-accordion-body"
role="region"
>
<div
className="uui-flex-row root uui-size-30 groupItems container align-items-center"
style={
Object {
"columnGap": undefined,
"rowGap": undefined,
}
}
>
<div
className="uui-flex-row root rowWrapper notPinned container align-items-top"
onPointerEnter={[Function]}
onPointerLeave={[Function]}
onPointerMove={[Function]}
Expand All @@ -338,11 +407,12 @@ exports[`ColumnsConfigurationModal should be rendered correctly 1`] = `
}
>
<div
className="dragHandle dndDisabled container uui-drag-handle uui-disabled"
className="dragHandle container uui-drag-handle"
onPointerDown={[Function]}
onTouchStart={[Function]}
>
<div
className="container uui-icon uui-disabled"
className="container uui-icon uui-enabled"
style={Object {}}
>
<svg
Expand Down Expand Up @@ -389,9 +459,26 @@ exports[`ColumnsConfigurationModal should be rendered correctly 1`] = `
}
>
<button
aria-disabled={true}
className="uui-button-box uui-disabled container uui-icon_button uui-color-primary root pinTogglerIcon"
tabIndex={-1}
aria-disabled={false}
className="uui-button-box uui-enabled -clickable container uui-icon_button uui-color-neutral root pinTogglerIcon"
onClick={[Function]}
tabIndex={0}
type="button"
>
<div
className="container uui-icon uui-enabled"
style={Object {}}
>
<svg
className=""
/>
</div>
</button>
<button
aria-disabled={false}
className="uui-button-box uui-enabled -clickable container uui-icon_button uui-color-neutral root pinTogglerIcon"
onClick={[Function]}
tabIndex={0}
type="button"
>
<div
Expand Down
Loading