feat: disable table features when infinite scroll is enabled (#40020)

This commit is contained in:
Jacques Ikot 2025-04-02 05:11:08 -07:00 committed by GitHub
parent 67ed4cfbdb
commit ca5f66d7dd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 457 additions and 9 deletions

View File

@ -160,6 +160,7 @@ const HeaderCellComponent = (props: HeaderProps) => {
canFreezeColumn,
editMode,
handleColumnFreeze,
isInfiniteScrollEnabled,
isResizingColumn,
isSortable,
multiRowSelection,
@ -193,7 +194,8 @@ const HeaderCellComponent = (props: HeaderProps) => {
sortTableColumn(columnIndex, sortOrder);
};
const disableSort = editMode === false && isSortable === false;
const disableSort =
isInfiniteScrollEnabled || (editMode === false && isSortable === false);
const isColumnEditable =
props.column.columnProperties.isCellEditable &&

View File

@ -1,3 +1,4 @@
import { updateAllowAddNewRowOnInfiniteScrollChange } from "../propertyUtils";
import {
totalRecordsCountValidation,
uniqueColumnNameValidation,
@ -9,6 +10,8 @@ import {
updateCustomColumnAliasOnLabelChange,
selectColumnOptionsValidation,
allowedFirstDayOfWeekRange,
updateCellEditabilityOnInfiniteScrollChange,
updateSearchSortFilterOnInfiniteScrollChange,
} from "../propertyUtils";
import _ from "lodash";
import type { ColumnTypes, TableWidgetProps } from "../../constants";
@ -1049,3 +1052,195 @@ describe("allowedFirstDayOfWeekRange", () => {
});
});
});
describe("Infinite Scroll Update Hooks - ", () => {
it("updateAllowAddNewRowOnInfiniteScrollChange - should disable/enable add new row when infinite scroll is toggled", () => {
const props = {} as TableWidgetProps;
// When infinite scroll is enabled
expect(
updateAllowAddNewRowOnInfiniteScrollChange(
props,
"infiniteScrollEnabled",
true,
),
).toEqual([
{
propertyPath: "allowAddNewRow",
propertyValue: false,
},
]);
// When infinite scroll is disabled
expect(
updateAllowAddNewRowOnInfiniteScrollChange(
props,
"infiniteScrollEnabled",
false,
),
).toEqual([
{
propertyPath: "allowAddNewRow",
propertyValue: true,
},
]);
// When some other value is passed
expect(
updateAllowAddNewRowOnInfiniteScrollChange(
props,
"infiniteScrollEnabled",
"some-other-value",
),
).toBeUndefined();
});
it("updateSearchSortFilterOnInfiniteScrollChange - should disable/enable search, filter, sort when infinite scroll is toggled", () => {
const props = {} as TableWidgetProps;
// When infinite scroll is enabled
expect(
updateSearchSortFilterOnInfiniteScrollChange(
props,
"infiniteScrollEnabled",
true,
),
).toEqual([
{
propertyPath: "isVisibleSearch",
propertyValue: false,
},
{
propertyPath: "isVisibleFilters",
propertyValue: false,
},
{
propertyPath: "isSortable",
propertyValue: false,
},
]);
// When infinite scroll is disabled
expect(
updateSearchSortFilterOnInfiniteScrollChange(
props,
"infiniteScrollEnabled",
false,
),
).toEqual([
{
propertyPath: "isVisibleFilters",
propertyValue: true,
},
{
propertyPath: "isVisibleSearch",
propertyValue: true,
},
{
propertyPath: "isSortable",
propertyValue: true,
},
]);
// When some other value is passed
expect(
updateSearchSortFilterOnInfiniteScrollChange(
props,
"infiniteScrollEnabled",
"some-other-value",
),
).toBeUndefined();
});
it("updateCellEditabilityOnInfiniteScrollChange - should disable cell editability when infinite scroll is enabled", () => {
// Setup mock primary columns
const props = {
primaryColumns: {
column1: {
id: "column1",
alias: "column1",
isEditable: true,
isCellEditable: true,
},
column2: {
id: "column2",
alias: "column2",
isEditable: true,
isCellEditable: true,
},
},
} as unknown as TableWidgetProps;
// When infinite scroll is enabled
expect(
updateCellEditabilityOnInfiniteScrollChange(
props,
"infiniteScrollEnabled",
true,
),
).toEqual([
{
propertyPath: "primaryColumns.column1.isCellEditable",
propertyValue: false,
},
{
propertyPath: "primaryColumns.column1.isEditable",
propertyValue: false,
},
{
propertyPath: "primaryColumns.column2.isCellEditable",
propertyValue: false,
},
{
propertyPath: "primaryColumns.column2.isEditable",
propertyValue: false,
},
]);
// When infinite scroll is disabled
expect(
updateCellEditabilityOnInfiniteScrollChange(
props,
"infiniteScrollEnabled",
false,
),
).toEqual([
{
propertyPath: "primaryColumns.column1.isCellEditable",
propertyValue: true,
},
{
propertyPath: "primaryColumns.column1.isEditable",
propertyValue: true,
},
{
propertyPath: "primaryColumns.column2.isCellEditable",
propertyValue: true,
},
{
propertyPath: "primaryColumns.column2.isEditable",
propertyValue: true,
},
]);
// Test with no primary columns
const propsWithoutColumns = {} as TableWidgetProps;
expect(
updateCellEditabilityOnInfiniteScrollChange(
propsWithoutColumns,
"infiniteScrollEnabled",
true,
),
).toBeUndefined();
// When some other value is passed
expect(
updateCellEditabilityOnInfiniteScrollChange(
props,
"infiniteScrollEnabled",
"some-other-value",
),
).toBeUndefined();
});
});

View File

@ -0,0 +1,114 @@
import contentConfig from "../contentConfig";
import type { TableWidgetProps } from "../../../constants";
import type { PropertyPaneSectionConfig } from "constants/PropertyControlConstants";
describe("TableWidgetV2 contentConfig tests", () => {
it("should disable relevant sections when infinite scroll is enabled", () => {
const sectionsToCheck = ["Search & filters", "Sorting", "Adding a row"];
const disabledHelpText =
"This feature is disabled because infinite scroll is enabled";
sectionsToCheck.forEach((sectionName) => {
const section = contentConfig.find(
(section) =>
(section as PropertyPaneSectionConfig).sectionName === sectionName,
) as PropertyPaneSectionConfig & { dependencies: string[] };
expect(section).toBeDefined();
if (section) {
expect(typeof section.shouldDisableSection).toBe("function");
expect(section.disabledHelpText).toBe(disabledHelpText);
expect(section.dependencies).toContain("infiniteScrollEnabled");
const enabledProps = {
infiniteScrollEnabled: true,
} as TableWidgetProps;
const disabledProps = {
infiniteScrollEnabled: false,
} as TableWidgetProps;
expect(section.shouldDisableSection!(enabledProps, "")).toBe(true);
expect(section.shouldDisableSection!(disabledProps, "")).toBe(false);
}
});
const paginationSection = contentConfig.find(
(section) =>
(section as PropertyPaneSectionConfig).sectionName === "Pagination",
) as PropertyPaneSectionConfig;
expect(paginationSection).toBeDefined();
if (paginationSection && paginationSection.children) {
const serverSidePagination = paginationSection.children.find(
(child) =>
(child as PropertyPaneSectionConfig & { propertyName: string })
.propertyName === "serverSidePaginationEnabled",
) as PropertyPaneSectionConfig & {
propertyName: string;
shouldDisableSection: (
props: TableWidgetProps,
propertyPath: string,
) => boolean;
disabledHelpText: string;
dependencies: string[];
};
expect(serverSidePagination).toBeDefined();
if (serverSidePagination) {
expect(typeof serverSidePagination.shouldDisableSection).toBe(
"function",
);
expect(serverSidePagination.disabledHelpText).toBe(disabledHelpText);
expect(serverSidePagination.dependencies).toContain(
"infiniteScrollEnabled",
);
const enabledProps = {
infiniteScrollEnabled: true,
} as TableWidgetProps;
const disabledProps = {
infiniteScrollEnabled: false,
} as TableWidgetProps;
expect(
serverSidePagination.shouldDisableSection(enabledProps, ""),
).toBe(true);
expect(
serverSidePagination.shouldDisableSection(disabledProps, ""),
).toBe(false);
}
}
});
it("should have proper update hooks for infiniteScrollEnabled property", () => {
const paginationSection = contentConfig.find(
(section) =>
(section as PropertyPaneSectionConfig).sectionName === "Pagination",
) as PropertyPaneSectionConfig;
expect(paginationSection).toBeDefined();
if (paginationSection && paginationSection.children) {
const infiniteScrollProperty = paginationSection.children.find(
(child) =>
(child as PropertyPaneSectionConfig & { propertyName: string })
.propertyName === "infiniteScrollEnabled",
) as PropertyPaneSectionConfig & {
propertyName: string;
updateHook: unknown;
dependencies: string[];
};
expect(infiniteScrollProperty).toBeDefined();
if (infiniteScrollProperty) {
expect(infiniteScrollProperty.updateHook).toBeDefined();
expect(infiniteScrollProperty.dependencies).toContain("primaryColumns");
}
}
});
});

View File

@ -1,30 +1,38 @@
import type { PropertyPaneConfig } from "constants/PropertyControlConstants";
import { ValidationTypes } from "constants/WidgetValidation";
import {
createMessage,
TABLE_WIDGET_TOTAL_RECORD_TOOLTIP,
} from "ee/constants/messages";
import type { PropertyPaneConfig } from "constants/PropertyControlConstants";
import { ValidationTypes } from "constants/WidgetValidation";
import { EvaluationSubstitutionType } from "ee/entities/DataTree/types";
import { AutocompleteDataType } from "utils/autocomplete/AutocompleteDataType";
import type { TableWidgetProps } from "widgets/TableWidgetV2/constants";
import {
INFINITE_SCROLL_ENABLED,
InlineEditingSaveOptions,
} from "widgets/TableWidgetV2/constants";
import { composePropertyUpdateHook } from "widgets/WidgetUtils";
import {
ALLOW_TABLE_WIDGET_SERVER_SIDE_FILTERING,
CUSTOM_SORT_FUNCTION_ENABLED,
} from "../../constants";
import { InlineEditingSaveOptions } from "widgets/TableWidgetV2/constants";
import { composePropertyUpdateHook } from "widgets/WidgetUtils";
import Widget from "../index";
import {
tableDataValidation,
totalRecordsCountValidation,
uniqueColumnNameValidation,
updateAllowAddNewRowOnInfiniteScrollChange,
updateCellEditabilityOnInfiniteScrollChange,
updateColumnOrderHook,
updateCustomColumnAliasOnLabelChange,
updateInlineEditingOptionDropdownVisibilityHook,
updateInlineEditingSaveOptionHook,
updateSearchSortFilterOnInfiniteScrollChange,
} from "../propertyUtils";
import panelConfig from "./PanelConfig";
import Widget from "../index";
import { INFINITE_SCROLL_ENABLED } from "../../constants";
const INFINITE_SCROLL_DISABLED_HELP_TEXT =
"This feature is disabled because infinite scroll is enabled";
export default [
{
@ -165,8 +173,6 @@ export default [
isBindProperty: true,
isTriggerProperty: false,
validation: { type: ValidationTypes.BOOLEAN },
hidden: (props: TableWidgetProps) => props.infiniteScrollEnabled,
dependencies: ["infiniteScrollEnabled"],
},
{
helpText:
@ -176,6 +182,10 @@ export default [
controlType: "SWITCH",
isBindProperty: false,
isTriggerProperty: false,
shouldDisableSection: (props: TableWidgetProps) =>
props.infiniteScrollEnabled,
disabledHelpText: INFINITE_SCROLL_DISABLED_HELP_TEXT,
dependencies: ["infiniteScrollEnabled"],
},
{
helpText:
@ -185,6 +195,12 @@ export default [
controlType: "SWITCH",
isBindProperty: false,
isTriggerProperty: false,
updateHook: composePropertyUpdateHook([
updateAllowAddNewRowOnInfiniteScrollChange,
updateCellEditabilityOnInfiniteScrollChange,
updateSearchSortFilterOnInfiniteScrollChange,
]),
dependencies: ["primaryColumns"],
hidden: () => !Widget.getFeatureFlag(INFINITE_SCROLL_ENABLED),
},
{
@ -236,6 +252,10 @@ export default [
},
{
sectionName: "Search & filters",
shouldDisableSection: (props: TableWidgetProps) =>
props.infiniteScrollEnabled,
disabledHelpText: INFINITE_SCROLL_DISABLED_HELP_TEXT,
dependencies: ["infiniteScrollEnabled"],
children: [
{
propertyName: "isVisibleSearch",
@ -385,6 +405,10 @@ export default [
},
{
sectionName: "Sorting",
shouldDisableSection: (props: TableWidgetProps) =>
props.infiniteScrollEnabled,
disabledHelpText: INFINITE_SCROLL_DISABLED_HELP_TEXT,
dependencies: ["infiniteScrollEnabled"],
children: [
{
helpText: "Controls sorting in View Mode",
@ -438,6 +462,10 @@ export default [
{
sectionName: "Adding a row",
shouldDisableSection: (props: TableWidgetProps) =>
props.infiniteScrollEnabled,
disabledHelpText: INFINITE_SCROLL_DISABLED_HELP_TEXT,
dependencies: ["infiniteScrollEnabled"],
children: [
{
propertyName: "allowAddNewRow",

View File

@ -1447,3 +1447,112 @@ export function colorForEachRowValidation(
return generateResponseAndReturn(false, DEFAULT_MESSAGE);
}
// Infinite scroll not supported for add new row yet
export const updateAllowAddNewRowOnInfiniteScrollChange = (
props: TableWidgetProps,
propertyPath: string,
propertyValue: unknown,
): Array<{ propertyPath: string; propertyValue: unknown }> | undefined => {
if (propertyValue === true) {
return [
{
propertyPath: "allowAddNewRow",
propertyValue: false,
},
];
} else if (propertyValue === false) {
return [
{
propertyPath: "allowAddNewRow",
propertyValue: true,
},
];
}
return;
};
// Infinite scroll not supported for search, sort and filters yet
export const updateSearchSortFilterOnInfiniteScrollChange = (
props: TableWidgetProps,
propertyPath: string,
propertyValue: unknown,
): Array<{ propertyPath: string; propertyValue: unknown }> | undefined => {
if (propertyValue === true) {
return [
{
propertyPath: "isVisibleSearch",
propertyValue: false,
},
{
propertyPath: "isVisibleFilters",
propertyValue: false,
},
{
propertyPath: "isSortable",
propertyValue: false,
},
];
} else if (propertyValue === false) {
return [
{
propertyPath: "isVisibleFilters",
propertyValue: true,
},
{
propertyPath: "isVisibleSearch",
propertyValue: true,
},
{
propertyPath: "isSortable",
propertyValue: true,
},
];
}
return;
};
// Disable cell editability when infinite scroll is enabled
export const updateCellEditabilityOnInfiniteScrollChange = (
props: TableWidgetProps,
propertyPath: string,
propertyValue: unknown,
): Array<{ propertyPath: string; propertyValue: unknown }> | undefined => {
if (!props.primaryColumns) return;
const updates: Array<{ propertyPath: string; propertyValue: unknown }> = [];
if (propertyValue === true) {
Object.entries(props.primaryColumns).forEach(([, column]) => {
const columnName = column.alias;
updates.push({
propertyPath: `primaryColumns.${columnName}.isCellEditable`,
propertyValue: false,
});
updates.push({
propertyPath: `primaryColumns.${columnName}.isEditable`,
propertyValue: false,
});
});
} else if (propertyValue === false) {
Object.entries(props.primaryColumns).forEach(([, column]) => {
const columnName = column.alias;
updates.push({
propertyPath: `primaryColumns.${columnName}.isCellEditable`,
propertyValue: true,
});
updates.push({
propertyPath: `primaryColumns.${columnName}.isEditable`,
propertyValue: true,
});
});
}
return updates.length > 0 ? updates : undefined;
};