diff --git a/Dockerfile b/Dockerfile
index 795368d8fc..8b72f70618 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -30,10 +30,10 @@ COPY ./app/client/build editor/
# Add RTS - Application Layer
COPY ./app/client/packages/rts/dist rts/
-ENV PATH /opt/appsmith/utils/node_modules/.bin:/opt/java/bin:/opt/node/bin:$PATH
+ENV PATH /opt/bin:/opt/appsmith/utils/node_modules/.bin:/opt/java/bin:/opt/node/bin:$PATH
RUN cd ./utils && npm install --only=prod && npm install --only=prod -g . && cd - \
- && chmod +x *.sh /watchtower-hooks/*.sh \
+ && chmod +x /opt/bin/* *.sh /watchtower-hooks/*.sh \
# Disable setuid/setgid bits for the files inside container.
&& find / \( -path /proc -prune \) -o \( \( -perm -2000 -o -perm -4000 \) -print -exec chmod -s '{}' + \) || true \
&& mkdir -p /.mongodb/mongosh /appsmith-stacks \
diff --git a/app/client/cypress/e2e/Regression/ClientSide/OtherUIFeatures/EmptyCanvas_spec.js b/app/client/cypress/e2e/Regression/ClientSide/OtherUIFeatures/EmptyCanvas_spec.js
deleted file mode 100644
index a3d9d72532..0000000000
--- a/app/client/cypress/e2e/Regression/ClientSide/OtherUIFeatures/EmptyCanvas_spec.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import { WIDGET } from "../../../../locators/WidgetLocators";
-import { ObjectsRegistry } from "../../../../support/Objects/Registry";
-import EditorNavigation, {
- EntityType,
-} from "../../../../support/Pages/EditorNavigation";
-import PageList from "../../../../support/Pages/PageList";
-
-const { CommonLocators: locators, EntityExplorer: ee } = ObjectsRegistry;
-
-describe("Empty canvas ctas", () => {
- it("1. Ctas validations", () => {
- cy.wait(3000); // for page to load, failing in CI
- //Ctas should not be shown in the second page
- cy.get(locators._emptyCanvasCta).should("be.visible");
- PageList.AddNewPage();
- cy.get(locators._emptyCanvasCta).should("not.exist");
- EditorNavigation.SelectEntityByName("Page1", EntityType.Page);
-
- //Ctas should continue to show on refresh
- cy.get(locators._emptyCanvasCta).should("be.visible");
- cy.reload();
- cy.get(locators._emptyCanvasCta).should("be.visible");
-
- //Hide cta on adding a widget
- cy.get(locators._emptyCanvasCta).should("be.visible");
- ee.DragDropWidgetNVerify(WIDGET.BUTTON, 200, 200);
- cy.get(locators._emptyCanvasCta).should("not.exist");
- PageList.AddNewPage();
- cy.get(locators._emptyCanvasCta).should("not.exist");
- });
-});
diff --git a/app/client/cypress/e2e/Regression/ClientSide/VisualTests/AppPageLayout_spec.js b/app/client/cypress/e2e/Regression/ClientSide/VisualTests/AppPageLayout_spec.js
index d46e558fa9..bc76f3bb8b 100644
--- a/app/client/cypress/e2e/Regression/ClientSide/VisualTests/AppPageLayout_spec.js
+++ b/app/client/cypress/e2e/Regression/ClientSide/VisualTests/AppPageLayout_spec.js
@@ -1,5 +1,6 @@
import homePage from "../../../../locators/HomePage";
import * as _ from "../../../../support/Objects/ObjectsCore";
+import PageList from "../../../../support/Pages/PageList";
describe("Visual regression tests", { tags: ["@tag.Visual"] }, () => {
// for any changes in UI, update the screenshot in snapshot folder, to do so:
@@ -18,7 +19,7 @@ describe("Visual regression tests", { tags: ["@tag.Visual"] }, () => {
cy.get("#root").matchImageSnapshot("apppage");
//Layout validation for Quick page wizard
- cy.get("[data-testid='generate-app']").click();
+ PageList.AddNewPage(Cypress.env("MESSAGES").GENERATE_PAGE_ACTION_TITLE());
cy.wait(2000);
// taking screenshot of generate crud page
cy.get("#root").matchImageSnapshot("quickPageWizard");
diff --git a/app/client/cypress/locators/GeneratePage.json b/app/client/cypress/locators/GeneratePage.json
index fafd5d1c4b..e6925eb1e7 100644
--- a/app/client/cypress/locators/GeneratePage.json
+++ b/app/client/cypress/locators/GeneratePage.json
@@ -1,5 +1,4 @@
{
- "generateCRUDPageActionCard": "[data-testid='generate-app']",
"selectDatasourceDropdown": "[data-testid=t--datasource-dropdown]",
"datasourceDropdownOption": "[data-testid=t--datasource-dropdown-option]",
"selectTableDropdown": "[data-testid=t--table-dropdown]",
diff --git a/app/client/cypress/support/Pages/HomePage.ts b/app/client/cypress/support/Pages/HomePage.ts
index ee55d6323b..2ae8b77ff8 100644
--- a/app/client/cypress/support/Pages/HomePage.ts
+++ b/app/client/cypress/support/Pages/HomePage.ts
@@ -68,7 +68,6 @@ export class HomePage {
_applicationName = ".t--application-name";
private _editAppName = "bp3-editable-text-editing";
private _appMenu = ".ads-v2-menu__menu-item-children";
- _buildFromDataTableActionCard = "[data-testid='generate-app']";
private _selectRole = "//span[text()='Select a role']/ancestor::div";
private _searchInput = "input[type='text']";
_appHoverIcon = (action: string) => ".t--application-" + action + "-link";
diff --git a/app/client/cypress/support/Pages/Table.ts b/app/client/cypress/support/Pages/Table.ts
index 7847e109e1..bac5097877 100644
--- a/app/client/cypress/support/Pages/Table.ts
+++ b/app/client/cypress/support/Pages/Table.ts
@@ -37,9 +37,7 @@ export class Table {
private assertHelper = ObjectsRegistry.AssertHelper;
private _tableWrap = "//div[contains(@class,'tableWrap')]";
- private _tableHeader =
- this._tableWrap +
- "//div[contains(@class,'thead')]//div[contains(@class,'tr')][1]";
+ private _tableHeader = ".thead div[role=columnheader]";
private _columnHeader = (columnName: string) =>
this._tableWrap +
"//div[contains(@class,'thead')]//div[contains(@class,'tr')][1]//div[@role='columnheader']//div[contains(text(),'" +
@@ -258,7 +256,7 @@ export class Table {
}
public AssertTableHeaderOrder(expectedOrder: string) {
- cy.xpath(this._tableHeader)
+ cy.get(this._tableHeader)
.invoke("text")
.then((x) => {
expect(x).to.eq(expectedOrder);
diff --git a/app/client/packages/design-system/widgets/src/components/Link/src/Link.tsx b/app/client/packages/design-system/widgets/src/components/Link/src/Link.tsx
index a7f1aceedf..d11abd039d 100644
--- a/app/client/packages/design-system/widgets/src/components/Link/src/Link.tsx
+++ b/app/client/packages/design-system/widgets/src/components/Link/src/Link.tsx
@@ -18,18 +18,18 @@ export function Link(props: LinkProps) {
} = props;
return (
-
-
+
+
{children}
-
-
+
+
);
}
diff --git a/app/client/packages/design-system/widgets/src/components/Link/src/styles.module.css b/app/client/packages/design-system/widgets/src/components/Link/src/styles.module.css
index f816fa47d0..802a5aeaed 100644
--- a/app/client/packages/design-system/widgets/src/components/Link/src/styles.module.css
+++ b/app/client/packages/design-system/widgets/src/components/Link/src/styles.module.css
@@ -1,11 +1,19 @@
.link {
+ position: relative;
text-decoration: underline;
- text-decoration-color: currentColor;
text-underline-offset: 2px;
color: currentColor;
+ text-decoration-color: var(--color-bd-accent);
+ text-decoration-thickness: 0.5px;
- &:hover {
- color: currentColor;
- text-decoration-color: currentColor;
+ &[data-hovered] {
+ text-decoration: none;
+ }
+
+ &[data-focus-visible] {
+ border-radius: var(--border-radius-elevation-3);
+ outline: 2px solid var(--color-bd-focus);
+ outline-offset: 4px;
+ text-decoration: none;
}
}
diff --git a/app/client/src/UITelemetry/generateTraces.ts b/app/client/src/UITelemetry/generateTraces.ts
index b7e358f6a3..08b977a62d 100644
--- a/app/client/src/UITelemetry/generateTraces.ts
+++ b/app/client/src/UITelemetry/generateTraces.ts
@@ -14,6 +14,9 @@ import { matchBuilderPath, matchViewerPath } from "constants/routes";
const GENERATOR_TRACE = "generator-tracer";
+export type OtlpSpan = Span;
+export type SpanAttributes = Attributes;
+
const getCommonTelemetryAttributes = () => {
const pathname = window.location.pathname;
const isEditorUrl = matchBuilderPath(pathname);
@@ -33,16 +36,13 @@ const getCommonTelemetryAttributes = () => {
export function startRootSpan(
spanName: string,
- spanAttributes: Attributes = {},
+ spanAttributes: SpanAttributes = {},
startTime?: TimeInput,
) {
const tracer = trace.getTracer(GENERATOR_TRACE);
- if (!spanName) {
- return;
- }
const commonAttributes = getCommonTelemetryAttributes();
- return tracer?.startSpan(spanName, {
+ return tracer.startSpan(spanName, {
kind: SpanKind.CLIENT,
attributes: {
...commonAttributes,
@@ -56,15 +56,10 @@ export const generateContext = (span: Span) => {
};
export function startNestedSpan(
spanName: string,
- parentSpan?: Span,
- spanAttributes: Attributes = {},
+ parentSpan: Span,
+ spanAttributes: SpanAttributes = {},
startTime?: TimeInput,
) {
- if (!spanName || !parentSpan) {
- // do not generate nested span without parentSpan..we cannot generate context out of it
- return;
- }
-
const parentContext = generateContext(parentSpan);
const generatorTrace = trace.getTracer(GENERATOR_TRACE);
@@ -81,14 +76,14 @@ export function startNestedSpan(
return generatorTrace.startSpan(spanName, spanOptions, parentContext);
}
-export function endSpan(span?: Span) {
- span?.end();
+export function endSpan(span: Span) {
+ span.end();
}
-export function setAttributesToSpan(span: Span, spanAttributes: Attributes) {
- if (!span) {
- return;
- }
+export function setAttributesToSpan(
+ span: Span,
+ spanAttributes: SpanAttributes,
+) {
span.setAttributes(spanAttributes);
}
@@ -96,5 +91,3 @@ export function wrapFnWithParentTraceContext(parentSpan: Span, fn: () => any) {
const parentContext = trace.setSpan(context.active(), parentSpan);
return context.with(parentContext, fn);
}
-
-export type OtlpSpan = Span;
diff --git a/app/client/src/UITelemetry/generateWebWorkerTraces.ts b/app/client/src/UITelemetry/generateWebWorkerTraces.ts
index 32c8ae3123..a9133cb32f 100644
--- a/app/client/src/UITelemetry/generateWebWorkerTraces.ts
+++ b/app/client/src/UITelemetry/generateWebWorkerTraces.ts
@@ -1,8 +1,9 @@
+import type { OtlpSpan, SpanAttributes } from "./generateTraces";
import { startNestedSpan } from "./generateTraces";
-import type { TimeInput, Attributes, Span } from "@opentelemetry/api";
+import type { TimeInput } from "@opentelemetry/api";
export interface WebworkerSpanData {
- attributes: Attributes;
+ attributes: SpanAttributes;
spanName: string;
startTime: TimeInput;
endTime: TimeInput;
@@ -13,7 +14,7 @@ export interface WebworkerSpanData {
//to regular otlp telemetry data and subsequently exported to our telemetry collector
export const newWebWorkerSpanData = (
spanName: string,
- attributes: Attributes,
+ attributes: SpanAttributes,
): WebworkerSpanData => {
return {
attributes,
@@ -29,8 +30,8 @@ const addEndTimeForWebWorkerSpanData = (span: WebworkerSpanData) => {
export const profileFn = (
spanName: string,
- attributes: Attributes = {},
- allSpans: Record,
+ attributes: SpanAttributes = {},
+ allSpans: Record,
fn: (...args: any[]) => any,
) => {
const span = newWebWorkerSpanData(spanName, attributes);
@@ -42,7 +43,7 @@ export const profileFn = (
//convert webworker spans to OTLP spans
export const convertWebworkerSpansToRegularSpans = (
- parentSpan: Span,
+ parentSpan: OtlpSpan,
allSpans: Record = {},
) => {
Object.values(allSpans)
@@ -53,3 +54,14 @@ export const convertWebworkerSpansToRegularSpans = (
span?.end(endTime);
});
};
+
+export const filterSpanData = (
+ spanData: Record,
+): Record => {
+ return Object.keys(spanData)
+ .filter((key) => !key.startsWith("__"))
+ .reduce>((obj, key) => {
+ obj[key] = spanData[key] as WebworkerSpanData;
+ return obj;
+ }, {});
+};
diff --git a/app/client/src/actions/gitSyncActions.ts b/app/client/src/actions/gitSyncActions.ts
index 29032f6435..fdda241f5a 100644
--- a/app/client/src/actions/gitSyncActions.ts
+++ b/app/client/src/actions/gitSyncActions.ts
@@ -6,7 +6,10 @@ import {
ReduxActionErrorTypes,
ReduxActionTypes,
} from "@appsmith/constants/ReduxActionConstants";
-import type { ConnectToGitPayload } from "api/GitSyncAPI";
+import type {
+ ConnectToGitPayload,
+ GitAutocommitProgressResponse,
+} from "api/GitSyncAPI";
import type { GitConfig, GitSyncModalTab, MergeStatus } from "entities/GitSync";
import type { GitApplicationMetadata } from "@appsmith/api/ApplicationApi";
import {
@@ -480,6 +483,7 @@ export const setShowBranchPopupAction = (show: boolean) => {
};
};
+// START autocommit
export const toggleAutocommitEnabledInit = () => ({
type: ReduxActionTypes.GIT_TOGGLE_AUTOCOMMIT_ENABLED_INIT,
});
@@ -489,14 +493,60 @@ export const setIsAutocommitModalOpen = (isAutocommitModalOpen: boolean) => ({
payload: { isAutocommitModalOpen },
});
-export const startAutocommitProgressPolling = () => ({
- type: ReduxActionTypes.GIT_AUTOCOMMIT_INITIATE_PROGRESS_POLLING,
+export const triggerAutocommitInitAction = () => ({
+ type: ReduxActionTypes.GIT_AUTOCOMMIT_TRIGGER_INIT,
});
-export const stopAutocommitProgressPolling = () => ({
+export const triggerAutocommitSuccessAction = () => ({
+ type: ReduxActionTypes.GIT_AUTOCOMMIT_TRIGGER_SUCCESS,
+});
+
+export interface TriggerAutocommitErrorActionPayload {
+ error: any;
+ show: boolean;
+}
+
+export const triggerAutocommitErrorAction = (
+ payload: TriggerAutocommitErrorActionPayload,
+) => ({
+ type: ReduxActionErrorTypes.GIT_AUTOCOMMIT_TRIGGER_ERROR,
+ payload,
+});
+
+export const startAutocommitProgressPollingAction = () => ({
+ type: ReduxActionTypes.GIT_AUTOCOMMIT_START_PROGRESS_POLLING,
+});
+
+export const stopAutocommitProgressPollingAction = () => ({
type: ReduxActionTypes.GIT_AUTOCOMMIT_STOP_PROGRESS_POLLING,
});
+export type SetAutocommitActionPayload = GitAutocommitProgressResponse;
+
+export const setAutocommitProgressAction = (
+ payload: SetAutocommitActionPayload,
+) => ({
+ type: ReduxActionTypes.GIT_SET_AUTOCOMMIT_PROGRESS,
+ payload,
+});
+
+export const resetAutocommitProgressAction = () => ({
+ type: ReduxActionTypes.GIT_RESET_AUTOCOMMIT_PROGRESS,
+});
+
+export interface AutocommitProgressErrorActionPayload {
+ error: any;
+ show: boolean;
+}
+
+export const autoCommitProgressErrorAction = (
+ payload: AutocommitProgressErrorActionPayload,
+) => ({
+ type: ReduxActionErrorTypes.GIT_AUTOCOMMIT_PROGRESS_POLLING_ERROR,
+ payload,
+});
+// END autocommit
+
export const getGitMetadataInitAction = () => ({
type: ReduxActionTypes.GIT_GET_METADATA_INIT,
});
diff --git a/app/client/src/api/GitSyncAPI.tsx b/app/client/src/api/GitSyncAPI.tsx
index c3c0150b86..22509b3041 100644
--- a/app/client/src/api/GitSyncAPI.tsx
+++ b/app/client/src/api/GitSyncAPI.tsx
@@ -43,6 +43,27 @@ interface GitRemoteStatusParam {
branch: string;
}
+export enum AutocommitResponseEnum {
+ IN_PROGRESS = "IN_PROGRESS",
+ LOCKED = "LOCKED",
+ PUBLISHED = "PUBLISHED",
+ IDLE = "IDLE",
+ NOT_REQUIRED = "NOT_REQUIRED",
+ NON_GIT_APP = "NON_GIT_APP",
+}
+
+export interface GitAutocommitProgressResponse {
+ autoCommitResponse: AutocommitResponseEnum;
+ progress: number;
+ branchName: string;
+}
+
+export interface GitTriggerAutocommitResponse {
+ autoCommitResponse: AutocommitResponseEnum;
+ progress: number;
+ branchName: string;
+}
+
class GitSyncAPI extends Api {
static baseURL = `/v1/git`;
@@ -227,6 +248,12 @@ class GitSyncAPI extends Api {
);
}
+ static async triggerAutocommit(applicationId: string, branchName: string) {
+ return Api.post(
+ `${GitSyncAPI.baseURL}/auto-commit/app/${applicationId}?branchName=${branchName}`,
+ );
+ }
+
static async getAutocommitProgress(applicationId: string) {
return Api.get(
`${GitSyncAPI.baseURL}/auto-commit/progress/app/${applicationId}`,
diff --git a/app/client/src/ce/constants/ReduxActionConstants.tsx b/app/client/src/ce/constants/ReduxActionConstants.tsx
index 558200332e..8d49cfbc7b 100644
--- a/app/client/src/ce/constants/ReduxActionConstants.tsx
+++ b/app/client/src/ce/constants/ReduxActionConstants.tsx
@@ -131,8 +131,8 @@ const ActionTypes = {
GIT_TOGGLE_AUTOCOMMIT_ENABLED_INIT: "GIT_TOGGLE_AUTOCOMMIT_ENABLED_INIT",
GIT_TOGGLE_AUTOCOMMIT_ENABLED_SUCCESS:
"GIT_TOGGLE_AUTOCOMMIT_ENABLED_SUCCESS",
- GIT_AUTOCOMMIT_INITIATE_PROGRESS_POLLING:
- "GIT_AUTOCOMMIT_INITIATE_PROGRESS_POLLING",
+ GIT_AUTOCOMMIT_TRIGGER_INIT: "GIT_AUTOCOMMIT_TRIGGER_INIT",
+ GIT_AUTOCOMMIT_TRIGGER_SUCCESS: "GIT_AUTOCOMMIT_TRIGGER_SUCCESS",
GIT_AUTOCOMMIT_START_PROGRESS_POLLING:
"GIT_AUTOCOMMIT_START_PROGRESS_POLLING",
GIT_AUTOCOMMIT_STOP_PROGRESS_POLLING: "GIT_AUTOCOMMIT_STOP_PROGRESS_POLLING",
@@ -962,6 +962,7 @@ export const ReduxActionErrorTypes = {
GIT_TOGGLE_AUTOCOMMIT_ENABLED_ERROR: "GIT_TOGGLE_AUTOCOMMIT_ENABLED_ERROR",
GIT_AUTOCOMMIT_PROGRESS_POLLING_ERROR:
"GIT_AUTOCOMMIT_PROGRESS_POLLING_ERROR",
+ GIT_AUTOCOMMIT_TRIGGER_ERROR: "GIT_AUTOCOMMIT_TRIGGER_ERROR",
GIT_GET_METADATA_ERROR: "GIT_GET_METADATA_ERROR",
FETCH_FEATURE_FLAGS_ERROR: "FETCH_FEATURE_FLAGS_ERROR",
FETCH_NOTIFICATIONS_ERROR: "FETCH_NOTIFICATIONS_ERROR",
diff --git a/app/client/src/ce/pages/Applications/CreateNewAppsOption.test.tsx b/app/client/src/ce/pages/Applications/CreateNewAppsOption.test.tsx
new file mode 100644
index 0000000000..97f9290e98
--- /dev/null
+++ b/app/client/src/ce/pages/Applications/CreateNewAppsOption.test.tsx
@@ -0,0 +1,119 @@
+import "@testing-library/jest-dom/extend-expect";
+import React from "react";
+import { render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
+import { lightTheme } from "selectors/themeSelectors";
+import { ThemeProvider } from "styled-components";
+import CreateNewAppsOption from "./CreateNewAppsOption";
+import { BrowserRouter as Router } from "react-router-dom";
+import { unitTestBaseMockStore } from "layoutSystems/common/dropTarget/unitTestUtils";
+
+const defaultStoreState = {
+ ...unitTestBaseMockStore,
+ tenant: {
+ tenantConfiguration: {},
+ },
+ entities: {
+ ...unitTestBaseMockStore.entities,
+ plugins: {
+ list: [],
+ },
+ datasources: {
+ list: [],
+ mockDatasourceList: [],
+ },
+ },
+ ui: {
+ ...unitTestBaseMockStore.ui,
+ selectedWorkspace: {
+ ...unitTestBaseMockStore.ui.selectedWorkspace,
+ applications: [unitTestBaseMockStore.ui.applications.currentApplication],
+ },
+ debugger: {
+ isOpen: false,
+ },
+ editor: {
+ loadingStates: {},
+ isProtectedMode: true,
+ zoomLevel: 1,
+ },
+ gitSync: {
+ globalGitConfig: {},
+ branches: [],
+ localGitConfig: {},
+ disconnectingGitApp: {},
+ },
+ users: {
+ loadingStates: {},
+ list: [],
+ users: [],
+ error: "",
+ currentUser: {},
+ featureFlag: {
+ data: {},
+ isFetched: true,
+ overriddenFlags: {},
+ },
+ productAlert: {
+ config: {},
+ },
+ },
+ apiPane: {
+ isCreating: false,
+ isRunning: {},
+ isSaving: {},
+ isDeleting: {},
+ isDirty: {},
+ extraformData: {},
+ selectedConfigTabIndex: 0,
+ debugger: {
+ open: false,
+ },
+ },
+ },
+};
+const mockStore = configureStore([]);
+describe("CreateNewAppsOption", () => {
+ let store: any;
+ it("Should not render skip button if no application is present", () => {
+ store = mockStore(defaultStoreState);
+
+ render(
+
+
+
+
+
+
+ ,
+ );
+
+ const button = screen.queryAllByTestId("t--create-new-app-option-skip");
+
+ // Check that the skip button to be absent in the document
+ expect(button).toHaveLength(0);
+ });
+
+ it("Should render skip button if application is present", () => {
+ render(
+
+
+
+
+
+
+ ,
+ );
+
+ const button = screen.queryAllByTestId("t--create-new-app-option-skip");
+
+ // Check that the skip button to be present in the document
+ expect(button).toHaveLength(1);
+ });
+
+ afterAll(() => {
+ jest.clearAllMocks();
+ store.clearActions();
+ });
+});
diff --git a/app/client/src/ce/pages/Applications/CreateNewAppsOption.tsx b/app/client/src/ce/pages/Applications/CreateNewAppsOption.tsx
index c151b5663e..2de8283c35 100644
--- a/app/client/src/ce/pages/Applications/CreateNewAppsOption.tsx
+++ b/app/client/src/ce/pages/Applications/CreateNewAppsOption.tsx
@@ -140,25 +140,24 @@ const CreateNewAppsOption = ({
};
const onClickSkipButton = () => {
- if (application) {
- urlBuilder.updateURLParams(
- {
- applicationSlug: application.slug,
- applicationVersion: application.applicationVersion,
- applicationId: application.id,
- },
- application.pages.map((page) => ({
- pageSlug: page.slug,
- customSlug: page.customSlug,
- pageId: page.id,
- })),
- );
- history.push(
- builderURL({
- pageId: application.pages[0].id,
- }),
- );
- }
+ const applicationObject = application!;
+ urlBuilder.updateURLParams(
+ {
+ applicationSlug: applicationObject.slug,
+ applicationVersion: applicationObject.applicationVersion,
+ applicationId: applicationObject.id,
+ },
+ applicationObject.pages.map((page) => ({
+ pageSlug: page.slug,
+ customSlug: page.customSlug,
+ pageId: page.id,
+ })),
+ );
+ history.push(
+ builderURL({
+ pageId: applicationObject.pages[0].id,
+ }),
+ );
addAnalyticEventsForSkip();
};
@@ -214,15 +213,16 @@ const CreateNewAppsOption = ({
>
{createMessage(GO_BACK)}
-
-
- {createMessage(SKIP_START_WITH_USE_CASE_TEMPLATES)}
-
+ {application && (
+
+ {createMessage(SKIP_START_WITH_USE_CASE_TEMPLATES)}
+
+ )}
{
method: TActions;
data: TData;
- webworkerTelemetry: Record;
+ webworkerTelemetry: Record;
}
diff --git a/app/client/src/entities/Engine/AppEditorEngine.ts b/app/client/src/entities/Engine/AppEditorEngine.ts
index 092f856a2c..407c72fa0b 100644
--- a/app/client/src/entities/Engine/AppEditorEngine.ts
+++ b/app/client/src/entities/Engine/AppEditorEngine.ts
@@ -5,7 +5,7 @@ import {
remoteUrlInputValue,
resetPullMergeStatus,
fetchBranchesInit,
- startAutocommitProgressPolling,
+ triggerAutocommitInitAction,
getGitMetadataInitAction,
} from "actions/gitSyncActions";
import { restoreRecentEntitiesRequest } from "actions/globalSearchActions";
@@ -296,10 +296,8 @@ export default class AppEditorEngine extends AppEngine {
yield put(fetchGitProtectedBranchesInit());
yield put(fetchGitProtectedBranchesInit());
yield put(getGitMetadataInitAction());
-
+ yield put(triggerAutocommitInitAction());
yield put(fetchGitStatusInit({ compareRemote: true }));
-
- yield put(startAutocommitProgressPolling());
yield put(resetPullMergeStatus());
}
}
diff --git a/app/client/src/pages/Editor/gitSync/QuickGitActions/BranchButton.tsx b/app/client/src/pages/Editor/gitSync/QuickGitActions/BranchButton.tsx
index 16a9fd459e..0f11070f48 100644
--- a/app/client/src/pages/Editor/gitSync/QuickGitActions/BranchButton.tsx
+++ b/app/client/src/pages/Editor/gitSync/QuickGitActions/BranchButton.tsx
@@ -9,6 +9,8 @@ import { getCurrentAppGitMetaData } from "@appsmith/selectors/applicationSelecto
import BranchList from "../components/BranchList";
import {
getGitStatus,
+ getIsPollingAutocommit,
+ getIsTriggeringAutocommit,
protectedModeSelector,
showBranchPopupSelector,
} from "selectors/gitSyncSelectors";
@@ -28,6 +30,10 @@ const ButtonContainer = styled(Button)`
margin: 0 ${(props) => props.theme.spaces[4]}px;
max-width: 122px;
min-width: unset !important;
+
+ :active {
+ border: 1px solid var(--ads-v2-color-border-muted);
+ }
`;
function BranchButton() {
@@ -38,6 +44,9 @@ function BranchButton() {
const labelTarget = useRef(null);
const status = useSelector(getGitStatus);
const isOpen = useSelector(showBranchPopupSelector);
+ const triggeringAutocommit = useSelector(getIsTriggeringAutocommit);
+ const pollingAutocommit = useSelector(getIsPollingAutocommit);
+ const isBranchChangeDisabled = triggeringAutocommit || pollingAutocommit;
const setIsOpen = (isOpen: boolean) => {
dispatch(setShowBranchPopupAction(isOpen));
@@ -47,6 +56,7 @@ function BranchButton() {
}
data-testid={"t--git-branch-button-popover"}
+ disabled={isBranchChangeDisabled}
hasBackdrop
isOpen={isOpen}
minimal
@@ -69,6 +79,7 @@ function BranchButton() {
{isProtectedMode ? (
diff --git a/app/client/src/reducers/uiReducers/gitSyncReducer.ts b/app/client/src/reducers/uiReducers/gitSyncReducer.ts
index 454a080061..8112865971 100644
--- a/app/client/src/reducers/uiReducers/gitSyncReducer.ts
+++ b/app/client/src/reducers/uiReducers/gitSyncReducer.ts
@@ -55,6 +55,7 @@ const initialState: GitSyncReducerState = {
isAutocommitModalOpen: false,
togglingAutocommit: false,
+ triggeringAutocommit: false,
pollingAutocommitStatus: false,
gitMetadata: null,
@@ -619,6 +620,18 @@ const gitSyncReducer = createReducer(initialState, {
...state,
togglingAutocommit: false,
}),
+ [ReduxActionTypes.GIT_AUTOCOMMIT_TRIGGER_INIT]: (state) => ({
+ ...state,
+ triggeringAutocommit: true,
+ }),
+ [ReduxActionTypes.GIT_AUTOCOMMIT_TRIGGER_SUCCESS]: (state) => ({
+ ...state,
+ triggeringAutocommit: false,
+ }),
+ [ReduxActionErrorTypes.GIT_AUTOCOMMIT_TRIGGER_ERROR]: (state) => ({
+ ...state,
+ triggeringAutocommit: false,
+ }),
[ReduxActionTypes.GIT_AUTOCOMMIT_START_PROGRESS_POLLING]: (state) => ({
...state,
pollingAutocommitStatus: true,
@@ -833,6 +846,7 @@ export type GitSyncReducerState = GitBranchDeleteState & {
isAutocommitModalOpen: boolean;
togglingAutocommit: boolean;
+ triggeringAutocommit: boolean;
pollingAutocommitStatus: boolean;
gitMetadata: GitMetadata | null;
diff --git a/app/client/src/sagas/ActionExecution/PluginActionSaga.ts b/app/client/src/sagas/ActionExecution/PluginActionSaga.ts
index 8da86d8cc3..f474374a59 100644
--- a/app/client/src/sagas/ActionExecution/PluginActionSaga.ts
+++ b/app/client/src/sagas/ActionExecution/PluginActionSaga.ts
@@ -1662,7 +1662,9 @@ function* handleUpdateActionData(
EVAL_WORKER_ACTIONS.UPDATE_ACTION_DATA,
actionDataPayload,
);
- endSpan(parentSpan);
+ if (parentSpan) {
+ endSpan(parentSpan);
+ }
}
export function* watchPluginActionExecutionSagas() {
diff --git a/app/client/src/sagas/GitSyncSagas.ts b/app/client/src/sagas/GitSyncSagas.ts
index 095689e541..75e2309b2b 100644
--- a/app/client/src/sagas/GitSyncSagas.ts
+++ b/app/client/src/sagas/GitSyncSagas.ts
@@ -20,8 +20,13 @@ import {
takeLatest,
} from "redux-saga/effects";
import type { TakeableChannel } from "@redux-saga/core";
-import type { MergeBranchPayload, MergeStatusPayload } from "api/GitSyncAPI";
-import GitSyncAPI from "api/GitSyncAPI";
+import type {
+ GitAutocommitProgressResponse,
+ GitTriggerAutocommitResponse,
+ MergeBranchPayload,
+ MergeStatusPayload,
+} from "api/GitSyncAPI";
+import GitSyncAPI, { AutocommitResponseEnum } from "api/GitSyncAPI";
import {
getCurrentApplicationId,
getCurrentPageId,
@@ -40,6 +45,13 @@ import {
updateGitProtectedBranchesInit,
clearCommitSuccessfulState,
setShowBranchPopupAction,
+ stopAutocommitProgressPollingAction,
+ startAutocommitProgressPollingAction,
+ setAutocommitProgressAction,
+ autoCommitProgressErrorAction,
+ resetAutocommitProgressAction,
+ triggerAutocommitErrorAction,
+ triggerAutocommitSuccessAction,
} from "actions/gitSyncActions";
import {
commitToRepoSuccess,
@@ -103,6 +115,7 @@ import { addBranchParam, GIT_BRANCH_QUERY_KEY } from "constants/routes";
import {
getCurrentGitBranch,
getDisconnectingGitApplication,
+ getGitMetadataSelector,
} from "selectors/gitSyncSelectors";
import { initEditor } from "actions/initActions";
import { fetchPage } from "actions/pageActions";
@@ -113,7 +126,10 @@ import { log } from "loglevel";
import GIT_ERROR_CODES from "constants/GitErrorCodes";
import { builderURL } from "@appsmith/RouteBuilder";
import { APP_MODE } from "entities/App";
-import type { GitDiscardResponse } from "reducers/uiReducers/gitSyncReducer";
+import type {
+ GitDiscardResponse,
+ GitMetadata,
+} from "reducers/uiReducers/gitSyncReducer";
import { FocusEntity, identifyEntityFromPath } from "navigation/FocusEntity";
import {
getActions,
@@ -123,6 +139,8 @@ import type { Action } from "entities/Action";
import type { JSCollectionDataState } from "@appsmith/reducers/entityReducers/jsActionsReducer";
import { toast } from "design-system";
import { gitExtendedSagas } from "@appsmith/sagas/GitExtendedSagas";
+import { selectFeatureFlagCheck } from "@appsmith/selectors/featureFlagsSelectors";
+import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
export function* handleRepoLimitReachedError(response?: ApiResponse) {
const { responseMeta } = response || {};
@@ -1159,78 +1177,110 @@ function* getGitMetadataSaga() {
}
}
+function isAutocommitHappening(
+ response:
+ | GitTriggerAutocommitResponse
+ | GitAutocommitProgressResponse
+ | undefined,
+): boolean {
+ return (
+ !!response &&
+ !!(
+ response.autoCommitResponse === AutocommitResponseEnum.PUBLISHED ||
+ response.autoCommitResponse === AutocommitResponseEnum.IN_PROGRESS ||
+ response.autoCommitResponse === AutocommitResponseEnum.LOCKED
+ )
+ );
+}
+
function* pollAutocommitProgressSaga(): any {
const applicationId: string = yield select(getCurrentApplicationId);
+ const branchName: string = yield select(getCurrentGitBranch);
+
+ let triggerResponse: ApiResponse | undefined;
try {
- const response: ApiResponse = yield call(
- GitSyncAPI.getAutocommitProgress,
+ const res = yield call(
+ GitSyncAPI.triggerAutocommit,
applicationId,
+ branchName,
);
const isValidResponse: boolean = yield validateResponse(
- response,
+ res,
false,
- getLogToSentryFromResponse(response),
+ getLogToSentryFromResponse(res),
);
- if (isValidResponse && response?.data?.isRunning) {
- yield put({
- type: ReduxActionTypes.GIT_AUTOCOMMIT_START_PROGRESS_POLLING,
- });
+ if (isValidResponse) {
+ triggerResponse = res;
+ yield put(triggerAutocommitSuccessAction());
+ } else {
+ yield put(
+ triggerAutocommitErrorAction({
+ error: res?.responseMeta?.error?.message,
+ show: true,
+ }),
+ );
+ }
+ } catch (err) {
+ yield put(triggerAutocommitErrorAction({ error: err, show: false }));
+ }
+
+ try {
+ if (isAutocommitHappening(triggerResponse?.data)) {
+ yield put(startAutocommitProgressPollingAction());
while (true) {
- const response: ApiResponse = yield call(
- GitSyncAPI.getAutocommitProgress,
- applicationId,
- );
+ const progressResponse: ApiResponse =
+ yield call(GitSyncAPI.getAutocommitProgress, applicationId);
const isValidResponse: boolean = yield validateResponse(
- response,
+ progressResponse,
false,
- getLogToSentryFromResponse(response),
+ getLogToSentryFromResponse(progressResponse),
);
if (isValidResponse) {
- yield put({
- type: ReduxActionTypes.GIT_SET_AUTOCOMMIT_PROGRESS,
- payload: response.data,
- });
- if (!response?.data?.isRunning) {
- yield put({
- type: ReduxActionTypes.GIT_AUTOCOMMIT_STOP_PROGRESS_POLLING,
- });
+ yield put(setAutocommitProgressAction(progressResponse.data));
+ if (!isAutocommitHappening(progressResponse?.data)) {
+ yield put(stopAutocommitProgressPollingAction());
}
} else {
- yield put({
- type: ReduxActionTypes.GIT_AUTOCOMMIT_STOP_PROGRESS_POLLING,
- });
- yield put({
- type: ReduxActionErrorTypes.GIT_AUTOCOMMIT_PROGRESS_POLLING_ERROR,
- payload: {
- error: response?.responseMeta?.error?.message,
+ yield put(stopAutocommitProgressPollingAction());
+ yield put(
+ autoCommitProgressErrorAction({
+ error: progressResponse?.responseMeta?.error?.message,
show: true,
- },
- });
+ }),
+ );
}
yield delay(1000);
}
} else {
- yield put({
- type: ReduxActionTypes.GIT_AUTOCOMMIT_STOP_PROGRESS_POLLING,
- });
+ yield put(stopAutocommitProgressPollingAction());
}
} catch (error) {
- yield put({
- type: ReduxActionTypes.GIT_AUTOCOMMIT_STOP_PROGRESS_POLLING,
- });
- yield put({
- type: ReduxActionErrorTypes.GIT_AUTOCOMMIT_PROGRESS_POLLING_ERROR,
- payload: { error },
- });
+ yield put(stopAutocommitProgressPollingAction());
+ yield put(autoCommitProgressErrorAction({ error, show: false }));
} finally {
if (yield cancelled()) {
- yield put({
- type: ReduxActionTypes.GIT_RESET_AUTOCOMMIT_PROGRESS,
- });
+ yield put(resetAutocommitProgressAction());
}
}
}
+function* triggerAutocommitSaga() {
+ const isAutocommitFeatureEnabled: boolean = yield select(
+ selectFeatureFlagCheck,
+ FEATURE_FLAG.release_git_autocommit_feature_enabled,
+ );
+ const gitMetadata: GitMetadata = yield select(getGitMetadataSelector);
+ const isAutocommitEnabled: boolean = !!gitMetadata?.autoCommitConfig?.enabled;
+ if (isAutocommitFeatureEnabled && isAutocommitEnabled) {
+ /* @ts-expect-error: not sure how to do typings of this */
+ const pollTask = yield fork(pollAutocommitProgressSaga);
+ yield take(ReduxActionTypes.GIT_AUTOCOMMIT_STOP_PROGRESS_POLLING);
+ yield cancel(pollTask);
+ } else {
+ yield put(triggerAutocommitSuccessAction());
+ }
+}
+
const gitRequestBlockingActions: Record<
(typeof ReduxActionTypes)[keyof typeof ReduxActionTypes],
(...args: any[]) => any
@@ -1252,6 +1302,9 @@ const gitRequestBlockingActions: Record<
[ReduxActionTypes.GIT_DISCARD_CHANGES]: discardChanges,
[ReduxActionTypes.GIT_UPDATE_PROTECTED_BRANCHES_INIT]:
updateGitProtectedBranchesSaga,
+ [ReduxActionTypes.GIT_AUTOCOMMIT_TRIGGER_INIT]: triggerAutocommitSaga,
+ [ReduxActionTypes.FETCH_GIT_STATUS_INIT]: fetchGitStatusSaga,
+ [ReduxActionTypes.GIT_GET_METADATA_INIT]: getGitMetadataSaga,
};
const gitRequestNonBlockingActions: Record<
@@ -1261,13 +1314,11 @@ const gitRequestNonBlockingActions: Record<
...gitExtendedSagas,
[ReduxActionTypes.FETCH_GLOBAL_GIT_CONFIG_INIT]: fetchGlobalGitConfig,
[ReduxActionTypes.FETCH_LOCAL_GIT_CONFIG_INIT]: fetchLocalGitConfig,
- [ReduxActionTypes.FETCH_GIT_STATUS_INIT]: fetchGitStatusSaga,
[ReduxActionTypes.SHOW_CONNECT_GIT_MODAL]: showConnectGitModal,
[ReduxActionTypes.FETCH_SSH_KEY_PAIR_INIT]: getSSHKeyPairSaga,
[ReduxActionTypes.GIT_FETCH_PROTECTED_BRANCHES_INIT]:
fetchGitProtectedBranchesSaga,
[ReduxActionTypes.GIT_TOGGLE_AUTOCOMMIT_ENABLED_INIT]: toggleAutocommitSaga,
- [ReduxActionTypes.GIT_GET_METADATA_INIT]: getGitMetadataSaga,
};
/**
@@ -1298,18 +1349,7 @@ function* watchGitNonBlockingRequests() {
}
}
-function* watchGitAutocommitPolling() {
- while (true) {
- yield take(ReduxActionTypes.GIT_AUTOCOMMIT_INITIATE_PROGRESS_POLLING);
- /* @ts-expect-error: not sure how to do typings of this */
- const pollTask = yield fork(pollAutocommitProgressSaga);
- yield take(ReduxActionTypes.GIT_AUTOCOMMIT_STOP_PROGRESS_POLLING);
- yield cancel(pollTask);
- }
-}
-
export default function* gitSyncSagas() {
yield fork(watchGitNonBlockingRequests);
yield fork(watchGitBlockingRequests);
- yield fork(watchGitAutocommitPolling);
}
diff --git a/app/client/src/selectors/gitSyncSelectors.tsx b/app/client/src/selectors/gitSyncSelectors.tsx
index 73fa17e8ee..9c9e5e5b69 100644
--- a/app/client/src/selectors/gitSyncSelectors.tsx
+++ b/app/client/src/selectors/gitSyncSelectors.tsx
@@ -257,6 +257,9 @@ export const getIsAutocommitToggling = (state: AppState) =>
export const getIsAutocommitModalOpen = (state: AppState) =>
state.ui.gitSync.isAutocommitModalOpen;
+export const getIsTriggeringAutocommit = (state: AppState) =>
+ state.ui.gitSync.triggeringAutocommit;
+
export const getIsPollingAutocommit = (state: AppState) =>
state.ui.gitSync.pollingAutocommitStatus;
diff --git a/app/client/src/utils/WorkerUtil.ts b/app/client/src/utils/WorkerUtil.ts
index a431b12c51..b9033f6a29 100644
--- a/app/client/src/utils/WorkerUtil.ts
+++ b/app/client/src/utils/WorkerUtil.ts
@@ -5,11 +5,16 @@ import { uniqueId } from "lodash";
import log from "loglevel";
import type { TMessage } from "./MessageUtil";
import { MessageType, sendMessage } from "./MessageUtil";
-import type { OtlpSpan } from "UITelemetry/generateTraces";
-import { endSpan, startRootSpan } from "UITelemetry/generateTraces";
+import type { OtlpSpan, SpanAttributes } from "UITelemetry/generateTraces";
+import {
+ endSpan,
+ setAttributesToSpan,
+ startRootSpan,
+} from "UITelemetry/generateTraces";
import type { WebworkerSpanData } from "UITelemetry/generateWebWorkerTraces";
import {
convertWebworkerSpansToRegularSpans,
+ filterSpanData,
newWebWorkerSpanData,
} from "UITelemetry/generateWebWorkerTraces";
@@ -156,33 +161,35 @@ export class GracefulWorkerService {
startTime,
webworkerTelemetry,
}: {
- webworkerTelemetry: Record;
+ webworkerTelemetry:
+ | Record
+ | undefined;
rootSpan: OtlpSpan | undefined;
method: string;
startTime: number;
endTime: number;
}) {
- const webworkerTelemetryResponse = webworkerTelemetry as Record<
- string,
- WebworkerSpanData
- >;
-
- if (webworkerTelemetryResponse) {
- const { transferDataToMainThread } = webworkerTelemetryResponse;
- if (transferDataToMainThread) {
- transferDataToMainThread.endTime = Date.now();
- }
- /// Add the completeWebworkerComputation span to the root span
- webworkerTelemetryResponse["completeWebworkerComputation"] = {
- startTime,
- endTime,
- attributes: {},
- spanName: "completeWebworkerComputation",
- };
+ if (!webworkerTelemetry) {
+ return;
}
+
+ const { transferDataToMainThread } = webworkerTelemetry;
+ if (transferDataToMainThread) {
+ transferDataToMainThread.endTime = Date.now();
+ }
+ /// Add the completeWebworkerComputation span to the root span
+ webworkerTelemetry["completeWebworkerComputation"] = {
+ startTime,
+ endTime,
+ attributes: {},
+ spanName: "completeWebworkerComputation",
+ };
//we are attaching the child spans to the root span over here
rootSpan &&
- convertWebworkerSpansToRegularSpans(rootSpan, webworkerTelemetryResponse);
+ convertWebworkerSpansToRegularSpans(
+ rootSpan,
+ filterSpanData(webworkerTelemetry),
+ );
//genereate separate completeWebworkerComputationRoot root span
// this span does not contain any child spans, it just captures the webworker computation alone
@@ -218,11 +225,15 @@ export class GracefulWorkerService {
let timeTaken;
const rootSpan = startRootSpan(method);
- const webworkerTelemetryData: Record = {
+ const webworkerTelemetryData: Record<
+ string,
+ WebworkerSpanData | SpanAttributes
+ > = {
transferDataToWorkerThread: newWebWorkerSpanData(
"transferDataToWorkerThread",
{},
),
+ __spanAttributes: {},
};
const body = {
@@ -231,6 +242,11 @@ export class GracefulWorkerService {
webworkerTelemetry: webworkerTelemetryData,
};
+ let webworkerTelemetryResponse: Record<
+ string,
+ WebworkerSpanData | SpanAttributes
+ > = {};
+
try {
sendMessage.call(this._Worker, {
messageType: MessageType.REQUEST,
@@ -241,9 +257,10 @@ export class GracefulWorkerService {
// The `this._broker` method is listening to events and will pass response to us over this channel.
const response = yield take(ch);
const { data, endTime, startTime } = response;
- const { webworkerTelemetry } = data;
+ webworkerTelemetryResponse = data.webworkerTelemetry;
+
this.addChildSpansToRootSpan({
- webworkerTelemetry,
+ webworkerTelemetry: webworkerTelemetryResponse,
rootSpan,
method,
startTime,
@@ -268,6 +285,14 @@ export class GracefulWorkerService {
log.debug(` Worker ${method} took ${timeTaken}ms`);
log.debug(` Transfer ${method} took ${transferTime}ms`);
}
+
+ if (webworkerTelemetryResponse) {
+ setAttributesToSpan(
+ rootSpan,
+ webworkerTelemetryResponse.__spanAttributes as SpanAttributes,
+ );
+ }
+
endSpan(rootSpan);
// Cleanup
ch.close();
diff --git a/app/client/src/workers/Evaluation/handlers/evalTree.ts b/app/client/src/workers/Evaluation/handlers/evalTree.ts
index 46160713e9..4c49a6c148 100644
--- a/app/client/src/workers/Evaluation/handlers/evalTree.ts
+++ b/app/client/src/workers/Evaluation/handlers/evalTree.ts
@@ -34,6 +34,7 @@ import {
profileFn,
newWebWorkerSpanData,
} from "UITelemetry/generateWebWorkerTraces";
+import type { SpanAttributes } from "UITelemetry/generateTraces";
import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer";
import type { MetaWidgetsReduxState } from "reducers/entityReducers/metaWidgetsReducer";
@@ -85,6 +86,9 @@ export function evalTree(request: EvalWorkerSyncRequest) {
let isNewTree = false;
try {
+ (webworkerTelemetry.__spanAttributes as SpanAttributes)["firstEvaluation"] =
+ !dataTreeEvaluator;
+
if (!dataTreeEvaluator) {
isCreateFirstTree = true;
replayMap = replayMap || {};
diff --git a/app/client/src/workers/Evaluation/types.ts b/app/client/src/workers/Evaluation/types.ts
index c93e566dca..e151e520eb 100644
--- a/app/client/src/workers/Evaluation/types.ts
+++ b/app/client/src/workers/Evaluation/types.ts
@@ -16,6 +16,7 @@ import type { WorkerRequest } from "@appsmith/workers/common/types";
import type { DataTreeDiff } from "@appsmith/workers/Evaluation/evaluationUtils";
import type { APP_MODE } from "entities/App";
import type { WebworkerSpanData } from "UITelemetry/generateWebWorkerTraces";
+import type { SpanAttributes } from "UITelemetry/generateTraces";
import type { AffectedJSObjects } from "sagas/EvaluationsSagaUtils";
export type EvalWorkerSyncRequest = WorkerRequest<
@@ -59,6 +60,6 @@ export interface EvalTreeResponseData {
isNewWidgetAdded: boolean;
undefinedEvalValuesMap: Record;
jsVarsCreatedEvent?: { path: string; type: string }[];
- webworkerTelemetry?: Record;
+ webworkerTelemetry?: Record;
updates: string;
}
diff --git a/app/client/src/workers/common/DataTreeEvaluator/index.ts b/app/client/src/workers/common/DataTreeEvaluator/index.ts
index fe938bb0d4..e658728d9e 100644
--- a/app/client/src/workers/common/DataTreeEvaluator/index.ts
+++ b/app/client/src/workers/common/DataTreeEvaluator/index.ts
@@ -137,6 +137,7 @@ import {
profileFn,
type WebworkerSpanData,
} from "UITelemetry/generateWebWorkerTraces";
+import type { SpanAttributes } from "UITelemetry/generateTraces";
import type { AffectedJSObjects } from "sagas/EvaluationsSagaUtils";
import generateOverrideContext from "@appsmith/workers/Evaluation/generateOverrideContext";
@@ -233,7 +234,7 @@ export default class DataTreeEvaluator {
setupFirstTree(
unEvalTree: any,
configTree: ConfigTree,
- webworkerTelemetry: Record = {},
+ webworkerTelemetry: Record = {},
): {
jsUpdates: Record;
evalOrder: string[];
@@ -489,7 +490,7 @@ export default class DataTreeEvaluator {
setupUpdateTree(
unEvalTree: any,
configTree: ConfigTree,
- webworkerTelemetry: Record = {},
+ webworkerTelemetry: Record = {},
affectedJSObjects: AffectedJSObjects = { isAllAffected: false, ids: [] },
): {
unEvalUpdates: DataTreeDiff[];
diff --git a/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java
index a058557dac..c960e50a7e 100644
--- a/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java
+++ b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java
@@ -288,8 +288,10 @@ public class FileUtilsCEImpl implements FileInterface {
// Save JS Libs if there's at least one change
if (modifiedResources != null
- && !CollectionUtils.isEmpty(
- modifiedResources.getModifiedResourceMap().get(CUSTOM_JS_LIB_LIST))) {
+ && (modifiedResources.isAllModified()
+ || !CollectionUtils.isEmpty(
+ modifiedResources.getModifiedResourceMap().get(CUSTOM_JS_LIB_LIST)))) {
+
Path jsLibDirectory = baseRepo.resolve(JS_LIB_DIRECTORY);
Set> jsLibEntries =
applicationGitReference.getJsLibraries().entrySet();
@@ -953,24 +955,62 @@ public class FileUtilsCEImpl implements FileInterface {
@Override
public Mono