chore: Add separate flow for Anvil app publish (#39891)
## Description Anvil apps can have additional tasks before publishing so separate it out Fixes https://www.notion.so/appsmith/Prompt-users-to-save-tools-on-deploy-1bcfe271b0e2804abe30fe462061f454?pvs=4 ## Automation /ok-to-test tags="@tag.Sanity" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/14052281640> > Commit: df611bee4f3c54107f2478f97b9263491b2b2e2e > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=14052281640&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.Sanity` > Spec: > <hr>Tue, 25 Mar 2025 06:04:32 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced an enhanced publishing flow for Anvil applications with dedicated actions for initiation, success, and error scenarios. - Updated the deployment behavior to automatically use the Anvil publishing process when enabled. - **Refactor** - Streamlined the code by removing legacy functionality related to schema generation. - Consolidated utility methods for determining default pages for improved consistency. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
b61b12ec00
commit
3d1192aba1
|
|
@ -20,16 +20,6 @@ export const isActionDirty = (id: string) =>
|
|||
const getActionRunningState = (state: AppState) =>
|
||||
state.ui.pluginActionEditor.isRunning;
|
||||
|
||||
const getActionSchemaGeneratingState = (state: AppState) =>
|
||||
state.ui.pluginActionEditor.isSchemaGenerating;
|
||||
|
||||
export const isActionSchemaGenerating = (id: string) =>
|
||||
createSelector(
|
||||
[getActionSchemaGeneratingState],
|
||||
(isSchemaGeneratingMap) =>
|
||||
id in isSchemaGeneratingMap && isSchemaGeneratingMap[id],
|
||||
);
|
||||
|
||||
export const isActionRunning = (id: string) =>
|
||||
createSelector(
|
||||
[getActionRunningState],
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ import type {
|
|||
ImportApplicationRequest,
|
||||
UpdateApplicationPayload,
|
||||
} from "ee/api/ApplicationApi";
|
||||
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
|
||||
import {
|
||||
ReduxActionErrorTypes,
|
||||
ReduxActionTypes,
|
||||
} from "ee/constants/ReduxActionConstants";
|
||||
import type { NavigationSetting, ThemeSetting } from "constants/AppConstants";
|
||||
import type { IconNames } from "@appsmith/ads";
|
||||
import type { Datasource } from "entities/Datasource";
|
||||
|
|
@ -154,6 +157,27 @@ export const publishApplication = (applicationId: string) => {
|
|||
};
|
||||
};
|
||||
|
||||
export const publishAnvilApplication = (applicationId: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.PUBLISH_ANVIL_APPLICATION_INIT,
|
||||
payload: {
|
||||
applicationId,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const publishAnvilApplicationSuccess = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.PUBLISH_ANVIL_APPLICATION_SUCCESS,
|
||||
};
|
||||
};
|
||||
|
||||
export const publishAnvilApplicationError = () => {
|
||||
return {
|
||||
type: ReduxActionErrorTypes.PUBLISH_ANVIL_APPLICATION_ERROR,
|
||||
};
|
||||
};
|
||||
|
||||
export const importApplication = (appDetails: ImportApplicationRequest) => {
|
||||
return {
|
||||
type: ReduxActionTypes.IMPORT_APPLICATION_INIT,
|
||||
|
|
|
|||
|
|
@ -984,6 +984,8 @@ const AppViewActionTypes = {
|
|||
FETCH_PUBLISHED_PAGE_RESOURCES_INIT: "FETCH_PUBLISHED_PAGE_RESOURCES_INIT",
|
||||
FETCH_PUBLISHED_PAGE_RESOURCES_SUCCESS:
|
||||
"FETCH_PUBLISHED_PAGE_RESOURCES_SUCCESS",
|
||||
PUBLISH_ANVIL_APPLICATION_INIT: "PUBLISH_ANVIL_APPLICATION_INIT",
|
||||
PUBLISH_ANVIL_APPLICATION_SUCCESS: "PUBLISH_ANVIL_APPLICATION_SUCCESS",
|
||||
};
|
||||
|
||||
const AppViewActionErrorTypes = {
|
||||
|
|
@ -993,6 +995,7 @@ const AppViewActionErrorTypes = {
|
|||
FETCH_ACTIONS_VIEW_MODE_ERROR: "FETCH_ACTION_VIEW_MODE_ERROR",
|
||||
FETCH_JS_ACTIONS_VIEW_MODE_ERROR: "FETCH_JS_ACTIONS_VIEW_MODE_ERROR",
|
||||
FETCH_PUBLISHED_PAGE_RESOURCES_ERROR: "FETCH_PUBLISHED_PAGE_RESOURCES_ERROR",
|
||||
PUBLISH_ANVIL_APPLICATION_ERROR: "PUBLISH_ANVIL_APPLICATION_ERROR",
|
||||
};
|
||||
|
||||
const WorkspaceActionTypes = {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import {
|
|||
ReduxActionTypes,
|
||||
} from "ee/constants/ReduxActionConstants";
|
||||
import type {
|
||||
ApplicationPagePayload,
|
||||
ApplicationResponsePayload,
|
||||
ChangeAppViewAccessRequest,
|
||||
CreateApplicationRequest,
|
||||
|
|
@ -29,7 +28,10 @@ import ApplicationApi from "ee/api/ApplicationApi";
|
|||
import { all, call, put, select, take } from "redux-saga/effects";
|
||||
|
||||
import { validateResponse } from "sagas/ErrorSagas";
|
||||
import { getCurrentApplicationIdForCreateNewApp } from "ee/selectors/applicationSelectors";
|
||||
import {
|
||||
getCurrentApplication,
|
||||
getCurrentApplicationIdForCreateNewApp,
|
||||
} from "ee/selectors/applicationSelectors";
|
||||
import type { ApiResponse } from "api/ApiResponses";
|
||||
import history from "utils/history";
|
||||
import type { AppState } from "ee/reducers";
|
||||
|
|
@ -103,6 +105,7 @@ import type { IconNames } from "@appsmith/ads";
|
|||
import {
|
||||
defaultNavigationSetting,
|
||||
keysOfNavigationSetting,
|
||||
type NavigationSetting,
|
||||
} from "constants/AppConstants";
|
||||
import { setAllEntityCollapsibleStates } from "actions/editorContextActions";
|
||||
import { getCurrentEnvironmentId } from "ee/selectors/environmentSelectors";
|
||||
|
|
@ -115,18 +118,52 @@ import equal from "fast-deep-equal";
|
|||
import { getFromServerWhenNoPrefetchedResult } from "sagas/helper";
|
||||
import type { Page } from "entities/Page";
|
||||
import type { ApplicationPayload } from "entities/Application";
|
||||
|
||||
export const findDefaultPage = (pages: ApplicationPagePayload[] = []) => {
|
||||
const defaultPage = pages.find((page) => page.isDefault) ?? pages[0];
|
||||
|
||||
return defaultPage;
|
||||
};
|
||||
import { objectKeys } from "@appsmith/utils";
|
||||
import { findDefaultPage } from "pages/utils";
|
||||
|
||||
export let windowReference: Window | null = null;
|
||||
|
||||
export function* publishApplicationSaga(
|
||||
requestAction: ReduxAction<PublishApplicationRequest>,
|
||||
) {
|
||||
const currentApplication: ApplicationPayload | undefined = yield select(
|
||||
getCurrentApplication,
|
||||
);
|
||||
|
||||
if (currentApplication) {
|
||||
const appName = currentApplication.name;
|
||||
const appId = currentApplication?.id;
|
||||
const pageCount = currentApplication?.pages?.length;
|
||||
const navigationSettingsWithPrefix: Record<
|
||||
string,
|
||||
NavigationSetting[keyof NavigationSetting]
|
||||
> = {};
|
||||
|
||||
if (currentApplication.applicationDetail?.navigationSetting) {
|
||||
const settingKeys = objectKeys(
|
||||
currentApplication.applicationDetail.navigationSetting,
|
||||
) as Array<keyof NavigationSetting>;
|
||||
|
||||
settingKeys.map((key: keyof NavigationSetting) => {
|
||||
if (currentApplication.applicationDetail?.navigationSetting?.[key]) {
|
||||
const value: NavigationSetting[keyof NavigationSetting] =
|
||||
currentApplication.applicationDetail.navigationSetting[key];
|
||||
|
||||
navigationSettingsWithPrefix[`navigationSetting_${key}`] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AnalyticsUtil.logEvent("PUBLISH_APP", {
|
||||
appId,
|
||||
appName,
|
||||
pageCount,
|
||||
...navigationSettingsWithPrefix,
|
||||
isPublic: !!currentApplication?.isPublic,
|
||||
templateTitle: currentApplication?.forkedFromTemplateTitle,
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const request = requestAction.payload;
|
||||
const response: PublishApplicationResponse = yield call(
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { Button, Tooltip } from "@appsmith/ads";
|
||||
import { objectKeys } from "@appsmith/utils";
|
||||
import { showConnectGitModal } from "actions/gitSyncActions";
|
||||
import { publishApplication } from "ee/actions/applicationActions";
|
||||
import { getCurrentApplication } from "ee/selectors/applicationSelectors";
|
||||
import type { NavigationSetting } from "constants/AppConstants";
|
||||
import {
|
||||
publishAnvilApplication,
|
||||
publishApplication,
|
||||
} from "ee/actions/applicationActions";
|
||||
import {
|
||||
createMessage,
|
||||
DEPLOY_BUTTON_TOOLTIP,
|
||||
|
|
@ -25,6 +25,7 @@ import {
|
|||
getIsPublishingApplication,
|
||||
} from "selectors/editorSelectors";
|
||||
import styled from "styled-components";
|
||||
import { getIsAnvilEnabledInCurrentApplication } from "layoutSystems/anvil/integrations/selectors";
|
||||
|
||||
// This wrapper maintains pointer events for tooltips when the child button is disabled.
|
||||
// Without this, disabled buttons won't trigger tooltips because they have pointer-events: none
|
||||
|
|
@ -34,7 +35,6 @@ const StyledTooltipTarget = styled.span`
|
|||
|
||||
function DeployButton() {
|
||||
const applicationId = useSelector(getCurrentApplicationId);
|
||||
const currentApplication = useSelector(getCurrentApplication);
|
||||
const isPackageUpgrading = useSelector(getIsPackageUpgrading);
|
||||
const isProtectedMode = useGitProtectedMode();
|
||||
const isDeployDisabled = isPackageUpgrading || isProtectedMode;
|
||||
|
|
@ -49,42 +49,7 @@ function DeployButton() {
|
|||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const handlePublish = useCallback(() => {
|
||||
if (applicationId) {
|
||||
dispatch(publishApplication(applicationId));
|
||||
|
||||
const appName = currentApplication ? currentApplication.name : "";
|
||||
const pageCount = currentApplication?.pages?.length;
|
||||
const navigationSettingsWithPrefix: Record<
|
||||
string,
|
||||
NavigationSetting[keyof NavigationSetting]
|
||||
> = {};
|
||||
|
||||
if (currentApplication?.applicationDetail?.navigationSetting) {
|
||||
const settingKeys = objectKeys(
|
||||
currentApplication.applicationDetail.navigationSetting,
|
||||
) as Array<keyof NavigationSetting>;
|
||||
|
||||
settingKeys.map((key: keyof NavigationSetting) => {
|
||||
if (currentApplication?.applicationDetail?.navigationSetting?.[key]) {
|
||||
const value: NavigationSetting[keyof NavigationSetting] =
|
||||
currentApplication.applicationDetail.navigationSetting[key];
|
||||
|
||||
navigationSettingsWithPrefix[`navigationSetting_${key}`] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AnalyticsUtil.logEvent("PUBLISH_APP", {
|
||||
appId: applicationId,
|
||||
appName,
|
||||
pageCount,
|
||||
...navigationSettingsWithPrefix,
|
||||
isPublic: !!currentApplication?.isPublic,
|
||||
templateTitle: currentApplication?.forkedFromTemplateTitle,
|
||||
});
|
||||
}
|
||||
}, [applicationId, currentApplication, dispatch]);
|
||||
const isAnvilEnabled = useSelector(getIsAnvilEnabledInCurrentApplication);
|
||||
|
||||
const handleClickDeploy = useCallback(() => {
|
||||
if (isGitConnected) {
|
||||
|
|
@ -97,12 +62,15 @@ function DeployButton() {
|
|||
AnalyticsUtil.logEvent("GS_DEPLOY_GIT_CLICK", {
|
||||
source: "Deploy button",
|
||||
});
|
||||
} else if (isAnvilEnabled) {
|
||||
dispatch(publishAnvilApplication(applicationId));
|
||||
} else {
|
||||
handlePublish();
|
||||
dispatch(publishApplication(applicationId));
|
||||
}
|
||||
}, [
|
||||
applicationId,
|
||||
dispatch,
|
||||
handlePublish,
|
||||
isAnvilEnabled,
|
||||
isGitConnected,
|
||||
isGitModEnabled,
|
||||
toggleOpsModal,
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ import type { Datasource } from "entities/Datasource";
|
|||
import AnalyticsUtil from "ee/utils/AnalyticsUtil";
|
||||
import { useQuery } from "../utils";
|
||||
import ListItemWrapper from "./components/DatasourceListItem";
|
||||
import { findDefaultPage } from "ee/sagas/ApplicationSagas";
|
||||
import { findDefaultPage } from "pages/utils";
|
||||
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
|
||||
import {
|
||||
getOAuthAccessToken,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { getSearchQuery } from "utils/helpers";
|
||||
import type { Location } from "history";
|
||||
import type { ApplicationPagePayload } from "ee/api/ApplicationApi";
|
||||
|
||||
export const getIsBranchUpdated = (
|
||||
prevLocation: Location<unknown>,
|
||||
|
|
@ -29,3 +30,8 @@ export const removeClassFromDocumentRoot = (className: string) => {
|
|||
element.classList.remove(className);
|
||||
}
|
||||
};
|
||||
export const findDefaultPage = (pages: ApplicationPagePayload[] = []) => {
|
||||
const defaultPage = pages.find((page) => page.isDefault) ?? pages[0];
|
||||
|
||||
return defaultPage;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import {
|
|||
ReduxActionTypes,
|
||||
} from "ee/constants/ReduxActionConstants";
|
||||
import urlBuilder from "ee/entities/URLRedirect/URLAssembly";
|
||||
import { findDefaultPage } from "ee/sagas/ApplicationSagas";
|
||||
import { findDefaultPage } from "pages/utils";
|
||||
import { fetchPageDSLSaga } from "ee/sagas/PageSagas";
|
||||
import { getCurrentWorkspaceId } from "ee/selectors/selectedWorkspaceSelectors";
|
||||
import { isAirgapped } from "ee/utils/airgapHelpers";
|
||||
|
|
|
|||
|
|
@ -23,9 +23,6 @@ export const getLastJSTab = (state: AppState): FocusEntityInfo | undefined => {
|
|||
}
|
||||
};
|
||||
|
||||
export const getIsGeneratingSchema = (state: AppState, collectionId: string) =>
|
||||
state.ui.jsPane.isSchemaGenerating[collectionId];
|
||||
|
||||
export const getIsJSCollectionSaving = (
|
||||
state: AppState,
|
||||
collectionId: string,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user