diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Text_new_feature_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Text_new_feature_spec.js index bd1a69cd45..34ccf763e8 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Text_new_feature_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Text_new_feature_spec.js @@ -118,9 +118,13 @@ describe("Text Widget color/font/alignment Functionality", function() { }); it("Test to validate enable scroll feature", function() { - cy.get(".t--property-control-enablescroll .bp3-switch").click({ - force: true, - }); + cy.selectDropdownValue( + commonlocators.textOverflowDropdown, + "Scroll contents", + ); + cy.get(commonlocators.textOverflowDropdown) + .last() + .should("have.text", "Scroll contents"); cy.wait("@updateLayout"); cy.get(commonlocators.headingTextStyle).trigger("mouseover", { force: true, diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Text_truncate_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Text_truncate_spec.js index 82df5532a9..6df1f7419c 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Text_truncate_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Text_truncate_spec.js @@ -1,10 +1,19 @@ const dsl = require("../../../../fixtures/textNewDsl.json"); +const commonlocators = require("../../../../locators/commonlocators.json"); describe("Text Widget Truncate Functionality", function() { before(() => { cy.addDsl(dsl); }); + it("Check default overflow property is No overflow", function() { + cy.openPropertyPane("textwidget"); + cy.get(commonlocators.textOverflowDropdown) + .last() + .should("have.text", "No overflow"); + cy.closePropertyPane(); + }); + it("Validate long text is not truncating in default", function() { cy.get( `.appsmith_widget_${dsl.dsl.children[0].widgetId} .t--draggable-textwidget`, @@ -23,7 +32,13 @@ describe("Text Widget Truncate Functionality", function() { }); it("Enable Truncate Text option and Validate", function() { - cy.get(".t--property-control-truncatetext > .bp3-switch").click(); + cy.selectDropdownValue( + commonlocators.textOverflowDropdown, + "Truncate text", + ); + cy.get(commonlocators.textOverflowDropdown) + .last() + .should("have.text", "Truncate text"); cy.wait("@updateLayout"); cy.get( `.appsmith_widget_${dsl.dsl.children[0].widgetId} .t--widget-textwidget-truncate`, diff --git a/app/client/cypress/locators/commonlocators.json b/app/client/cypress/locators/commonlocators.json index b353611edf..fe6166b562 100644 --- a/app/client/cypress/locators/commonlocators.json +++ b/app/client/cypress/locators/commonlocators.json @@ -118,6 +118,7 @@ "filePickerOnFilesSelected": ".t--property-control-onfilesselected", "dataType": ".t--property-control-datatype .bp3-popover-target", "recaptchaVersion": ".t--property-control-googlerecaptchaversion .bp3-popover-target", + "textOverflowDropdown": ".t--property-control-overflow .bp3-popover-target", "jsonFormFieldType": ".t--property-control-fieldtype .bp3-popover-target", "jsonFormAddNewCustomFieldBtn": ".t--property-control-fieldconfiguration .t--add-column-btn", "evaluateMsg": ".t--evaluatedPopup-error", diff --git a/app/client/src/constants/WidgetConstants.tsx b/app/client/src/constants/WidgetConstants.tsx index 5814880889..828f8e7c9b 100644 --- a/app/client/src/constants/WidgetConstants.tsx +++ b/app/client/src/constants/WidgetConstants.tsx @@ -69,7 +69,7 @@ export const layoutConfigurations: LayoutConfigurations = { FLUID: { minWidth: -1, maxWidth: -1 }, }; -export const LATEST_PAGE_VERSION = 53; +export const LATEST_PAGE_VERSION = 54; export const GridDefaults = { DEFAULT_CELL_SIZE: 1, diff --git a/app/client/src/utils/DSLMigrations.ts b/app/client/src/utils/DSLMigrations.ts index 5456b852a5..e2a3f6a946 100644 --- a/app/client/src/utils/DSLMigrations.ts +++ b/app/client/src/utils/DSLMigrations.ts @@ -26,7 +26,10 @@ import { isSortableMigration, migrateTableWidgetIconButtonVariant, } from "./migrations/TableWidget"; -import { migrateTextStyleFromTextWidget } from "./migrations/TextWidgetReplaceTextStyle"; +import { + migrateTextStyleFromTextWidget, + migrateScrollTruncateProperties, +} from "./migrations/TextWidget"; import { DATA_BIND_REGEX_GLOBAL } from "constants/BindingsConstants"; import { theme } from "constants/DefaultTheme"; import { getCanvasSnapRows } from "./WidgetPropsUtils"; @@ -1056,6 +1059,11 @@ export const transformDSL = ( if (currentDSL.version === 52) { currentDSL = migrateModalIconButtonWidget(currentDSL); + currentDSL.version = 53; + } + + if (currentDSL.version === 53) { + currentDSL = migrateScrollTruncateProperties(currentDSL); currentDSL.version = LATEST_PAGE_VERSION; } diff --git a/app/client/src/utils/DSLMigrationsUtils.test.ts b/app/client/src/utils/DSLMigrationsUtils.test.ts index ec9df808f0..54511dc65b 100644 --- a/app/client/src/utils/DSLMigrationsUtils.test.ts +++ b/app/client/src/utils/DSLMigrationsUtils.test.ts @@ -2,6 +2,7 @@ import { transformDSL } from "./DSLMigrations"; import { LATEST_PAGE_VERSION, RenderModes } from "constants/WidgetConstants"; import { ContainerWidgetProps } from "widgets/ContainerWidget/widget"; import { WidgetProps } from "widgets/BaseWidget"; +import { OverflowTypes } from "widgets/TextWidget/constants"; describe("correctly migrate dsl", () => { it("AddsPrivateWidgetsToAllListWidgets", () => { @@ -975,7 +976,6 @@ describe("correctly migrate dsl", () => { }, ], leftColumn: 16, - shouldTruncate: false, truncateButtonColor: "#FFC13D", text: "{{currentItem.name}}", key: "yd217bk315", @@ -1019,7 +1019,7 @@ describe("correctly migrate dsl", () => { isVisible: true, fontStyle: "BOLD", textColor: "#231F20", - shouldScroll: false, + overflow: OverflowTypes.NONE, version: 1, parentId: "vqn2okwc6a", renderMode: "CANVAS", @@ -1043,7 +1043,6 @@ describe("correctly migrate dsl", () => { }, ], leftColumn: 16, - shouldTruncate: false, truncateButtonColor: "#FFC13D", text: "{{currentItem.id}}", key: "yd217bk315", @@ -1087,7 +1086,7 @@ describe("correctly migrate dsl", () => { isVisible: true, fontStyle: "BOLD", textColor: "#231F20", - shouldScroll: false, + overflow: OverflowTypes.NONE, version: 1, parentId: "vqn2okwc6a", renderMode: "CANVAS", diff --git a/app/client/src/utils/migrations/TextWidget.test.ts b/app/client/src/utils/migrations/TextWidget.test.ts new file mode 100644 index 0000000000..af8f2bed89 --- /dev/null +++ b/app/client/src/utils/migrations/TextWidget.test.ts @@ -0,0 +1,618 @@ +import { + migrateTextStyleFromTextWidget, + migrateScrollTruncateProperties, +} from "utils/migrations/TextWidget"; +import { FontStyleTypes, TextSizes } from "constants/WidgetConstants"; +import { DSLWidget } from "widgets/constants"; +import { OverflowTypes } from "widgets/TextWidget/constants"; + +const inputDsl1: DSLWidget = { + widgetName: "MainContainer", + backgroundColor: "none", + rightColumn: 1118, + snapColumns: 16, + detachFromLayout: true, + widgetId: "0", + topRow: 0, + bottomRow: 1280, + containerStyle: "none", + snapRows: 33, + parentRowSpace: 1, + type: "CANVAS_WIDGET", + canExtend: true, + version: 15, + minHeight: 1292, + parentColumnSpace: 1, + dynamicTriggerPathList: [], + dynamicBindingPathList: [], + leftColumn: 0, + isLoading: false, + parentId: "", + renderMode: "CANVAS", + children: [ + { + isVisible: true, + text: "Label", + textStyle: "LABEL", + textAlign: "LEFT", + widgetName: "Text1", + version: 1, + type: "TEXT_WIDGET", + isLoading: false, + parentColumnSpace: 67.375, + parentRowSpace: 40, + leftColumn: 3, + rightColumn: 7, + topRow: 1, + bottomRow: 2, + parentId: "0", + widgetId: "yf8bhokz7d", + dynamicBindingPathList: [], + renderMode: "CANVAS", + }, + ], +}; + +const inputDsl2: DSLWidget = { + widgetName: "MainContainer", + backgroundColor: "none", + rightColumn: 1118, + snapColumns: 16, + detachFromLayout: true, + widgetId: "0", + topRow: 0, + bottomRow: 1280, + containerStyle: "none", + snapRows: 33, + parentRowSpace: 1, + type: "CANVAS_WIDGET", + canExtend: true, + version: 15, + minHeight: 1292, + parentColumnSpace: 1, + dynamicTriggerPathList: [], + dynamicBindingPathList: [], + leftColumn: 0, + isLoading: false, + parentId: "", + renderMode: "CANVAS", + children: [ + { + isVisible: true, + text: "Label", + textStyle: "HEADING", + textAlign: "LEFT", + widgetName: "Text1", + version: 1, + type: "TEXT_WIDGET", + isLoading: false, + parentColumnSpace: 67.375, + parentRowSpace: 40, + leftColumn: 3, + rightColumn: 7, + topRow: 1, + bottomRow: 2, + parentId: "0", + widgetId: "yf8bhokz7d", + dynamicBindingPathList: [], + renderMode: "CANVAS", + }, + ], +}; + +const inputDsl3: DSLWidget = { + widgetName: "MainContainer", + backgroundColor: "none", + rightColumn: 1118, + snapColumns: 16, + detachFromLayout: true, + widgetId: "0", + topRow: 0, + bottomRow: 1280, + containerStyle: "none", + snapRows: 33, + parentRowSpace: 1, + type: "CANVAS_WIDGET", + canExtend: true, + version: 15, + minHeight: 1292, + parentColumnSpace: 1, + dynamicTriggerPathList: [], + dynamicBindingPathList: [], + leftColumn: 0, + isLoading: false, + parentId: "", + renderMode: "CANVAS", + children: [ + { + isVisible: true, + text: "Label", + textStyle: "BODY", + textAlign: "LEFT", + widgetName: "Text1", + version: 1, + type: "TEXT_WIDGET", + isLoading: false, + parentColumnSpace: 67.375, + parentRowSpace: 40, + leftColumn: 3, + rightColumn: 7, + topRow: 1, + bottomRow: 2, + parentId: "0", + widgetId: "yf8bhokz7d", + dynamicBindingPathList: [], + renderMode: "CANVAS", + }, + ], +}; + +const outputDsl1: DSLWidget = { + widgetName: "MainContainer", + backgroundColor: "none", + rightColumn: 1118, + snapColumns: 16, + detachFromLayout: true, + widgetId: "0", + topRow: 0, + bottomRow: 1280, + containerStyle: "none", + snapRows: 33, + parentRowSpace: 1, + type: "CANVAS_WIDGET", + canExtend: true, + version: 15, + minHeight: 1292, + parentColumnSpace: 1, + dynamicTriggerPathList: [], + dynamicBindingPathList: [], + leftColumn: 0, + isLoading: false, + parentId: "", + renderMode: "CANVAS", + children: [ + { + isVisible: true, + text: "Label", + textAlign: "LEFT", + widgetName: "Text1", + version: 1, + type: "TEXT_WIDGET", + isLoading: false, + parentColumnSpace: 67.375, + parentRowSpace: 40, + leftColumn: 3, + rightColumn: 7, + topRow: 1, + bottomRow: 2, + parentId: "0", + widgetId: "yf8bhokz7d", + dynamicBindingPathList: [], + fontSize: TextSizes.PARAGRAPH, + fontStyle: FontStyleTypes.BOLD, + renderMode: "CANVAS", + }, + ], +}; + +const outputDsl2: DSLWidget = { + widgetName: "MainContainer", + backgroundColor: "none", + rightColumn: 1118, + snapColumns: 16, + detachFromLayout: true, + widgetId: "0", + topRow: 0, + bottomRow: 1280, + containerStyle: "none", + snapRows: 33, + parentRowSpace: 1, + type: "CANVAS_WIDGET", + canExtend: true, + version: 15, + minHeight: 1292, + parentColumnSpace: 1, + dynamicTriggerPathList: [], + dynamicBindingPathList: [], + leftColumn: 0, + isLoading: false, + parentId: "", + renderMode: "CANVAS", + children: [ + { + isVisible: true, + text: "Label", + textAlign: "LEFT", + widgetName: "Text1", + version: 1, + type: "TEXT_WIDGET", + isLoading: false, + parentColumnSpace: 67.375, + parentRowSpace: 40, + leftColumn: 3, + rightColumn: 7, + topRow: 1, + bottomRow: 2, + parentId: "0", + widgetId: "yf8bhokz7d", + dynamicBindingPathList: [], + fontSize: TextSizes.HEADING1, + fontStyle: FontStyleTypes.BOLD, + renderMode: "CANVAS", + }, + ], +}; + +const outputDsl3: DSLWidget = { + widgetName: "MainContainer", + backgroundColor: "none", + rightColumn: 1118, + snapColumns: 16, + detachFromLayout: true, + widgetId: "0", + topRow: 0, + bottomRow: 1280, + containerStyle: "none", + snapRows: 33, + parentRowSpace: 1, + type: "CANVAS_WIDGET", + canExtend: true, + version: 15, + minHeight: 1292, + parentColumnSpace: 1, + dynamicTriggerPathList: [], + dynamicBindingPathList: [], + leftColumn: 0, + isLoading: false, + parentId: "", + renderMode: "CANVAS", + children: [ + { + isVisible: true, + text: "Label", + textAlign: "LEFT", + widgetName: "Text1", + version: 1, + type: "TEXT_WIDGET", + isLoading: false, + parentColumnSpace: 67.375, + parentRowSpace: 40, + leftColumn: 3, + rightColumn: 7, + topRow: 1, + bottomRow: 2, + parentId: "0", + widgetId: "yf8bhokz7d", + dynamicBindingPathList: [], + fontSize: TextSizes.PARAGRAPH, + renderMode: "CANVAS", + }, + ], +}; + +describe("Text Widget Property Pane Upgrade", () => { + it("To test text widget textStyle property is migrated", () => { + const newDsl = migrateTextStyleFromTextWidget(inputDsl1); + expect(JSON.stringify(newDsl) === JSON.stringify(outputDsl1)); + }); + it("To test text widget textStyle property is migrated", () => { + const newDsl = migrateTextStyleFromTextWidget(inputDsl2); + expect(JSON.stringify(newDsl) === JSON.stringify(outputDsl2)); + }); + it("To test text widget textStyle property is migrated", () => { + const newDsl = migrateTextStyleFromTextWidget(inputDsl3); + expect(JSON.stringify(newDsl) === JSON.stringify(outputDsl3)); + }); +}); + +const inputDsl4: DSLWidget = { + widgetName: "MainContainer", + backgroundColor: "none", + rightColumn: 1118, + snapColumns: 16, + detachFromLayout: true, + widgetId: "0", + topRow: 0, + bottomRow: 1280, + containerStyle: "none", + snapRows: 33, + parentRowSpace: 1, + type: "CANVAS_WIDGET", + canExtend: true, + version: 15, + minHeight: 1292, + parentColumnSpace: 1, + dynamicTriggerPathList: [], + dynamicBindingPathList: [], + leftColumn: 0, + isLoading: false, + parentId: "", + renderMode: "CANVAS", + children: [ + { + isVisible: true, + text: "Label", + textAlign: "LEFT", + widgetName: "Text1", + version: 1, + type: "TEXT_WIDGET", + isLoading: false, + parentColumnSpace: 67.375, + parentRowSpace: 40, + leftColumn: 3, + rightColumn: 7, + topRow: 1, + bottomRow: 2, + parentId: "0", + widgetId: "yf8bhokz7d", + dynamicBindingPathList: [], + fontSize: TextSizes.PARAGRAPH, + fontStyle: FontStyleTypes.BOLD, + renderMode: "CANVAS", + shouldScroll: true, + shouldTruncate: false, + }, + ], +}; + +const outputDsl4: DSLWidget = { + widgetName: "MainContainer", + backgroundColor: "none", + rightColumn: 1118, + snapColumns: 16, + detachFromLayout: true, + widgetId: "0", + topRow: 0, + bottomRow: 1280, + containerStyle: "none", + snapRows: 33, + parentRowSpace: 1, + type: "CANVAS_WIDGET", + canExtend: true, + version: 15, + minHeight: 1292, + parentColumnSpace: 1, + dynamicTriggerPathList: [], + dynamicBindingPathList: [], + leftColumn: 0, + isLoading: false, + parentId: "", + renderMode: "CANVAS", + children: [ + { + isVisible: true, + text: "Label", + textAlign: "LEFT", + widgetName: "Text1", + version: 1, + type: "TEXT_WIDGET", + isLoading: false, + parentColumnSpace: 67.375, + parentRowSpace: 40, + leftColumn: 3, + rightColumn: 7, + topRow: 1, + bottomRow: 2, + parentId: "0", + widgetId: "yf8bhokz7d", + dynamicBindingPathList: [], + fontSize: TextSizes.PARAGRAPH, + fontStyle: FontStyleTypes.BOLD, + renderMode: "CANVAS", + overflow: OverflowTypes.SCROLL, + }, + ], +}; + +const inputDsl5: DSLWidget = { + widgetName: "MainContainer", + backgroundColor: "none", + rightColumn: 1118, + snapColumns: 16, + detachFromLayout: true, + widgetId: "0", + topRow: 0, + bottomRow: 1280, + containerStyle: "none", + snapRows: 33, + parentRowSpace: 1, + type: "CANVAS_WIDGET", + canExtend: true, + version: 15, + minHeight: 1292, + parentColumnSpace: 1, + dynamicTriggerPathList: [], + dynamicBindingPathList: [], + leftColumn: 0, + isLoading: false, + parentId: "", + renderMode: "CANVAS", + children: [ + { + isVisible: true, + text: "Label", + textAlign: "LEFT", + widgetName: "Text1", + version: 1, + type: "TEXT_WIDGET", + isLoading: false, + parentColumnSpace: 67.375, + parentRowSpace: 40, + leftColumn: 3, + rightColumn: 7, + topRow: 1, + bottomRow: 2, + parentId: "0", + widgetId: "yf8bhokz7d", + dynamicBindingPathList: [], + fontSize: TextSizes.PARAGRAPH, + fontStyle: FontStyleTypes.BOLD, + renderMode: "CANVAS", + shouldScroll: true, + shouldTruncate: true, + }, + ], +}; + +const outputDsl5: DSLWidget = { + widgetName: "MainContainer", + backgroundColor: "none", + rightColumn: 1118, + snapColumns: 16, + detachFromLayout: true, + widgetId: "0", + topRow: 0, + bottomRow: 1280, + containerStyle: "none", + snapRows: 33, + parentRowSpace: 1, + type: "CANVAS_WIDGET", + canExtend: true, + version: 15, + minHeight: 1292, + parentColumnSpace: 1, + dynamicTriggerPathList: [], + dynamicBindingPathList: [], + leftColumn: 0, + isLoading: false, + parentId: "", + renderMode: "CANVAS", + children: [ + { + isVisible: true, + text: "Label", + textAlign: "LEFT", + widgetName: "Text1", + version: 1, + type: "TEXT_WIDGET", + isLoading: false, + parentColumnSpace: 67.375, + parentRowSpace: 40, + leftColumn: 3, + rightColumn: 7, + topRow: 1, + bottomRow: 2, + parentId: "0", + widgetId: "yf8bhokz7d", + dynamicBindingPathList: [], + fontSize: TextSizes.PARAGRAPH, + fontStyle: FontStyleTypes.BOLD, + renderMode: "CANVAS", + overflow: OverflowTypes.TRUNCATE, + }, + ], +}; + +const inputDsl6: DSLWidget = { + widgetName: "MainContainer", + backgroundColor: "none", + rightColumn: 1118, + snapColumns: 16, + detachFromLayout: true, + widgetId: "0", + topRow: 0, + bottomRow: 1280, + containerStyle: "none", + snapRows: 33, + parentRowSpace: 1, + type: "CANVAS_WIDGET", + canExtend: true, + version: 15, + minHeight: 1292, + parentColumnSpace: 1, + dynamicTriggerPathList: [], + dynamicBindingPathList: [], + leftColumn: 0, + isLoading: false, + parentId: "", + renderMode: "CANVAS", + children: [ + { + isVisible: true, + text: "Label", + textAlign: "LEFT", + widgetName: "Text1", + version: 1, + type: "TEXT_WIDGET", + isLoading: false, + parentColumnSpace: 67.375, + parentRowSpace: 40, + leftColumn: 3, + rightColumn: 7, + topRow: 1, + bottomRow: 2, + parentId: "0", + widgetId: "yf8bhokz7d", + dynamicBindingPathList: [], + fontSize: TextSizes.PARAGRAPH, + fontStyle: FontStyleTypes.BOLD, + renderMode: "CANVAS", + shouldScroll: false, + shouldTruncate: false, + }, + ], +}; + +const outputDsl6: DSLWidget = { + widgetName: "MainContainer", + backgroundColor: "none", + rightColumn: 1118, + snapColumns: 16, + detachFromLayout: true, + widgetId: "0", + topRow: 0, + bottomRow: 1280, + containerStyle: "none", + snapRows: 33, + parentRowSpace: 1, + type: "CANVAS_WIDGET", + canExtend: true, + version: 15, + minHeight: 1292, + parentColumnSpace: 1, + dynamicTriggerPathList: [], + dynamicBindingPathList: [], + leftColumn: 0, + isLoading: false, + parentId: "", + renderMode: "CANVAS", + children: [ + { + isVisible: true, + text: "Label", + textAlign: "LEFT", + widgetName: "Text1", + version: 1, + type: "TEXT_WIDGET", + isLoading: false, + parentColumnSpace: 67.375, + parentRowSpace: 40, + leftColumn: 3, + rightColumn: 7, + topRow: 1, + bottomRow: 2, + parentId: "0", + widgetId: "yf8bhokz7d", + dynamicBindingPathList: [], + fontSize: TextSizes.PARAGRAPH, + fontStyle: FontStyleTypes.BOLD, + renderMode: "CANVAS", + overflow: OverflowTypes.NONE, + }, + ], +}; + +describe("Text Widget Scroll and Truncate Property migrate", () => { + it("Overflow value should be SCROLL instead of shouldScroll true", () => { + const newDsl = migrateScrollTruncateProperties(inputDsl4); + expect(newDsl).toEqual(outputDsl4); + }); + it("Overflow value should be TRUNCATE instead of shouldTruncate true", () => { + const newDsl = migrateScrollTruncateProperties(inputDsl5); + expect(newDsl).toEqual(outputDsl5); + }); + it("Overflow value should be NONE in case of shouldScroll and shouldTruncate are false", () => { + const newDsl = migrateScrollTruncateProperties(inputDsl6); + expect(newDsl).toEqual(outputDsl6); + }); +}); diff --git a/app/client/src/utils/migrations/TextWidgetReplaceTextStyle.ts b/app/client/src/utils/migrations/TextWidget.ts similarity index 59% rename from app/client/src/utils/migrations/TextWidgetReplaceTextStyle.ts rename to app/client/src/utils/migrations/TextWidget.ts index 3b708f5e44..d2284d36e4 100644 --- a/app/client/src/utils/migrations/TextWidgetReplaceTextStyle.ts +++ b/app/client/src/utils/migrations/TextWidget.ts @@ -1,6 +1,7 @@ import { WidgetProps } from "widgets/BaseWidget"; import { FontStyleTypes, TextSizes } from "constants/WidgetConstants"; import { DSLWidget } from "widgets/constants"; +import { OverflowTypes } from "widgets/TextWidget/constants"; export const migrateTextStyleFromTextWidget = ( currentDSL: DSLWidget, @@ -33,3 +34,25 @@ export const migrateTextStyleFromTextWidget = ( }); return currentDSL; }; + +export const migrateScrollTruncateProperties = ( + currentDSL: DSLWidget, +): DSLWidget => { + currentDSL.children = currentDSL.children?.map((child: WidgetProps) => { + if (child.type === "TEXT_WIDGET") { + if (child.shouldTruncate) { + child.overflow = OverflowTypes.TRUNCATE; + } else if (child.shouldScroll) { + child.overflow = OverflowTypes.SCROLL; + } else { + child.overflow = OverflowTypes.NONE; + } + delete child.shouldScroll; + delete child.shouldTruncate; + } else if (child.children && child.children.length > 0) { + child = migrateScrollTruncateProperties(child); + } + return child; + }); + return currentDSL; +}; diff --git a/app/client/src/utils/migrations/TextWidgetReplaceTextStyle.test.ts b/app/client/src/utils/migrations/TextWidgetReplaceTextStyle.test.ts deleted file mode 100644 index b25b0cf00c..0000000000 --- a/app/client/src/utils/migrations/TextWidgetReplaceTextStyle.test.ts +++ /dev/null @@ -1,302 +0,0 @@ -import { migrateTextStyleFromTextWidget } from "utils/migrations/TextWidgetReplaceTextStyle"; -import { FontStyleTypes, TextSizes } from "constants/WidgetConstants"; -import { DSLWidget } from "widgets/constants"; - -const inputDsl1: DSLWidget = { - widgetName: "MainContainer", - backgroundColor: "none", - rightColumn: 1118, - snapColumns: 16, - detachFromLayout: true, - widgetId: "0", - topRow: 0, - bottomRow: 1280, - containerStyle: "none", - snapRows: 33, - parentRowSpace: 1, - type: "CANVAS_WIDGET", - canExtend: true, - version: 15, - minHeight: 1292, - parentColumnSpace: 1, - dynamicTriggerPathList: [], - dynamicBindingPathList: [], - leftColumn: 0, - isLoading: false, - parentId: "", - renderMode: "CANVAS", - children: [ - { - isVisible: true, - text: "Label", - textStyle: "LABEL", - textAlign: "LEFT", - widgetName: "Text1", - version: 1, - type: "TEXT_WIDGET", - isLoading: false, - parentColumnSpace: 67.375, - parentRowSpace: 40, - leftColumn: 3, - rightColumn: 7, - topRow: 1, - bottomRow: 2, - parentId: "0", - widgetId: "yf8bhokz7d", - dynamicBindingPathList: [], - renderMode: "CANVAS", - }, - ], -}; - -const inputDsl2: DSLWidget = { - widgetName: "MainContainer", - backgroundColor: "none", - rightColumn: 1118, - snapColumns: 16, - detachFromLayout: true, - widgetId: "0", - topRow: 0, - bottomRow: 1280, - containerStyle: "none", - snapRows: 33, - parentRowSpace: 1, - type: "CANVAS_WIDGET", - canExtend: true, - version: 15, - minHeight: 1292, - parentColumnSpace: 1, - dynamicTriggerPathList: [], - dynamicBindingPathList: [], - leftColumn: 0, - isLoading: false, - parentId: "", - renderMode: "CANVAS", - children: [ - { - isVisible: true, - text: "Label", - textStyle: "HEADING", - textAlign: "LEFT", - widgetName: "Text1", - version: 1, - type: "TEXT_WIDGET", - isLoading: false, - parentColumnSpace: 67.375, - parentRowSpace: 40, - leftColumn: 3, - rightColumn: 7, - topRow: 1, - bottomRow: 2, - parentId: "0", - widgetId: "yf8bhokz7d", - dynamicBindingPathList: [], - renderMode: "CANVAS", - }, - ], -}; - -const inputDsl3: DSLWidget = { - widgetName: "MainContainer", - backgroundColor: "none", - rightColumn: 1118, - snapColumns: 16, - detachFromLayout: true, - widgetId: "0", - topRow: 0, - bottomRow: 1280, - containerStyle: "none", - snapRows: 33, - parentRowSpace: 1, - type: "CANVAS_WIDGET", - canExtend: true, - version: 15, - minHeight: 1292, - parentColumnSpace: 1, - dynamicTriggerPathList: [], - dynamicBindingPathList: [], - leftColumn: 0, - isLoading: false, - parentId: "", - renderMode: "CANVAS", - children: [ - { - isVisible: true, - text: "Label", - textStyle: "BODY", - textAlign: "LEFT", - widgetName: "Text1", - version: 1, - type: "TEXT_WIDGET", - isLoading: false, - parentColumnSpace: 67.375, - parentRowSpace: 40, - leftColumn: 3, - rightColumn: 7, - topRow: 1, - bottomRow: 2, - parentId: "0", - widgetId: "yf8bhokz7d", - dynamicBindingPathList: [], - renderMode: "CANVAS", - }, - ], -}; - -const outputDsl1: DSLWidget = { - widgetName: "MainContainer", - backgroundColor: "none", - rightColumn: 1118, - snapColumns: 16, - detachFromLayout: true, - widgetId: "0", - topRow: 0, - bottomRow: 1280, - containerStyle: "none", - snapRows: 33, - parentRowSpace: 1, - type: "CANVAS_WIDGET", - canExtend: true, - version: 15, - minHeight: 1292, - parentColumnSpace: 1, - dynamicTriggerPathList: [], - dynamicBindingPathList: [], - leftColumn: 0, - isLoading: false, - parentId: "", - renderMode: "CANVAS", - children: [ - { - isVisible: true, - text: "Label", - textAlign: "LEFT", - widgetName: "Text1", - version: 1, - type: "TEXT_WIDGET", - isLoading: false, - parentColumnSpace: 67.375, - parentRowSpace: 40, - leftColumn: 3, - rightColumn: 7, - topRow: 1, - bottomRow: 2, - parentId: "0", - widgetId: "yf8bhokz7d", - dynamicBindingPathList: [], - fontSize: TextSizes.PARAGRAPH, - fontStyle: FontStyleTypes.BOLD, - renderMode: "CANVAS", - }, - ], -}; - -const outputDsl2: DSLWidget = { - widgetName: "MainContainer", - backgroundColor: "none", - rightColumn: 1118, - snapColumns: 16, - detachFromLayout: true, - widgetId: "0", - topRow: 0, - bottomRow: 1280, - containerStyle: "none", - snapRows: 33, - parentRowSpace: 1, - type: "CANVAS_WIDGET", - canExtend: true, - version: 15, - minHeight: 1292, - parentColumnSpace: 1, - dynamicTriggerPathList: [], - dynamicBindingPathList: [], - leftColumn: 0, - isLoading: false, - parentId: "", - renderMode: "CANVAS", - children: [ - { - isVisible: true, - text: "Label", - textAlign: "LEFT", - widgetName: "Text1", - version: 1, - type: "TEXT_WIDGET", - isLoading: false, - parentColumnSpace: 67.375, - parentRowSpace: 40, - leftColumn: 3, - rightColumn: 7, - topRow: 1, - bottomRow: 2, - parentId: "0", - widgetId: "yf8bhokz7d", - dynamicBindingPathList: [], - fontSize: TextSizes.HEADING1, - fontStyle: FontStyleTypes.BOLD, - renderMode: "CANVAS", - }, - ], -}; - -const outputDsl3: DSLWidget = { - widgetName: "MainContainer", - backgroundColor: "none", - rightColumn: 1118, - snapColumns: 16, - detachFromLayout: true, - widgetId: "0", - topRow: 0, - bottomRow: 1280, - containerStyle: "none", - snapRows: 33, - parentRowSpace: 1, - type: "CANVAS_WIDGET", - canExtend: true, - version: 15, - minHeight: 1292, - parentColumnSpace: 1, - dynamicTriggerPathList: [], - dynamicBindingPathList: [], - leftColumn: 0, - isLoading: false, - parentId: "", - renderMode: "CANVAS", - children: [ - { - isVisible: true, - text: "Label", - textAlign: "LEFT", - widgetName: "Text1", - version: 1, - type: "TEXT_WIDGET", - isLoading: false, - parentColumnSpace: 67.375, - parentRowSpace: 40, - leftColumn: 3, - rightColumn: 7, - topRow: 1, - bottomRow: 2, - parentId: "0", - widgetId: "yf8bhokz7d", - dynamicBindingPathList: [], - fontSize: TextSizes.PARAGRAPH, - renderMode: "CANVAS", - }, - ], -}; - -describe("Text Widget Property Pane Upgrade", () => { - it("To test text widget textStyle property is migrated", () => { - const newDsl = migrateTextStyleFromTextWidget(inputDsl1); - expect(JSON.stringify(newDsl) === JSON.stringify(outputDsl1)); - }); - it("To test text widget textStyle property is migrated", () => { - const newDsl = migrateTextStyleFromTextWidget(inputDsl2); - expect(JSON.stringify(newDsl) === JSON.stringify(outputDsl2)); - }); - it("To test text widget textStyle property is migrated", () => { - const newDsl = migrateTextStyleFromTextWidget(inputDsl3); - expect(JSON.stringify(newDsl) === JSON.stringify(outputDsl3)); - }); -}); diff --git a/app/client/src/widgets/TextWidget/component/index.tsx b/app/client/src/widgets/TextWidget/component/index.tsx index cd541cad5a..cddef3a19f 100644 --- a/app/client/src/widgets/TextWidget/component/index.tsx +++ b/app/client/src/widgets/TextWidget/component/index.tsx @@ -13,6 +13,7 @@ import Icon, { IconSize } from "components/ads/Icon"; import { isEqual, get } from "lodash"; import ModalComponent from "components/designSystems/appsmith/ModalComponent"; import { Colors } from "constants/Colors"; +import { OverflowTypes } from "../constants"; export type TextAlign = "LEFT" | "CENTER" | "RIGHT" | "JUSTIFY"; @@ -94,8 +95,7 @@ const StyledIcon = styled(Icon)<{ backgroundColor?: string }>` `; export const StyledText = styled(Text)<{ - scroll: boolean; - truncate: boolean; + overflow: OverflowTypes; isTruncated: boolean; textAlign: string; backgroundColor?: string; @@ -104,10 +104,15 @@ export const StyledText = styled(Text)<{ fontSize?: TextSize; }>` height: ${(props) => - props.isTruncated ? `calc(100% - ${ELLIPSIS_HEIGHT}px)` : "100%"}; + props.overflow === OverflowTypes.TRUNCATE + ? `calc(100% - ${ELLIPSIS_HEIGHT}px)` + : "100%"}; overflow-x: hidden; overflow-y: ${(props) => - props.scroll ? (props.isTruncated ? "hidden" : "auto") : "hidden"}; + props.overflow !== OverflowTypes.SCROLL || + props.overflow === OverflowTypes.TRUNCATE.valueOf() + ? "hidden" + : "auto"}; text-overflow: ellipsis; text-align: ${(props) => props.textAlign.toLowerCase()}; display: flex; @@ -115,7 +120,10 @@ export const StyledText = styled(Text)<{ justify-content: flex-start; flex-direction: ${(props) => (props.isTruncated ? "column" : "unset")}; align-items: ${(props) => - props.scroll || props.truncate ? "flex-start" : "center"}; + props.overflow === OverflowTypes.SCROLL || + props.overflow === OverflowTypes.TRUNCATE + ? "flex-start" + : "center"}; background: ${(props) => props?.backgroundColor}; color: ${(props) => props?.textColor}; font-style: ${(props) => @@ -185,13 +193,12 @@ export interface TextComponentProps extends ComponentProps { ellipsize?: boolean; fontSize?: TextSize; isLoading: boolean; - shouldScroll?: boolean; backgroundColor?: string; textColor?: string; fontStyle?: string; disableLink: boolean; - shouldTruncate: boolean; truncateButtonColor?: string; + overflow: OverflowTypes; // helpers to detect and re-calculate content width bottomRow?: number; leftColumn?: number; @@ -225,7 +232,7 @@ class TextComponent extends React.Component { componentDidMount = () => { const textRef = get(this.textRef, "current.textRef"); - if (textRef && this.props.shouldTruncate) { + if (textRef && this.props.overflow === OverflowTypes.TRUNCATE) { const isTruncated = this.getTruncate(textRef); this.setState({ isTruncated }); } @@ -233,13 +240,16 @@ class TextComponent extends React.Component { componentDidUpdate = (prevProps: TextComponentProps) => { if (!isEqual(prevProps, this.props)) { - if (this.props.shouldTruncate) { + if (this.props.overflow === OverflowTypes.TRUNCATE) { const textRef = get(this.textRef, "current.textRef"); if (textRef) { const isTruncated = this.getTruncate(textRef); this.setState({ isTruncated }); } - } else if (prevProps.shouldTruncate && !this.props.shouldTruncate) { + } else if ( + prevProps.overflow === OverflowTypes.TRUNCATE && + this.props.overflow !== OverflowTypes.TRUNCATE.valueOf() + ) { this.setState({ isTruncated: false }); } } @@ -260,8 +270,7 @@ class TextComponent extends React.Component { ellipsize, fontSize, fontStyle, - shouldScroll, - shouldTruncate, + overflow, text, textAlign, textColor, @@ -278,11 +287,10 @@ class TextComponent extends React.Component { fontSize={fontSize} fontStyle={fontStyle} isTruncated={this.state.isTruncated} + overflow={overflow} ref={this.textRef} - scroll={!!shouldScroll} textAlign={textAlign} textColor={textColor} - truncate={!!shouldTruncate} > { static getPropertyPaneConfig() { @@ -33,18 +34,25 @@ class TextWidget extends BaseWidget { }, }, { - propertyName: "shouldScroll", - label: "Enable Scroll", - helpText: "Allows scrolling text instead of truncation", - controlType: "SWITCH", - isBindProperty: false, - isTriggerProperty: false, - }, - { - propertyName: "shouldTruncate", - label: "Truncate Text", - helpText: "Set truncate text", - controlType: "SWITCH", + propertyName: "overflow", + label: "Overflow", + helpText: "Controls the text behavior when length of text exceeds", + controlType: "DROP_DOWN", + options: [ + { + label: "Scroll contents", + value: OverflowTypes.SCROLL, + }, + { + label: "Truncate text", + value: OverflowTypes.TRUNCATE, + }, + { + label: "No overflow", + value: OverflowTypes.NONE, + }, + ], + defaultValue: OverflowTypes.NONE, isBindProperty: false, isTriggerProperty: false, }, @@ -130,9 +138,9 @@ class TextWidget extends BaseWidget { regex: /^(?![<|{{]).+/, }, }, - dependencies: ["shouldTruncate"], + dependencies: ["overflow"], hidden: (props: TextWidgetProps) => { - return !props.shouldTruncate; + return props.overflow !== OverflowTypes.TRUNCATE; }, }, { @@ -275,9 +283,8 @@ class TextWidget extends BaseWidget { isLoading={this.props.isLoading} key={this.props.widgetId} leftColumn={this.props.leftColumn} + overflow={this.props.overflow} rightColumn={this.props.rightColumn} - shouldScroll={this.props.shouldScroll} - shouldTruncate={this.props.shouldTruncate} text={this.props.text} textAlign={this.props.textAlign ? this.props.textAlign : "LEFT"} textColor={this.props.textColor} @@ -315,9 +322,8 @@ export interface TextWidgetProps WidgetStyleContainerProps { text?: string; isLoading: boolean; - shouldScroll: boolean; - shouldTruncate: boolean; disableLink: boolean; + overflow: OverflowTypes; } export default TextWidget;