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
3 changes: 3 additions & 0 deletions app/client/src/ce/entities/FeatureFlag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export const FEATURE_FLAG = {
release_anvil_toggle_enabled: "release_anvil_toggle_enabled",
release_git_persist_branch_enabled: "release_git_persist_branch_enabled",
release_ide_animations_enabled: "release_ide_animations_enabled",
release_table_custom_loading_state_enabled:
"release_table_custom_loading_state_enabled",
} as const;

export type FeatureFlag = keyof typeof FEATURE_FLAG;
Expand Down Expand Up @@ -74,6 +76,7 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = {
release_anvil_toggle_enabled: false,
release_git_persist_branch_enabled: false,
release_ide_animations_enabled: false,
release_table_custom_loading_state_enabled: false,
};

export const AB_TESTING_EVENT_KEYS = {
Expand Down
5 changes: 5 additions & 0 deletions app/client/src/widgets/TableWidgetV2/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ export interface TableWidgetProps
firstEditableColumnIdByOrder: string;
enableServerSideFiltering: boolean;
onTableFilterUpdate: string;
customIsLoading: boolean;
customIsLoadingValue: boolean;
}

export enum TableVariantTypes {
Expand Down Expand Up @@ -237,3 +239,6 @@ export const DEFAULT_COLUMN_NAME = "Table Column";

export const ALLOW_TABLE_WIDGET_SERVER_SIDE_FILTERING =
FEATURE_FLAG["release_table_serverside_filtering_enabled"];

export const CUSTOM_LOADING_STATE_ENABLED =
FEATURE_FLAG["release_table_custom_loading_state_enabled"];
181 changes: 181 additions & 0 deletions app/client/src/widgets/TableWidgetV2/widget/TableRendered.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import { ResponsiveBehavior } from "layoutSystems/common/utils/constants";
import TableWidgetV2 from ".";
import type { TableWidgetProps } from "../constants";

describe("TableWidgetV2 getWidgetView", () => {
const tableWidgetProps: TableWidgetProps = {
customIsLoading: false,
customIsLoadingValue: false,
delimiter: ",",
filteredTableData: [],
isVisibleDownload: true,
isVisibleFilters: true,
isVisiblePagination: true,
isVisibleSearch: true,
pageSize: 10,
primaryColumns: {},
totalRecordsCount: 100,
accentColor: "#000000",
borderColor: "#000000",
borderRadius: "40px",
borderWidth: "1px",
boxShadow: "none",
canFreezeColumn: true,
columnWidthMap: {},
compactMode: "DEFAULT",
filters: [],
isAddRowInProgress: false,
isEditableCellsValid: {},
isLoading: false,
isSortable: true,
multiRowSelection: false,
pageNo: 1,
renderMode: "CANVAS",
searchText: "",
selectedRowIndex: -1,
selectedRowIndices: [],
serverSidePaginationEnabled: false,
tableData: [],
widgetId: "widgetId",
widgetName: "TableWidget",
componentWidth: 800,
componentHeight: 600,
onPageChange: "",
onSearchTextChanged: "",
onSort: "",
onRowSelected: "",
onAddNewRowSave: "",
onAddNewRowDiscard: "",
onBulkSave: "",
onBulkDiscard: "",
onPageSizeChange: "",
commitBatchMetaUpdates: jest.fn(),
pushBatchMetaUpdates: jest.fn(),
updateWidgetMetaProperty: jest.fn(),
updateWidgetProperty: "",
updateOneClickBindingOptionsVisibility: "",
// Added missing properties
primaryColumnId: "",
columnOrder: [],
derivedColumns: {},
dynamicPropertyPathList: [],
dynamicTriggerPathList: [],
dynamicBindingPathList: [],
childStylesheet: {},
isVisible: true,
version: 1,
parentColumnSpace: 1,
parentRowSpace: 1,
leftColumn: 0,
rightColumn: 0,
topRow: 0,
bottomRow: 0,
parentId: "",
responsiveBehavior: ResponsiveBehavior.Hug,
minWidth: 0,
minHeight: 0,
isDisabled: false,
animateLoading: false,
primaryColor: "",
backgroundColor: "",
textColor: "",
fontFamily: "",
fontSize: "",
fontStyle: "",
textAlign: "",
textDecoration: "",
textTransform: "",
letterSpacing: "",
lineHeight: "",
whiteSpace: "",
overflow: "",
textOverflow: "",
wordBreak: "",
wordWrap: "",
cursor: "",
zIndex: 0,
pristine: true,
label: "TableWidget",
defaultSearchText: "",
sortOrder: { column: "", order: null },
transientTableData: { data: { name: "name" } },
newRow: {},
firstEditableColumnIdByOrder: "",
enableServerSideFiltering: false,
onTableFilterUpdate: "",
type: "",
allowAddNewRow: false,
defaultNewRow: {},
frozenColumnIndices: { a: 1 },
};

describe("TableWidgetV2 loading checks", () => {
describe("When custom loading logic is not provided", () => {
it("Should not be loading with built-in property isLoading is set to false", () => {
const tableWidget = new TableWidgetV2(tableWidgetProps);
const widgetView = tableWidget.getWidgetView();

expect(widgetView.props.children.props.isLoading).toBe(false);
});
it("Should be loading with built-in property isLoading is set to true", () => {
const tableWidget = new TableWidgetV2({
...tableWidgetProps,
isLoading: true,
});
const widgetView = tableWidget.getWidgetView();

expect(widgetView.props.children.props.isLoading).toBe(true);
});
});
describe("When custom loading logic is provided", () => {
describe("When isLoading is false", () => {
it("Should not be loading with isLoading: false, customIsLoading: true and customIsLoadingTrue: true", () => {
const tableWidget = new TableWidgetV2({
...tableWidgetProps,
customIsLoading: true,
customIsLoadingValue: false,
isLoading: false,
});
const widgetView = tableWidget.getWidgetView();

expect(widgetView.props.children.props.isLoading).toBe(false);
});
it("Should be loading with customIsLoading set to true and customIsLoadingTrue set to true", () => {
const tableWidget = new TableWidgetV2({
...tableWidgetProps,
customIsLoading: true,
customIsLoadingValue: true,
isLoading: false,
});
const widgetView = tableWidget.getWidgetView();

expect(widgetView.props.children.props.isLoading).toBe(true);
});
});
describe("When isLoading is true", () => {
it("Should be loading with customIsLoading set to true and customIsLoadingTrue set to false", () => {
const tableWidget = new TableWidgetV2({
...tableWidgetProps,
customIsLoading: true,
customIsLoadingValue: false,
isLoading: true,
});
const widgetView = tableWidget.getWidgetView();

expect(widgetView.props.children.props.isLoading).toBe(true);
});
it("Should be loading with customIsLoading set to true and customIsLoadingTrue set to true, even if in built loading is false", () => {
const tableWidget = new TableWidgetV2({
...tableWidgetProps,
customIsLoading: true,
customIsLoadingValue: true,
isLoading: true,
});
const widgetView = tableWidget.getWidgetView();

expect(widgetView.props.children.props.isLoading).toBe(true);
});
});
});
});
});
10 changes: 9 additions & 1 deletion app/client/src/widgets/TableWidgetV2/widget/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ class TableWidgetV2 extends BaseWidget<TableWidgetProps, WidgetState> {
)
? false
: undefined,
customIsLoading: false,
customIsLoadingValue: "",
};
}

Expand Down Expand Up @@ -1211,6 +1213,8 @@ class TableWidgetV2 extends BaseWidget<TableWidgetProps, WidgetState> {

getWidgetView() {
const {
customIsLoading,
customIsLoadingValue,
delimiter,
filteredTableData = [],
isVisibleDownload,
Expand Down Expand Up @@ -1266,7 +1270,11 @@ class TableWidgetV2 extends BaseWidget<TableWidgetProps, WidgetState> {
height={componentHeight}
isAddRowInProgress={this.props.isAddRowInProgress}
isEditableCellsValid={this.props.isEditableCellsValid}
isLoading={this.props.isLoading}
isLoading={
customIsLoading
? customIsLoadingValue || this.props.isLoading
: this.props.isLoading
}
isSortable={this.props.isSortable ?? true}
isVisibleDownload={isVisibleDownload}
isVisibleFilters={isVisibleFilters}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import { ValidationTypes } from "constants/WidgetValidation";
import { EvaluationSubstitutionType } from "entities/DataTree/dataTreeFactory";
import { AutocompleteDataType } from "utils/autocomplete/AutocompleteDataType";
import type { TableWidgetProps } from "widgets/TableWidgetV2/constants";
import { ALLOW_TABLE_WIDGET_SERVER_SIDE_FILTERING } from "../../constants";
import {
ALLOW_TABLE_WIDGET_SERVER_SIDE_FILTERING,
CUSTOM_LOADING_STATE_ENABLED,
} from "../../constants";
import { InlineEditingSaveOptions } from "widgets/TableWidgetV2/constants";
import { composePropertyUpdateHook } from "widgets/WidgetUtils";
import {
Expand Down Expand Up @@ -494,13 +497,35 @@ export default [
propertyName: "animateLoading",
label: "Animate loading",
controlType: "SWITCH",
helpText: "Controls the loading of the widget",
helpText: "Controls the animation loading of the widget",
defaultValue: true,
isJSConvertible: true,
isBindProperty: true,
isTriggerProperty: false,
validation: { type: ValidationTypes.BOOLEAN },
},
{
propertyName: "customIsLoading",
label: `Custom loading state`,
controlType: "SWITCH",
helpText: "Defines a custom value for the loading state",
defaultValue: false,
isBindProperty: true,
isTriggerProperty: false,
validation: { type: ValidationTypes.BOOLEAN },
hidden: () => !Widget.getFeatureFlag(CUSTOM_LOADING_STATE_ENABLED),
},
{
propertyName: "customIsLoadingValue",
label: "isLoading value",
controlType: "INPUT_TEXT",
defaultValue: "",
isBindProperty: true,
isTriggerProperty: false,
validation: { type: ValidationTypes.BOOLEAN },
hidden: (props: TableWidgetProps) => !props.customIsLoading,
dependencies: ["customIsLoading"],
},
Comment on lines +519 to +528
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Mismatch between controlType and validation for customIsLoadingValue.

The controlType is set to "INPUT_TEXT" but the validation expects a BOOLEAN. Consider updating the controlType to "SWITCH" or adjusting the validation accordingly.

Apply this diff to resolve the mismatch:

            propertyName: "customIsLoadingValue",
            label: "isLoading value",
-           controlType: "INPUT_TEXT",
+           controlType: "SWITCH",
            defaultValue: "",
            isBindProperty: true,
            isTriggerProperty: false,
            validation: { type: ValidationTypes.BOOLEAN },
            hidden: (props: TableWidgetProps) => !props.customIsLoading,
            dependencies: ["customIsLoading"],
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
propertyName: "customIsLoadingValue",
label: "isLoading value",
controlType: "INPUT_TEXT",
defaultValue: "",
isBindProperty: true,
isTriggerProperty: false,
validation: { type: ValidationTypes.BOOLEAN },
hidden: (props: TableWidgetProps) => !props.customIsLoading,
dependencies: ["customIsLoading"],
},
propertyName: "customIsLoadingValue",
label: "isLoading value",
controlType: "SWITCH",
defaultValue: "",
isBindProperty: true,
isTriggerProperty: false,
validation: { type: ValidationTypes.BOOLEAN },
hidden: (props: TableWidgetProps) => !props.customIsLoading,
dependencies: ["customIsLoading"],
},

{
propertyName: "isVisibleDownload",
helpText: "Toggle visibility of the data download",
Expand Down