diff --git a/app/client/cypress/e2e/Regression/ClientSide/Widgets/TableV2/TableV2_Derived_Column_Data_validation_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Widgets/TableV2/TableV2_Derived_Column_Data_validation_spec.js index ac2d450fcfcb..0a56162c813a 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Widgets/TableV2/TableV2_Derived_Column_Data_validation_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Widgets/TableV2/TableV2_Derived_Column_Data_validation_spec.js @@ -7,6 +7,7 @@ const commonlocators = require("../../../../../locators/commonlocators.json"); import { agHelper, apiPage, + entityExplorer, propPane, } from "../../../../../support/Objects/ObjectsCore"; @@ -115,38 +116,6 @@ describe( // verify customColumn is visible in the table cy.get(".draggable-header:contains('CustomColumn')").should("be.visible"); cy.closePropertyPane(); - cy.deleteColumn("customColumn1"); - }); - - it("5. Verify computed value with try-catch blocks handles missing nested properties", function () { - cy.openPropertyPane("tablewidgetv2"); - - // Set table data with nested object and missing property - propPane.UpdatePropertyFieldValue( - "Table data", - `{{[{"name": "Rahul", age: {value: 31}}, {"name": "Jacq", age: {}}, {"name": "John"}]}}`, - ); - - cy.editColumn("age"); - propPane.UpdatePropertyFieldValue( - "Computed value", - "{{currentRow.age.value}}", - ); - - cy.readTableV2data(0, 1).then((val) => { - expect(val).to.equal("31"); - }); - - cy.readTableV2data(1, 1).then((val) => { - expect(val).to.equal(""); - }); - - cy.readTableV2data(2, 1).then((val) => { - expect(val).to.equal(""); - }); - - // Clean up - cy.backFromPropertyPanel(); }); }, ); diff --git a/app/client/packages/dsl/src/migrate/index.ts b/app/client/packages/dsl/src/migrate/index.ts index 9d0508427d21..75ce6f7b6d5f 100644 --- a/app/client/packages/dsl/src/migrate/index.ts +++ b/app/client/packages/dsl/src/migrate/index.ts @@ -91,10 +91,9 @@ import { migrateTableServerSideFiltering } from "./migrations/086-migrate-table- import { migrateChartwidgetCustomEchartConfig } from "./migrations/087-migrate-chart-widget-customechartdata"; import { migrateCustomWidgetDynamicHeight } from "./migrations/088-migrate-custom-widget-dynamic-height"; import { migrateTableWidgetV2CurrentRowInValidationsBinding } from "./migrations/089-migrage-table-widget-v2-currentRow-binding"; -import { migrateTableWidgetV2ValidationTryCatch } from "./migrations/090-migrate-table-widget-v2-validation-try-catch"; import type { DSLWidget } from "./types"; -export const LATEST_DSL_VERSION = 92; +export const LATEST_DSL_VERSION = 91; export const calculateDynamicHeight = () => { const DEFAULT_GRID_ROW_HEIGHT = 10; @@ -625,11 +624,6 @@ const migrateVersionedDSL = async (currentDSL: DSLWidget, newPage = false) => { * What we missed was that, the auto-commit does not handle clientVersion, which lead to this bug: https://github.com/appsmithorg/appsmith/issues/38511 * We are bumping this version to make sure that the auto-commit will handle this version bump. */ - currentDSL.version = 91; - } - - if (currentDSL.version === 91) { - currentDSL = migrateTableWidgetV2ValidationTryCatch(currentDSL); currentDSL.version = LATEST_DSL_VERSION; } diff --git a/app/client/packages/dsl/src/migrate/migrations/090-migrate-table-widget-v2-validation-try-catch.ts b/app/client/packages/dsl/src/migrate/migrations/090-migrate-table-widget-v2-validation-try-catch.ts deleted file mode 100644 index 4faefd3f4c4a..000000000000 --- a/app/client/packages/dsl/src/migrate/migrations/090-migrate-table-widget-v2-validation-try-catch.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { ColumnProperties, DSLWidget, WidgetProps } from "../types"; -import { isDynamicValue, traverseDSLAndMigrate } from "../utils"; - -const oldBindingPrefix = (tableName: string) => { - return `{{${tableName}.processedTableData.map((currentRow, currentIndex) => (`; -}; - -const newBindingPrefix = (tableName: string) => { - return `{{${tableName}.processedTableData.map((currentRow, currentIndex) => { try { return (`; -}; - -const oldBindingSuffix = `))}}`; -const newBindingSuffix = `); } catch (e) { return null; }})}}`; - -export const migrateTableWidgetV2ValidationTryCatch = ( - currentDSL: DSLWidget, -) => { - return traverseDSLAndMigrate(currentDSL, (widget: WidgetProps) => { - if (widget.type !== "TABLE_WIDGET_V2") return; - - const primaryColumns: Record = - widget.primaryColumns as Record; - - Object.values(primaryColumns).forEach((colProperties) => { - if (!colProperties.computedValue) return; - - const value = colProperties.computedValue; - - if (!isDynamicValue(value)) return; - - const tableName = widget.widgetName; - const oldPrefix = oldBindingPrefix(tableName); - - // Only update if it matches the old format - if (!value.startsWith(oldPrefix)) return; - - // Replace old prefix/suffix with new ones - const computation = value - .replace(oldPrefix, "") - .replace(oldBindingSuffix, ""); - - // Add the new prefix and suffix with try-catch - colProperties.computedValue = `${newBindingPrefix(tableName)}${computation}${newBindingSuffix}`; - }); - }); -}; diff --git a/app/client/packages/dsl/src/migrate/tests/DSLMigration.test.ts b/app/client/packages/dsl/src/migrate/tests/DSLMigration.test.ts index e58adcfceb87..fd03b573d57e 100644 --- a/app/client/packages/dsl/src/migrate/tests/DSLMigration.test.ts +++ b/app/client/packages/dsl/src/migrate/tests/DSLMigration.test.ts @@ -90,7 +90,6 @@ import * as m86 from "../migrations/086-migrate-table-server-side-filtering"; import * as m87 from "../migrations/087-migrate-chart-widget-customechartdata"; import * as m88 from "../migrations/088-migrate-custom-widget-dynamic-height"; import * as m89 from "../migrations/089-migrage-table-widget-v2-currentRow-binding"; -import * as m91 from "../migrations/090-migrate-table-widget-v2-validation-try-catch"; interface Migration { functionLookup: { @@ -935,15 +934,6 @@ const migrations: Migration[] = [ functionLookup: [], version: 90, }, - { - functionLookup: [ - { - moduleObj: m91, - functionName: "migrateTableWidgetV2ValidationTryCatch", - }, - ], - version: 91, - }, ]; const mockFnObj: Record = {}; diff --git a/app/client/packages/dsl/src/migrate/tests/TableWidgetV2/DSLs/ValidationTryCatchDSLs.ts b/app/client/packages/dsl/src/migrate/tests/TableWidgetV2/DSLs/ValidationTryCatchDSLs.ts deleted file mode 100644 index 4db0a19fc3f0..000000000000 --- a/app/client/packages/dsl/src/migrate/tests/TableWidgetV2/DSLs/ValidationTryCatchDSLs.ts +++ /dev/null @@ -1,48 +0,0 @@ -import type { DSLWidget } from "../../../types"; - -const oldBindingPrefix = (tableName: string) => { - return `{{${tableName}.processedTableData.map((currentRow, currentIndex) => (`; -}; - -const newBindingPrefix = (tableName: string) => { - return `{{${tableName}.processedTableData.map((currentRow, currentIndex) => { try { return (`; -}; - -const oldBindingSuffix = `))}}`; -const newBindingSuffix = `); } catch (e) { return null; }})}}`; - -const computation = "currentRow.id + '_' + currentIndex"; - -export const validationTryCatchInput = { - children: [ - { - widgetName: "Table1", - type: "TABLE_WIDGET_V2", - primaryColumns: { - customColumn1: { - computedValue: `${oldBindingPrefix("Table1")}${computation}${oldBindingSuffix}`, - }, - customColumn2: { - computedValue: "static value", // Should not be modified - }, - }, - }, - ], -} as any as DSLWidget; - -export const validationTryCatchOutput = { - children: [ - { - widgetName: "Table1", - type: "TABLE_WIDGET_V2", - primaryColumns: { - customColumn1: { - computedValue: `${newBindingPrefix("Table1")}${computation}${newBindingSuffix}`, - }, - customColumn2: { - computedValue: "static value", // Not modified - }, - }, - }, - ], -} as any as DSLWidget; diff --git a/app/client/packages/dsl/src/migrate/tests/TableWidgetV2/ValidationTryCatch.test.ts b/app/client/packages/dsl/src/migrate/tests/TableWidgetV2/ValidationTryCatch.test.ts deleted file mode 100644 index 666513c22501..000000000000 --- a/app/client/packages/dsl/src/migrate/tests/TableWidgetV2/ValidationTryCatch.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { migrateTableWidgetV2ValidationTryCatch } from "../../migrations/090-migrate-table-widget-v2-validation-try-catch"; -import { - validationTryCatchInput, - validationTryCatchOutput, -} from "./DSLs/ValidationTryCatchDSLs"; - -describe("migrateTableWidgetV2ValidationTryCatch", () => { - it("should add try-catch blocks to table compute value bindings", () => { - const migratedDSL = migrateTableWidgetV2ValidationTryCatch( - validationTryCatchInput, - ); - - expect(migratedDSL).toEqual(validationTryCatchOutput); - }); -}); diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/PluginActionResponse.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/PluginActionResponse.tsx index ef8fdb3f4558..12afc6913894 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/PluginActionResponse.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/PluginActionResponse.tsx @@ -1,5 +1,7 @@ import React, { useCallback, useEffect, useMemo } from "react"; import { IDEBottomView, ViewHideBehaviour } from "IDE"; +import { PluginType } from "entities/Plugin"; +import { getIsAnvilEnabledInCurrentApplication } from "layoutSystems/anvil/integrations/selectors"; import { ActionExecutionResizerHeight } from "./constants"; import EntityBottomTabs from "components/editorComponents/EntityBottomTabs"; import { useDispatch, useSelector } from "react-redux"; @@ -15,7 +17,8 @@ import { useDefaultTab } from "ee/PluginActionEditor/components/PluginActionResp function PluginActionResponse() { const dispatch = useDispatch(); - const { actionResponse } = usePluginActionContext(); + const { actionResponse, plugin } = usePluginActionContext(); + const isAnvilEnabled = useSelector(getIsAnvilEnabledInCurrentApplication); const tabs = usePluginActionResponseTabs(); @@ -36,6 +39,9 @@ function PluginActionResponse() { // as for page load queries, query response is available and can be shown in response tab useEffect( function openResponseTabForPageLoadQueries() { + // disable the opening of RESPONSE_TAB for the AI plugin in Anvil + if (isAnvilEnabled && plugin.type === PluginType.AI) return; + // actionResponse and responseDisplayFormat is present only when query has response available if ( !!responseDisplayFormat?.title && @@ -53,11 +59,16 @@ function PluginActionResponse() { responseDisplayFormat?.title, actionResponse?.isExecutionSuccess, dispatch, + isAnvilEnabled, + plugin.type, ], ); useEffect( function openResponseTabOnError() { + // disable the opening of RESPONSE_TAB for the AI plugin in Anvil + if (isAnvilEnabled && plugin.type === PluginType.AI) return; + if (executionFailed) { dispatch( setPluginActionEditorDebuggerState({ @@ -67,7 +78,7 @@ function PluginActionResponse() { ); } }, - [executionFailed, dispatch], + [executionFailed, dispatch, isAnvilEnabled, plugin.type], ); useDefaultTab(); diff --git a/app/client/src/PluginActionEditor/components/PluginActionToolbar.tsx b/app/client/src/PluginActionEditor/components/PluginActionToolbar.tsx index f44c486f69d6..0087807f5d53 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionToolbar.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionToolbar.tsx @@ -2,6 +2,8 @@ import React, { useCallback } from "react"; import { IDEToolbar } from "IDE"; import { Button, Menu, MenuContent, MenuTrigger, Tooltip } from "@appsmith/ads"; import { modText } from "utils/helpers"; +import { PluginType } from "../../entities/Plugin"; +import { getIsAnvilEnabledInCurrentApplication } from "../../layoutSystems/anvil/integrations/selectors"; import { usePluginActionContext } from "../PluginActionContext"; import { useBlockExecution, @@ -20,17 +22,21 @@ interface PluginActionToolbarProps { } const PluginActionToolbar = (props: PluginActionToolbarProps) => { - const { action } = usePluginActionContext(); + const { action, plugin } = usePluginActionContext(); const { handleRunClick } = useHandleRunClick(); const { callRunActionAnalytics } = useAnalyticsOnRunClick(); const [isMenuOpen, toggleMenuOpen] = useToggle([false, true]); const blockExecution = useBlockExecution(); const isRunning = useSelector(isActionRunning(action.id)); + const isAnvilEnabled = useSelector(getIsAnvilEnabledInCurrentApplication); const onRunClick = useCallback(() => { + const isSkipOpeningDebugger = + isAnvilEnabled && plugin.type === PluginType.AI; + callRunActionAnalytics(); - handleRunClick(); - }, [callRunActionAnalytics, handleRunClick]); + handleRunClick(isSkipOpeningDebugger); + }, [callRunActionAnalytics, handleRunClick, isAnvilEnabled, plugin.type]); return ( diff --git a/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts b/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts index a698845448d6..3bcafcdc6359 100644 --- a/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts +++ b/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts @@ -103,10 +103,17 @@ export const handlers = { }, [ReduxActionTypes.RUN_ACTION_REQUEST]: ( state: PluginActionEditorState, - action: ReduxAction<{ id: string }>, + action: ReduxAction<{ + skipOpeningDebugger: boolean; + id: string; + }>, ) => { set(state, ["isRunning", action.payload.id], true); - set(state, ["debugger", "selectedTab"], DEBUGGER_TAB_KEYS.RESPONSE_TAB); + + if (!action.payload.skipOpeningDebugger) { + set(state, ["debugger", "selectedTab"], DEBUGGER_TAB_KEYS.RESPONSE_TAB); + } + set(state, ["debugger", "open"], true); }, [ReduxActionTypes.RUN_ACTION_CANCELLED]: ( diff --git a/app/client/src/ce/PluginActionEditor/hooks/useHandleRunClick.ts b/app/client/src/ce/PluginActionEditor/hooks/useHandleRunClick.ts index 62d8075bcbda..6eb749e6fad1 100644 --- a/app/client/src/ce/PluginActionEditor/hooks/useHandleRunClick.ts +++ b/app/client/src/ce/PluginActionEditor/hooks/useHandleRunClick.ts @@ -1,7 +1,6 @@ import { useCallback } from "react"; import { useDispatch } from "react-redux"; import { runAction } from "actions/pluginActionActions"; -import type { PaginationField } from "api/ActionAPI"; import { usePluginActionContext } from "PluginActionEditor/PluginActionContext"; function useHandleRunClick() { @@ -9,8 +8,8 @@ function useHandleRunClick() { const dispatch = useDispatch(); const handleRunClick = useCallback( - (paginationField?: PaginationField) => { - dispatch(runAction(action?.id ?? "", paginationField)); + (skipOpeningDebugger = false) => { + dispatch(runAction(action?.id ?? "", undefined, skipOpeningDebugger)); }, [action.id, dispatch], ); diff --git a/app/client/src/components/propertyControls/TableComputeValue.tsx b/app/client/src/components/propertyControls/TableComputeValue.tsx index 3a70fd704f26..1eba59f89e07 100644 --- a/app/client/src/components/propertyControls/TableComputeValue.tsx +++ b/app/client/src/components/propertyControls/TableComputeValue.tsx @@ -100,10 +100,10 @@ function InputText(props: InputTextProp) { class ComputeTablePropertyControlV2 extends BaseControl { static getBindingPrefix(tableName: string) { - return `{{${tableName}.processedTableData.map((currentRow, currentIndex) => { try { return ( `; + return `{{${tableName}.processedTableData.map((currentRow, currentIndex) => ( `; } - static bindingSuffix = `); } catch (e) { return null; }})}}`; + static bindingSuffix = `))}}`; render() { const { diff --git a/app/client/src/sagas/ActionExecution/PluginActionSaga.ts b/app/client/src/sagas/ActionExecution/PluginActionSaga.ts index 5328457b8a7d..3096c7b1fe35 100644 --- a/app/client/src/sagas/ActionExecution/PluginActionSaga.ts +++ b/app/client/src/sagas/ActionExecution/PluginActionSaga.ts @@ -129,7 +129,8 @@ import { findDatatype, isTrueObject, } from "ee/workers/Evaluation/evaluationUtils"; -import type { Plugin } from "entities/Plugin"; +import { type Plugin, PluginType } from "entities/Plugin"; +import { getIsAnvilEnabledInCurrentApplication } from "../../layoutSystems/anvil/integrations/selectors"; import { setDefaultActionDisplayFormat } from "./PluginActionSagaUtils"; import { checkAndLogErrorsIfCyclicDependency } from "sagas/helper"; import { toast } from "@appsmith/ads"; @@ -1120,6 +1121,9 @@ function* executePageLoadAction( const datasourceId: string = (action?.datasource as any)?.id; const datasource: Datasource = yield select(getDatasource, datasourceId); const plugin: Plugin = yield select(getPlugin, action?.pluginId); + const isAnvilEnabled: boolean = yield select( + getIsAnvilEnabledInCurrentApplication, + ); AnalyticsUtil.logEvent("EXECUTE_ACTION", { type: pageAction.pluginType, @@ -1179,7 +1183,10 @@ function* executePageLoadAction( // open response tab in debugger on exection of action on page load. // Only if current page is the page on which the action is executed. - if (window.location.pathname.includes(pageAction.id)) + if ( + window.location.pathname.includes(pageAction.id) && + !(isAnvilEnabled && pageAction.pluginType === PluginType.AI) + ) yield put( setPluginActionEditorDebuggerState({ open: true, diff --git a/app/client/src/widgets/TableWidgetV2/widget/reactTableUtils/transformDataPureFn.tsx b/app/client/src/widgets/TableWidgetV2/widget/reactTableUtils/transformDataPureFn.tsx index ff2200f4857d..1454694ce8b3 100644 --- a/app/client/src/widgets/TableWidgetV2/widget/reactTableUtils/transformDataPureFn.tsx +++ b/app/client/src/widgets/TableWidgetV2/widget/reactTableUtils/transformDataPureFn.tsx @@ -16,7 +16,9 @@ export const transformDataPureFn = ( ): tableData => { if (isArray(tableData)) { return tableData.map((row, rowIndex) => { - const newRow: { [key: string]: unknown } = {}; + // TODO: Fix this the next time the file is edited + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const newRow: { [key: string]: any } = {}; columns.forEach((column) => { const { alias } = column; diff --git a/app/client/src/widgets/TableWidgetV2/widget/utilities.ts b/app/client/src/widgets/TableWidgetV2/widget/utilities.ts index 13e8e8d12d29..502c8527779a 100644 --- a/app/client/src/widgets/TableWidgetV2/widget/utilities.ts +++ b/app/client/src/widgets/TableWidgetV2/widget/utilities.ts @@ -210,9 +210,9 @@ export function getDefaultColumnProperties( isDiscardVisible: true, computedValue: isDerived ? "" - : `{{${widgetName}.processedTableData.map((currentRow, currentIndex) => { try { return ( currentRow["${escapeString( + : `{{${widgetName}.processedTableData.map((currentRow, currentIndex) => ( currentRow["${escapeString( id, - )}"]); } catch (e) { return null; }})}}`, + )}"]))}}`, sticky: StickyType.NONE, validation: {}, currencyCode: "USD", diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Tenant.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Tenant.java index e0ad66274d17..f4a005bbff76 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Tenant.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Tenant.java @@ -10,7 +10,6 @@ import org.springframework.data.annotation.Transient; import org.springframework.data.mongodb.core.mapping.Document; -import java.io.Serial; import java.io.Serializable; @Getter @@ -21,11 +20,6 @@ @FieldNameConstants public class Tenant extends BaseDomain implements Serializable { - // When changing tenant object, update the serialization version number to ensure that in a multi pod - // deployment, new pods only read the new tenant object and not the old one from redis cache. - @Serial - private static final long serialVersionUID = 1459916000401322518L; - @Unique String slug; String displayName; diff --git a/deploy/docker/fs/opt/appsmith/run-rts.sh b/deploy/docker/fs/opt/appsmith/run-rts.sh new file mode 100644 index 000000000000..c9a5bccd3866 --- /dev/null +++ b/deploy/docker/fs/opt/appsmith/run-rts.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +exec node /opt/appsmith/rts/bundle/server.js \ No newline at end of file diff --git a/deploy/docker/fs/opt/appsmith/templates/supervisord/application_process/rts.conf b/deploy/docker/fs/opt/appsmith/templates/supervisord/application_process/rts.conf index 2ff862db027f..e4adbc36a2cb 100644 --- a/deploy/docker/fs/opt/appsmith/templates/supervisord/application_process/rts.conf +++ b/deploy/docker/fs/opt/appsmith/templates/supervisord/application_process/rts.conf @@ -1,6 +1,5 @@ [program:rts] -directory=/opt/appsmith/rts/bundle -command=/opt/appsmith/run-with-env.sh node server.js +command=/opt/appsmith/run-with-env.sh /opt/appsmith/run-rts.sh autorestart=true autostart=true priority=15