chore: rm dr ce (#34765)

Co-authored-by: brayn003 <rudra@appsmith.com>
This commit is contained in:
Nidhi 2024-07-31 08:24:51 +05:30 committed by GitHub
parent c7a7c3fa3f
commit de443104f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
453 changed files with 6401 additions and 9038 deletions

View File

@ -88,8 +88,8 @@ describe(
cy.wait("@getConsolidatedData").then((intercept2) => {
const { application, pages } = intercept2.response.body.data.pages.data;
const defaultPage = pages.find((p) => p.isDefault);
legacyPathname = `/applications/${application.id}/pages/${defaultPage.id}`;
newPathname = `/app/${application.slug}/${defaultPage.slug}-${defaultPage.id}`;
legacyPathname = `/applications/${application.baseId}/pages/${defaultPage.baseId}`;
newPathname = `/app/${application.slug}/${defaultPage.slug}-${defaultPage.baseId}`;
});
cy.location().should((location) => {

View File

@ -62,11 +62,13 @@ describe("Private embed in-app ramp", { tags: ["@tag.Settings"] }, () => {
featureFlagIntercept({
license_private_embeds_enabled: false,
});
_.agHelper.WaitUntilEleAppear("[data-testid=t--canvas-artboard]");
_.inviteModal.OpenShareModal();
checkRampTextInShareModal();
featureFlagIntercept({
license_private_embeds_enabled: true,
});
_.agHelper.WaitUntilEleAppear("[data-testid=t--canvas-artboard]");
_.inviteModal.OpenShareModal();
_.agHelper.AssertElementAbsence(
_.inviteModal.locators._privateEmbedRampAppSettings,

View File

@ -47,17 +47,6 @@ export const updateBodyContentType = (
payload: { title, apiId },
});
export const redirectToNewIntegrations = (
pageId: string,
params?: any,
): ReduxAction<{
pageId: string;
params: any;
}> => ({
type: ReduxActionTypes.REDIRECT_TO_NEW_INTEGRATIONS,
payload: { pageId, params },
});
export const executeCommandAction = (payload: SlashCommandPayload) => ({
type: ReduxActionTypes.EXECUTE_COMMAND,
payload: payload,

View File

@ -8,41 +8,41 @@ export const initCurrentPage = () => {
};
};
export interface InitializeEditorPayload {
applicationId?: string;
pageId?: string;
export interface InitEditorActionPayload {
baseApplicationId?: string;
basePageId?: string;
branch?: string;
mode: APP_MODE;
shouldInitialiseUserDetails?: boolean;
}
export const initEditor = (
payload: InitializeEditorPayload,
): ReduxAction<InitializeEditorPayload> => ({
export const initEditorAction = (
payload: InitEditorActionPayload,
): ReduxAction<InitEditorActionPayload> => ({
type: ReduxActionTypes.INITIALIZE_EDITOR,
payload,
});
export interface InitAppViewerPayload {
branch: string;
applicationId?: string;
pageId: string;
baseApplicationId?: string;
basePageId: string;
mode: APP_MODE;
shouldInitialiseUserDetails?: boolean;
}
export const initAppViewer = ({
applicationId,
export const initAppViewerAction = ({
baseApplicationId,
basePageId,
branch,
mode,
pageId,
shouldInitialiseUserDetails,
}: InitAppViewerPayload) => ({
type: ReduxActionTypes.INITIALIZE_PAGE_VIEWER,
payload: {
branch: branch,
applicationId,
pageId,
baseApplicationId,
basePageId,
mode,
shouldInitialiseUserDetails,
},

View File

@ -32,14 +32,14 @@ export const disableStartSignpostingAction = () => {
export const firstTimeUserOnboardingInit = (
applicationId: string | undefined,
pageId: string,
basePageId: string,
suffix?: string,
) => {
return {
type: ReduxActionTypes.FIRST_TIME_USER_ONBOARDING_INIT,
payload: {
applicationId: applicationId,
pageId: pageId,
applicationId,
basePageId,
suffix,
},
};

View File

@ -4,6 +4,7 @@ import type {
ReduxAction,
UpdateCanvasPayload,
AnyReduxAction,
ClonePageSuccessPayload,
} from "@appsmith/constants/ReduxActionConstants";
import {
ReduxActionTypes,
@ -15,7 +16,6 @@ import type { DynamicPath } from "utils/DynamicBindingUtils";
import AnalyticsUtil from "@appsmith/utils/AnalyticsUtil";
import type { WidgetOperation } from "widgets/BaseWidget";
import type {
FetchPageRequest,
FetchPageResponse,
PageLayout,
SavePageResponse,
@ -25,7 +25,6 @@ import type {
import type { UrlDataState } from "reducers/entityReducers/appReducer";
import type { APP_MODE } from "entities/App";
import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer";
import type { GenerateTemplatePageRequest } from "api/PageApi";
import type { ENTITY_TYPE } from "@appsmith/entities/AppsmithConsole/utils";
import type { Replayable } from "entities/Replay/ReplayEntity/ReplayEditor";
import * as Sentry from "@sentry/react";
@ -35,28 +34,23 @@ export interface FetchPageListPayload {
mode: APP_MODE;
}
export interface ClonePageActionPayload {
id: string;
blockNavigation?: boolean;
}
export interface CreatePageActionPayload {
applicationId: string;
name: string;
layouts: Partial<PageLayout>[];
}
export interface updateLayoutOptions {
isRetry?: boolean;
shouldReplay?: boolean;
updatedWidgetIds?: string[];
}
export const fetchPage = (
export interface FetchPageActionPayload {
id: string;
isFirstLoad?: boolean;
pageWithMigratedDsl?: FetchPageResponse;
}
export const fetchPageAction = (
pageId: string,
isFirstLoad = false,
pageWithMigratedDsl?: FetchPageResponse,
): ReduxAction<FetchPageRequest> => {
): ReduxAction<FetchPageActionPayload> => {
return {
type: ReduxActionTypes.FETCH_PAGE_INIT,
payload: {
@ -67,12 +61,20 @@ export const fetchPage = (
};
};
export const fetchPublishedPage = (
// fetch a published page
export interface FetchPublishedPageActionPayload {
pageId: string;
bustCache?: boolean;
firstLoad?: boolean;
pageWithMigratedDsl?: FetchPageResponse;
}
export const fetchPublishedPageAction = (
pageId: string,
bustCache = false,
firstLoad = false,
pageWithMigratedDsl?: FetchPageResponse,
) => ({
): ReduxAction<FetchPublishedPageActionPayload> => ({
type: ReduxActionTypes.FETCH_PUBLISHED_PAGE_INIT,
payload: {
pageId,
@ -110,11 +112,17 @@ export const fetchAllPageEntityCompletion = (
payload: undefined,
});
export interface UpdateCurrentPagePayload {
id: string;
slug?: string;
permissions?: string[];
}
export const updateCurrentPage = (
id: string,
slug?: string,
permissions?: string[],
) => ({
): ReduxAction<UpdateCurrentPagePayload> => ({
type: ReduxActionTypes.SWITCH_CURRENT_PAGE_ID,
payload: { id, slug, permissions },
});
@ -170,7 +178,13 @@ export const saveLayout = (isRetry?: boolean) => {
};
};
export const createPage = (
export interface CreatePageActionPayload {
applicationId: string;
name: string;
layouts: Partial<PageLayout>[];
}
export const createPageAction = (
applicationId: string,
pageName: string,
layouts: Partial<PageLayout>[],
@ -212,14 +226,16 @@ export const createNewPageFromEntities = (
};
};
/**
* action to clone page
*
* @param pageId
* @param blockNavigation
* @returns
*/
export const clonePageInit = (pageId: string, blockNavigation?: boolean) => {
// cloning a page
export interface ClonePageActionPayload {
id: string;
blockNavigation?: boolean;
}
export const clonePageInit = (
pageId: string,
blockNavigation?: boolean,
): ReduxAction<ClonePageActionPayload> => {
return {
type: ReduxActionTypes.CLONE_PAGE_INIT,
payload: {
@ -229,24 +245,37 @@ export const clonePageInit = (pageId: string, blockNavigation?: boolean) => {
};
};
export const clonePageSuccess = (
pageId: string,
pageName: string,
layoutId: string,
pageSlug: string,
) => {
export const clonePageSuccess = ({
basePageId,
layoutId,
pageId,
pageName,
slug,
}: ClonePageSuccessPayload) => {
return {
type: ReduxActionTypes.CLONE_PAGE_SUCCESS,
payload: {
pageId,
basePageId,
pageName,
layoutId,
pageSlug,
slug,
},
};
};
export const updatePage = (payload: UpdatePageRequest) => {
// update a page
export interface UpdatePageActionPayload {
id: string;
name?: string;
isHidden?: boolean;
customSlug?: string;
}
export const updatePageAction = (
payload: UpdatePageActionPayload,
): ReduxAction<UpdatePageActionPayload> => {
// Update page *needs* id to be there. We found certain scenarios
// where this was not happening and capturing the error to know gather
// more info: https://github.com/appsmithorg/appsmith/issues/16435
@ -408,6 +437,7 @@ export interface GenerateCRUDSuccess {
page: {
layouts: Array<any>;
id: string;
baseId: string;
name: string;
isDefault?: boolean;
slug: string;
@ -429,6 +459,17 @@ export const generateTemplateError = () => {
};
};
export interface GenerateTemplatePageActionPayload {
pageId: string;
tableName: string;
datasourceId: string;
applicationId: string;
columns?: string[];
searchColumn?: string;
mode?: string;
pluginSpecificParams?: Record<any, any>;
}
export const generateTemplateToUpdatePage = ({
applicationId,
columns,
@ -438,7 +479,7 @@ export const generateTemplateToUpdatePage = ({
pluginSpecificParams,
searchColumn,
tableName,
}: GenerateTemplatePageRequest): ReduxActionWithExtraParams<GenerateTemplatePageRequest> => {
}: GenerateTemplatePageActionPayload): ReduxActionWithExtraParams<GenerateTemplatePageActionPayload> => {
return {
type: ReduxActionTypes.GENERATE_TEMPLATE_PAGE_INIT,
payload: {
@ -485,14 +526,15 @@ export function redoAction() {
};
}
/**
* action for delete page
*
* @param pageId
* @param pageName
* @returns
*/
export const deletePage = (pageId: string) => {
// delete a page
export interface DeletePageActionPayload {
id: string;
}
export const deletePageAction = (
pageId: string,
): ReduxAction<DeletePageActionPayload> => {
return {
type: ReduxActionTypes.DELETE_PAGE_INIT,
payload: {
@ -501,14 +543,15 @@ export const deletePage = (pageId: string) => {
};
};
/**
* action for set page as default
*
* @param pageId
* @param applicationId
* @returns
*/
export const setPageAsDefault = (pageId: string, applicationId?: string) => {
export interface SetDefaultPageActionPayload {
id: string;
applicationId: string;
}
export const setPageAsDefault = (
pageId: string,
applicationId: string,
): ReduxAction<SetDefaultPageActionPayload> => {
return {
type: ReduxActionTypes.SET_DEFAULT_APPLICATION_PAGE_INIT,
payload: {
@ -518,18 +561,17 @@ export const setPageAsDefault = (pageId: string, applicationId?: string) => {
};
};
/**
* action for updating order of a page
*
* @param pageId
* @param applicationId
* @returns
*/
export interface SetPageOrderActionPayload {
pageId: string;
order: number;
applicationId: string;
}
export const setPageOrder = (
applicationId: string,
pageId: string,
order: number,
) => {
): ReduxAction<SetPageOrderActionPayload> => {
return {
type: ReduxActionTypes.SET_PAGE_ORDER_INIT,
payload: {
@ -552,12 +594,17 @@ export const fetchPageDSLs = (payload?: any) => ({
type: ReduxActionTypes.POPULATE_PAGEDSLS_INIT,
payload,
});
export interface SetupPageActionPayload {
id: string;
isFirstLoad?: boolean;
pageWithMigratedDsl?: FetchPageResponse;
}
export const setupPage = (
export const setupPageAction = (
pageId: string,
isFirstLoad = false,
pageWithMigratedDsl?: FetchPageResponse,
): ReduxAction<FetchPageRequest> => ({
): ReduxAction<SetupPageActionPayload> => ({
type: ReduxActionTypes.SETUP_PAGE_INIT,
payload: {
id: pageId,
@ -566,12 +613,19 @@ export const setupPage = (
},
});
export interface SetupPublishedPageActionPayload {
pageId: string;
bustCache: boolean;
firstLoad: boolean;
pageWithMigratedDsl?: FetchPageResponse;
}
export const setupPublishedPage = (
pageId: string,
bustCache = false,
firstLoad = false,
pageWithMigratedDsl?: FetchPageResponse,
) => ({
): ReduxAction<SetupPublishedPageActionPayload> => ({
type: ReduxActionTypes.SETUP_PUBLISHED_PAGE_INIT,
payload: {
pageId,

View File

@ -250,6 +250,7 @@ export const executePluginActionRequest = (payload: { id: string }) => ({
export interface ExecutePluginActionSuccessPayload {
id: string;
baseId: string;
response: ActionResponse;
isPageLoad?: boolean;
isActionCreatedInApp: boolean;
@ -364,7 +365,7 @@ export const setJSActionsToExecuteOnPageLoad = (
export const bindDataOnCanvas = (payload: {
queryId: string;
applicationId: string;
pageId: string;
basePageId: string;
}) => {
return {
type: ReduxActionTypes.BIND_DATA_ON_CANVAS,

View File

@ -4,10 +4,10 @@ import type { Action } from "entities/Action";
import type { QueryPaneDebuggerState } from "@appsmith/reducers/uiReducers/queryPaneReducer";
export interface ChangeQueryPayload {
id: string;
baseQueryId: string;
packageId?: string;
applicationId?: string;
pageId?: string;
basePageId?: string;
moduleId?: string;
workflowId?: string;
newQuery?: boolean;

View File

@ -7,14 +7,14 @@ export interface WidgetSelectionRequestPayload {
selectionRequestType: SelectionRequestType;
payload?: string[];
invokedBy?: NavigationMethod;
pageId?: string;
basePageId?: string;
}
export type WidgetSelectionRequest = (
selectionRequestType: SelectionRequestType,
payload?: string[],
invokedBy?: NavigationMethod,
pageId?: string,
basePageId?: string,
) => ReduxAction<WidgetSelectionRequestPayload>;
// Use to select a widget programmatically via platform action
@ -22,10 +22,10 @@ export const selectWidgetInitAction: WidgetSelectionRequest = (
selectionRequestType,
payload,
invokedBy?: NavigationMethod,
pageId?: string,
basePageId?: string,
) => ({
type: ReduxActionTypes.SELECT_WIDGET_INIT,
payload: { selectionRequestType, payload, pageId, invokedBy },
payload: { selectionRequestType, payload, basePageId, invokedBy },
});
export interface SetSelectedWidgetsPayload {

View File

@ -19,6 +19,7 @@ export interface Property {
export type ActionCreateUpdateResponse = ApiResponse & {
id: string;
baseId: string;
jsonPathKeys: Record<string, string>;
datasource: {
id?: string;

View File

@ -8,7 +8,6 @@ export interface CommitPayload {
applicationId: string;
commitMessage: string;
doPush: boolean;
branch: string;
}
export interface MergeBranchPayload {
@ -34,15 +33,9 @@ export interface ConnectToGitPayload {
interface GitStatusParam {
applicationId: string;
branch: string;
compareRemote: boolean;
}
interface GitRemoteStatusParam {
applicationId: string;
branch: string;
}
export enum AutocommitResponseEnum {
IN_PROGRESS = "IN_PROGRESS",
LOCKED = "LOCKED",
@ -69,17 +62,13 @@ class GitSyncAPI extends Api {
static async commit({
applicationId,
branch,
commitMessage,
doPush,
}: CommitPayload): Promise<AxiosPromise<ApiResponse>> {
return Api.post(
`${GitSyncAPI.baseURL}/commit/app/${applicationId}?branchName=${branch}`,
{
commitMessage,
doPush,
},
);
return Api.post(`${GitSyncAPI.baseURL}/commit/app/${applicationId}`, {
commitMessage,
doPush,
});
}
static async merge({
@ -108,9 +97,12 @@ class GitSyncAPI extends Api {
return Api.get(`${GitSyncAPI.baseURL}/pull/app/${applicationId}`);
}
static async connect(payload: ConnectToGitPayload, applicationId: string) {
static async connect(
payload: ConnectToGitPayload,
baseApplicationId: string,
) {
return Api.post(
`${GitSyncAPI.baseURL}/connect/app/${applicationId}`,
`${GitSyncAPI.baseURL}/connect/app/${baseApplicationId}`,
payload,
);
}
@ -150,70 +142,60 @@ class GitSyncAPI extends Api {
);
}
static async getLocalConfig(applicationId: string) {
return Api.get(`${GitSyncAPI.baseURL}/profile/app/${applicationId}`);
static async getLocalConfig(baseApplicationId: string) {
return Api.get(`${GitSyncAPI.baseURL}/profile/app/${baseApplicationId}`);
}
static async setLocalConfig(payload: GitConfig, applicationId: string) {
static async setLocalConfig(payload: GitConfig, baseApplicationId: string) {
return Api.put(
`${GitSyncAPI.baseURL}/profile/app/${applicationId}`,
`${GitSyncAPI.baseURL}/profile/app/${baseApplicationId}`,
payload,
);
}
static async getGitStatus({
applicationId,
branch,
compareRemote = true,
}: GitStatusParam) {
return Api.get(
`${GitSyncAPI.baseURL}/status/app/${applicationId}`,
{ compareRemote },
{ headers: { branchName: branch } },
);
return Api.get(`${GitSyncAPI.baseURL}/status/app/${applicationId}`, {
compareRemote,
});
}
static async getGitRemoteStatus({
applicationId,
branch,
}: GitRemoteStatusParam) {
return Api.get(
`${GitSyncAPI.baseURL}/fetch/remote/app/${applicationId}`,
{},
{ headers: { branchName: branch } },
static async revokeGit(baseApplicationId: string) {
return Api.post(
`${GitSyncAPI.baseURL}/disconnect/app/${baseApplicationId}`,
);
}
static async revokeGit({ applicationId }: { applicationId: string }) {
return Api.post(`${GitSyncAPI.baseURL}/disconnect/app/${applicationId}`);
}
static async importApp(payload: ConnectToGitPayload, workspaceId: string) {
return Api.post(`${GitSyncAPI.baseURL}/import/${workspaceId}`, payload);
}
static async getSSHKeyPair(
applicationId: string,
baseApplicationId: string,
): Promise<AxiosPromise<ApiResponse>> {
return Api.get(ApplicationApi.baseURL + "/ssh-keypair/" + applicationId);
return Api.get(
ApplicationApi.baseURL + "/ssh-keypair/" + baseApplicationId,
);
}
static async generateSSHKeyPair(
applicationId: string,
baseApplicationId: string,
keyType: string,
isImporting?: boolean,
): Promise<AxiosPromise<ApiResponse>> {
const url = isImporting
? `v1/git/import/keys?keyType=${keyType}`
: `${ApplicationApi.baseURL}/ssh-keypair/${applicationId}?keyType=${keyType}`;
: `${ApplicationApi.baseURL}/ssh-keypair/${baseApplicationId}?keyType=${keyType}`;
return isImporting ? Api.get(url) : Api.post(url);
}
static async deleteBranch(
applicationId: string,
baseApplicationId: string,
branchName: string,
): Promise<AxiosPromise<ApiResponse>> {
return Api.delete(GitSyncAPI.baseURL + "/branch/app/" + applicationId, {
return Api.delete(GitSyncAPI.baseURL + "/branch/app/" + baseApplicationId, {
branchName,
});
}
@ -222,41 +204,39 @@ class GitSyncAPI extends Api {
return Api.put(`${GitSyncAPI.baseURL}/discard/app/${applicationId}`);
}
static async getProtectedBranches(applicationId: string) {
static async getProtectedBranches(baseApplicationId: string) {
return Api.get(
`${GitSyncAPI.baseURL}/branch/app/${applicationId}/protected`,
`${GitSyncAPI.baseURL}/branch/app/${baseApplicationId}/protected`,
);
}
static async updateProtectedBranches(
applicationId: string,
baseApplicationId: string,
branchNames: string[],
) {
return Api.post(
`${GitSyncAPI.baseURL}/branch/app/${applicationId}/protected`,
`${GitSyncAPI.baseURL}/branch/app/${baseApplicationId}/protected`,
{ branchNames },
);
}
static async getGitMetadata(applicationId: string) {
return Api.get(`${GitSyncAPI.baseURL}/metadata/app/${applicationId}`);
static async getGitMetadata(baseApplicationId: string) {
return Api.get(`${GitSyncAPI.baseURL}/metadata/app/${baseApplicationId}`);
}
static async toggleAutocommit(applicationId: string) {
static async toggleAutocommit(baseApplicationId: string) {
return Api.patch(
`${GitSyncAPI.baseURL}/auto-commit/toggle/app/${applicationId}`,
`${GitSyncAPI.baseURL}/auto-commit/toggle/app/${baseApplicationId}`,
);
}
static async triggerAutocommit(applicationId: string, branchName: string) {
return Api.post(
`${GitSyncAPI.baseURL}/auto-commit/app/${applicationId}?branchName=${branchName}`,
);
static async triggerAutocommit(applicationId: string) {
return Api.post(`${GitSyncAPI.baseURL}/auto-commit/app/${applicationId}`);
}
static async getAutocommitProgress(applicationId: string) {
static async getAutocommitProgress(baseApplicationId: string) {
return Api.get(
`${GitSyncAPI.baseURL}/auto-commit/progress/app/${applicationId}`,
`${GitSyncAPI.baseURL}/auto-commit/progress/app/${baseApplicationId}`,
);
}
}

View File

@ -7,14 +7,11 @@ import type {
PageAction,
} from "constants/AppsmithActionConstants/ActionConstants";
import type { DSLWidget } from "WidgetProvider/constants";
import type {
ClonePageActionPayload,
CreatePageActionPayload,
} from "actions/pageActions";
import type { FetchApplicationResponse } from "@appsmith/api/ApplicationApi";
import type { APP_MODE } from "entities/App";
export interface FetchPageRequest {
id: string;
pageId: string;
isFirstLoad?: boolean;
handleResponseLater?: boolean;
migrateDSL?: boolean;
@ -51,6 +48,7 @@ export interface PageLayoutsRequest {
export interface FetchPageResponseData {
id: string;
baseId: string;
name: string;
slug: string;
applicationId: string;
@ -77,13 +75,14 @@ export interface SavePageResponseData {
layoutOnLoadActionErrors?: Array<LayoutOnLoadActionErrors>;
}
export type CreatePageRequest = Omit<
CreatePageActionPayload,
"blockNavigation"
>;
export interface CreatePageRequest {
applicationId: string;
name: string;
layouts: Partial<PageLayout>[];
}
export interface UpdatePageRequest {
id: string;
pageId: string;
name?: string;
isHidden?: boolean;
customSlug?: string;
@ -91,6 +90,7 @@ export interface UpdatePageRequest {
export interface UpdatePageResponse {
id: string;
baseId: string;
name: string;
slug: string;
customSlug?: string;
@ -112,6 +112,7 @@ export type CreatePageResponse = ApiResponse;
export interface FetchPageListResponseData {
pages: Array<{
id: string;
baseId: string;
name: string;
isDefault: boolean;
isHidden?: boolean;
@ -124,10 +125,12 @@ export interface FetchPageListResponseData {
}
export interface DeletePageRequest {
id: string;
pageId: string;
}
export type ClonePageRequest = Omit<ClonePageActionPayload, "blockNavigation">;
export interface ClonePageRequest {
pageId: string;
}
export interface UpdateWidgetNameRequest {
pageId: string;
@ -168,59 +171,41 @@ export type FetchPageResponse = ApiResponse<FetchPageResponseData>;
export type FetchPublishedPageResponse =
ApiResponse<FetchPublishedPageResponseData>;
export interface FetchAppAndPagesRequest {
applicationId?: string | null;
pageId?: string | null;
mode: APP_MODE;
}
class PageApi extends Api {
static url = "v1/pages";
static refactorLayoutURL = "v1/layouts/refactor";
static pageUpdateCancelTokenSource?: CancelTokenSource = undefined;
static getLayoutUpdateURL = (
applicationId: string,
pageId: string,
layoutId: string,
) => {
return `v1/layouts/${layoutId}/pages/${pageId}?applicationId=${applicationId}`;
};
static getGenerateTemplateURL = (pageId?: string) => {
return `${PageApi.url}/crud-page${pageId ? `/${pageId}` : ""}`;
};
static getPublishedPageURL = (pageId: string, bustCache?: boolean) => {
const url = `v1/pages/${pageId}/view`;
return !!bustCache ? url + "?v=" + +new Date() : url;
};
static getSaveAllPagesURL = (applicationId: string) => {
return `v1/layouts/application/${applicationId}`;
};
static updatePageUrl = (pageId: string) => `${PageApi.url}/${pageId}`;
static setPageOrderUrl = (
applicationId: string,
pageId: string,
order: number,
) => `v1/applications/${applicationId}/page/${pageId}/reorder?order=${order}`;
static async fetchPage(
pageRequest: FetchPageRequest,
): Promise<AxiosPromise<FetchPageResponse>> {
const params = { migrateDsl: pageRequest.migrateDSL };
return Api.get(PageApi.url + "/" + pageRequest.id, undefined, { params });
return Api.get(PageApi.url + "/" + pageRequest.pageId, undefined, {
params,
});
}
static savePage(
savePageRequest: SavePageRequest,
request: SavePageRequest,
): AxiosPromise<SavePageResponse> | undefined {
if (PageApi.pageUpdateCancelTokenSource) {
PageApi.pageUpdateCancelTokenSource.cancel();
}
const body = { dsl: savePageRequest.dsl };
const body = { dsl: request.dsl };
PageApi.pageUpdateCancelTokenSource = axios.CancelToken.source();
const { applicationId, layoutId, pageId } = request;
return Api.put(
PageApi.getLayoutUpdateURL(
savePageRequest.applicationId,
savePageRequest.pageId,
savePageRequest.layoutId,
),
`v1/layouts/${layoutId}/pages/${pageId}?applicationId=${applicationId}`,
body,
undefined,
{ cancelToken: PageApi.pageUpdateCancelTokenSource.token },
@ -231,7 +216,7 @@ class PageApi extends Api {
applicationId: string,
pageLayouts: PageLayoutsRequest[],
) {
return Api.put(PageApi.getSaveAllPagesURL(applicationId), {
return Api.put(`v1/layouts/application/${applicationId}`, {
pageLayouts,
});
}
@ -245,78 +230,58 @@ class PageApi extends Api {
}
static async createPage(
createPageRequest: CreatePageRequest,
request: CreatePageRequest,
): Promise<AxiosPromise<FetchPageResponse>> {
return Api.post(PageApi.url, createPageRequest);
return Api.post(PageApi.url, request);
}
static async updatePage(
request: UpdatePageRequest,
): Promise<AxiosPromise<ApiResponse<UpdatePageResponse>>> {
return Api.put(PageApi.updatePageUrl(request.id), {
...request,
id: undefined,
});
const { pageId, ...rest } = request;
return Api.put(`${PageApi.url}/${pageId}`, rest);
}
static async generateTemplatePage(
request: GenerateTemplatePageRequest,
): Promise<AxiosPromise<ApiResponse>> {
const payload = {
...request,
pageId: undefined,
};
if (request.pageId) {
return Api.put(PageApi.getGenerateTemplateURL(request.pageId), payload);
const { pageId, ...rest } = request;
if (pageId) {
return Api.put(`${PageApi.url}/crud-page/${pageId}`, rest);
} else {
return Api.post(PageApi.getGenerateTemplateURL(), payload);
return Api.post(`${PageApi.url}/crud-page`, rest);
}
}
static async fetchPageList(
applicationId: string,
): Promise<AxiosPromise<FetchPageListResponse>> {
return Api.get(PageApi.url + "/application/" + applicationId);
}
static async fetchPageListViewMode(
applicationId: string,
): Promise<AxiosPromise<FetchPageListResponse>> {
return Api.get(PageApi.url + "/view/application/" + applicationId);
}
static async deletePage(
request: DeletePageRequest,
): Promise<AxiosPromise<ApiResponse>> {
return Api.delete(PageApi.url + "/" + request.id);
return Api.delete(`${PageApi.url}/${request.pageId}`);
}
static async clonePage(
request: ClonePageRequest,
): Promise<AxiosPromise<ApiResponse>> {
return Api.post(PageApi.url + "/clone/" + request.id);
): Promise<AxiosPromise<FetchPageResponse>> {
return Api.post(`${PageApi.url}/clone/${request.pageId}`);
}
static async updateWidgetName(
request: UpdateWidgetNameRequest,
): Promise<AxiosPromise<UpdateWidgetNameResponse>> {
return Api.put(PageApi.refactorLayoutURL, request);
return Api.put("v1/layouts/refactor", request);
}
static async setPageOrder(
request: SetPageOrderRequest,
): Promise<AxiosPromise<FetchPageListResponse>> {
const { applicationId, order, pageId } = request;
return Api.put(
PageApi.setPageOrderUrl(
request.applicationId,
request.pageId,
request.order,
),
`v1/applications/${applicationId}/page/${pageId}/reorder?order=${order}`,
);
}
static async fetchAppAndPages(
params: any,
params: FetchAppAndPagesRequest,
): Promise<AxiosPromise<FetchApplicationResponse>> {
return Api.get(PageApi.url, params);
}

View File

@ -21,11 +21,11 @@ export const fillPathname = (
page: Page,
) => {
const replaceValue = page.customSlug
? getViewerCustomPath(page.customSlug, page.pageId)
: getViewerPath(application.slug, page.slug, page.pageId);
? getViewerCustomPath(page.customSlug, page.basePageId)
: getViewerPath(application.slug, page.slug, page.basePageId);
return pathname.replace(
`/applications/${application.id}/pages/${page.pageId}`,
`/applications/${application.baseId}/pages/${page.basePageId}`,
replaceValue,
);
};
@ -54,14 +54,14 @@ export interface WithAddView {
export const jsCollectionIdURL = (
props: URLBuilderParams &
WithAddView & {
collectionId: string;
baseCollectionId: string;
// Pass a function name to set the cursor directly on the function
functionName?: string;
},
): string => {
return urlBuilder.build({
...props,
suffix: `jsObjects/${props.collectionId}${props.add ? ADD_PATH : ""}`,
suffix: `jsObjects/${props.baseCollectionId}${props.add ? ADD_PATH : ""}`,
hash: props.functionName,
});
};
@ -79,23 +79,23 @@ export const integrationEditorURL = (
export const queryEditorIdURL = (
props: URLBuilderParams &
WithAddView & {
queryId: string;
baseQueryId: string;
},
): string =>
urlBuilder.build({
...props,
suffix: `queries/${props.queryId}${props.add ? ADD_PATH : ""}`,
suffix: `queries/${props.baseQueryId}${props.add ? ADD_PATH : ""}`,
});
export const apiEditorIdURL = (
props: URLBuilderParams &
WithAddView & {
apiId: string;
baseApiId: string;
},
): string =>
urlBuilder.build({
...props,
suffix: `api/${props.apiId}${props.add ? ADD_PATH : ""}`,
suffix: `api/${props.baseApiId}${props.add ? ADD_PATH : ""}`,
});
export const saasEditorDatasourceIdURL = (
@ -113,12 +113,12 @@ export const saasEditorApiIdURL = (
props: URLBuilderParams &
WithAddView & {
pluginPackageName: string;
apiId: string;
baseApiId: string;
},
): string =>
urlBuilder.build({
...props,
suffix: `saas/${props.pluginPackageName}/api/${props.apiId}${
suffix: `saas/${props.pluginPackageName}/api/${props.baseApiId}${
props.add ? ADD_PATH : ""
}`,
});

View File

@ -22,13 +22,13 @@ export const handler = (action: ReduxAction<any>) => {
const application: ApplicationPayload = action.payload;
const { pages } = application;
appParams = {
applicationId: application.id,
baseApplicationId: application.baseId,
applicationSlug: application.slug,
applicationVersion: application.applicationVersion,
};
pageParams = pages.map((page) => ({
pageSlug: page.slug,
pageId: page.id,
basePageId: page.baseId,
customSlug: page.customSlug,
}));
break;
@ -38,13 +38,13 @@ export const handler = (action: ReduxAction<any>) => {
const application: ApplicationPayload = action.payload.application;
const { pages } = application;
appParams = {
applicationId: application.id,
baseApplicationId: application.baseId,
applicationSlug: application.slug,
applicationVersion: application.applicationVersion,
};
pageParams = pages.map((page) => ({
pageSlug: page.slug,
pageId: page.id,
basePageId: page.baseId,
customSlug: page.customSlug,
}));
break;
@ -52,7 +52,7 @@ export const handler = (action: ReduxAction<any>) => {
case ReduxActionTypes.CURRENT_APPLICATION_NAME_UPDATE: {
const application = action.payload;
appParams = {
applicationId: application.id,
baseApplicationId: application.baseId,
applicationSlug: application.slug,
applicationVersion: application.applicationVersion,
};
@ -62,7 +62,7 @@ export const handler = (action: ReduxAction<any>) => {
const pages: Page[] = action.payload.pages;
pageParams = pages.map((page) => ({
pageSlug: page.slug,
pageId: page.pageId,
basePageId: page.basePageId,
customSlug: page.customSlug,
}));
break;
@ -72,7 +72,7 @@ export const handler = (action: ReduxAction<any>) => {
pageParams = [
{
pageSlug: page.slug,
pageId: page.id,
basePageId: page.baseId,
customSlug: page.customSlug,
},
];
@ -83,7 +83,7 @@ export const handler = (action: ReduxAction<any>) => {
pageParams = [
{
pageSlug: page.slug,
pageId: page.pageId,
basePageId: page.basePageId,
customSlug: page.customSlug,
},
];
@ -94,7 +94,7 @@ export const handler = (action: ReduxAction<any>) => {
urlBuilder.updateURLParams(null, [
{
pageSlug: page.slug,
pageId: page.id,
basePageId: page.baseId,
customSlug: page.customSlug,
},
]);
@ -103,16 +103,16 @@ export const handler = (action: ReduxAction<any>) => {
case ReduxActionTypes.UPDATE_APPLICATION_SUCCESS:
const application = action.payload;
appParams = {
applicationId: application.id,
baseApplicationId: application.baseid,
applicationSlug: application.slug,
applicationVersion: application.applicationVersion,
};
break;
case ReduxActionTypes.CLONE_PAGE_SUCCESS:
const { pageId, pageSlug } = action.payload;
const { basePageId, pageSlug } = action.payload;
pageParams = [
{
pageId,
basePageId,
pageSlug,
},
];

View File

@ -29,12 +29,13 @@ export type PublishApplicationResponse = ApiResponse;
export interface ApplicationPagePayload {
id: string;
baseId: string;
name: string;
isDefault: boolean;
slug: string;
isHidden?: boolean;
customSlug?: string;
userPermissions?: string;
userPermissions?: string[];
}
export type GitApplicationMetadata =
@ -52,6 +53,7 @@ export type GitApplicationMetadata =
export interface ApplicationResponsePayload {
id: string;
baseId: string;
name: string;
workspaceId: string;
evaluationVersion?: EvaluationVersion;
@ -95,7 +97,7 @@ export interface CreateApplicationRequest {
}
export interface SetDefaultPageRequest {
id: string;
pageId: string;
applicationId: string;
}
@ -226,7 +228,7 @@ export interface UpdateApplicationResponse {
export interface PageDefaultMeta {
id: string;
isDefault: boolean;
defaultPageId: string;
baseId: string;
default: boolean;
}
@ -287,7 +289,7 @@ export class ApplicationApi extends Api {
static changeAppViewAccessPath = (applicationId: string) =>
`/${applicationId}/changeAccess`;
static setDefaultPagePath = (request: SetDefaultPageRequest) =>
`${ApplicationApi.baseURL}/${request.applicationId}/page/${request.id}/makeDefault`;
`${ApplicationApi.baseURL}/${request.applicationId}/page/${request.pageId}/makeDefault`;
static async publishApplication(
publishApplicationRequest: PublishApplicationRequest,
): Promise<AxiosPromise<PublishApplicationResponse>> {

View File

@ -30,7 +30,13 @@ const ActionSelectorReduxActionTypes = {
"CLEAR_EVALUATED_ACTION_SELECTOR_FIELD",
};
const ResourceMapActionTypes = {
SET_PAGE_RESOURCE_MAPS: "SET_PAGE_RESOURCE_MAPS",
RESET_ALL_RESOURCE_MAPS: "RESET_ALL_RESOURCE_MAPS",
};
const ActionTypes = {
...ResourceMapActionTypes,
TOGGLE_INSTALLER: "TOGGLE_INSTALLER",
FETCH_JS_LIBRARIES_INIT: "FETCH_JS_LIBRARIES_INIT",
FETCH_JS_LIBRARIES_SUCCESS: "FETCH_JS_LIBRARIES_SUCCESS",
@ -182,7 +188,6 @@ const ActionTypes = {
REPORT_ERROR: "REPORT_ERROR",
FLUSH_ERRORS: "FLUSH_ERRORS",
FLUSH_AND_REDIRECT: "FLUSH_AND_REDIRECT",
REDIRECT_TO_NEW_INTEGRATIONS: "REDIRECT_TO_NEW_INTEGRATIONS",
SAFE_CRASH_APPSMITH: "SAFE_CRASH_APPSMITH",
SAFE_CRASH_APPSMITH_REQUEST: "SAFE_CRASH_APPSMITH_REQUEST",
INIT_CANVAS_LAYOUT: "INIT_CANVAS_LAYOUT",
@ -574,6 +579,8 @@ const ActionTypes = {
"RESET_APPLICATION_WIDGET_STATE_REQUEST",
SAAS_GET_OAUTH_ACCESS_TOKEN: "SAAS_GET_OAUTH_ACCESS_TOKEN",
GET_OAUTH_ACCESS_TOKEN: "GET_OAUTH_ACCESS_TOKEN",
GET_OAUTH_ACCESS_TOKEN_SUCCESS: "GET_OAUTH_ACCESS_TOKEN_SUCCESS",
GET_OAUTH_ACCESS_TOKEN_ERROR: "GET_OAUTH_ACCESS_TOKEN_ERROR",
RESTORE_RECENT_ENTITIES_REQUEST: "RESTORE_RECENT_ENTITIES_REQUEST",
RESTORE_RECENT_ENTITIES_SUCCESS: "RESTORE_RECENT_ENTITIES_SUCCESS",
SET_RECENT_ENTITIES: "SET_RECENT_ENTITIES",
@ -1236,6 +1243,7 @@ export interface Page {
pageName: string;
description?: string;
pageId: string;
basePageId: string;
isDefault: boolean;
latest?: boolean;
isHidden?: boolean;
@ -1248,6 +1256,7 @@ export interface ClonePageSuccessPayload {
pageName: string;
description?: string;
pageId: string;
basePageId: string;
layoutId: string;
isDefault: boolean;
slug: string;
@ -1255,11 +1264,13 @@ export interface ClonePageSuccessPayload {
export interface ApplicationPayload {
id: string;
baseId: string;
name: string;
color?: string;
icon?: string;
workspaceId: string;
defaultPageId: string;
defaultBasePageId: string;
isPublic?: boolean;
userPermissions?: string[];
appIsExample: boolean;

View File

@ -17,19 +17,20 @@ export const ID_EXTRACTION_REGEX = `(${MONGO_OBJECT_ID_REGEX}|${UUID_REGEX})`;
export const BUILDER_BASE_PATH_DEPRECATED = "/applications";
export const BUILDER_VIEWER_PATH_PREFIX = "/app/";
export const BUILDER_PATH = `${BUILDER_VIEWER_PATH_PREFIX}:applicationSlug/:pageSlug(.*\-):pageId${ID_EXTRACTION_REGEX}/edit`;
export const BUILDER_CUSTOM_PATH = `${BUILDER_VIEWER_PATH_PREFIX}:customSlug(.*\-):pageId${ID_EXTRACTION_REGEX}/edit`;
export const VIEWER_PATH = `${BUILDER_VIEWER_PATH_PREFIX}:applicationSlug/:pageSlug(.*\-):pageId${ID_EXTRACTION_REGEX}`;
export const VIEWER_CUSTOM_PATH = `${BUILDER_VIEWER_PATH_PREFIX}:customSlug(.*\-):pageId${ID_EXTRACTION_REGEX}`;
export const BUILDER_PATH = `${BUILDER_VIEWER_PATH_PREFIX}:applicationSlug/:pageSlug(.*\-):basePageId${ID_EXTRACTION_REGEX}/edit`;
export const BUILDER_CUSTOM_PATH = `${BUILDER_VIEWER_PATH_PREFIX}:customSlug(.*\-):basePageId${ID_EXTRACTION_REGEX}/edit`;
export const VIEWER_PATH = `${BUILDER_VIEWER_PATH_PREFIX}:applicationSlug/:pageSlug(.*\-):basePageId${ID_EXTRACTION_REGEX}`;
export const VIEWER_CUSTOM_PATH = `${BUILDER_VIEWER_PATH_PREFIX}:customSlug(.*\-):basePageId${ID_EXTRACTION_REGEX}`;
export const getViewerPath = (
applicationSlug: string,
pageSlug: string,
pageId: string,
) => `${BUILDER_VIEWER_PATH_PREFIX}${applicationSlug}/${pageSlug}-${pageId}`;
export const getViewerCustomPath = (customSlug: string, pageId: string) =>
`${BUILDER_VIEWER_PATH_PREFIX}${customSlug}-${pageId}`;
export const BUILDER_PATH_DEPRECATED = `/applications/:applicationId${ID_EXTRACTION_REGEX}/pages/:pageId${ID_EXTRACTION_REGEX}/edit`;
export const VIEWER_PATH_DEPRECATED = `/applications/:applicationId${ID_EXTRACTION_REGEX}/pages/:pageId${ID_EXTRACTION_REGEX}`;
basePageId: string,
) =>
`${BUILDER_VIEWER_PATH_PREFIX}${applicationSlug}/${pageSlug}-${basePageId}`;
export const getViewerCustomPath = (customSlug: string, basePageId: string) =>
`${BUILDER_VIEWER_PATH_PREFIX}${customSlug}-${basePageId}`;
export const BUILDER_PATH_DEPRECATED = `/applications/:baseApplicationId${ID_EXTRACTION_REGEX}/pages/:basePageId${ID_EXTRACTION_REGEX}/edit`;
export const VIEWER_PATH_DEPRECATED = `/applications/:baseApplicationId${ID_EXTRACTION_REGEX}/pages/:basePageId${ID_EXTRACTION_REGEX}`;
export const VIEWER_PATH_DEPRECATED_REGEX =
/\/applications\/[^/]+\/pages\/[^/]+/;
@ -48,20 +49,20 @@ export const CUSTOM_WIDGETS_DEPRECATED_EDITOR_ID_PATH = `${BUILDER_PATH_DEPRECAT
/* */
export const API_EDITOR_BASE_PATH = `/api`;
export const API_EDITOR_ID_PATH = `${API_EDITOR_BASE_PATH}/:apiId`;
export const API_EDITOR_ID_ADD_PATH = `${API_EDITOR_BASE_PATH}/:apiId/add`;
export const API_EDITOR_ID_PATH = `${API_EDITOR_BASE_PATH}/:baseApiId`;
export const API_EDITOR_ID_ADD_PATH = `${API_EDITOR_BASE_PATH}/:baseApiId/add`;
export const API_EDITOR_PATH_WITH_SELECTED_PAGE_ID = `${API_EDITOR_BASE_PATH}?importTo=:importTo`;
export const QUERIES_EDITOR_BASE_PATH = `/queries`;
export const ADD_PATH = `/add`;
export const LIST_PATH = "/list";
export const ENTITY_PATH = "/:entity";
export const QUERIES_EDITOR_ID_PATH = `${QUERIES_EDITOR_BASE_PATH}/:queryId`;
export const QUERIES_EDITOR_ID_PATH = `${QUERIES_EDITOR_BASE_PATH}/:baseQueryId`;
export const QUERIES_EDITOR_ADD_PATH = `${QUERIES_EDITOR_BASE_PATH}${ADD_PATH}`;
export const QUERIES_EDITOR_ID_ADD_PATH = `${QUERIES_EDITOR_BASE_PATH}/:queryId/add`;
export const QUERIES_EDITOR_ID_ADD_PATH = `${QUERIES_EDITOR_BASE_PATH}/:baseQueryId/add`;
export const JS_COLLECTION_EDITOR_PATH = `/jsObjects`;
export const JS_COLLECTION_ID_PATH = `${JS_COLLECTION_EDITOR_PATH}/:collectionId`;
export const JS_COLLECTION_ID_ADD_PATH = `${JS_COLLECTION_EDITOR_PATH}/:collectionId/add`;
export const JS_COLLECTION_ID_PATH = `${JS_COLLECTION_EDITOR_PATH}/:baseCollectionId`;
export const JS_COLLECTION_ID_ADD_PATH = `${JS_COLLECTION_EDITOR_PATH}/:baseCollectionId/add`;
export const DATA_SOURCES_EDITOR_LIST_PATH = `/datasource`;
export const DATA_SOURCES_EDITOR_ID_PATH = `/datasource/:datasourceId`;
export const APP_LIBRARIES_EDITOR_PATH = `/libraries`;
@ -77,8 +78,8 @@ export const ADMIN_SETTINGS_CATEGORY_DEFAULT_PATH = "/settings/general";
export const ADMIN_SETTINGS_CATEGORY_ACL_PATH = "/settings/groups";
export const ADMIN_SETTINGS_CATEGORY_AUDIT_LOGS_PATH = "/settings/audit-logs";
export const ADMIN_SETTINGS_CATEGORY_PATH = "/settings/:category/:selected?";
export const BUILDER_PATCH_PATH = `/:applicationSlug/:pageSlug(.*\-):pageId${ID_EXTRACTION_REGEX}/edit`;
export const VIEWER_PATCH_PATH = `/:applicationSlug/:pageSlug(.*\-):pageId${ID_EXTRACTION_REGEX}`;
export const BUILDER_PATCH_PATH = `/:applicationSlug/:pageSlug(.*\-):basePageId${ID_EXTRACTION_REGEX}/edit`;
export const VIEWER_PATCH_PATH = `/:applicationSlug/:pageSlug(.*\-):basePageId${ID_EXTRACTION_REGEX}`;
export const matchApiBasePath = match(API_EDITOR_BASE_PATH);
export const matchApiPath = match(API_EDITOR_ID_PATH);
@ -133,29 +134,29 @@ export const addBranchParam = (branch: string) => {
};
export interface BuilderRouteParams {
pageId: string;
applicationId: string;
basePageId: string;
baseApplicationId: string;
}
export interface AppViewerRouteParams {
pageId: string;
applicationId?: string;
basePageId: string;
baseApplicationId?: string;
}
export interface APIEditorRouteParams {
pageId: string;
apiId?: string;
basePageId: string;
baseApiId?: string;
}
export interface QueryEditorRouteParams {
pageId: string;
queryId?: string;
apiId?: string;
basePageId: string;
baseQueryId?: string;
baseApiId?: string;
}
export interface JSEditorRouteParams {
pageId: string;
collectionId?: string;
basePageId: string;
baseCollectionId?: string;
}
export const GIT_BRANCH_QUERY_KEY = "branch";
@ -171,7 +172,7 @@ export const INTEGRATION_EDITOR_MODES = {
};
export const PLACEHOLDER_APP_SLUG = "application";
export const PLACEHOLDER_PAGE_ID = "pageId";
export const PLACEHOLDER_PAGE_ID = "basePageId";
export const PLACEHOLDER_PAGE_SLUG = "page";
export const SHOW_FILE_PICKER_KEY = "showPicker";

View File

@ -4,12 +4,19 @@ import {
ReduxActionErrorTypes,
ReduxActionTypes,
} from "@appsmith/constants/ReduxActionConstants";
import type { ExplorerURLParams } from "@appsmith/pages/Editor/Explorer/helpers";
import type { DependentFeatureFlags } from "@appsmith/selectors/engineSelectors";
import { fetchDatasources } from "actions/datasourceActions";
import { fetchPageDSLs } from "actions/pageActions";
import { fetchPlugins } from "actions/pluginActions";
import type { Plugin } from "api/PluginApi";
import { useSelector } from "react-redux";
import { useParams } from "react-router";
import type { EditConsolidatedApi } from "sagas/InitSagas";
import {
convertToBaseParentEntityIdSelector,
convertToPageIdSelector,
} from "selectors/pageListSelectors";
export const CreateNewActionKey = {
PAGE: "pageId",
@ -58,16 +65,28 @@ export const doesPluginRequireDatasource = (plugin: Plugin | undefined) => {
export enum APPSMITH_NAMESPACED_FUNCTIONS {}
export const getParentEntityDetailsFromParams = (
parentEntityIdObject: { pageId?: string },
export const useParentEntityDetailsFromParams = (
parentEntityIdProp: string,
isInsideReconnectModal?: boolean,
) => {
const { pageId } = parentEntityIdObject;
const parentEntityIdQuery = pageId || "";
const baseParentEntityIdProp = useSelector((state) =>
convertToBaseParentEntityIdSelector(state, parentEntityIdProp),
);
const { basePageId } = useParams<ExplorerURLParams>();
const parentEntityIdQuery = basePageId || "";
const pageId = useSelector((state) =>
convertToPageIdSelector(state, basePageId),
);
const baseParentEntityIdQuery = pageId || "";
const parentEntityId = isInsideReconnectModal
? parentEntityIdProp
: parentEntityIdQuery;
const baseParentEntityId = isInsideReconnectModal
? baseParentEntityIdProp
: baseParentEntityIdQuery;
const entityType = ActionParentEntityType.PAGE;
return { parentEntityId, entityType };
return { baseParentEntityId, parentEntityId, entityType };
};

View File

@ -10,11 +10,11 @@ describe("URLBuilder", () => {
urlBuilder.resetURLParams();
});
it("should correctly set and use currentPageId in build function when currentPageId is set", () => {
const testPageId = "testPageId";
it("should correctly set and use currentBasePageId in build function when currentBasePageId is set", () => {
const testBasePageId = "testBasePageId";
const testMode = APP_MODE.EDIT;
urlBuilder.setCurrentPageId(testPageId);
urlBuilder.setCurrentBasePageId(testBasePageId);
const builderParams = {
suffix: "testSuffix",
@ -24,92 +24,92 @@ describe("URLBuilder", () => {
persistExistingParams: true,
};
URLBuilder.prototype.generateBasePath = jest.fn((pageId, mode) => {
expect(pageId).toBe(testPageId); // Ensure the current page id is used
URLBuilder.prototype.generateBasePath = jest.fn((basePageId, mode) => {
expect(basePageId).toBe(testBasePageId); // Ensure the current page id is used
expect(mode).toBe(testMode);
return `mockedBasePath/${pageId}/${mode}`;
return `mockedBasePath/${basePageId}/${mode}`;
});
const result = urlBuilder.build(builderParams, testMode);
expect(URLBuilder.prototype.generateBasePath).toHaveBeenCalledWith(
testPageId,
testBasePageId,
testMode,
);
expect(result).toEqual(
"mockedBasePath/testPageId/EDIT/testSuffix?param1=value1&param2=value2&branch=testBranch#testHash",
"mockedBasePath/testBasePageId/EDIT/testSuffix?param1=value1&param2=value2&branch=testBranch#testHash",
);
});
it("should correctly set and use pageId in build function when currentPageId is set to null", () => {
const testPageId = "testPageId";
it("should correctly set and use basePageId in build function when currentBasePageId is set to null", () => {
const testBasePageId = "testBasePageId";
const testMode = APP_MODE.EDIT;
// Set currentPageId to null
urlBuilder.setCurrentPageId(null);
// Set currentBasePageId to null
urlBuilder.setCurrentBasePageId(null);
const builderParams = {
suffix: "testSuffix",
branch: "testBranch",
hash: "testHash",
params: { param1: "value1", param2: "value2" },
pageId: testPageId, // Set the pageId to be used
basePageId: testBasePageId, // Set the basePageId to be used
persistExistingParams: true,
};
URLBuilder.prototype.generateBasePath = jest.fn((pageId, mode) => {
expect(pageId).toBe(testPageId); // Ensure the passed pageId is used
URLBuilder.prototype.generateBasePath = jest.fn((basePageId, mode) => {
expect(basePageId).toBe(testBasePageId); // Ensure the passed basePageId is used
expect(mode).toBe(testMode);
return `mockedBasePath/${pageId}/${mode}`;
return `mockedBasePath/${basePageId}/${mode}`;
});
const result = urlBuilder.build(builderParams, testMode);
expect(URLBuilder.prototype.generateBasePath).toHaveBeenCalledWith(
testPageId,
testBasePageId,
testMode,
);
expect(result).toEqual(
"mockedBasePath/testPageId/EDIT/testSuffix?param1=value1&param2=value2&branch=testBranch#testHash",
"mockedBasePath/testBasePageId/EDIT/testSuffix?param1=value1&param2=value2&branch=testBranch#testHash",
);
});
it("should correctly set and use pageId in build function when currentPageId is set", () => {
const currentPageId = "currentPageId";
const testPageId = "testPageId";
it("should correctly set and use basePageId in build function when currentBasePageId is set", () => {
const currentBasePageId = "currentBasePageId";
const testBasePageId = "testBasePageId";
const testMode = APP_MODE.EDIT;
urlBuilder.setCurrentPageId(currentPageId);
urlBuilder.setCurrentBasePageId(currentBasePageId);
const builderParams = {
suffix: "testSuffix",
branch: "testBranch",
hash: "testHash",
params: { param1: "value1", param2: "value2" },
pageId: testPageId, // This should override the current page id
basePageId: testBasePageId, // This should override the current page id
persistExistingParams: true,
};
URLBuilder.prototype.generateBasePath = jest.fn((pageId, mode) => {
return `mockedBasePath/${pageId}/${mode}`;
URLBuilder.prototype.generateBasePath = jest.fn((basePageId, mode) => {
return `mockedBasePath/${basePageId}/${mode}`;
});
const result = urlBuilder.build(builderParams, testMode);
expect(URLBuilder.prototype.generateBasePath).toHaveBeenCalledWith(
testPageId,
testBasePageId,
testMode,
);
expect(result).toEqual(
"mockedBasePath/testPageId/EDIT/testSuffix?param1=value1&param2=value2&branch=testBranch#testHash",
"mockedBasePath/testBasePageId/EDIT/testSuffix?param1=value1&param2=value2&branch=testBranch#testHash",
);
});
it("should throw an error when pageId is missing", () => {
urlBuilder.setCurrentPageId(null);
it("should throw an error when basePageId is missing", () => {
urlBuilder.setCurrentBasePageId(null);
expect(() => {
urlBuilder.build({}, APP_MODE.EDIT);

View File

@ -19,10 +19,11 @@ export interface URLBuilderParams {
branch?: string;
hash?: string;
params?: Record<string, any>;
pageId?: string | null;
basePageId?: string | null;
persistExistingParams?: boolean;
// This is used to pass ID if the sender doesn't know the type of the entity
parentEntityId?: string;
// base version of parent entity id, can be basePageId or moduleId
baseParentEntityId?: string;
generateEditorPath?: boolean;
}
@ -48,13 +49,13 @@ export const baseURLRegistry = {
};
export interface ApplicationURLParams {
applicationId?: string;
baseApplicationId?: string;
applicationSlug?: string;
applicationVersion?: ApplicationVersion;
}
export interface PageURLParams {
pageId: string;
basePageId: string;
pageSlug: string;
customSlug?: string;
}
@ -101,8 +102,8 @@ const fetchQueryParamsToPersist = (persistExistingParams: boolean) => {
*
* This class is inherited in EE and basePath generation is modified based on the type
* of editor the user is currently on. This is done to remove the dependency of current
* page as a required param to build any route. However if a pageId is provided while
* building a route, it will override the cache and use the passed pageId value.
* page as a required param to build any route. However if a basePageId is provided while
* building a route, it will override the cache and use the passed basePageId value.
*
* However the current implementation can be improved and a holistic solution can be
* devised to support all different types of routing pattern. The current solution acts as a stop-gap
@ -111,17 +112,17 @@ const fetchQueryParamsToPersist = (persistExistingParams: boolean) => {
export class URLBuilder {
appParams: ApplicationURLParams;
pageParams: Record<string, PageURLParams>;
currentPageId?: string | null;
currentBasePageId?: string | null;
static _instance: URLBuilder;
constructor() {
this.appParams = {
applicationId: "",
baseApplicationId: "",
applicationSlug: PLACEHOLDER_APP_SLUG,
};
this.pageParams = {};
this.currentPageId;
this.currentBasePageId;
}
static getInstance() {
@ -143,26 +144,26 @@ export class URLBuilder {
return URL_TYPE.SLUG;
}
private getFormattedParams(pageId: string) {
private getFormattedParams(basePageId: string) {
const currentAppParams = {
applicationSlug: this.appParams.applicationSlug || PLACEHOLDER_APP_SLUG,
applicationId: this.appParams.applicationId,
baseApplicationId: this.appParams.baseApplicationId,
};
let currentPageParams = this.pageParams[pageId] || {};
let currentPageParams = this.pageParams[basePageId] || {};
currentPageParams = {
...currentPageParams,
pageSlug: `${currentPageParams.pageSlug || PLACEHOLDER_PAGE_SLUG}-`,
customSlug: currentPageParams.customSlug
? `${currentPageParams.customSlug}-`
: "",
pageId,
basePageId,
};
return { ...currentAppParams, ...currentPageParams };
}
setCurrentPageId(pageId?: string | null) {
this.currentPageId = pageId;
setCurrentBasePageId(basePageId?: string | null) {
this.currentBasePageId = basePageId;
}
public updateURLParams(
@ -170,8 +171,8 @@ export class URLBuilder {
pageParams?: PageURLParams[],
) {
if (appParams) {
this.appParams.applicationId =
appParams.applicationId || this.appParams.applicationId;
this.appParams.baseApplicationId =
appParams.baseApplicationId || this.appParams.baseApplicationId;
this.appParams.applicationSlug =
appParams.applicationSlug || this.appParams.applicationSlug;
this.appParams.applicationVersion =
@ -180,7 +181,7 @@ export class URLBuilder {
if (pageParams) {
const params = pageParams.reduce(
(acc, page) => {
acc[page.pageId] = page;
acc[page.basePageId] = page;
return acc;
},
{} as Record<string, PageURLParams>,
@ -192,54 +193,54 @@ export class URLBuilder {
// Currently only used in pages/Applications page on mount
resetURLParams() {
this.appParams = {
applicationId: "",
baseApplicationId: "",
applicationSlug: "",
};
this.pageParams = {};
}
// Current only used in src/pages/slug.test.tsx
getURLParams(pageId: string) {
return { ...this.appParams, ...this.pageParams[pageId] };
getURLParams(basePageId: string) {
return { ...this.appParams, ...this.pageParams[basePageId] };
}
generateBasePathForApp(pageId: string, mode: APP_MODE) {
generateBasePathForApp(basePageId: string, mode: APP_MODE) {
const { applicationVersion } = this.appParams;
const customSlug = this.pageParams[pageId]?.customSlug || "";
const customSlug = this.pageParams[basePageId]?.customSlug || "";
const urlType = this.getURLType(applicationVersion, customSlug);
const urlPattern = baseURLRegistry[urlType][mode];
const formattedParams = this.getFormattedParams(pageId);
const formattedParams = this.getFormattedParams(basePageId);
const basePath = generatePath(urlPattern, formattedParams);
return basePath;
}
generateBasePath(pageId: string, mode: APP_MODE) {
return this.generateBasePathForApp(pageId, mode);
generateBasePath(basePageId: string, mode: APP_MODE) {
return this.generateBasePathForApp(basePageId, mode);
}
getCustomSlugPathPreview(pageId: string, customSlug: string) {
getCustomSlugPathPreview(basePageId: string, customSlug: string) {
const urlPattern =
baseURLRegistry[URL_TYPE.CUSTOM_SLUG][APP_MODE.PUBLISHED];
return generatePath(urlPattern, {
pageId,
basePageId,
customSlug: `${customSlug}-`,
}).toLowerCase();
}
getPagePathPreview(pageId: string, pageName: string) {
getPagePathPreview(basePageId: string, pageName: string) {
const { applicationVersion } = this.appParams;
const urlType = this.getURLType(applicationVersion);
const urlPattern = baseURLRegistry[urlType][APP_MODE.PUBLISHED];
const formattedParams = this.getFormattedParams(pageId);
const formattedParams = this.getFormattedParams(basePageId);
formattedParams.pageSlug = `${pageName}-`;
@ -247,18 +248,18 @@ export class URLBuilder {
}
resolveEntityIdForApp(builderParams: URLBuilderParams) {
const pageId =
builderParams.pageId ||
builderParams?.parentEntityId ||
this.currentPageId;
const basePageId =
builderParams.basePageId ||
builderParams?.baseParentEntityId ||
this.currentBasePageId;
if (!pageId) {
if (!basePageId) {
throw new URIError(
"Missing pageId. If you are trying to set href inside a react component use the 'useHref' hook.",
"Missing basePageId. If you are trying to set href inside a react component use the 'useHref' hook.",
);
}
return pageId;
return basePageId;
}
resolveEntityId(builderParams: URLBuilderParams): string {

View File

@ -20,9 +20,8 @@ import { useShowPageGenerationOnHeader } from "pages/Editor/DataSourceEditor/hoo
import React from "react";
import { useSelector } from "react-redux";
import {
getCurrentApplication,
getCurrentApplicationId,
getCurrentPageId,
getCurrentBasePageId,
getPagePermissions,
} from "selectors/editorSelectors";
import { getIsAnvilEnabledInCurrentApplication } from "layoutSystems/anvil/integrations/selectors";
@ -30,6 +29,7 @@ import { isEnabledForPreviewData } from "utils/editorContextUtils";
import history from "utils/history";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { EditorNames } from "./";
import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors";
export interface HeaderActionProps {
datasource: Datasource | ApiDatasourceForm | undefined;
@ -47,7 +47,7 @@ export const useHeaderActions = (
showReconnectButton = false,
}: HeaderActionProps,
) => {
const pageId = useSelector(getCurrentPageId);
const basePageId = useSelector(getCurrentBasePageId);
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const releaseDragDropBuildingBlocks = useFeatureFlag(
FEATURE_FLAG.release_drag_drop_building_blocks_enabled,
@ -98,7 +98,7 @@ export const useHeaderActions = (
AnalyticsUtil.logEvent("DATASOURCE_CARD_GEN_CRUD_PAGE_ACTION");
history.push(
generateTemplateFormURL({
pageId,
basePageId,
params: {
datasourceId: (datasource as Datasource).id,
new_page: true,
@ -146,11 +146,11 @@ export const useHeaderActions = (
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const useParentEntityInfo = (editorType: string) => {
const appId = useSelector(getCurrentApplicationId);
const pageId = useSelector(getCurrentPageId);
const basePageId = useSelector(getCurrentBasePageId);
return {
editorId: appId || "",
parentEntityId: pageId || "",
parentEntityId: basePageId || "",
parentEntityType: ActionParentEntityType.PAGE,
};
};

View File

@ -23,21 +23,21 @@ export function setSelectedDatasource(id?: string) {
}
export function setSelectedQuery(entityInfo?: FocusEntityInfo) {
if (entityInfo && entityInfo.params.pageId) {
if (entityInfo && entityInfo.params.basePageId) {
if ([FocusEntity.API, FocusEntity.QUERY].includes(entityInfo.entity)) {
const { apiId, pluginPackageName, queryId } = entityInfo.params;
const key = apiId ? apiId : queryId;
const { baseApiId, baseQueryId, pluginPackageName } = entityInfo.params;
const key = baseApiId ? baseApiId : baseQueryId;
if (!key) return undefined;
let type: PluginType = PluginType.API;
if (pluginPackageName) {
type = PluginType.SAAS;
} else if (queryId) {
} else if (baseQueryId) {
type = PluginType.DB;
}
const url = getQueryEntityItemUrl(
{ type, key, title: key },
entityInfo.params.pageId,
entityInfo.params.basePageId,
);
history.replace(url, { invokedBy: NavigationMethod.ContextSwitching });
}
@ -48,7 +48,7 @@ export function setSelectedJSObject(focusInfo?: FocusEntityInfo) {
if (focusInfo && focusInfo.entity === FocusEntity.JS_OBJECT) {
history.replace(
jsCollectionIdURL({
collectionId: focusInfo.id,
baseCollectionId: focusInfo.id,
}),
{ invokedBy: NavigationMethod.ContextSwitching },
);

View File

@ -5,8 +5,8 @@ import { getIDETestState } from "test/factories/AppIDEFactoryUtils";
import { all, take } from "redux-saga/effects";
import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants";
const pageId1 = "0123456789abcdef00000000",
pageId2 = "0123456789abcdef00000001";
const basePageId1 = "0123456789abcdef00000000";
const basePageId2 = "0123456789abcdef00000001";
describe("AppIDEFocusStrategy", () => {
describe("getEntitiesForSet", () => {
@ -30,8 +30,8 @@ describe("AppIDEFocusStrategy", () => {
getState: () => ({ state: "test" }),
},
AppIDEFocusStrategy.getEntitiesForSet,
`/app/appSlug/pageSlug-${pageId1}/edit`,
`/app/appSlug/pageSlug-${pageId1}/edit/widgets`,
`/app/appSlug/pageSlug-${basePageId1}/edit`,
`/app/appSlug/pageSlug-${basePageId1}/edit/widgets`,
{ invokedBy: NavigationMethod.EntityExplorer },
).toPromise();
@ -44,8 +44,8 @@ describe("AppIDEFocusStrategy", () => {
getState: () => ({ state: "test" }),
},
AppIDEFocusStrategy.getEntitiesForSet,
`/app/appSlug/pageSlug-${pageId1}/edit/widgets/1`,
`/app/appSlug/pageSlug-${pageId1}/edit/widgets`,
`/app/appSlug/pageSlug-${basePageId1}/edit/widgets/1`,
`/app/appSlug/pageSlug-${basePageId1}/edit/widgets`,
{ invokedBy: undefined },
).toPromise();
@ -58,8 +58,8 @@ describe("AppIDEFocusStrategy", () => {
getState: () => state,
},
AppIDEFocusStrategy.getEntitiesForSet,
`/app/appSlug/pageSlug-${pageId1}/edit/widgets/1`,
`/app/appSlug/pageSlug-${pageId2}/edit/widgets`,
`/app/appSlug/pageSlug-${basePageId1}/edit/widgets/1`,
`/app/appSlug/pageSlug-${basePageId2}/edit/widgets`,
{ invokedBy: undefined },
).toPromise();
@ -72,11 +72,11 @@ describe("AppIDEFocusStrategy", () => {
params: {
applicationSlug: "appSlug",
entity: "widgets",
pageId: pageId2,
basePageId: basePageId2,
pageSlug: "pageSlug-",
},
},
key: `/app/appSlug/pageSlug-${pageId2}/edit/widgets#main`,
key: `/app/appSlug/pageSlug-${basePageId2}/edit/widgets#main`,
},
]);
});
@ -88,8 +88,8 @@ describe("AppIDEFocusStrategy", () => {
getState: () => state,
},
AppIDEFocusStrategy.getEntitiesForSet,
`/app/appSlug/pageSlug-${pageId1}/edit/datasource/data_id`,
`/app/appSlug/pageSlug-${pageId1}/edit`,
`/app/appSlug/pageSlug-${basePageId1}/edit/datasource/data_id`,
`/app/appSlug/pageSlug-${basePageId1}/edit`,
{ invokedBy: undefined },
).toPromise();
@ -97,10 +97,10 @@ describe("AppIDEFocusStrategy", () => {
entityInfo: {
appState: "EDITOR",
entity: "EDITOR",
id: `EDITOR.${pageId1}`,
id: `EDITOR.${basePageId1}`,
params: {},
},
key: `EDITOR_STATE.${pageId1}#main`,
key: `EDITOR_STATE.${basePageId1}#main`,
});
const pageIdChangeResult = await runSaga(
@ -108,8 +108,8 @@ describe("AppIDEFocusStrategy", () => {
getState: () => state,
},
AppIDEFocusStrategy.getEntitiesForSet,
`/app/appSlug/pageSlug-${pageId1}/edit/widgets/1`,
`/app/appSlug/pageSlug-${pageId2}/edit`,
`/app/appSlug/pageSlug-${basePageId1}/edit/widgets/1`,
`/app/appSlug/pageSlug-${basePageId2}/edit`,
{ invokedBy: undefined },
).toPromise();
@ -117,10 +117,10 @@ describe("AppIDEFocusStrategy", () => {
entityInfo: {
appState: "EDITOR",
entity: "EDITOR",
id: `EDITOR.${pageId2}`,
id: `EDITOR.${basePageId2}`,
params: {},
},
key: `EDITOR_STATE.${pageId2}#main`,
key: `EDITOR_STATE.${basePageId2}#main`,
});
});
@ -131,8 +131,8 @@ describe("AppIDEFocusStrategy", () => {
getState: () => state,
},
AppIDEFocusStrategy.getEntitiesForSet,
`/app/appSlug/pageSlug-${pageId1}/edit/datasource/data_id`,
`/app/appSlug/pageSlug-${pageId1}/edit/datasource/data_id2`,
`/app/appSlug/pageSlug-${basePageId1}/edit/datasource/data_id`,
`/app/appSlug/pageSlug-${basePageId1}/edit/datasource/data_id2`,
{ invokedBy: undefined },
).toPromise();
@ -145,11 +145,11 @@ describe("AppIDEFocusStrategy", () => {
params: {
applicationSlug: "appSlug",
datasourceId: "data_id2",
pageId: pageId1,
basePageId: basePageId1,
pageSlug: "pageSlug-",
},
},
key: `/app/appSlug/pageSlug-${pageId1}/edit/datasource/data_id2#main`,
key: `/app/appSlug/pageSlug-${basePageId1}/edit/datasource/data_id2#main`,
},
]);
});
@ -163,8 +163,8 @@ describe("AppIDEFocusStrategy", () => {
getState: () => state,
},
AppIDEFocusStrategy.getEntitiesForStore,
`/app/appSlug/pageSlug-${pageId1}/edit/datasource/data_id`,
`/app/appSlug/pageSlug-${pageId1}/edit/datasource/data_id2`,
`/app/appSlug/pageSlug-${basePageId1}/edit/datasource/data_id`,
`/app/appSlug/pageSlug-${basePageId1}/edit/datasource/data_id2`,
).toPromise();
expect(result).toContainEqual({
@ -182,8 +182,8 @@ describe("AppIDEFocusStrategy", () => {
getState: () => state,
},
AppIDEFocusStrategy.getEntitiesForStore,
`/app/appSlug/pageSlug-${pageId1}/edit/jsObjects/js_id`,
`/app/appSlug/pageSlug-${pageId1}/edit/widgets/widget_id`,
`/app/appSlug/pageSlug-${basePageId1}/edit/jsObjects/js_id`,
`/app/appSlug/pageSlug-${basePageId1}/edit/widgets/widget_id`,
).toPromise();
expect(result).toContainEqual({
@ -191,7 +191,7 @@ describe("AppIDEFocusStrategy", () => {
appState: "EDITOR",
entity: "EDITOR",
}),
key: `EDITOR_STATE.${pageId1}#main`,
key: `EDITOR_STATE.${basePageId1}#main`,
});
});
@ -201,8 +201,8 @@ describe("AppIDEFocusStrategy", () => {
getState: () => state,
},
AppIDEFocusStrategy.getEntitiesForStore,
`/app/appSlug/pageSlug-${pageId1}/edit/jsObjects`,
`/app/appSlug/pageSlug-${pageId1}/edit/jsObjects/js_id`,
`/app/appSlug/pageSlug-${basePageId1}/edit/jsObjects`,
`/app/appSlug/pageSlug-${basePageId1}/edit/jsObjects/js_id`,
).toPromise();
expect(result).not.toContainEqual({
@ -217,8 +217,8 @@ describe("AppIDEFocusStrategy", () => {
getState: () => state,
},
AppIDEFocusStrategy.getEntitiesForStore,
`/app/appSlug/pageSlug-${pageId1}/edit/jsObjects/js_id2`,
`/app/appSlug/pageSlug-${pageId1}/edit/jsObjects/js_id`,
`/app/appSlug/pageSlug-${basePageId1}/edit/jsObjects/js_id2`,
`/app/appSlug/pageSlug-${basePageId1}/edit/jsObjects/js_id`,
).toPromise();
expect(resultWithNoParent).toContainEqual({
@ -234,8 +234,8 @@ describe("AppIDEFocusStrategy", () => {
describe("Wait for Path Load", () => {
it("waits for page fetch success when page changes", () => {
const pageChangeGen = AppIDEFocusStrategy.waitForPathLoad(
`/app/appSlug/pageSlug1-${pageId1}/edit`,
`/app/appSlug/pageSlug2-${pageId2}/edit`,
`/app/appSlug/pageSlug1-${basePageId1}/edit`,
`/app/appSlug/pageSlug2-${basePageId2}/edit`,
);
expect(pageChangeGen.next().value).toEqual(
@ -245,8 +245,8 @@ describe("AppIDEFocusStrategy", () => {
it("does not wait for page fetch success when page does not change", () => {
const pageChangeGen = AppIDEFocusStrategy.waitForPathLoad(
`/app/appSlug/pageSlug1-${pageId1}/edit/widgets/1`,
`/app/appSlug/pageSlug1-${pageId1}/edit/widgets/2`,
`/app/appSlug/pageSlug1-${basePageId1}/edit/widgets/1`,
`/app/appSlug/pageSlug1-${basePageId1}/edit/widgets/2`,
);
expect(pageChangeGen.next().value).toEqual(undefined);

View File

@ -71,22 +71,23 @@ const isPageChange = (prevPath: string, currentPath: string) => {
const prevFocusEntityInfo = identifyEntityFromPath(prevPath);
const currFocusEntityInfo = identifyEntityFromPath(currentPath);
if (
prevFocusEntityInfo.params.pageId === "" ||
currFocusEntityInfo.params.pageId === ""
prevFocusEntityInfo.params.basePageId === "" ||
currFocusEntityInfo.params.basePageId === ""
) {
return false;
}
return (
prevFocusEntityInfo.params.pageId !== currFocusEntityInfo.params.pageId
prevFocusEntityInfo.params.basePageId !==
currFocusEntityInfo.params.basePageId
);
};
export const createEditorFocusInfoKey = (pageId: string, branch?: string) =>
`EDITOR_STATE.${pageId}#${branch}`;
export const createEditorFocusInfo = (pageId: string, branch?: string) => ({
key: createEditorFocusInfoKey(pageId, branch),
export const createEditorFocusInfoKey = (basePageId: string, branch?: string) =>
`EDITOR_STATE.${basePageId}#${branch}`;
export const createEditorFocusInfo = (basePageId: string, branch?: string) => ({
key: createEditorFocusInfoKey(basePageId, branch),
entityInfo: {
id: `EDITOR.${pageId}`,
id: `EDITOR.${basePageId}`,
appState: EditorState.EDITOR,
entity: FocusEntity.EDITOR,
params: {},
@ -111,12 +112,13 @@ export const AppIDEFocusStrategy: FocusStrategy = {
// Only set the editor state if switching between pages or app states
if (
currentEntityInfo.entity === FocusEntity.CANVAS &&
(prevEntityInfo.params.pageId !== currentEntityInfo.params.pageId ||
(prevEntityInfo.params.basePageId !==
currentEntityInfo.params.basePageId ||
prevEntityInfo.appState !== currentEntityInfo.appState)
) {
if (currentEntityInfo.params.pageId) {
if (currentEntityInfo.params.basePageId) {
entities.push(
createEditorFocusInfo(currentEntityInfo.params.pageId, branch),
createEditorFocusInfo(currentEntityInfo.params.basePageId, branch),
);
}
}
@ -159,17 +161,17 @@ export const AppIDEFocusStrategy: FocusStrategy = {
prevFocusEntityInfo.appState === EditorState.EDITOR &&
prevFocusEntityInfo.entity !== FocusEntity.NONE &&
(prevFocusEntityInfo.entity !== currentFocusEntityInfo.entity ||
prevFocusEntityInfo.params.pageId !==
currentFocusEntityInfo.params.pageId)
prevFocusEntityInfo.params.basePageId !==
currentFocusEntityInfo.params.basePageId)
) {
entities.push({
entityInfo: {
entity: FocusEntity.EDITOR,
id: `EDITOR.${prevFocusEntityInfo.params.pageId}`,
id: `EDITOR.${prevFocusEntityInfo.params.basePageId}`,
appState: EditorState.EDITOR,
params: prevFocusEntityInfo.params,
},
key: `EDITOR_STATE.${prevFocusEntityInfo.params.pageId}#${branch}`,
key: `EDITOR_STATE.${prevFocusEntityInfo.params.basePageId}#${branch}`,
});
}
@ -192,22 +194,22 @@ export const AppIDEFocusStrategy: FocusStrategy = {
let parentUrl: string = "";
if (parentEntity === FocusEntity.WIDGET_LIST) {
parentUrl = widgetListURL({
pageId: entityInfo.params.pageId,
basePageId: entityInfo.params.basePageId,
});
}
if (parentEntity === FocusEntity.DATASOURCE_LIST) {
parentUrl = datasourcesEditorURL({
pageId: entityInfo.params.pageId,
basePageId: entityInfo.params.basePageId,
});
}
if (parentEntity === FocusEntity.JS_OBJECT_LIST) {
parentUrl = jsCollectionListURL({
pageId: entityInfo.params.pageId,
basePageId: entityInfo.params.basePageId,
});
}
if (parentEntity === FocusEntity.QUERY_LIST) {
parentUrl = queryListURL({
pageId: entityInfo.params.pageId,
basePageId: entityInfo.params.basePageId,
});
}
// We do not have to add any query params because this url is used as the key

View File

@ -40,7 +40,7 @@ function NavigationLogo(props: NavigationLogoProps) {
const pageUrl = useHref(
appMode === APP_MODE.PUBLISHED ? viewerURL : builderURL,
{
pageId: defaultPage?.pageId,
basePageId: defaultPage?.basePageId,
},
);
const logoAssetId = get(

View File

@ -59,7 +59,7 @@ function ApplicationCardList({
title={title}
titleTag={titleTag}
>
{applications.map((application: any) => {
{applications.map((application) => {
return (
<PaddingWrapper isMobile={isMobile} key={application.id}>
<ApplicationCard

View File

@ -145,17 +145,17 @@ const CreateNewAppsOption = ({
{
applicationSlug: applicationObject.slug,
applicationVersion: applicationObject.applicationVersion,
applicationId: applicationObject.id,
baseApplicationId: applicationObject.baseId,
},
applicationObject.pages.map((page) => ({
pageSlug: page.slug,
customSlug: page.customSlug,
pageId: page.id,
basePageId: page.baseId,
})),
);
history.push(
builderURL({
pageId: applicationObject.pages[0].id,
basePageId: applicationObject.pages[0].baseId,
}),
);
@ -178,12 +178,12 @@ const CreateNewAppsOption = ({
{
applicationSlug: application.slug,
applicationVersion: application.applicationVersion,
applicationId: application.id,
baseApplicationId: application.baseId,
},
application.pages.map((page) => ({
pageSlug: page.slug,
customSlug: page.customSlug,
pageId: page.id,
basePageId: page.baseId,
})),
);

View File

@ -8,7 +8,6 @@ import {
createMessage,
IN_APP_EMBED_SETTING,
} from "@appsmith/constants/messages";
import { getCurrentApplication } from "selectors/editorSelectors";
import PrivateEmbeddingContent, {
PrivateEmbedRampModal,
PrivateEmbedRampSidebar,
@ -17,6 +16,7 @@ import PropertyHelpLabel from "pages/Editor/PropertyPane/PropertyHelpLabel";
import { ADMIN_SETTINGS_PATH } from "constants/routes";
import { defaultOptionSelected, to, getSnippetUrl } from "@appsmith/utils";
import { PrivateEmbedSettings } from "@appsmith/pages/Applications/PrivateEmbedSettings";
import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors";
export const StyledPropertyHelpLabel = styled(PropertyHelpLabel)`
.bp3-popover-content > div {

View File

@ -37,7 +37,7 @@ export const ContextMenuPopoverModifiers: IPopoverSharedProps["modifiers"] = {
};
export interface ExplorerURLParams {
pageId: string;
basePageId: string;
}
export interface ExplorerFileEntity {
@ -59,36 +59,36 @@ export const getActionIdFromURL = () => {
const baseMatch = matchBasePath(window.location.pathname);
if (!baseMatch) return;
const { path: basePath } = baseMatch;
const apiMatch = matchPath<{ apiId: string }>(window.location.pathname, {
const apiMatch = matchPath<{ baseApiId: string }>(window.location.pathname, {
path: `${basePath}${API_EDITOR_ID_PATH}`,
});
if (apiMatch?.params?.apiId) {
return apiMatch.params.apiId;
if (apiMatch?.params?.baseApiId) {
return apiMatch.params.baseApiId;
}
const match = matchPath<{ queryId: string }>(window.location.pathname, {
const match = matchPath<{ baseQueryId: string }>(window.location.pathname, {
path: `${basePath}${QUERIES_EDITOR_ID_PATH}`,
});
if (match?.params?.queryId) {
return match.params.queryId;
if (match?.params?.baseQueryId) {
return match.params.baseQueryId;
}
const saasMatch = matchPath<{ apiId: string }>(window.location.pathname, {
const saasMatch = matchPath<{ baseApiId: string }>(window.location.pathname, {
path: `${basePath}${SAAS_EDITOR_API_ID_PATH}`,
});
if (saasMatch?.params?.apiId) {
return saasMatch.params.apiId;
if (saasMatch?.params?.baseApiId) {
return saasMatch.params.baseApiId;
}
};
export function getAppViewerPageIdFromPath(path: string): string | null {
const regexes = [
`${BUILDER_VIEWER_PATH_PREFIX}:applicationSlug/:pageSlug(.*\\-):pageId`, // VIEWER_PATH
`${BUILDER_VIEWER_PATH_PREFIX}:customSlug(.*\\-):pageId`, // VIEWER_CUSTOM_PATH
`/applications/:applicationId/pages/:pageId`, // VIEWER_PATH_DEPRECATED
`${BUILDER_VIEWER_PATH_PREFIX}:applicationSlug/:pageSlug(.*\\-):basePageId`, // VIEWER_PATH
`${BUILDER_VIEWER_PATH_PREFIX}:customSlug(.*\\-):basePageId`, // VIEWER_CUSTOM_PATH
`/applications/:baseApplicationId/pages/:basePageId`, // VIEWER_PATH_DEPRECATED
];
for (const regex of regexes) {
const match = matchPath<{ pageId: string }>(path, { path: regex });
if (match?.params.pageId) {
return match.params.pageId;
const match = matchPath<{ basePageId: string }>(path, { path: regex });
if (match?.params.basePageId) {
return match.params.basePageId;
}
}
return null;
@ -96,7 +96,7 @@ export function getAppViewerPageIdFromPath(path: string): string | null {
export const matchEditorPath = (
path: string,
): Match<{ applicationId: string; pageId: string }> => {
): Match<{ baseApplicationId: string; basePageId: string }> => {
return matchBuilderPath(path, { end: false });
};
export const isEditorPath = (path: string) => {
@ -111,14 +111,14 @@ export const getJSCollectionIdFromURL = () => {
const baseMatch = matchBasePath(window.location.pathname);
if (!baseMatch) return;
const { path: basePath } = baseMatch;
const functionMatch = matchPath<{ collectionId: string }>(
const functionMatch = matchPath<{ baseCollectionId: string }>(
window.location.pathname,
{
path: `${basePath}${JS_COLLECTION_ID_PATH}`,
},
);
if (functionMatch?.params?.collectionId) {
return functionMatch?.params?.collectionId;
if (functionMatch?.params?.baseCollectionId) {
return functionMatch?.params?.baseCollectionId;
}
};
@ -126,11 +126,11 @@ export const getQueryIdFromURL = () => {
const baseMatch = matchBasePath(window.location.pathname);
if (!baseMatch) return;
const { path: basePath } = baseMatch;
const match = matchPath<{ queryId: string }>(window.location.pathname, {
const match = matchPath<{ baseQueryId: string }>(window.location.pathname, {
path: `${basePath}${QUERIES_EDITOR_ID_PATH}`,
});
if (match?.params?.queryId) {
return match.params.queryId;
if (match?.params?.baseQueryId) {
return match.params.baseQueryId;
}
};

View File

@ -266,11 +266,11 @@ export const useEntityEditState = (entityId: string) => {
);
};
export function useActiveAction() {
export function useActiveActionBaseId() {
const location = useLocation();
const path = basePathForActiveAction;
const baseMatch = matchPath<{ apiId: string }>(location.pathname, {
const baseMatch = matchPath<{ baseApiId: string }>(location.pathname, {
path,
strict: false,
exact: false,
@ -278,29 +278,29 @@ export function useActiveAction() {
const basePath = baseMatch?.path || "";
const apiMatch = matchPath<{ apiId: string }>(location.pathname, {
const apiMatch = matchPath<{ baseApiId: string }>(location.pathname, {
path: `${basePath}${API_EDITOR_ID_PATH}`,
});
if (apiMatch?.params?.apiId) {
return apiMatch.params.apiId;
if (apiMatch?.params?.baseApiId) {
return apiMatch.params.baseApiId;
}
const queryMatch = matchPath<{ queryId: string }>(location.pathname, {
const queryMatch = matchPath<{ baseQueryId: string }>(location.pathname, {
path: `${basePath}${QUERIES_EDITOR_ID_PATH}`,
});
if (queryMatch?.params?.queryId) {
return queryMatch.params.queryId;
if (queryMatch?.params?.baseQueryId) {
return queryMatch.params.baseQueryId;
}
const jsMatch = matchPath<{ collectionId: string }>(location.pathname, {
const jsMatch = matchPath<{ baseCollectionId: string }>(location.pathname, {
path: `${basePath}${JS_COLLECTION_ID_PATH}`,
});
if (jsMatch?.params?.collectionId) {
return jsMatch.params.collectionId;
if (jsMatch?.params?.baseCollectionId) {
return jsMatch.params.baseCollectionId;
}
const saasMatch = matchPath<{ apiId: string }>(location.pathname, {
const saasMatch = matchPath<{ baseApiId: string }>(location.pathname, {
path: `${basePath}${SAAS_EDITOR_API_ID_PATH}`,
});
if (saasMatch?.params?.apiId) {
return saasMatch.params.apiId;
if (saasMatch?.params?.baseApiId) {
return saasMatch.params.baseApiId;
}
}

View File

@ -16,7 +16,7 @@ export const JSListItem = (props: JSListItemProps) => {
return (
<Flex data-testid="t--ide-list-item" flexDirection={"column"}>
<ExplorerJSCollectionEntity
id={item.key}
baseCollectionId={item.key}
isActive={isActive}
key={item.key}
parentEntityId={parentEntityId}

View File

@ -86,13 +86,13 @@ export const useJSSegmentRoutes = (path: string): UseRoutes => {
exact: true,
key: "AddJS",
component: AddJS,
path: [`${path}${ADD_PATH}`, `${path}/:collectionId${ADD_PATH}`],
path: [`${path}${ADD_PATH}`, `${path}/:baseCollectionId${ADD_PATH}`],
},
{
exact: true,
key: "JSEditor",
component: JSEditor,
path: [path + "/:collectionId"],
path: [path + "/:baseCollectionId"],
},
{
key: "JSEmpty",
@ -107,7 +107,11 @@ export const useJSSegmentRoutes = (path: string): UseRoutes => {
exact: false,
key: "ListJS",
component: ListJS,
path: [path, `${path}${ADD_PATH}`, `${path}/:collectionId${ADD_PATH}`],
path: [
path,
`${path}${ADD_PATH}`,
`${path}/:baseCollectionId${ADD_PATH}`,
],
},
];
};

View File

@ -6,7 +6,7 @@ import { FocusEntity } from "navigation/FocusEntity";
import { EditorState } from "@appsmith/entities/IDE/constants";
describe("getJSEntityItemUrl", () => {
urlBuilder.setCurrentPageId("0123456789abcdef00000000");
urlBuilder.setCurrentBasePageId("0123456789abcdef00000000");
it("returns a JS url", () => {
const url = getJSEntityItemUrl(
{
@ -16,7 +16,6 @@ describe("getJSEntityItemUrl", () => {
},
"0123456789abcdef00000000",
);
expect(url).toEqual(
"/app/application/page-0123456789abcdef00000000/edit/jsObjects/abc",
);
@ -24,7 +23,7 @@ describe("getJSEntityItemUrl", () => {
});
describe("getJSUrl", () => {
urlBuilder.setCurrentPageId("0123456789abcdef00000000");
urlBuilder.setCurrentBasePageId("0123456789abcdef00000000");
it("returns a JS collection url", () => {
const focusEntity: FocusEntityInfo = {
entity: FocusEntity.JS_OBJECT,
@ -62,8 +61,8 @@ describe("getJSUrl", () => {
id: "abc",
appState: EditorState.EDITOR,
params: {
queryId: "abc",
pageId: "0123456789abcdef00000000",
baseQueryId: "abc",
basePageId: "0123456789abcdef00000000",
},
};
const url = getJSUrl(focusEntity, false);

View File

@ -8,11 +8,11 @@ import { FocusEntity, type FocusEntityInfo } from "navigation/FocusEntity";
export const getJSEntityItemUrl = (
item: EntityItem,
pageId: string,
basePageId: string,
): string => {
return jsCollectionIdURL({
collectionId: item.key,
pageId,
baseCollectionId: item.key,
basePageId,
});
};
@ -22,13 +22,13 @@ export const getJSUrl = (
): string => {
if (item.entity === FocusEntity.JS_OBJECT) {
return jsCollectionIdURL({
collectionId: item.id,
baseCollectionId: item.id || "",
add,
});
} else if (item.entity === FocusEntity.JS_OBJECT_ADD) {
return jsCollectionListURL({ pageId: item.params.pageId });
return jsCollectionListURL({ basePageId: item.params.basePageId });
}
return add
? jsCollectionAddURL({ pageId: item.params.pageId })
: jsCollectionListURL({ pageId: item.params.pageId });
? jsCollectionAddURL({ basePageId: item.params.basePageId })
: jsCollectionListURL({ basePageId: item.params.basePageId });
};

View File

@ -14,7 +14,7 @@ export const QueryListItem = (props: QueryListItemProps) => {
const { isActive, item, parentEntityId, parentEntityType } = props;
return (
<ExplorerActionEntity
id={item.key}
baseId={item.key}
isActive={isActive}
key={item.key}
parentEntityId={parentEntityId}

View File

@ -127,7 +127,7 @@ export const useQuerySegmentRoutes = (path: string): UseRoutes => {
key: "AddQuery",
exact: true,
component: AddQuery,
path: [`${path}${ADD_PATH}`, `${path}/:queryId${ADD_PATH}`],
path: [`${path}${ADD_PATH}`, `${path}/:baseQueryId${ADD_PATH}`],
},
{
key: "SAASEditor",
@ -143,7 +143,7 @@ export const useQuerySegmentRoutes = (path: string): UseRoutes => {
key: "QueryEditor",
component: QueryEditor,
exact: true,
path: [path + "/:queryId"],
path: [path + "/:baseQueryId"],
},
{
key: "QueryEmpty",
@ -158,7 +158,7 @@ export const useQuerySegmentRoutes = (path: string): UseRoutes => {
key: "ListQuery",
exact: false,
component: ListQuery,
path: [path, `${path}${ADD_PATH}`, `${path}/:queryId${ADD_PATH}`],
path: [path, `${path}${ADD_PATH}`, `${path}/:baseQueryId${ADD_PATH}`],
},
];
};

View File

@ -30,7 +30,7 @@ describe("getQueryEntityItemUrl", () => {
});
describe("getQueryUrl", () => {
urlBuilder.setCurrentPageId("0123456789abcdef00000000");
urlBuilder.setCurrentBasePageId("0123456789abcdef00000000");
it("gets the correct SAAS plugin url", () => {
const focusEntity: FocusEntityInfo = {
entity: FocusEntity.QUERY,
@ -38,7 +38,7 @@ describe("getQueryUrl", () => {
appState: EditorState.EDITOR,
params: {
pluginPackageName: PluginPackageName.GOOGLE_SHEETS,
apiId: "abc",
baseApiId: "abc",
},
};
@ -59,7 +59,7 @@ describe("getQueryUrl", () => {
id: "abc",
appState: EditorState.EDITOR,
params: {
apiId: "abc",
baseApiId: "abc",
},
};
@ -80,7 +80,7 @@ describe("getQueryUrl", () => {
id: "abc",
appState: EditorState.EDITOR,
params: {
queryId: "abc",
baseQueryId: "abc",
},
};
@ -101,7 +101,7 @@ describe("getQueryUrl", () => {
id: "add",
appState: EditorState.EDITOR,
params: {
queryId: "add",
baseQueryId: "add",
},
};
@ -117,7 +117,7 @@ describe("getQueryUrl", () => {
id: "abc",
appState: EditorState.EDITOR,
params: {
collectionId: "abc",
baseCollectionId: "abc",
},
};

View File

@ -11,42 +11,42 @@ import {
export const getQueryEntityItemUrl = (
item: EntityItem,
pageId: string,
basePageId: string,
): string => {
const config = getActionConfig(item.type);
if (!config) {
throw Error(`Cannot find url of plugin type ${item.type}`);
}
return config.getURL(pageId, item.key, item.type);
return config.getURL(basePageId, item.key, item.type);
};
export const getQueryUrl = (
item: FocusEntityInfo,
add: boolean = true,
): string => {
if (item.params.apiId) {
if (item.params.baseApiId) {
if (item.params.pluginPackageName) {
return saasEditorApiIdURL({
pluginPackageName: item.params.pluginPackageName,
apiId: item.params.apiId,
baseApiId: item.params.baseApiId,
add,
});
} else {
return apiEditorIdURL({
apiId: item.params.apiId,
baseApiId: item.params.baseApiId,
add,
});
}
} else if (item.params.queryId) {
if (item.params.queryId === "add") {
return queryListURL({ pageId: item.params.pageId });
} else if (item.params.baseQueryId) {
if (item.params.baseQueryId === "add") {
return queryListURL({ basePageId: item.params.basePageId });
}
return queryEditorIdURL({
queryId: item.params.queryId,
baseQueryId: item.params.baseQueryId,
add,
});
}
return add
? queryAddURL({ pageId: item.params.pageId })
: queryListURL({ pageId: item.params.pageId });
? queryAddURL({ basePageId: item.params.basePageId })
: queryListURL({ basePageId: item.params.basePageId });
};

View File

@ -5,6 +5,8 @@ import {
createMessage,
} from "@appsmith/constants/messages";
import { EditorNames } from "@appsmith/hooks";
import { getApplicationByIdFromWorkspaces } from "@appsmith/selectors/applicationSelectors";
import { useSelector } from "react-redux";
interface UseReconnectModalDataProps {
pageId: string | null;
@ -12,10 +14,16 @@ interface UseReconnectModalDataProps {
}
function useReconnectModalData({ appId, pageId }: UseReconnectModalDataProps) {
const application = useSelector((state) =>
getApplicationByIdFromWorkspaces(state, appId ?? ""),
);
const basePageId = application?.pages?.find(
(page) => page.id === pageId,
)?.baseId;
const editorURL =
pageId &&
basePageId &&
builderURL({
pageId,
basePageId,
});
return {

View File

@ -31,7 +31,7 @@ export interface ActionDataWithMeta extends ActionData {
export type ActionDataState = ActionData[];
export interface PartialActionData {
isLoading: boolean;
config: { id: string };
config: { id: string; baseId: string };
data?: ActionResponse;
}
@ -111,7 +111,11 @@ export const handlers = {
) => {
return draftMetaState.concat([
{
config: { ...action.payload, id: action.payload.name },
config: {
...action.payload,
baseId: action.payload.name,
id: action.payload.name,
},
isLoading: false,
},
]);
@ -196,7 +200,7 @@ export const handlers = {
} else {
const partialAction: PartialActionData = {
isLoading: false,
config: { id: action.payload.id },
config: { id: action.payload.id, baseId: action.payload.baseId },
data: action.payload.response,
};
draftMetaState.push(partialAction);

View File

@ -780,6 +780,7 @@ export interface ApplicationsReduxState {
export interface Application {
id: string;
baseId: string;
name: string;
workspaceId: string;
isPublic: boolean;

View File

@ -42,8 +42,8 @@ import {
} from "sagas/ActionExecution/geolocationSaga";
import { postMessageSaga } from "sagas/ActionExecution/PostMessageSaga";
import type { ActionDescription } from "@appsmith/workers/Evaluation/fns";
import { getActionById } from "selectors/editorSelectors";
import type { AppState } from "@appsmith/reducers";
import { getAction } from "@appsmith/selectors/entitiesSelector";
export interface TriggerMeta {
source?: TriggerSource;
@ -71,15 +71,8 @@ export function* executeActionTriggers(
break;
case "CLEAR_PLUGIN_ACTION":
yield put(clearActionResponse(trigger.payload.actionId));
const action: ReturnType<typeof getActionById> = yield select(
(state: AppState) =>
getActionById(state, {
match: {
params: {
apiId: trigger.payload.actionId,
},
},
}),
const action: ReturnType<typeof getAction> = yield select(
(state: AppState) => getAction(state, trigger.payload.actionId),
);
if (action) {
yield put(

View File

@ -68,6 +68,7 @@ import type { Workspace } from "@appsmith/constants/workspaceConstants";
import type { AppColorCode } from "constants/DefaultTheme";
import {
getCurrentApplicationId,
getCurrentBasePageId,
getCurrentPageId,
getIsEditorInitialized,
} from "selectors/editorSelectors";
@ -92,7 +93,7 @@ import type { Datasource } from "entities/Datasource";
import { builderURL, viewerURL } from "@appsmith/RouteBuilder";
import { getDefaultPageId as selectDefaultPageId } from "sagas/selectors";
import PageApi from "api/PageApi";
import { identity, isEmpty, merge, pickBy } from "lodash";
import { isEmpty, merge } from "lodash";
import { checkAndGetPluginFormConfigsSaga } from "sagas/PluginSagas";
import {
getPageList,
@ -100,6 +101,7 @@ import {
} from "@appsmith/selectors/entitiesSelector";
import { getConfigInitialValues } from "components/formControls/utils";
import DatasourcesApi from "api/DatasourcesApi";
import type { SetDefaultPageActionPayload } from "actions/pageActions";
import { resetApplicationWidgets } from "actions/pageActions";
import { setCanvasCardsState } from "actions/editorActions";
import { toast } from "design-system";
@ -123,17 +125,10 @@ import {
import equal from "fast-deep-equal";
import { getFromServerWhenNoPrefetchedResult } from "sagas/helper";
import { getIsAnvilLayoutEnabled } from "layoutSystems/anvil/integrations/selectors";
export const getDefaultPageId = (
pages?: ApplicationPagePayload[],
): string | undefined => {
let defaultPage: ApplicationPagePayload | undefined = undefined;
if (pages) {
defaultPage = pages.find((page) => page.isDefault);
if (!defaultPage) {
defaultPage = pages[0];
}
}
return defaultPage ? defaultPage.id : undefined;
export const findDefaultPage = (pages: ApplicationPagePayload[] = []) => {
const defaultPage = pages.find((page) => page.isDefault) ?? pages[0];
return defaultPage;
};
export let windowReference: Window | null = null;
@ -154,10 +149,11 @@ export function* publishApplicationSaga(
});
const applicationId: string = yield select(getCurrentApplicationId);
const currentBasePageId: string = yield select(getCurrentBasePageId);
const currentPageId: string = yield select(getCurrentPageId);
const appicationViewPageUrl = viewerURL({
pageId: currentPageId,
basePageId: currentBasePageId,
});
yield put(
@ -208,9 +204,11 @@ export function* fetchAllApplicationsOfWorkspaceSaga(
const isValidResponse: boolean = yield validateResponse(response);
if (isValidResponse) {
const applications = response.data.map((application) => {
const defaultPage = findDefaultPage(application.pages);
return {
...application,
defaultPageId: getDefaultPageId(application.pages),
defaultPageId: defaultPage?.id,
defaultBasePageId: defaultPage?.baseId,
};
});
yield put({
@ -241,15 +239,20 @@ export function* fetchAppAndPagesSaga(
) {
try {
const { pages, ...payload } = action.payload;
const params = pickBy(payload, identity);
if (params.pageId && params.applicationId) {
delete params.applicationId;
const request = {
applicationId: payload.applicationId,
pageId: payload.pageId,
mode: payload.mode,
};
if (request.pageId && request.applicationId) {
delete request.applicationId;
}
const response: FetchApplicationResponse = yield call(
getFromServerWhenNoPrefetchedResult,
pages,
() => call(PageApi.fetchAppAndPages, params),
() => call(PageApi.fetchAppAndPages, request),
);
const isValidResponse: boolean = yield call(validateResponse, response);
if (isValidResponse) {
const prevPagesState: Page[] = yield select(getPageList);
@ -271,6 +274,7 @@ export function* fetchAppAndPagesSaga(
pages: response.data.pages.map((page) => ({
pageName: page.name,
pageId: page.id,
basePageId: page.baseId,
isDefault: page.isDefault,
isHidden: !!page.isHidden,
slug: page.slug,
@ -280,6 +284,7 @@ export function* fetchAppAndPagesSaga(
: pagePermissionsMap[page.id],
})),
applicationId: response.data.application?.id,
baseApplicationId: response.data.application?.baseId,
},
});
@ -328,12 +333,15 @@ export function* handleFetchApplicationError(error: any) {
}
export function* setDefaultApplicationPageSaga(
action: ReduxAction<SetDefaultPageRequest>,
action: ReduxAction<SetDefaultPageActionPayload>,
) {
try {
const defaultPageId: string = yield select(selectDefaultPageId);
if (defaultPageId !== action.payload.id) {
const request: SetDefaultPageRequest = action.payload;
const request: SetDefaultPageRequest = {
...action.payload,
pageId: action.payload.id,
};
const response: ApiResponse = yield call(
ApplicationApi.setDefaultApplicationPage,
request,
@ -341,7 +349,10 @@ export function* setDefaultApplicationPageSaga(
const isValidResponse: boolean = yield validateResponse(response);
if (isValidResponse) {
yield put(
setDefaultApplicationPageSuccess(request.id, request.applicationId),
setDefaultApplicationPageSuccess(
request.pageId,
request.applicationId,
),
);
}
}
@ -564,9 +575,11 @@ export function* createApplicationSaga(
);
const isValidResponse: boolean = yield validateResponse(response);
if (isValidResponse) {
const defaultPage = findDefaultPage(response.data.pages);
const application: ApplicationPayload = {
...response.data,
defaultPageId: getDefaultPageId(response.data.pages) as string,
defaultPageId: defaultPage?.id,
defaultBasePageId: defaultPage?.baseId,
};
AnalyticsUtil.logEvent("CREATE_APP", {
appName: application.name,
@ -601,13 +614,10 @@ export function* createApplicationSaga(
payload: application.id,
});
}
// Show cta's in empty canvas for the first page
yield put(
setCanvasCardsState(getDefaultPageId(response.data.pages) ?? ""),
);
yield put(setCanvasCardsState(defaultPage?.id ?? ""));
history.push(
builderURL({
pageId: application.defaultPageId as string,
basePageId: defaultPage?.baseId,
}),
);
@ -645,10 +655,11 @@ export function* forkApplicationSaga(
const isValidResponse: boolean = yield validateResponse(response);
if (isValidResponse) {
yield put(resetCurrentApplication());
const defaultPage = findDefaultPage(response.data.application.pages);
const application: ApplicationPayload = {
...response.data.application,
// @ts-expect-error: response is of type unknown
defaultPageId: getDefaultPageId(response.data.application.pages),
defaultPageId: defaultPage?.id,
defaultBasePageId: defaultPage?.baseId,
};
yield put({
type: ReduxActionTypes.FORK_APPLICATION_SUCCESS,
@ -666,18 +677,16 @@ export function* forkApplicationSaga(
});
const pageURL = builderURL({
pageId: application.defaultPageId as string,
basePageId: defaultPage?.baseId,
params: { branch: null },
});
if (action.payload.editMode) {
const appId = application.id;
const pageId = application.defaultPageId;
yield put({
type: ReduxActionTypes.FETCH_APPLICATION_INIT,
payload: {
applicationId: appId,
pageId,
applicationId: application.id,
pageId: defaultPage?.id,
},
});
}
@ -773,11 +782,9 @@ export function* importApplicationSaga(
// @ts-expect-error: pages is of type any
// TODO: Update route params here
const { application } = response.data;
const defaultPage = pages.filter(
(eachPage: any) => !!eachPage.isDefault,
);
const defaultPage = findDefaultPage(pages);
const pageURL = builderURL({
pageId: defaultPage[0].id,
basePageId: defaultPage?.baseId,
});
if (isApplicationUrl) {
const appId = application.id;

View File

@ -31,7 +31,10 @@ import {
getPageNameByPageId,
} from "@appsmith/selectors/entitiesSelector";
import history from "utils/history";
import { getCurrentPageId } from "selectors/editorSelectors";
import {
getCurrentBasePageId,
getCurrentPageId,
} from "selectors/editorSelectors";
import type { JSCollectionCreateUpdateResponse } from "@appsmith/api/JSActionAPI";
import JSActionAPI from "@appsmith/api/JSActionAPI";
import {
@ -75,6 +78,7 @@ import { getIDETypeByUrl } from "@appsmith/entities/IDE/utils";
import { IDE_TYPE } from "@appsmith/entities/IDE/constants";
import { CreateNewActionKey } from "@appsmith/entities/Engine/actionHelpers";
import { getAllActionTestPayloads } from "utils/storage";
import { convertToBasePageIdSelector } from "selectors/pageListSelectors";
export function* fetchJSCollectionsSaga(
action: EvaluationReduxAction<FetchActionsPayload>,
@ -198,11 +202,12 @@ export function* copyJSCollectionSaga(
export function* handleMoveOrCopySaga(
actionPayload: ReduxAction<JSCollection>,
) {
const { id, pageId } = actionPayload.payload;
const { baseId: baseCollectionId, pageId } = actionPayload.payload;
const basePageId: string = yield select(convertToBasePageIdSelector, pageId);
history.push(
jsCollectionIdURL({
pageId: pageId,
collectionId: id,
basePageId,
baseCollectionId: baseCollectionId,
}),
);
}
@ -299,7 +304,7 @@ export function* deleteJSCollectionSaga(
try {
const id = actionPayload.payload.id;
const currentUrl = window.location.pathname;
const pageId: string = yield select(getCurrentPageId);
const basePageId: string = yield select(getCurrentBasePageId);
const response: ApiResponse = yield JSActionAPI.deleteJSCollection(id);
const isValidResponse: boolean = yield validateResponse(response);
const ideType = getIDETypeByUrl(currentUrl);
@ -313,7 +318,7 @@ export function* deleteJSCollectionSaga(
if (ideType === IDE_TYPE.App) {
yield call(handleJSEntityRedirect, id);
} else {
history.push(builderURL({ pageId }));
history.push(builderURL({ basePageId }));
}
AppsmithConsole.info({
logType: LOG_TYPE.ENTITY_DELETED,
@ -327,11 +332,11 @@ export function* deleteJSCollectionSaga(
},
});
yield put(deleteJSCollectionSuccess({ id }));
yield put(closeJsActionTabSuccess({ id, parentId: pageId }));
yield put(closeJsActionTabSuccess({ id, parentId: basePageId }));
const widgets: CanvasWidgetsReduxState = yield select(getWidgets);
if (pageId) {
if (basePageId) {
yield put(
updateAndSaveLayout(widgets, {
shouldReplay: false,
@ -388,7 +393,7 @@ export function* refactorJSObjectName(
oldName: string,
newName: string,
) {
const params: FetchPageRequest = { id: pageId, migrateDSL: true };
const params: FetchPageRequest = { pageId, migrateDSL: true };
const pageResponse: FetchPageResponse = yield call(PageApi.fetchPage, params);
// check if page request is successful
const isPageRequestSuccessful: boolean = yield validateResponse(pageResponse);

View File

@ -11,13 +11,24 @@ import {
import type {
ClonePageActionPayload,
CreatePageActionPayload,
DeletePageActionPayload,
FetchPageActionPayload,
FetchPublishedPageActionPayload,
GenerateTemplatePageActionPayload,
SetPageOrderActionPayload,
SetupPageActionPayload,
SetupPublishedPageActionPayload,
UpdatePageActionPayload,
} from "actions/pageActions";
import {
createPageAction,
fetchPageAction,
fetchPublishedPageAction,
} from "actions/pageActions";
import { createPage, fetchPublishedPage } from "actions/pageActions";
import {
clonePageSuccess,
deletePageSuccess,
fetchAllPageEntityCompletion,
fetchPage,
fetchPageSuccess,
fetchPublishedPageSuccess,
generateTemplateError,
@ -34,21 +45,15 @@ import {
updateWidgetNameSuccess,
} from "actions/pageActions";
import type {
ClonePageRequest,
CreatePageRequest,
DeletePageRequest,
FetchPageRequest,
FetchPageResponse,
FetchPageResponseData,
FetchPublishedPageRequest,
GenerateTemplatePageRequest,
PageLayout,
PageLayoutsRequest,
SavePageRequest,
SavePageResponse,
SavePageResponseData,
SetPageOrderRequest,
UpdatePageRequest,
UpdatePageResponse,
UpdateWidgetNameRequest,
UpdateWidgetNameResponse,
@ -63,7 +68,8 @@ import history from "utils/history";
import { isNameValid } from "utils/helpers";
import { extractCurrentDSL } from "utils/WidgetPropsUtils";
import {
getAllPageIds,
getAllPageIdentities,
getDefaultBasePageId,
getDefaultPageId,
getEditorConfigs,
getWidgets,
@ -73,6 +79,7 @@ import type { ApiResponse } from "api/ApiResponses";
import {
combinedPreviewModeSelector,
getCurrentApplicationId,
getCurrentBasePageId,
getCurrentLayoutId,
getCurrentPageId,
getCurrentPageName,
@ -144,6 +151,7 @@ import { getCurrentWorkspaceId } from "@appsmith/selectors/selectedWorkspaceSele
import { ActionExecutionContext } from "entities/Action";
import type { LayoutSystemTypes } from "layoutSystems/types";
import { getIsAnvilLayout } from "layoutSystems/anvil/integrations/selectors";
import { convertToBasePageIdSelector } from "selectors/pageListSelectors";
export const checkIfMigrationIsNeeded = (
fetchPageResponse?: FetchPageResponse,
@ -162,7 +170,7 @@ export const getWidgetName = (state: AppState, widgetId: string) =>
export function* refreshTheApp() {
try {
const currentPageId: string = yield select(getCurrentPageId);
const defaultPageId: string = yield select(getDefaultPageId);
const defaultBasePageId: string = yield select(getDefaultBasePageId);
const pagesList: Page[] = yield select(getPageList);
const gitBranch: string = yield select(getCurrentGitBranch);
@ -174,7 +182,7 @@ export function* refreshTheApp() {
} else {
location.assign(
builderURL({
pageId: defaultPageId,
basePageId: defaultBasePageId,
branch: gitBranch,
}),
);
@ -284,17 +292,19 @@ export function* handleFetchedPage({
export const getLastUpdateTime = (pageResponse: FetchPageResponse): number =>
pageResponse.data.lastUpdatedTime;
export function* fetchPageSaga(
pageRequestAction: ReduxAction<FetchPageRequest>,
) {
export function* fetchPageSaga(action: ReduxAction<FetchPageActionPayload>) {
try {
const { id, isFirstLoad, pageWithMigratedDsl } = pageRequestAction.payload;
const {
id: pageId,
isFirstLoad = false,
pageWithMigratedDsl,
} = action.payload;
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_API,
{ pageId: id },
{ pageId },
);
const params: FetchPageRequest = { id, migrateDSL: true };
const params: FetchPageRequest = { pageId, migrateDSL: true };
const fetchPageResponse: FetchPageResponse = yield call(
getFromServerWhenNoPrefetchedResult,
pageWithMigratedDsl,
@ -303,7 +313,7 @@ export function* fetchPageSaga(
yield handleFetchedPage({
fetchPageResponse,
pageId: id,
pageId,
isFirstLoad,
});
@ -328,16 +338,11 @@ export function* fetchPageSaga(
}
export function* fetchPublishedPageSaga(
pageRequestAction: ReduxAction<{
pageId: string;
bustCache: boolean;
firstLoad: boolean;
pageWithMigratedDsl?: FetchPageResponse;
}>,
action: ReduxAction<FetchPublishedPageActionPayload>,
) {
try {
const { bustCache, firstLoad, pageId, pageWithMigratedDsl } =
pageRequestAction.payload;
action.payload;
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_API,
{
@ -345,15 +350,11 @@ export function* fetchPublishedPageSaga(
published: true,
},
);
const request: FetchPublishedPageRequest = {
pageId,
bustCache,
};
const params = { pageId, bustCache };
const response: FetchPageResponse = yield call(
getFromServerWhenNoPrefetchedResult,
pageWithMigratedDsl,
() => call(PageApi.fetchPublishedPage, request),
() => call(PageApi.fetchPublishedPage, params),
);
const isValidResponse: boolean = yield validateResponse(response);
@ -415,10 +416,14 @@ export function* fetchPublishedPageSaga(
export function* fetchAllPublishedPagesSaga() {
try {
const pageIds: string[] = yield select(getAllPageIds);
const pageIdentities: { pageId: string; basePageId: string }[] =
yield select(getAllPageIdentities);
yield all(
pageIds.map((pageId: string) => {
return call(PageApi.fetchPublishedPage, { pageId, bustCache: true });
pageIdentities.map((pageIdentity) => {
return call(PageApi.fetchPublishedPage, {
pageId: pageIdentity.pageId,
bustCache: true,
});
}),
);
} catch (error) {
@ -642,7 +647,7 @@ export function* saveLayoutSaga(action: ReduxAction<{ isRetry?: boolean }>) {
}
export function* createNewPageFromEntity(
createPageAction: ReduxAction<CreatePageActionPayload>,
action: ReduxAction<CreatePageActionPayload>,
) {
try {
const layoutSystemType: LayoutSystemTypes =
@ -666,7 +671,7 @@ export function* createNewPageFromEntity(
},
];
const { applicationId, name } = createPageAction?.payload || {};
const { applicationId, name } = action?.payload || {};
const workspaceId: string = yield select(getCurrentWorkspaceId);
const instanceId: string | undefined = yield select(getInstanceId);
@ -676,7 +681,7 @@ export function* createNewPageFromEntity(
// At the end we call the `createPage` saga that actually calls the API to
// create a page
yield put(
createPage(
createPageAction(
applicationId,
name,
defaultPageLayouts,
@ -693,9 +698,7 @@ export function* createNewPageFromEntity(
});
}
}
export function* createPageSaga(
createPageAction: ReduxAction<CreatePageActionPayload>,
) {
export function* createPageSaga(action: ReduxAction<CreatePageActionPayload>) {
try {
const layoutSystemType: LayoutSystemTypes =
yield select(getLayoutSystemType);
@ -706,14 +709,15 @@ export function* createPageSaga(
mainCanvasProps.width,
);
const request: CreatePageRequest = createPageAction.payload;
const response: FetchPageResponse = yield call(PageApi.createPage, request);
const params = { ...action.payload };
const response: FetchPageResponse = yield call(PageApi.createPage, params);
const isValidResponse: boolean = yield validateResponse(response);
if (isValidResponse) {
yield put({
type: ReduxActionTypes.CREATE_PAGE_SUCCESS,
payload: {
pageId: response.data.id,
basePageId: response.data.baseId,
pageName: response.data.name,
layoutId: response.data.layouts[0].id,
slug: response.data.slug,
@ -739,7 +743,7 @@ export function* createPageSaga(
// route to generate template for new page created
history.push(
builderURL({
pageId: response.data.id,
basePageId: response.data.baseId,
}),
);
}
@ -753,16 +757,13 @@ export function* createPageSaga(
}
}
export function* updatePageSaga(action: ReduxAction<UpdatePageRequest>) {
export function* updatePageSaga(action: ReduxAction<UpdatePageActionPayload>) {
const params = { ...action.payload, pageId: action.payload.id };
try {
const request: UpdatePageRequest = action.payload;
// to be done in backend
request.customSlug = request.customSlug?.replaceAll(" ", "-");
params.customSlug = params.customSlug?.replaceAll(" ", "-");
const response: ApiResponse<UpdatePageResponse> = yield call(
PageApi.updatePage,
request,
params,
);
const isValidResponse: boolean = yield validateResponse(response);
if (isValidResponse) {
@ -771,23 +772,25 @@ export function* updatePageSaga(action: ReduxAction<UpdatePageRequest>) {
} catch (error) {
yield put(
updatePageError({
request: action.payload,
request: params,
error,
}),
);
}
}
export function* deletePageSaga(action: ReduxAction<DeletePageRequest>) {
export function* deletePageSaga(action: ReduxAction<DeletePageActionPayload>) {
try {
const request: DeletePageRequest = action.payload;
const defaultPageId: string = yield select(
(state: AppState) => state.entities.pageList.defaultPageId,
);
if (defaultPageId === request.id) {
const { id: pageId } = action.payload;
const defaultPageId: string = yield select(getDefaultPageId);
const defaultBasePageId: string = yield select(getDefaultBasePageId);
const currentPageId: string = yield select(getCurrentPageId);
if (defaultPageId === pageId) {
throw Error("Cannot delete the home page.");
} else {
const response: ApiResponse = yield call(PageApi.deletePage, request);
const params = { pageId: pageId };
const response: ApiResponse = yield call(PageApi.deletePage, params);
const isValidResponse: boolean = yield validateResponse(response);
if (isValidResponse) {
yield put(deletePageSuccess());
@ -796,18 +799,15 @@ export function* deletePageSaga(action: ReduxAction<DeletePageRequest>) {
yield put({
type: ReduxActionTypes.FETCH_PAGE_DSL_SUCCESS,
payload: {
pageId: request.id,
pageId,
dsl: undefined,
},
});
// Update route params here
const currentPageId: string = yield select(
(state: AppState) => state.entities.pageList.currentPageId,
);
if (currentPageId === action.payload.id)
if (currentPageId === pageId)
history.push(
builderURL({
pageId: defaultPageId,
basePageId: defaultBasePageId,
}),
);
}
@ -826,17 +826,22 @@ export function* clonePageSaga(
clonePageAction: ReduxAction<ClonePageActionPayload>,
) {
try {
const request: ClonePageRequest = clonePageAction.payload;
const request = {
pageId: clonePageAction.payload.id,
};
const response: FetchPageResponse = yield call(PageApi.clonePage, request);
const isValidResponse: boolean = yield validateResponse(response);
if (isValidResponse) {
yield put(
clonePageSuccess(
response.data.id,
response.data.name,
response.data.layouts[0].id,
response.data.slug,
),
clonePageSuccess({
pageId: response.data.id,
basePageId: response.data.baseId,
pageName: response.data.name,
layoutId: response.data.layouts[0].id,
slug: response.data.slug,
isDefault: false,
}),
);
// Add this to the page DSLs for entity explorer
// We're not sending the `dslTransformer` to the `extractCurrentDSL` function
@ -887,7 +892,7 @@ export function* clonePageSaga(
if (!clonePageAction.payload.blockNavigation) {
history.push(
builderURL({
pageId: response.data.id,
basePageId: response.data.baseId,
}),
);
}
@ -1100,7 +1105,7 @@ export function* fetchPageDSLSaga(
layoutSystemType,
mainCanvasProps.width,
);
const params: FetchPageRequest = { id: pageId, migrateDSL: true };
const params: FetchPageRequest = { pageId, migrateDSL: true };
const fetchPageResponse: FetchPageResponse = yield call(
getFromServerWhenNoPrefetchedResult,
pageDSL,
@ -1184,14 +1189,15 @@ export function* populatePageDSLsSaga(action?: {
}
}
/**
* saga to update the page order
*
* @param action
*/
export function* setPageOrderSaga(action: ReduxAction<SetPageOrderRequest>) {
export function* setPageOrderSaga(
action: ReduxAction<SetPageOrderActionPayload>,
) {
try {
const request: SetPageOrderRequest = action.payload;
const request = {
applicationId: action.payload.applicationId,
pageId: action.payload.pageId,
order: action.payload.order,
};
const response: ApiResponse = yield call(PageApi.setPageOrder, request);
const isValidResponse: boolean = yield validateResponse(response);
if (isValidResponse) {
@ -1214,7 +1220,7 @@ export function* setPageOrderSaga(action: ReduxAction<SetPageOrderRequest>) {
}
export function* generateTemplatePageSaga(
action: ReduxAction<GenerateTemplatePageRequest>,
action: ReduxAction<GenerateTemplatePageActionPayload>,
) {
try {
const request: GenerateTemplatePageRequest = action.payload;
@ -1246,7 +1252,7 @@ export function* generateTemplatePageSaga(
isFirstLoad: true,
});
yield put(fetchPage(pageId));
yield put(fetchPageAction(pageId));
// trigger evaluation after completion of page success & fetch actions for page + fetch jsobject for page
@ -1275,10 +1281,13 @@ export function* generateTemplatePageSaga(
executePageLoadActions(ActionExecutionContext.GENERATE_CRUD_PAGE),
]),
);
const basePageId: string = yield select(
convertToBasePageIdSelector,
pageId,
);
history.replace(
builderURL({
pageId,
basePageId,
}),
);
// TODO : Add it to onSuccessCallback
@ -1324,14 +1333,14 @@ export function* setCanvasCardsStateSaga(action: ReduxAction<string>) {
}
export function* setPreviewModeInitSaga(action: ReduxAction<boolean>) {
const currentPageId: string = yield select(getCurrentPageId);
const currentBasePageId: string = yield select(getCurrentBasePageId);
const isPreviewMode: boolean = yield select(combinedPreviewModeSelector);
if (action.payload) {
// we animate out elements and then move to the canvas
yield put(setPreviewModeAction(action.payload));
history.push(
builderURL({
pageId: currentPageId,
basePageId: currentBasePageId,
}),
);
} else if (isPreviewMode) {
@ -1346,15 +1355,19 @@ export function* setPreviewModeInitSaga(action: ReduxAction<boolean>) {
}
}
export function* setupPageSaga(action: ReduxAction<FetchPageRequest>) {
export function* setupPageSaga(action: ReduxAction<SetupPageActionPayload>) {
try {
const { id, isFirstLoad, pageWithMigratedDsl } = action.payload;
const {
id: pageId,
isFirstLoad = false,
pageWithMigratedDsl,
} = action.payload;
/*
Added the first line for isPageSwitching redux state to be true when page is being fetched to fix scroll position issue.
Added the second line for sync call instead of async (due to first line) as it was leading to issue with on page load actions trigger.
*/
yield put(fetchPage(id, isFirstLoad, pageWithMigratedDsl));
yield put(fetchPageAction(pageId, isFirstLoad, pageWithMigratedDsl));
yield take(ReduxActionTypes.FETCH_PAGE_SUCCESS);
yield put({
@ -1369,12 +1382,7 @@ export function* setupPageSaga(action: ReduxAction<FetchPageRequest>) {
}
export function* setupPublishedPageSaga(
action: ReduxAction<{
pageId: string;
bustCache: boolean;
firstLoad: boolean;
pageWithMigratedDsl?: FetchPageResponse;
}>,
action: ReduxAction<SetupPublishedPageActionPayload>,
) {
try {
const { bustCache, firstLoad, pageId, pageWithMigratedDsl } =
@ -1385,7 +1393,12 @@ export function* setupPublishedPageSaga(
Added the second line for sync call instead of async (due to first line) as it was leading to issue with on page load actions trigger.
*/
yield put(
fetchPublishedPage(pageId, bustCache, firstLoad, pageWithMigratedDsl),
fetchPublishedPageAction(
pageId,
bustCache,
firstLoad,
pageWithMigratedDsl,
),
);
yield take(ReduxActionTypes.FETCH_PUBLISHED_PAGE_SUCCESS);

View File

@ -3,12 +3,17 @@ import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants";
import { testSaga } from "redux-saga-test-plan";
import { setupPageSaga, setupPublishedPageSaga } from "../PageSagas";
import mockResponse from "./mockConsolidatedApiResponse.json";
import type { FetchPageRequest, FetchPageResponse } from "api/PageApi";
import { fetchPage, fetchPublishedPage } from "actions/pageActions";
import type { FetchPageResponse } from "api/PageApi";
import {
fetchPageAction,
fetchPublishedPageAction,
type SetupPageActionPayload,
type SetupPublishedPageActionPayload,
} from "actions/pageActions";
describe("ce/PageSaga", () => {
it("should put setupPageSaga with pageWithMigratedDsl", () => {
const action: ReduxAction<FetchPageRequest> = {
const action: ReduxAction<SetupPageActionPayload> = {
type: ReduxActionTypes.SETUP_PAGE_INIT,
payload: {
id: "pageId",
@ -20,7 +25,7 @@ describe("ce/PageSaga", () => {
testSaga(setupPageSaga, action)
.next()
.put(
fetchPage(
fetchPageAction(
action.payload.id,
action.payload.isFirstLoad,
action.payload.pageWithMigratedDsl,
@ -35,12 +40,7 @@ describe("ce/PageSaga", () => {
});
it("should put setupPublishedPageSaga with pageWithMigratedDsl", () => {
const action: ReduxAction<{
pageId: string;
bustCache: boolean;
firstLoad: boolean;
pageWithMigratedDsl?: FetchPageResponse;
}> = {
const action: ReduxAction<SetupPublishedPageActionPayload> = {
type: ReduxActionTypes.SETUP_PAGE_INIT,
payload: {
pageId: "pageId",
@ -54,7 +54,7 @@ describe("ce/PageSaga", () => {
testSaga(setupPublishedPageSaga, action)
.next()
.put(
fetchPublishedPage(
fetchPublishedPageAction(
action.payload.pageId,
action.payload.bustCache,
action.payload.firstLoad,

View File

@ -11,6 +11,7 @@
},
"data": {
"id": "661c28791c2412092c170119",
"baseId": "661c28791c2412092c170118",
"name": "Page1",
"slug": "page1",
"applicationId": "661c28791c2412092c170116",

View File

@ -2,10 +2,7 @@ import { getCurrentUser } from "selectors/usersSelectors";
import { getInstanceId } from "@appsmith/selectors/tenantSelectors";
import { call, select } from "redux-saga/effects";
import type { APP_MODE } from "entities/App";
import {
getCurrentApplication,
getCurrentPageId,
} from "selectors/editorSelectors";
import { getCurrentPageId } from "selectors/editorSelectors";
import type { TriggerMeta } from "@appsmith/sagas/ActionExecution/ActionExecutionSagas";
import { TriggerKind } from "constants/AppsmithActionConstants/ActionConstants";
import { isArray } from "lodash";
@ -14,6 +11,7 @@ import { getAppMode } from "@appsmith/selectors/entitiesSelector";
import type { AppState } from "@appsmith/reducers";
import { getWidget } from "sagas/selectors";
import { getUserSource } from "@appsmith/utils/AnalyticsUtil";
import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors";
export interface UserAndAppDetails {
pageId: string;

View File

@ -542,7 +542,8 @@ export const getQueryName = (state: AppState, actionId: string): string => {
return action?.config.name ?? "";
};
export const getCurrentPageId = (state: AppState) =>
// * This is only for internal use to avoid cyclic dependency issue
const getCurrentPageId = (state: AppState) =>
state.entities.pageList.currentPageId;
export const getDatasourcePlugins = createSelector(getPlugins, (plugins) => {
@ -735,6 +736,17 @@ export const getAction = (
return action ? action.config : undefined;
};
export const getActionByBaseId = (
state: AppState,
baseActionId: string,
): Action | undefined => {
const action = find(
state.entities.actions,
(a) => a.config.baseId === baseActionId,
);
return action ? action.config : undefined;
};
export const getActionData = (
state: AppState,
actionId: string,
@ -743,10 +755,21 @@ export const getActionData = (
return action ? action.data : undefined;
};
export const getJSCollection = (state: AppState, actionId: string) => {
export const getJSCollection = (state: AppState, collectionId: string) => {
const jsaction = find(
state.entities.jsActions,
(a) => a.config.id === actionId,
(a) => a.config.id === collectionId,
);
return jsaction && jsaction.config;
};
export const getJsCollectionByBaseId = (
state: AppState,
baseCollectionId: string,
) => {
const jsaction = find(
state.entities.jsActions,
(a) => a.config.baseId === baseCollectionId,
);
return jsaction && jsaction.config;
};
@ -1519,7 +1542,7 @@ export const getQuerySegmentItems = createSelector(
return {
icon: ActionUrlIcon(iconUrl),
title: action.config.name,
key: action.config.id,
key: action.config.baseId,
type: action.config.pluginType,
group,
};
@ -1533,7 +1556,7 @@ export const getJSSegmentItems = createSelector(
const items: EntityItem[] = jsActions.map((js) => ({
icon: JsFileIconV2(),
title: js.config.name,
key: js.config.id,
key: js.config.baseId,
type: PluginType.JS,
}));
return items;

View File

@ -18,6 +18,7 @@ describe("getTestPayloadFromCollectionData", () => {
isLoading: false,
config: {
id: "",
baseId: "",
applicationId: "",
workspaceId: "",
name: "",
@ -37,6 +38,7 @@ describe("getTestPayloadFromCollectionData", () => {
isLoading: false,
config: {
id: "",
baseId: "",
applicationId: "",
workspaceId: "",
name: "",

View File

@ -18,13 +18,13 @@ import { Request as NFRequest, Response as NFResponse } from "node-fetch";
delete: jest.fn(),
};
const applicationId = "b0123456789abcdef0000000";
const pageId = "a0123456789abcdef0000000";
const baseApplicationId = "b0123456789abcdef0000000";
const basePageId = "a0123456789abcdef0000000";
describe("serviceWorkerUtils", () => {
describe("matchBuilderPath", () => {
it("should match the standard builder path", () => {
const pathName = `/app/applicationSlug/pageSlug-${pageId}/edit`;
const pathName = `/app/applicationSlug/pageSlug-${basePageId}/edit`;
const options = { end: false };
const result = matchBuilderPath(pathName, options);
@ -32,14 +32,14 @@ describe("serviceWorkerUtils", () => {
if (result) {
expect(result.params).toHaveProperty("applicationSlug");
expect(result.params).toHaveProperty("pageSlug");
expect(result.params).toHaveProperty("pageId", pageId);
expect(result.params).toHaveProperty("basePageId", basePageId);
} else {
fail("Expected result to be truthy");
}
});
it("should match the standard builder path for alphanumeric pageId", () => {
const pathName = `/app/applicationSlug/pageSlug-${pageId}/edit`;
it("should match the standard builder path for alphanumeric basePageId", () => {
const pathName = `/app/applicationSlug/pageSlug-${basePageId}/edit`;
const options = { end: false };
const result = matchBuilderPath(pathName, options);
@ -47,35 +47,38 @@ describe("serviceWorkerUtils", () => {
if (result) {
expect(result.params).toHaveProperty("applicationSlug");
expect(result.params).toHaveProperty("pageSlug");
expect(result.params).toHaveProperty("pageId", pageId);
expect(result.params).toHaveProperty("basePageId", basePageId);
} else {
fail("Expected result to be truthy");
}
});
it("should match the custom builder path", () => {
const pathName = `/app/customSlug-custom-${pageId}/edit`;
const pathName = `/app/customSlug-custom-${basePageId}/edit`;
const options = { end: false };
const result = matchBuilderPath(pathName, options);
expect(result).toBeTruthy();
if (result) {
expect(result.params).toHaveProperty("customSlug");
expect(result.params).toHaveProperty("pageId", pageId);
expect(result.params).toHaveProperty("basePageId", basePageId);
} else {
fail("Expected result to be truthy");
}
});
it("should match the deprecated builder path", () => {
const pathName = `/applications/${applicationId}/pages/${pageId}/edit`;
const pathName = `/applications/${baseApplicationId}/pages/${basePageId}/edit`;
const options = { end: false };
const result = matchBuilderPath(pathName, options);
expect(result).toBeTruthy();
if (result) {
expect(result.params).toHaveProperty("applicationId", applicationId);
expect(result.params).toHaveProperty("pageId", pageId);
expect(result.params).toHaveProperty(
"baseApplicationId",
baseApplicationId,
);
expect(result.params).toHaveProperty("basePageId", basePageId);
} else {
fail("Expected result to be truthy");
}
@ -89,7 +92,7 @@ describe("serviceWorkerUtils", () => {
expect(result).toBeFalsy();
});
it("should not match when no pageId is present", () => {
it("should not match when no basePageId is present", () => {
const pathName = "/app/applicationSlug/pageSlug-edit";
const options = { end: false };
const result = matchBuilderPath(pathName, options);
@ -98,14 +101,14 @@ describe("serviceWorkerUtils", () => {
});
it("should match when the path is edit widgets", () => {
const pathName = `/app/applicationSlug/pageSlug-${pageId}/edit/widgets/t36hb2zukr`;
const pathName = `/app/applicationSlug/pageSlug-${basePageId}/edit/widgets/t36hb2zukr`;
const options = { end: false };
const result = matchBuilderPath(pathName, options);
if (result) {
expect(result.params).toHaveProperty("applicationSlug");
expect(result.params).toHaveProperty("pageSlug");
expect(result.params).toHaveProperty("pageId", pageId);
expect(result.params).toHaveProperty("basePageId", basePageId);
} else {
fail("Expected result to be truthy");
}
@ -114,46 +117,49 @@ describe("serviceWorkerUtils", () => {
describe("matchViewerPath", () => {
it("should match the standard viewer path", () => {
const pathName = `/app/applicationSlug/pageSlug-${pageId}`;
const pathName = `/app/applicationSlug/pageSlug-${basePageId}`;
const result = matchViewerPath(pathName);
expect(result).toBeTruthy();
if (result) {
expect(result.params).toHaveProperty("applicationSlug");
expect(result.params).toHaveProperty("pageSlug");
expect(result.params).toHaveProperty("pageId", pageId);
expect(result.params).toHaveProperty("basePageId", basePageId);
} else {
fail("Expected result to be truthy");
}
});
it("should match the custom viewer path", () => {
const pathName = `/app/customSlug-custom-${pageId}`;
const pathName = `/app/customSlug-custom-${basePageId}`;
const result = matchViewerPath(pathName);
expect(result).toBeTruthy();
if (result) {
expect(result.params).toHaveProperty("customSlug");
expect(result.params).toHaveProperty("pageId", pageId);
expect(result.params).toHaveProperty("basePageId", basePageId);
} else {
fail("Expected result to be truthy");
}
});
it("should match the deprecated viewer path", () => {
const pathName = `/applications/${applicationId}/pages/${pageId}`;
const pathName = `/applications/${baseApplicationId}/pages/${basePageId}`;
const result = matchViewerPath(pathName);
expect(result).toBeTruthy();
if (result) {
expect(result.params).toHaveProperty("applicationId", applicationId);
expect(result.params).toHaveProperty("pageId", pageId);
expect(result.params).toHaveProperty(
"baseApplicationId",
baseApplicationId,
);
expect(result.params).toHaveProperty("basePageId", basePageId);
} else {
fail("Expected result to be truthy");
}
});
it("should not match when no pageId is present", () => {
it("should not match when no basePageId is present", () => {
const pathName = "/app/applicationSlug/pageSlug";
const result = matchViewerPath(pathName);
@ -187,12 +193,12 @@ describe("serviceWorkerUtils", () => {
describe("getApplicationParamsFromUrl", () => {
it("should parse URL and return correct params for builder path", () => {
const url = new URL(
`https://app.appsmith.com/app/my-app/page-${pageId}/edit?branch=main`,
`https://app.appsmith.com/app/my-app/page-${basePageId}/edit?branch=main`,
);
const expectedParams: TApplicationParams = {
origin: "https://app.appsmith.com",
pageId,
applicationId: undefined,
basePageId,
baseApplicationId: undefined,
branchName: "main",
appMode: APP_MODE.EDIT,
};
@ -202,12 +208,12 @@ describe("serviceWorkerUtils", () => {
it("should parse URL and return correct params for viewer path", () => {
const url = new URL(
`https://app.appsmith.com/app/my-app/page-${pageId}?branch=main`,
`https://app.appsmith.com/app/my-app/page-${basePageId}?branch=main`,
);
const expectedParams: TApplicationParams = {
origin: "https://app.appsmith.com",
pageId,
applicationId: undefined,
basePageId,
baseApplicationId: undefined,
branchName: "main",
appMode: APP_MODE.PUBLISHED,
};
@ -222,12 +228,12 @@ describe("serviceWorkerUtils", () => {
it("should parse deprecated builder path and return correct params", () => {
const url = new URL(
`https://app.appsmith.com/applications/${applicationId}/pages/${pageId}/edit?branch=main`,
`https://app.appsmith.com/applications/${baseApplicationId}/pages/${basePageId}/edit?branch=main`,
);
const expectedParams: TApplicationParams = {
origin: "https://app.appsmith.com",
pageId,
applicationId,
basePageId,
baseApplicationId,
branchName: "main",
appMode: APP_MODE.EDIT,
};
@ -237,12 +243,12 @@ describe("serviceWorkerUtils", () => {
it("should parse deprecated viewer path and return correct params", () => {
const url = new URL(
`https://app.appsmith.com/applications/${applicationId}/pages/${pageId}?branch=main`,
`https://app.appsmith.com/applications/${baseApplicationId}/pages/${basePageId}?branch=main`,
);
const expectedParams: TApplicationParams = {
origin: "https://app.appsmith.com",
pageId,
applicationId,
basePageId,
baseApplicationId,
branchName: "main",
appMode: APP_MODE.PUBLISHED,
};
@ -252,12 +258,12 @@ describe("serviceWorkerUtils", () => {
it("should parse custom builder path and return correct params", () => {
const url = new URL(
`https://app.appsmith.com/app/custom-app-${pageId}/edit?branch=main`,
`https://app.appsmith.com/app/custom-app-${basePageId}/edit?branch=main`,
);
const expectedParams: TApplicationParams = {
origin: "https://app.appsmith.com",
pageId,
applicationId: undefined,
basePageId,
baseApplicationId: undefined,
branchName: "main",
appMode: APP_MODE.EDIT,
};
@ -267,12 +273,12 @@ describe("serviceWorkerUtils", () => {
it("should parse custom viewer path and return correct params", () => {
const url = new URL(
`https://app.appsmith.com/app/custom-app-${pageId}?branch=main`,
`https://app.appsmith.com/app/custom-app-${basePageId}?branch=main`,
);
const expectedParams: TApplicationParams = {
origin: "https://app.appsmith.com",
pageId,
applicationId: undefined,
basePageId,
baseApplicationId: undefined,
branchName: "main",
appMode: APP_MODE.PUBLISHED,
};
@ -282,12 +288,12 @@ describe("serviceWorkerUtils", () => {
it("should parse URL and return params with empty branch name if branch query param is not present", () => {
const url = new URL(
`https://app.appsmith.com/app/my-app/page-${pageId}/edit`,
`https://app.appsmith.com/app/my-app/page-${basePageId}/edit`,
);
const expectedParams: TApplicationParams = {
origin: "https://app.appsmith.com",
pageId,
applicationId: undefined,
basePageId,
baseApplicationId: undefined,
branchName: "",
appMode: APP_MODE.EDIT,
};
@ -301,7 +307,7 @@ describe("serviceWorkerUtils", () => {
(global as any).Request = NFRequest;
});
it("should return null if pageId is not provided", () => {
it("should return null if basePageId is not provided", () => {
const params: TApplicationParams = {
origin: "https://app.appsmith.com",
branchName: "main",
@ -314,8 +320,8 @@ describe("serviceWorkerUtils", () => {
it("should create request for EDIT mode with applicationId", () => {
const params: TApplicationParams = {
origin: "https://app.appsmith.com",
pageId,
applicationId,
basePageId,
baseApplicationId,
branchName: "main",
appMode: APP_MODE.EDIT,
};
@ -323,7 +329,7 @@ describe("serviceWorkerUtils", () => {
const request = getConsolidatedApiPrefetchRequest(params);
expect(request).toBeInstanceOf(Request);
expect(request?.url).toBe(
`https://app.appsmith.com/api/v1/consolidated-api/edit?defaultPageId=${pageId}&applicationId=${applicationId}`,
`https://app.appsmith.com/api/v1/consolidated-api/edit?defaultPageId=${basePageId}&applicationId=${baseApplicationId}`,
);
expect(request?.method).toBe("GET");
expect(request?.headers.get("Branchname")).toBe("main");
@ -332,8 +338,8 @@ describe("serviceWorkerUtils", () => {
it("should create request for PUBLISHED mode with applicationId", () => {
const params: TApplicationParams = {
origin: "https://app.appsmith.com",
pageId,
applicationId,
basePageId,
baseApplicationId,
branchName: "main",
appMode: APP_MODE.PUBLISHED,
};
@ -341,7 +347,7 @@ describe("serviceWorkerUtils", () => {
const request = getConsolidatedApiPrefetchRequest(params);
expect(request).toBeInstanceOf(Request);
expect(request?.url).toBe(
`https://app.appsmith.com/api/v1/consolidated-api/view?defaultPageId=${pageId}&applicationId=${applicationId}`,
`https://app.appsmith.com/api/v1/consolidated-api/view?defaultPageId=${basePageId}&applicationId=${baseApplicationId}`,
);
expect(request?.method).toBe("GET");
expect(request?.headers.get("Branchname")).toBe("main");
@ -350,7 +356,7 @@ describe("serviceWorkerUtils", () => {
it("should create request for EDIT mode without applicationId", () => {
const params: TApplicationParams = {
origin: "https://app.appsmith.com",
pageId: "page123",
basePageId: "page123",
branchName: "main",
appMode: APP_MODE.EDIT,
};
@ -367,7 +373,7 @@ describe("serviceWorkerUtils", () => {
it("should create request for PUBLISHED mode without applicationId", () => {
const params: TApplicationParams = {
origin: "https://app.appsmith.com",
pageId: "page123",
basePageId: "page123",
branchName: "main",
appMode: APP_MODE.PUBLISHED,
};
@ -384,7 +390,7 @@ describe("serviceWorkerUtils", () => {
it("should return null for an unknown app mode", () => {
const params: TApplicationParams = {
origin: "https://app.appsmith.com",
pageId: "page123",
basePageId: "page123",
branchName: "main",
appMode: "UNKNOWN" as APP_MODE,
};
@ -399,7 +405,7 @@ describe("serviceWorkerUtils", () => {
origin: "https://app.appsmith.com",
branchName: "main",
appMode: APP_MODE.EDIT,
pageId: "page123",
basePageId: "page123",
};
const requests = getPrefetchRequests(params);
expect(requests).toHaveLength(1);

View File

@ -12,14 +12,14 @@ import {
} from "@appsmith/constants/routes/appRoutes";
interface TMatchResult {
pageId?: string;
applicationId?: string;
basePageId?: string;
baseApplicationId?: string;
}
export interface TApplicationParams {
origin: string;
pageId?: string;
applicationId?: string;
basePageId?: string;
baseApplicationId?: string;
branchName: string;
appMode: APP_MODE;
}
@ -69,8 +69,8 @@ export const getApplicationParamsFromUrl = (
if (matchedBuilder) {
return {
origin: url.origin,
pageId: matchedBuilder.params.pageId,
applicationId: matchedBuilder.params.applicationId,
basePageId: matchedBuilder.params.basePageId,
baseApplicationId: matchedBuilder.params.baseApplicationId,
branchName,
appMode: APP_MODE.EDIT,
};
@ -79,8 +79,8 @@ export const getApplicationParamsFromUrl = (
if (matchedViewer) {
return {
origin: url.origin,
pageId: matchedViewer.params.pageId,
applicationId: matchedViewer.params.applicationId,
basePageId: matchedViewer.params.basePageId,
baseApplicationId: matchedViewer.params.baseApplicationId,
branchName,
appMode: APP_MODE.PUBLISHED,
};
@ -95,20 +95,20 @@ export const getApplicationParamsFromUrl = (
export const getConsolidatedApiPrefetchRequest = (
applicationProps: TApplicationParams,
) => {
const { applicationId, appMode, branchName, origin, pageId } =
const { appMode, baseApplicationId, basePageId, branchName, origin } =
applicationProps;
const headers = new Headers();
const searchParams = new URLSearchParams();
if (!pageId) {
if (!basePageId) {
return null;
}
searchParams.append("defaultPageId", pageId);
searchParams.append("defaultPageId", basePageId);
if (applicationId) {
searchParams.append("applicationId", applicationId);
if (baseApplicationId) {
searchParams.append("applicationId", baseApplicationId);
}
// Add the branch name to the headers

View File

@ -38,8 +38,8 @@ export const redirectUserAfterSignup = (
urlObject = new URL(redirectUrl);
} catch (e) {}
const match = matchPath<{
pageId: string;
applicationId: string;
basePageId: string;
baseApplicationId: string;
}>(urlObject?.pathname ?? redirectUrl, {
path: [
BUILDER_PATH,
@ -50,16 +50,28 @@ export const redirectUserAfterSignup = (
strict: false,
exact: false,
});
const { applicationId, pageId } = match?.params || {};
if (applicationId || pageId) {
const { baseApplicationId, basePageId } = match?.params || {};
/** ! Dev Note:
* setCurrentApplicationIdForCreateNewApp & firstTimeUserOnboardingInit
* in the following block support only applicationId
* but since baseId and id are same for applications created outside git context
* and since these redux actions are only called during onboarding,
* passing baseApplicationId as applicationId should be fine
* **/
if (baseApplicationId || basePageId) {
if (isEnabledForCreateNew) {
dispatch(
setCurrentApplicationIdForCreateNewApp(applicationId as string),
setCurrentApplicationIdForCreateNewApp(
baseApplicationId as string,
),
);
history.replace(APPLICATIONS_URL);
} else {
dispatch(
firstTimeUserOnboardingInit(applicationId, pageId as string),
firstTimeUserOnboardingInit(
baseApplicationId,
basePageId as string,
),
);
}
} else {

View File

@ -14,10 +14,10 @@ const BackToCanvasLink = styled(Link)`
`;
interface BackToCanvasProps {
pageId: string;
basePageId: string;
}
function BackToCanvas({ pageId }: BackToCanvasProps) {
function BackToCanvas({ basePageId }: BackToCanvasProps) {
const { isOpened: isWalkthroughOpened, popFeature } =
useContext(WalkthroughContext) || {};
@ -32,7 +32,7 @@ function BackToCanvas({ pageId }: BackToCanvasProps) {
id="back-to-canvas"
kind="secondary"
onClick={() => {
history.push(builderURL({ pageId }));
history.push(builderURL({ basePageId }));
handleCloseWalkthrough();
}}

View File

@ -10,7 +10,10 @@ import type { AppState } from "@appsmith/reducers";
import { saveActionName } from "actions/pluginActionActions";
import { Flex } from "design-system";
import { getAction, getPlugin } from "@appsmith/selectors/entitiesSelector";
import {
getActionByBaseId,
getPlugin,
} from "@appsmith/selectors/entitiesSelector";
import NameEditorComponent, {
IconBox,
IconWrapper,
@ -44,10 +47,10 @@ interface ActionNameEditorProps {
}
function ActionNameEditor(props: ActionNameEditorProps) {
const params = useParams<{ apiId?: string; queryId?: string }>();
const params = useParams<{ baseApiId?: string; baseQueryId?: string }>();
const currentActionConfig = useSelector((state: AppState) =>
getAction(state, params.apiId || params.queryId || ""),
getActionByBaseId(state, params.baseApiId || params.baseQueryId || ""),
);
const currentPlugin = useSelector((state: AppState) =>

View File

@ -11,7 +11,7 @@ import {
widgetListURL,
} from "@appsmith/RouteBuilder";
import { useSelector } from "react-redux";
import { getCurrentPageId } from "selectors/editorSelectors";
import { getCurrentBasePageId } from "selectors/editorSelectors";
import AnalyticsUtil from "@appsmith/utils/AnalyticsUtil";
import { Link } from "design-system";
import styled from "styled-components";
@ -29,7 +29,7 @@ function CloseEditor() {
const params: string = location.search;
const searchParamsInstance = new URLSearchParams(params);
const redirectTo = searchParamsInstance.get("from");
const pageId = useSelector(getCurrentPageId);
const basePageId = useSelector(getCurrentBasePageId);
const isGeneratePageInitiator = getIsGeneratePageInitiator();
let integrationTab = INTEGRATION_TABS.ACTIVE;
@ -51,13 +51,13 @@ function CloseEditor() {
// then route user back to `/generate-page/form`
// else go back to BUILDER_PAGE
const redirectURL = isGeneratePageInitiator
? generateTemplateFormURL({ pageId })
: widgetListURL({ pageId });
? generateTemplateFormURL({ basePageId })
: widgetListURL({ basePageId });
const URL =
redirectTo === "datasources"
? integrationEditorURL({
pageId,
basePageId,
selectedTab: integrationTab,
params: getQueryParams(),
})

View File

@ -3,7 +3,7 @@ import AnalyticsUtil from "@appsmith/utils/AnalyticsUtil";
import { DebuggerEntityLink, type EntityLinkProps } from "./DebuggerEntityLink";
import { useSelector } from "react-redux";
import type { AppState } from "@appsmith/reducers";
import { getCurrentPageId } from "selectors/editorSelectors";
import { getCurrentBasePageId } from "selectors/editorSelectors";
import { getDatasource } from "@appsmith/selectors/entitiesSelector";
import history from "utils/history";
import { getQueryParams } from "utils/URLUtils";
@ -13,13 +13,13 @@ export default function DatasourceLink(props: EntityLinkProps) {
const datasource = useSelector((state: AppState) =>
getDatasource(state, props.id),
);
const pageId = useSelector(getCurrentPageId);
const basePageId = useSelector(getCurrentBasePageId);
const onClick = () => {
if (datasource) {
history.push(
datasourcesEditorIdURL({
pageId,
basePageId,
datasourceId: datasource.id,
params: getQueryParams(),
}),

View File

@ -7,9 +7,13 @@ import type { AppState } from "@appsmith/reducers";
import { getWidget } from "sagas/selectors";
import {
getCurrentApplicationId,
getCurrentPageId,
getCurrentBasePageId,
} from "selectors/editorSelectors";
import { getAction, getPlugins } from "@appsmith/selectors/entitiesSelector";
import {
getAction,
getActionByBaseId,
getPlugins,
} from "@appsmith/selectors/entitiesSelector";
import { onApiEditor, onCanvas, onQueryEditor } from "../helpers";
import { getLastSelectedWidget } from "selectors/ui";
import { getConfigTree, getDataTree } from "selectors/dataTreeSelectors";
@ -93,9 +97,9 @@ export const useSelectedEntity = () => {
const params: any = useParams();
const action = useSelector((state: AppState) => {
if (onApiEditor() || onQueryEditor()) {
const id = params.apiId || params.queryId;
const baseId = params.baseApiId || params.baseQueryId;
return getAction(state, id);
return getActionByBaseId(state, baseId);
}
return null;
@ -128,7 +132,7 @@ export const useSelectedEntity = () => {
};
export const useEntityLink = () => {
const pageId = useSelector(getCurrentPageId);
const basePageId = useSelector(getCurrentBasePageId);
const plugins = useSelector(getPlugins);
const applicationId = useSelector(getCurrentApplicationId);
@ -136,21 +140,23 @@ export const useEntityLink = () => {
const navigateToEntity = useCallback(
(name) => {
const dataTree = getDataTree(store.getState());
const appState = store.getState();
const dataTree = getDataTree(appState);
const configTree = getConfigTree();
const entity = dataTree[name];
const entityConfig = configTree[name];
if (!pageId) return;
if (!basePageId) return;
if (isWidget(entity)) {
const widgetEntity = entity as WidgetEntity;
navigateToWidget(
widgetEntity.widgetId,
entity.type,
pageId || "",
basePageId || "",
NavigationMethod.Debugger,
);
} else if (isAction(entity)) {
const actionConfig = getActionConfig(entityConfig.pluginType);
const action = getAction(appState, entity.actionId);
let plugin;
if (entityConfig?.pluginType === PluginType.SAAS) {
plugin = plugins.find(
@ -160,8 +166,8 @@ export const useEntityLink = () => {
const url =
applicationId &&
actionConfig?.getURL(
pageId,
entity.actionId,
basePageId,
action?.baseId || "",
entityConfig.pluginType,
plugin,
);
@ -170,15 +176,16 @@ export const useEntityLink = () => {
history.push(url);
}
} else if (isJSAction(entity)) {
const action = getAction(appState, entity.actionId);
history.push(
jsCollectionIdURL({
pageId,
collectionId: entity.actionId,
basePageId,
baseCollectionId: action?.baseId || "",
}),
);
}
},
[pageId],
[basePageId],
);
return {

View File

@ -38,7 +38,7 @@ const queryDebuggerConfig: Config = {
const getConfig = (focusInfo: FocusEntityInfo): Config => {
switch (focusInfo.entity) {
case FocusEntity.QUERY:
if (focusInfo.params.apiId) {
if (focusInfo.params.baseApiId) {
if (focusInfo.params.pluginPackageName) {
return queryDebuggerConfig;
}

View File

@ -168,10 +168,10 @@ export const useFilteredAndSortedFileOperations = ({
.filter((ds) => ds.title.toLowerCase().includes(query.toLowerCase()));
// Add genetic datasource creation
const onRedirect = (pageId: string) => {
const onRedirect = (basePageId: string) => {
history.push(
integrationEditorURL({
pageId,
basePageId,
selectedTab: INTEGRATION_TABS.NEW,
generateEditorPath: true,
}),

View File

@ -46,7 +46,7 @@ export const SearchItemContainer = styled.div<{
: "default"};
display: flex;
align-items: center;
padding: ${(props) => props.theme.spaces[4]}px};
padding: ${(props) => props.theme.spaces[4] + "px"};
transition: 0.3s background-color ease;
border-radius: var(--ads-v2-border-radius);
background-color: ${(props) =>

View File

@ -71,6 +71,10 @@ import {
import { getHasCreateActionPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import {
getBasePageIdToPageIdMap,
getPageIdToBasePageIdMap,
} from "selectors/pageListSelectors";
const StyledContainer = styled.div<{ category: SearchCategory; query: string }>`
max-height: 530px;
@ -171,6 +175,8 @@ function GlobalSearch() {
[dispatch],
);
const params = useParams<ExplorerURLParams>();
const pageIdToBasePageIdMap = useSelector(getPageIdToBasePageIdMap);
const basePageIdToPageIdMap = useSelector(getBasePageIdToPageIdMap);
const toggleShow = () => {
if (modalOpen) {
@ -209,9 +215,9 @@ function GlobalSearch() {
const datasourcesList = useMemo(() => {
return reducerDatasources.map((datasource) => ({
...datasource,
pageId: params?.pageId,
pageId: basePageIdToPageIdMap[params?.basePageId],
}));
}, [params?.pageId, reducerDatasources]);
}, [basePageIdToPageIdMap, params?.basePageId, reducerDatasources]);
const filteredDatasources = useMemo(() => {
if (!query) return datasourcesList;
@ -354,7 +360,7 @@ function GlobalSearch() {
navigateToWidget(
activeItem.widgetId,
activeItem.type,
activeItem.pageId,
pageIdToBasePageIdMap[activeItem.pageId],
NavigationMethod.Omnibar,
lastSelectedWidgetId === activeItem.widgetId,
false,
@ -365,21 +371,28 @@ function GlobalSearch() {
const handleActionClick = (item: SearchItem) => {
const { config } = item;
const { id, pageId, pluginId, pluginType } = config;
const { baseId: baseActionId, pageId, pluginId, pluginType } = config;
const actionConfig = getActionConfig(pluginType);
const plugin = plugins.find((plugin) => plugin?.id === pluginId);
const url = actionConfig?.getURL(pageId, id, pluginType, plugin);
const basePageId = pageIdToBasePageIdMap[pageId];
const url = actionConfig?.getURL(
basePageId,
baseActionId,
pluginType,
plugin,
);
toggleShow();
url && history.push(url, { invokedBy: NavigationMethod.Omnibar });
};
const handleJSCollectionClick = (item: SearchItem) => {
const { config } = item;
const { id, pageId } = config;
const { baseId: baseCollectionId, pageId } = config;
const basePageId = pageIdToBasePageIdMap[pageId];
history.push(
jsCollectionIdURL({
pageId,
collectionId: id,
basePageId,
baseCollectionId,
}),
{ invokedBy: NavigationMethod.Omnibar },
);
@ -388,9 +401,10 @@ function GlobalSearch() {
const handleDatasourceClick = (item: SearchItem) => {
toggleShow();
const basePageId = pageIdToBasePageIdMap[item.pageId];
history.push(
datasourcesEditorIdURL({
pageId: item.pageId,
basePageId: basePageId,
datasourceId: item.id,
params: getQueryParams(),
}),
@ -402,7 +416,7 @@ function GlobalSearch() {
toggleShow();
history.push(
builderURL({
pageId: item.pageId,
basePageId: item.basePageId,
}),
{ invokedBy: NavigationMethod.Omnibar },
);

View File

@ -69,6 +69,7 @@ const collectionData: JSCollectionData = {
isLoading: false,
config: {
id: "12",
baseId: "b12",
applicationId: "app1",
workspaceId: "w1234",
name: "asas",

View File

@ -7,7 +7,7 @@ import { connect, useDispatch, useSelector } from "react-redux";
import history from "utils/history";
import { datasourcesEditorIdURL } from "@appsmith/RouteBuilder";
import { getQueryParams } from "utils/URLUtils";
import { getCurrentPageId } from "selectors/editorSelectors";
import { getCurrentBasePageId } from "selectors/editorSelectors";
import {
createMessage,
EDIT_DATASOURCE,
@ -34,7 +34,7 @@ interface ReduxDispatchProps {
function StoreAsDatasource(props: storeDataSourceProps) {
const dispatch = useDispatch();
const pageId = useSelector(getCurrentPageId);
const basePageId = useSelector(getCurrentBasePageId);
const saveOrEditDatasource = () => {
if (props.shouldSave) {
@ -47,7 +47,7 @@ function StoreAsDatasource(props: storeDataSourceProps) {
});
history.push(
datasourcesEditorIdURL({
pageId,
basePageId,
datasourceId: props.datasourceId,
params: getQueryParams(),
generateEditorPath: true,

View File

@ -30,7 +30,7 @@ function useOtherOptions(props: OtherOptionsProps) {
sampleData,
updateConfig,
} = useContext(WidgetQueryGeneratorFormContext);
const { pageId: currentPageId } = useParams<ExplorerURLParams>();
const { basePageId } = useParams<ExplorerURLParams>();
const isAddBindingAllowed =
datasourceDropdownVariant === DROPDOWN_VARIANT.CREATE_OR_EDIT_RECORDS;
const { widget } = props;
@ -44,7 +44,7 @@ function useOtherOptions(props: OtherOptionsProps) {
onSelect: () => {
history.push(
integrationEditorURL({
pageId: currentPageId,
basePageId,
selectedTab: INTEGRATION_TABS.NEW,
}),
);
@ -117,14 +117,7 @@ function useOtherOptions(props: OtherOptionsProps) {
}
return options;
}, [
currentPageId,
sampleData,
addBinding,
updateConfig,
widget,
propertyName,
]);
}, [basePageId, sampleData, addBinding, updateConfig, widget, propertyName]);
return otherOptions;
}

View File

@ -2,8 +2,10 @@ import { JSResponseState } from "./JSResponseView";
import { getJSResponseViewState } from "./utils";
const TEST_JS_FUNCTION_ID = "627ccff468e1fa5185b7f901";
const TEST_JS_FUNCTION_BASE_ID = "627ccff468e1fa5185b7f912";
const TEST_JS_FUNCTION = {
id: TEST_JS_FUNCTION_ID,
baseId: TEST_JS_FUNCTION_BASE_ID,
applicationId: "627aaf637e9e9b75e43ad2ff",
workspaceId: "61e52bb4847aa804d79fc7c1",
pluginType: "JS",

View File

@ -322,6 +322,9 @@ const mapStateToProps = (
options = dynamicFetchedValues.data;
}
} catch (e) {
// Printing error to console
// eslint-disable-next-line no-console
console.error(e);
} finally {
return { isLoading, options, formValues };
}

View File

@ -9,12 +9,12 @@ describe("builderURL", () => {
urlBuilder.updateURLParams(
{
applicationSlug: ":applicationSlug",
applicationId: ":applicationId",
baseApplicationId: ":baseApplicationId",
applicationVersion: 2,
},
[
{
pageId: "0123456789abcdef00000000",
basePageId: "0123456789abcdef00000000",
pageSlug: ":pageSlug",
},
],
@ -24,7 +24,7 @@ describe("builderURL", () => {
it("persists embed query param", () => {
(window as any).location = new URL("https://example.com?embed=true");
const pageURL = builderURL({
pageId: "0123456789abcdef00000000",
basePageId: "0123456789abcdef00000000",
});
const pageURLObject = new URL(`${window.origin}${pageURL}`);
expect(pageURLObject.searchParams.get("embed")).toBe("true");
@ -33,7 +33,7 @@ describe("builderURL", () => {
it("does not append embed query param when it does not exist", () => {
(window as any).location = new URL("https://example.com");
const pageURL = builderURL({
pageId: "0123456789abcdef00000000",
basePageId: "0123456789abcdef00000000",
});
const pageURLObject = new URL(`${window.origin}${pageURL}`);
expect(pageURLObject.searchParams.get("embed")).toBe(null);
@ -52,12 +52,12 @@ describe("viewerURL", () => {
urlBuilder.updateURLParams(
{
applicationSlug: ":applicationSlug",
applicationId: ":applicationId",
baseApplicationId: ":baseApplicationId",
applicationVersion: 2,
},
[
{
pageId: "0123456789abcdef00000000",
basePageId: "0123456789abcdef00000000",
pageSlug: ":pageSlug",
},
],
@ -67,7 +67,7 @@ describe("viewerURL", () => {
it("persists embed query param", () => {
(window as any).location = new URL("https://example.com?embed=true");
const pageURL = viewerURL({
pageId: "0123456789abcdef00000000",
basePageId: "0123456789abcdef00000000",
});
const pageURLObject = new URL(`${window.origin}${pageURL}`);
expect(pageURLObject.searchParams.get("embed")).toBe("true");
@ -76,7 +76,7 @@ describe("viewerURL", () => {
it("does not append embed query param when it does not exist", () => {
(window as any).location = new URL("https://example.com");
const pageURL = viewerURL({
pageId: "0123456789abcdef00000000",
basePageId: "0123456789abcdef00000000",
});
const pageURLObject = new URL(`${window.origin}${pageURL}`);
expect(pageURLObject.searchParams.get("embed")).toBe(null);

View File

@ -12,11 +12,13 @@ const DEFAULT_ACTION: Action = {
dynamicBindingPathList: [],
executeOnLoad: false,
id: "",
baseId: "",
invalids: [],
isValid: false,
jsonPathKeys: [],
name: "",
workspaceId: "",
applicationId: "",
pageId: "",
pluginId: "",
messages: [],

View File

@ -161,8 +161,10 @@ export interface StoredDatasource {
export interface BaseAction {
id: string;
baseId: string;
name: string;
workspaceId: string;
applicationId: string;
pageId: string;
collectionId?: string;
pluginId: string;
@ -233,6 +235,7 @@ export interface QueryAction extends BaseAction {
export interface ActionViewMode {
id: string;
baseId: string;
name: string;
pageId: string;
jsonPathKeys: string[];

View File

@ -10,7 +10,10 @@ import {
} from "actions/gitSyncActions";
import { restoreRecentEntitiesRequest } from "actions/globalSearchActions";
import { resetEditorSuccess } from "actions/initActions";
import { fetchAllPageEntityCompletion, setupPage } from "actions/pageActions";
import {
fetchAllPageEntityCompletion,
setupPageAction,
} from "actions/pageActions";
import {
executePageLoadActions,
fetchActions,
@ -30,7 +33,6 @@ import {
reportSWStatus,
waitForWidgetConfigBuild,
} from "sagas/InitSagas";
import { getCurrentApplication } from "selectors/editorSelectors";
import { getCurrentGitBranch } from "selectors/gitSyncSelectors";
import AnalyticsUtil from "@appsmith/utils/AnalyticsUtil";
import history from "utils/history";
@ -66,6 +68,7 @@ import {
fetchAppThemesAction,
fetchSelectedAppThemeAction,
} from "actions/appThemingActions";
import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors";
import type { Span } from "@opentelemetry/api";
import { endSpan, startNestedSpan } from "UITelemetry/generateTraces";
@ -134,7 +137,7 @@ export default class AppEditorEngine extends AppEngine {
unpublishedActions,
} = allResponses;
const initActionsCalls = [
setupPage(toLoadPageId, true, pageWithMigratedDsl),
setupPageAction(toLoadPageId, true, pageWithMigratedDsl),
fetchActions({ applicationId, unpublishedActions }, []),
fetchJSCollections({ applicationId, unpublishedActionCollections }),
fetchSelectedAppThemeAction(applicationId, currentTheme),

View File

@ -11,7 +11,7 @@ import log from "loglevel";
import { call, put, select } from "redux-saga/effects";
import type { InitConsolidatedApi } from "sagas/InitSagas";
import { failFastApiCalls } from "sagas/InitSagas";
import { getDefaultPageId } from "sagas/selectors";
import { getDefaultBasePageId, getDefaultPageId } from "sagas/selectors";
import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors";
import history from "utils/history";
import type URLRedirect from "entities/URLRedirect/index";
@ -24,7 +24,7 @@ import { endSpan, startNestedSpan } from "UITelemetry/generateTraces";
export interface AppEnginePayload {
applicationId?: string;
pageId?: string;
basePageId?: string;
branch?: string;
mode: APP_MODE;
shouldInitialiseUserDetails?: boolean;
@ -74,13 +74,14 @@ export default abstract class AppEngine {
rootSpan: Span,
) {
const loadAppDataSpan = startNestedSpan("AppEngine.loadAppData", rootSpan);
const { applicationId, branch, pageId } = payload;
const { applicationId, basePageId, branch } = payload;
const { pages } = allResponses;
const page = pages.data?.pages?.find((page) => page.baseId === basePageId);
const apiCalls: boolean = yield failFastApiCalls(
[
fetchApplication({
applicationId,
pageId,
pageId: page?.id,
mode: this._mode,
pages,
}),
@ -94,11 +95,9 @@ export default abstract class AppEngine {
ReduxActionErrorTypes.FETCH_PAGE_LIST_ERROR,
],
);
if (!apiCalls) {
throw new PageNotFoundError(`Cannot find page with id: ${pageId}`);
throw new PageNotFoundError(`Cannot find page with pageId: ${page?.id}`);
}
const application: ApplicationPayload = yield select(getCurrentApplication);
const currentGitBranch: ReturnType<typeof getCurrentGitBranch> =
yield select(getCurrentGitBranch);
@ -107,14 +106,16 @@ export default abstract class AppEngine {
getPersistentAppStore(application.id, branch || currentGitBranch),
),
);
const toLoadPageId: string = pageId || (yield select(getDefaultPageId));
const defaultPageId: string = yield select(getDefaultPageId);
const defaultPageBaseId: string = yield select(getDefaultBasePageId);
const toLoadPageId: string = page?.id || defaultPageId;
const toLoadBasePageId: string = page?.baseId || defaultPageBaseId;
this._urlRedirect = URLGeneratorFactory.create(
application.applicationVersion,
this._mode,
);
endSpan(loadAppDataSpan);
return { toLoadPageId, applicationId: application.id };
return { toLoadPageId, toLoadBasePageId, applicationId: application.id };
}
*setupEngine(payload: AppEnginePayload, rootSpan: Span): any {
@ -130,12 +131,12 @@ export default abstract class AppEngine {
}
*loadAppURL({
pageId,
pageIdInUrl,
basePageId,
basePageIdInUrl,
rootSpan,
}: {
pageId: string;
pageIdInUrl?: string;
basePageId: string;
basePageIdInUrl?: string;
rootSpan: Span;
}) {
try {
@ -144,8 +145,8 @@ export default abstract class AppEngine {
const loadAppUrlSpan = startNestedSpan("AppEngine.loadAppURL", rootSpan);
const newURL: string = yield call(
this._urlRedirect.generateRedirectURL.bind(this),
pageId,
pageIdInUrl,
basePageId,
basePageIdInUrl,
);
endSpan(loadAppUrlSpan);

View File

@ -9,6 +9,7 @@ export interface Variable {
}
export interface JSCollection {
id: string;
baseId: string;
applicationId: string;
workspaceId: string;
name: string;

View File

@ -12,7 +12,7 @@ export default class DefaultURLRedirect extends URLRedirect {
super(mode);
}
*generateRedirectURL(pageId: string) {
*generateRedirectURL(basePageId: string) {
const currentApplication: ApplicationPayload = yield select(
getCurrentApplication,
);
@ -28,7 +28,7 @@ export default class DefaultURLRedirect extends URLRedirect {
// we need to compute the legacy url
// This scenario can happen only in edit mode.
newURL = builderURL({
pageId: pageId,
basePageId,
hash,
});
return newURL;

View File

@ -6,7 +6,7 @@ import { APP_MODE } from "entities/App";
import { select } from "redux-saga/effects";
import { fillPathname, viewerURL } from "@appsmith/RouteBuilder";
import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors";
import { getPageById } from "selectors/editorSelectors";
import { getPageByBaseId } from "selectors/editorSelectors";
import { getUpdatedRoute, isURLDeprecated } from "utils/helpers";
import URLRedirect from ".";
@ -15,22 +15,23 @@ export class SlugURLRedirect extends URLRedirect {
super(mode);
}
*generateRedirectURL(pageId: string, pageIdInUrl: string) {
*generateRedirectURL(basePageId: string, basePageIdInUrl: string) {
const currentApplication: ApplicationPayload = yield select(
getCurrentApplication,
);
const applicationSlug = currentApplication.slug;
const currentPage: Page = yield select(getPageById(pageId));
const currentPage: Page = yield select(getPageByBaseId(basePageId));
const { customSlug = "", slug: pageSlug } = currentPage;
let newURL = "";
const { hash, pathname, search } = window.location;
const isCurrentURLDeprecated = isURLDeprecated(pathname) || !pageIdInUrl;
const isCurrentURLDeprecated =
isURLDeprecated(pathname) || !basePageIdInUrl;
if (!isCurrentURLDeprecated) {
newURL =
getUpdatedRoute(pathname, {
applicationSlug,
pageSlug,
pageId,
basePageId,
customSlug,
}) +
search +
@ -43,7 +44,7 @@ export class SlugURLRedirect extends URLRedirect {
fillPathname(pathname, currentApplication, currentPage) + search + hash;
} else {
// View Mode - generate a new viewer URL - auto updates query params
newURL = viewerURL({ pageId, hash });
newURL = viewerURL({ basePageId, hash });
}
return newURL;
}

View File

@ -5,5 +5,8 @@ export default abstract class URLRedirect {
constructor(mode: APP_MODE) {
this._mode = mode;
}
abstract generateRedirectURL(pageId: string, pageIdInUrl?: string): any;
abstract generateRedirectURL(
basePageId: string,
basePageIdInUrl?: string,
): any;
}

View File

@ -5,7 +5,7 @@ import { getSelectedWidgetWhenPasting } from "sagas/WidgetOperationUtils";
import { getWidgets } from "sagas/selectors";
import { updateAndSaveAnvilLayout } from "../../../utils/anvilChecksUtils";
import { builderURL } from "@appsmith/RouteBuilder";
import { getCurrentPageId } from "selectors/editorSelectors";
import { getCurrentBasePageId } from "selectors/editorSelectors";
import {
type ReduxAction,
ReduxActionErrorTypes,
@ -134,10 +134,10 @@ export function* pasteWidgetSagas() {
*/
yield call(updateAndSaveAnvilLayout, allWidgets);
const pageId: string = yield select(getCurrentPageId);
const basePageId: string = yield select(getCurrentBasePageId);
if (originalWidgets?.length) {
history.push(builderURL({ pageId }));
history.push(builderURL({ basePageId }));
}
const widgetsToSelect = copiedWidgets.map(

View File

@ -9,7 +9,7 @@ import {
} from "sagas/WidgetOperationUtils";
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
import { getWidgets } from "sagas/selectors";
import { getCurrentPageId } from "selectors/editorSelectors";
import { getCurrentBasePageId } from "selectors/editorSelectors";
import { SelectionRequestType } from "sagas/WidgetSelectUtils";
import { getDataTree } from "selectors/dataTreeSelectors";
import { generateReactKey } from "utils/generators";
@ -45,7 +45,7 @@ jest.mock("selectors/layoutSystemSelectors", () => ({
getLayoutSystemType: jest.fn(),
}));
describe("pasteSagas", () => {
const pageId = "0123456789abcdef00000000";
const basePageId = "0123456789abcdef00000000";
beforeAll(() => {
registerLayoutComponents();
@ -101,7 +101,7 @@ describe("pasteSagas", () => {
const { effects } = await expectSaga(pasteWidgetSagas as any)
.provide([
[select(getWidgets), allWidgets],
[select(getCurrentPageId), pageId],
[select(getCurrentBasePageId), basePageId],
])
.run();
// check the effects
@ -203,7 +203,7 @@ describe("pasteSagas", () => {
const { effects } = await expectSaga(pasteWidgetSagas as any)
.provide([
[select(getWidgets), allWidgets],
[select(getCurrentPageId), pageId],
[select(getCurrentBasePageId), basePageId],
])
.run();
// Check the effects

View File

@ -7,158 +7,158 @@ interface TestCase {
expected: FocusEntityInfo;
}
const applicationId = "a0123456789abcdef0000000";
const pageId = "b0123456789abcdef0000000";
const baseApplicationId = "a0123456789abcdef0000000";
const basePageId = "b0123456789abcdef0000000";
describe("identifyEntityFromPath", () => {
const oldUrlCases: TestCase[] = [
{
path: `/applications/${applicationId}/pages/${pageId}/edit`,
path: `/applications/${baseApplicationId}/pages/${basePageId}/edit`,
expected: {
entity: FocusEntity.CANVAS,
id: "",
appState: EditorState.EDITOR,
params: {
applicationId,
pageId,
baseApplicationId,
basePageId,
},
},
},
{
path: `/applications/${applicationId}/pages/${pageId}/edit/widgets/ryvc8i7oja`,
path: `/applications/${baseApplicationId}/pages/${basePageId}/edit/widgets/ryvc8i7oja`,
expected: {
entity: FocusEntity.PROPERTY_PANE,
id: "ryvc8i7oja",
appState: EditorState.EDITOR,
params: {
applicationId,
pageId,
baseApplicationId,
basePageId,
widgetIds: "ryvc8i7oja",
},
},
},
{
path: `/applications/${applicationId}/pages/${pageId}/edit/queries`,
path: `/applications/${baseApplicationId}/pages/${basePageId}/edit/queries`,
expected: {
entity: FocusEntity.QUERY_LIST,
id: "",
appState: EditorState.EDITOR,
params: {
applicationId,
baseApplicationId,
entity: "queries",
pageId,
basePageId,
},
},
},
{
path: `/applications/${applicationId}/pages/${pageId}/edit/api/myApiId`,
path: `/applications/${baseApplicationId}/pages/${basePageId}/edit/api/myApiId`,
expected: {
entity: FocusEntity.QUERY,
id: "myApiId",
appState: EditorState.EDITOR,
params: {
apiId: "myApiId",
applicationId,
pageId,
baseApiId: "myApiId",
baseApplicationId,
basePageId,
},
},
},
{
path: `/applications/${applicationId}/pages/${pageId}/edit/queries/myQueryId`,
path: `/applications/${baseApplicationId}/pages/${basePageId}/edit/queries/myQueryId`,
expected: {
entity: FocusEntity.QUERY,
id: "myQueryId",
appState: EditorState.EDITOR,
params: {
queryId: "myQueryId",
applicationId,
pageId,
baseQueryId: "myQueryId",
baseApplicationId,
basePageId,
},
},
},
{
path: `/applications/${applicationId}/pages/${pageId}/edit/jsObjects`,
path: `/applications/${baseApplicationId}/pages/${basePageId}/edit/jsObjects`,
expected: {
entity: FocusEntity.JS_OBJECT_LIST,
id: "",
appState: EditorState.EDITOR,
params: {
applicationId,
baseApplicationId,
entity: "jsObjects",
pageId,
basePageId,
},
},
},
{
path: `/applications/${applicationId}/pages/${pageId}/edit/jsObjects/myJSId`,
path: `/applications/${baseApplicationId}/pages/${basePageId}/edit/jsObjects/myJSId`,
expected: {
entity: FocusEntity.JS_OBJECT,
id: "myJSId",
appState: EditorState.EDITOR,
params: {
applicationId,
collectionId: "myJSId",
pageId,
baseApplicationId,
baseCollectionId: "myJSId",
basePageId,
},
},
},
{
path: `/applications/${applicationId}/pages/${pageId}/edit/datasource`,
path: `/applications/${baseApplicationId}/pages/${basePageId}/edit/datasource`,
expected: {
entity: FocusEntity.DATASOURCE_LIST,
id: "",
appState: EditorState.DATA,
params: {
applicationId,
baseApplicationId,
entity: "datasource",
pageId,
basePageId,
},
},
},
{
path: `/applications/${applicationId}/pages/${pageId}/edit/datasource/myDatasourceId`,
path: `/applications/${baseApplicationId}/pages/${basePageId}/edit/datasource/myDatasourceId`,
expected: {
entity: FocusEntity.DATASOURCE,
id: "myDatasourceId",
appState: EditorState.DATA,
params: {
applicationId,
baseApplicationId,
datasourceId: "myDatasourceId",
pageId,
basePageId,
},
},
},
];
const pageSlugCases: TestCase[] = [
{
path: `/app/eval/page1-${pageId}/edit`,
path: `/app/eval/page1-${basePageId}/edit`,
expected: {
entity: FocusEntity.CANVAS,
id: "",
appState: EditorState.EDITOR,
params: {
applicationSlug: "eval",
pageId,
basePageId,
pageSlug: "page1-",
},
},
},
{
path: `/app/app-slug/page1-${pageId}/edit/widgets/ryvc8i7oja`,
path: `/app/app-slug/page1-${basePageId}/edit/widgets/ryvc8i7oja`,
expected: {
entity: FocusEntity.PROPERTY_PANE,
id: "ryvc8i7oja",
appState: EditorState.EDITOR,
params: {
applicationSlug: "app-slug",
pageId,
basePageId,
pageSlug: "page1-",
widgetIds: "ryvc8i7oja",
},
},
},
{
path: `/app/eval/page1-${pageId}/edit/queries`,
path: `/app/eval/page1-${basePageId}/edit/queries`,
expected: {
entity: FocusEntity.QUERY_LIST,
id: "",
@ -166,41 +166,41 @@ describe("identifyEntityFromPath", () => {
params: {
applicationSlug: "eval",
entity: "queries",
pageId,
basePageId,
pageSlug: "page1-",
},
},
},
{
path: `/app/eval/page1-${pageId}/edit/api/myApiId`,
path: `/app/eval/page1-${basePageId}/edit/api/myApiId`,
expected: {
entity: FocusEntity.QUERY,
id: "myApiId",
appState: EditorState.EDITOR,
params: {
apiId: "myApiId",
baseApiId: "myApiId",
applicationSlug: "eval",
pageId,
basePageId,
pageSlug: "page1-",
},
},
},
{
path: `/app/eval/page1-${pageId}/edit/queries/myQueryId`,
path: `/app/eval/page1-${basePageId}/edit/queries/myQueryId`,
expected: {
entity: FocusEntity.QUERY,
id: "myQueryId",
appState: EditorState.EDITOR,
params: {
applicationSlug: "eval",
pageId,
basePageId,
pageSlug: "page1-",
queryId: "myQueryId",
baseQueryId: "myQueryId",
},
},
},
{
path: `/app/eval/page1-${pageId}/edit/jsObjects`,
path: `/app/eval/page1-${basePageId}/edit/jsObjects`,
expected: {
entity: FocusEntity.JS_OBJECT_LIST,
id: "",
@ -208,27 +208,27 @@ describe("identifyEntityFromPath", () => {
params: {
applicationSlug: "eval",
entity: "jsObjects",
pageId,
basePageId,
pageSlug: "page1-",
},
},
},
{
path: `/app/eval/page1-${pageId}/edit/jsObjects/myJSId`,
path: `/app/eval/page1-${basePageId}/edit/jsObjects/myJSId`,
expected: {
entity: FocusEntity.JS_OBJECT,
id: "myJSId",
appState: EditorState.EDITOR,
params: {
applicationSlug: "eval",
collectionId: "myJSId",
pageId,
baseCollectionId: "myJSId",
basePageId,
pageSlug: "page1-",
},
},
},
{
path: `/app/eval/page1-${pageId}/edit/datasource`,
path: `/app/eval/page1-${basePageId}/edit/datasource`,
expected: {
entity: FocusEntity.DATASOURCE_LIST,
id: "",
@ -236,13 +236,13 @@ describe("identifyEntityFromPath", () => {
params: {
applicationSlug: "eval",
entity: "datasource",
pageId,
basePageId,
pageSlug: "page1-",
},
},
},
{
path: `/app/eval/page1-${pageId}/edit/datasource/myDatasourceId`,
path: `/app/eval/page1-${basePageId}/edit/datasource/myDatasourceId`,
expected: {
entity: FocusEntity.DATASOURCE,
id: "myDatasourceId",
@ -250,7 +250,7 @@ describe("identifyEntityFromPath", () => {
params: {
applicationSlug: "eval",
datasourceId: "myDatasourceId",
pageId,
basePageId,
pageSlug: "page1-",
},
},
@ -258,116 +258,116 @@ describe("identifyEntityFromPath", () => {
];
const customSlugCases: TestCase[] = [
{
path: `/app/myCustomSlug-${pageId}/edit`,
path: `/app/myCustomSlug-${basePageId}/edit`,
expected: {
entity: FocusEntity.CANVAS,
id: "",
appState: EditorState.EDITOR,
params: {
pageId,
basePageId,
customSlug: "myCustomSlug-",
},
},
},
{
path: `/app/myCustomSlug-${pageId}/edit/widgets/ryvc8i7oja`,
path: `/app/myCustomSlug-${basePageId}/edit/widgets/ryvc8i7oja`,
expected: {
entity: FocusEntity.PROPERTY_PANE,
id: "ryvc8i7oja",
appState: EditorState.EDITOR,
params: {
pageId,
basePageId,
customSlug: "myCustomSlug-",
widgetIds: "ryvc8i7oja",
},
},
},
{
path: `/app/myCustomSlug-${pageId}/edit/queries`,
path: `/app/myCustomSlug-${basePageId}/edit/queries`,
expected: {
entity: FocusEntity.QUERY_LIST,
id: "",
appState: EditorState.EDITOR,
params: {
pageId,
basePageId,
customSlug: "myCustomSlug-",
entity: "queries",
},
},
},
{
path: `/app/myCustomSlug-${pageId}/edit/api/myApiId`,
path: `/app/myCustomSlug-${basePageId}/edit/api/myApiId`,
expected: {
entity: FocusEntity.QUERY,
id: "myApiId",
appState: EditorState.EDITOR,
params: {
pageId,
basePageId,
customSlug: "myCustomSlug-",
apiId: "myApiId",
baseApiId: "myApiId",
},
},
},
{
path: `/app/myCustomSlug-${pageId}/edit/queries/myQueryId`,
path: `/app/myCustomSlug-${basePageId}/edit/queries/myQueryId`,
expected: {
entity: FocusEntity.QUERY,
id: "myQueryId",
appState: EditorState.EDITOR,
params: {
pageId,
basePageId,
customSlug: "myCustomSlug-",
queryId: "myQueryId",
baseQueryId: "myQueryId",
},
},
},
{
path: `/app/myCustomSlug-${pageId}/edit/jsObjects`,
path: `/app/myCustomSlug-${basePageId}/edit/jsObjects`,
expected: {
entity: FocusEntity.JS_OBJECT_LIST,
id: "",
appState: EditorState.EDITOR,
params: {
pageId,
basePageId,
entity: "jsObjects",
customSlug: "myCustomSlug-",
},
},
},
{
path: `/app/myCustomSlug-${pageId}/edit/jsObjects/myJSId`,
path: `/app/myCustomSlug-${basePageId}/edit/jsObjects/myJSId`,
expected: {
entity: FocusEntity.JS_OBJECT,
id: "myJSId",
appState: EditorState.EDITOR,
params: {
collectionId: "myJSId",
pageId,
baseCollectionId: "myJSId",
basePageId,
customSlug: "myCustomSlug-",
},
},
},
{
path: `/app/myCustomSlug-${pageId}/edit/datasource`,
path: `/app/myCustomSlug-${basePageId}/edit/datasource`,
expected: {
entity: FocusEntity.DATASOURCE_LIST,
id: "",
appState: EditorState.DATA,
params: {
entity: "datasource",
pageId,
basePageId,
customSlug: "myCustomSlug-",
},
},
},
{
path: `/app/myCustomSlug-${pageId}/edit/datasource/myDatasourceId`,
path: `/app/myCustomSlug-${basePageId}/edit/datasource/myDatasourceId`,
expected: {
entity: FocusEntity.DATASOURCE,
id: "myDatasourceId",
appState: EditorState.DATA,
params: {
pageId,
basePageId,
customSlug: "myCustomSlug-",
datasourceId: "myDatasourceId",
},

View File

@ -60,20 +60,20 @@ const getMatchPaths = memoize((type: IDEType): string[] => {
});
export interface MatchEntityFromPath {
applicationId?: string;
baseApplicationId?: string;
customSlug?: string;
applicationSlug?: string;
packageId?: string;
moduleId?: string;
workflowId?: string;
pageSlug?: string;
apiId?: string;
baseApiId?: string;
datasourceId?: string;
pluginPackageName?: string;
queryId?: string;
baseQueryId?: string;
appId?: string;
pageId?: string;
collectionId?: string;
basePageId?: string;
baseCollectionId?: string;
widgetIds?: string;
selectedTab?: string;
moduleType?: string;
@ -120,14 +120,14 @@ export function identifyEntityFromPath(path: string): FocusEntityInfo {
params: {},
};
}
if (match.params.apiId) {
if (match.params.baseApiId) {
if (match.params.pluginPackageName) {
if (match.url.endsWith(ADD_PATH)) {
return getQueryAddPathObj(match);
}
return {
entity: FocusEntity.QUERY,
id: match.params.apiId,
id: match.params.baseApiId,
appState: EditorState.EDITOR,
params: match.params,
};
@ -137,7 +137,7 @@ export function identifyEntityFromPath(path: string): FocusEntityInfo {
}
return {
entity: FocusEntity.QUERY,
id: match.params.apiId,
id: match.params.baseApiId,
appState: EditorState.EDITOR,
params: match.params,
};
@ -175,13 +175,13 @@ export function identifyEntityFromPath(path: string): FocusEntityInfo {
params: match.params,
};
}
if (match.params.queryId) {
if (match.params.queryId == "add" || match.url.endsWith(ADD_PATH)) {
if (match.params.baseQueryId) {
if (match.params.baseQueryId == "add" || match.url.endsWith(ADD_PATH)) {
return getQueryAddPathObj(match);
}
return {
entity: FocusEntity.QUERY,
id: match.params.queryId,
id: match.params.baseQueryId,
appState: EditorState.EDITOR,
params: match.params,
};
@ -210,13 +210,16 @@ export function identifyEntityFromPath(path: string): FocusEntityInfo {
};
}
}
if (match.params.collectionId) {
if (match.params.collectionId == "add" || match.url.endsWith(ADD_PATH)) {
if (match.params.baseCollectionId) {
if (
match.params.baseCollectionId == "add" ||
match.url.endsWith(ADD_PATH)
) {
return getJSAddPathObj(match);
}
return {
entity: FocusEntity.JS_OBJECT,
id: match.params.collectionId,
id: match.params.baseCollectionId,
appState: EditorState.EDITOR,
params: match.params,
};

View File

@ -15,13 +15,14 @@ import { useCanvasWidthAutoResize } from "../../hooks/useCanvasWidthAutoResize";
interface AppPageProps {
appName?: string;
canvasWidth: number;
pageId?: string;
basePageId?: string;
pageName?: string;
widgetsStructure: CanvasWidgetStructure;
}
export function AppPage(props: AppPageProps) {
const { appName, canvasWidth, pageId, pageName, widgetsStructure } = props;
const { appName, basePageId, canvasWidth, pageName, widgetsStructure } =
props;
const appMode = useSelector(getAppMode);
const isPublished = appMode === APP_MODE.PUBLISHED;
@ -38,11 +39,11 @@ export function AppPage(props: AppPageProps) {
useEffect(() => {
AnalyticsUtil.logEvent("PAGE_LOAD", {
pageName: pageName,
pageId: pageId,
pageId: basePageId,
appName: appName,
mode: "VIEW",
});
}, [appName, pageId, pageName]);
}, [appName, basePageId, pageName]);
return (
<PageViewWrapper

View File

@ -53,7 +53,7 @@ function AppViewerPageContainer(props: AppViewerPageContainerProps) {
Please add widgets to this page in the&nbsp;
<Link
to={builderURL({
pageId: props.match.params.pageId as string,
basePageId: props.match.params.basePageId as string,
})}
>
Appsmith Editor
@ -94,8 +94,8 @@ function AppViewerPageContainer(props: AppViewerPageContainerProps) {
<Section>
<AppPage
appName={currentApplication?.name}
basePageId={match.params.basePageId}
canvasWidth={canvasWidth}
pageId={match.params.pageId}
pageName={currentPageName}
widgetsStructure={widgetsStructure}
/>

View File

@ -16,7 +16,7 @@ import { useHref } from "pages/Editor/utils";
import { builderURL } from "@appsmith/RouteBuilder";
import {
combinedPreviewModeSelector,
getCurrentPageId,
getCurrentBasePageId,
} from "selectors/editorSelectors";
import type { User } from "constants/userConstants";
import SidebarProfileComponent from "./components/SidebarProfileComponent";
@ -76,8 +76,8 @@ export function Sidebar(props: SidebarProps) {
const location = useLocation();
const { pathname } = location;
const [query, setQuery] = useState("");
const pageId = useSelector(getCurrentPageId);
const editorURL = useHref(builderURL, { pageId });
const basePageId = useSelector(getCurrentBasePageId);
const editorURL = useHref(builderURL, { basePageId });
const dispatch = useDispatch();
const isPinned = useSelector(getAppSidebarPinned);
const [isOpen, setIsOpen] = useState(true);

View File

@ -32,7 +32,7 @@ const MenuItem = ({
const appMode = useSelector(getAppMode);
const pageURL = useHref(
appMode === APP_MODE.PUBLISHED ? viewerURL : builderURL,
{ pageId: page.pageId },
{ basePageId: page.basePageId },
);
const selectedTheme = useSelector(getSelectedAppTheme);
const navColorStyle =

View File

@ -105,10 +105,10 @@ const MoreDropdownButton = ({
const pageURL =
appMode === APP_MODE.PUBLISHED
? viewerURL({
pageId: page.pageId,
basePageId: page.basePageId,
})
: builderURL({
pageId: page.pageId,
basePageId: page.basePageId,
});
return (

View File

@ -9,7 +9,7 @@ import React from "react";
import { useSelector } from "react-redux";
import { builderURL } from "@appsmith/RouteBuilder";
import { getSelectedAppTheme } from "selectors/appThemingSelectors";
import { getCurrentPageId } from "selectors/editorSelectors";
import { getCurrentBasePageId } from "selectors/editorSelectors";
import MobileNavToggle from "./MobileNavToggle";
import ApplicationName from "./ApplicationName";
import ShareButton from "./ShareButton";
@ -59,8 +59,8 @@ const TopHeader = (props: TopHeaderProps) => {
"properties.colors.primaryColor",
"inherit",
);
const pageId = useSelector(getCurrentPageId);
const editorURL = useHref(builderURL, { pageId });
const basePageId = useSelector(getCurrentBasePageId);
const editorURL = useHref(builderURL, { basePageId });
return (
<StyledNav

View File

@ -5,7 +5,7 @@ import type { ApplicationPayload } from "@appsmith/constants/ReduxActionConstant
import { useDispatch, useSelector } from "react-redux";
import type { AppState } from "@appsmith/reducers";
import {
getCurrentPageId,
getCurrentBasePageId,
getViewModePageList,
} from "selectors/editorSelectors";
import { getCurrentWorkspaceId } from "@appsmith/selectors/selectedWorkspaceSelectors";
@ -33,8 +33,8 @@ export function Navigation() {
const hideHeader = isEmbed && !showNavBar;
const [isMenuOpen, setMenuOpen] = useState(false);
const headerRef = useRef<HTMLDivElement>(null);
const pageId = useSelector(getCurrentPageId);
const editorURL = useHref(builderURL, { pageId });
const basePageId = useSelector(getCurrentBasePageId);
const editorURL = useHref(builderURL, { basePageId });
const currentWorkspaceId: string = useSelector(getCurrentWorkspaceId);
const currentUser: User | undefined = useSelector(getCurrentUser);
const lightTheme: Theme = useSelector((state: AppState) =>

View File

@ -180,7 +180,7 @@ function PageNavLink({
const selectedTheme = useSelector(getSelectedAppTheme);
const pathname = useHref(
appMode === APP_MODE.PUBLISHED ? viewerURL : builderURL,
{ pageId: page.pageId },
{ basePageId: page.basePageId },
);
return (
@ -190,7 +190,7 @@ function PageNavLink({
borderColor: selectedTheme.properties.colors.primaryColor,
}}
className="flex flex-col px-4 py-2 no-underline border-transparent border-r-3 hover:no-underline"
key={page.pageId}
key={page.basePageId}
navColorStyle={navColorStyle}
onClick={closeMenu}
primaryColor={primaryColor}

View File

@ -166,7 +166,7 @@ export function PageTabs(props: Props) {
{appPages.map((page) => {
return (
<PageTabContainer
isTabActive={pathname.indexOf(page.pageId) > -1}
isTabActive={pathname.indexOf(page.basePageId) > -1}
key={page.pageId}
setShowScrollArrows={props.setShowScrollArrows}
tabsScrollable={props.tabsScrollable}
@ -197,7 +197,7 @@ function PageTabItem({
const appMode = useSelector(getAppMode);
const pageURL = useHref(
appMode === APP_MODE.PUBLISHED ? viewerURL : builderURL,
{ pageId: page.pageId },
{ basePageId: page.basePageId },
);
const selectedTheme = useSelector(getSelectedAppTheme);
const navColorStyle =

View File

@ -27,9 +27,11 @@ export const initialState: any = {
pageList: {
applicationId: 1,
currentPageId: "0123456789abcdef00000000",
currentBasePageId: "0123456789abcdef00000123",
pages: [
{
pageId: "0123456789abcdef00000000",
basePageId: "0123456789abcdef00000123",
slug: "pageSlug",
},
],
@ -67,6 +69,7 @@ export const initialState: any = {
applications: {
currentApplication: {
id: "605c435a91dea93f0eaf91b8",
baseId: "605c435a91dea93f0eaf9123",
name: "My Application",
slug: "my-application",
workspaceId: "",
@ -126,6 +129,7 @@ export const fetchApplicationMockResponse = {
data: {
application: {
id: "605c435a91dea93f0eaf91b8",
baseId: "605c435a91dea93f0eaf9123",
name: "My Application",
slug: "my-application",
workspaceId: "",
@ -139,12 +143,14 @@ export const fetchApplicationMockResponse = {
pages: [
{
id: "605c435a91dea93f0eaf91ba",
baseId: "605c435a91dea93f0eaf9123",
name: "Page1",
isDefault: true,
slug: "page-1",
},
{
id: "605c435a91dea93f0eaf91bc",
baseId: "605c435a91dea93f0eaf9123",
name: "Page2",
isDefault: false,
slug: "page-2",
@ -162,7 +168,7 @@ describe("App viewer fork button", () => {
<PrimaryCTA
navColorStyle="solid"
primaryColor="red"
url={"/app/test-3/page1-63cccd44463c535b9fbc297c/edit"}
url={"/app/test-3/page1-605c435a91dea93f0eaf9123/edit"}
/>
</ThemeProvider>
</Provider>,
@ -178,7 +184,7 @@ describe("App viewer fork button", () => {
<PrimaryCTA
navColorStyle="solid"
primaryColor="red"
url={"/app/test-3/page1-63cccd44463c535b9fbc297c/edit"}
url={"/app/test-3/page1-605c435a91dea93f0eaf9123/edit"}
/>
</ThemeProvider>
</Provider>,

View File

@ -7,8 +7,7 @@ import {
isPermitted,
} from "@appsmith/utils/permissionHelpers";
import {
getCurrentApplication,
getCurrentPageId,
getCurrentBasePageId,
previewModeSelector,
} from "selectors/editorSelectors";
import { getSelectedAppTheme } from "selectors/appThemingSelectors";
@ -30,6 +29,7 @@ import { getApplicationNameTextColor } from "./utils";
import { ButtonVariantTypes } from "components/constants";
import { setPreviewModeInitAction } from "actions/editorActions";
import { protectedModeSelector } from "selectors/gitSyncSelectors";
import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors";
/**
* ---------------------------------------------------------------------------------------------------
@ -61,7 +61,7 @@ function PrimaryCTA(props: Props) {
url,
} = props;
const currentUser = useSelector(getCurrentUser);
const currentPageID = useSelector(getCurrentPageId);
const currentBasePageId = useSelector(getCurrentBasePageId);
const selectedTheme = useSelector(getSelectedAppTheme);
const currentApplication = useSelector(getCurrentApplication);
const history = useHistory();
@ -116,7 +116,7 @@ function PrimaryCTA(props: Props) {
}, [currentApplication?.forkingEnabled, currentUser?.username]);
const appViewerURL = useHref(viewerURL, {
pageId: currentPageID,
basePageId: currentBasePageId,
params: {
fork: "true",
branch: null,

View File

@ -32,7 +32,7 @@ import { setupPublishedPage } from "actions/pageActions";
import usePrevious from "utils/hooks/usePrevious";
import { getIsBranchUpdated } from "../utils";
import { APP_MODE } from "entities/App";
import { initAppViewer } from "actions/initActions";
import { initAppViewerAction } from "actions/initActions";
import { WidgetGlobaStyles } from "globalStyles/WidgetGlobalStyles";
import useWidgetFocus from "utils/hooks/useWidgetFocus/useWidgetFocus";
import HtmlTitle from "./AppViewerHtmlTitle";
@ -86,7 +86,7 @@ const DEFAULT_FONT_NAME = "System Default";
function AppViewer(props: Props) {
const dispatch = useDispatch();
const { pathname, search } = props.location;
const { applicationId, pageId } = props.match.params;
const { baseApplicationId, basePageId } = props.match.params;
const isInitialized = useSelector(getIsInitialized);
const pages = useSelector(getViewModePageList);
const selectedTheme = useSelector(getSelectedAppTheme);
@ -95,7 +95,11 @@ function AppViewer(props: Props) {
);
const headerHeight = useSelector(getAppViewHeaderHeight);
const branch = getSearchQuery(search, GIT_BRANCH_QUERY_KEY);
const prevValues = usePrevious({ branch, location: props.location, pageId });
const prevValues = usePrevious({
branch,
location: props.location,
basePageId,
});
const hideWatermark = useSelector(getHideWatermark);
const pageDescription = useSelector(getCurrentPageDescription);
const currentApplicationDetails: ApplicationPayload | undefined = useSelector(
@ -135,20 +139,20 @@ function AppViewer(props: Props) {
useEffect(() => {
const prevBranch = prevValues?.branch;
const prevLocation = prevValues?.location;
const prevPageId = prevValues?.pageId;
const prevPageBaseId = prevValues?.basePageId;
let isBranchUpdated = false;
if (prevBranch && prevLocation) {
isBranchUpdated = getIsBranchUpdated(props.location, prevLocation);
}
const isPageIdUpdated = pageId !== prevPageId;
const isPageIdUpdated = basePageId !== prevPageBaseId;
if (prevBranch && isBranchUpdated && (applicationId || pageId)) {
if (prevBranch && isBranchUpdated && (baseApplicationId || basePageId)) {
dispatch(
initAppViewer({
applicationId,
initAppViewerAction({
baseApplicationId,
branch,
pageId,
basePageId,
mode: APP_MODE.PUBLISHED,
}),
);
@ -158,19 +162,24 @@ function AppViewer(props: Props) {
* If we don't check for `prevPageId`: fetch page is retriggered
* when redirected to the default page
*/
if (prevPageId && pageId && isPageIdUpdated) {
dispatch(setupPublishedPage(pageId, true));
if (prevPageBaseId && basePageId && isPageIdUpdated) {
const pageId = pages.find(
(page) => page.basePageId === basePageId,
)?.pageId;
if (pageId) {
dispatch(setupPublishedPage(pageId, true));
}
}
}
}, [branch, pageId, applicationId, pathname]);
}, [branch, basePageId, baseApplicationId, pathname]);
useEffect(() => {
urlBuilder.setCurrentPageId(pageId);
urlBuilder.setCurrentBasePageId(basePageId);
return () => {
urlBuilder.setCurrentPageId(null);
urlBuilder.setCurrentBasePageId(null);
};
}, [pageId]);
}, [basePageId]);
useEffect(() => {
const header = document.querySelector(".js-appviewer-header");

View File

@ -3,7 +3,7 @@ import type { RouteComponentProps } from "react-router";
import PageLoadingBar from "pages/common/PageLoadingBar";
import { retryPromise } from "utils/AppsmithUtils";
import type { InitAppViewerPayload } from "actions/initActions";
import { initAppViewer } from "actions/initActions";
import { initAppViewerAction } from "actions/initActions";
import { APP_MODE } from "entities/App";
import { connect } from "react-redux";
import { getSearchQuery } from "utils/helpers";
@ -13,7 +13,7 @@ import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants";
type Props = {
initAppViewer: (payload: InitAppViewerPayload) => void;
clearCache: () => void;
} & RouteComponentProps<{ pageId: string; applicationId?: string }>;
} & RouteComponentProps<{ basePageId: string; baseApplicationId?: string }>;
class AppViewerLoader extends React.PureComponent<Props, { Page: any }> {
constructor(props: any) {
@ -44,14 +44,14 @@ class AppViewerLoader extends React.PureComponent<Props, { Page: any }> {
location: { search },
match: { params },
} = this.props;
const { applicationId, pageId } = params;
const { baseApplicationId, basePageId } = params;
const branch = getSearchQuery(search, GIT_BRANCH_QUERY_KEY);
// onMount initPage
if (applicationId || pageId) {
if (baseApplicationId || basePageId) {
initAppViewer({
applicationId,
baseApplicationId,
branch,
pageId,
basePageId,
mode: APP_MODE.PUBLISHED,
});
}
@ -65,7 +65,7 @@ class AppViewerLoader extends React.PureComponent<Props, { Page: any }> {
const mapDispatchToProps = (dispatch: any) => {
return {
initAppViewer: (payload: InitAppViewerPayload) =>
dispatch(initAppViewer(payload)),
dispatch(initAppViewerAction(payload)),
clearCache: () => {
dispatch({ type: ReduxActionTypes.CLEAR_CACHE });
},

View File

@ -403,31 +403,27 @@ export function ApplicationCard(props: ApplicationCardProps) {
{
applicationSlug: props.application.slug,
applicationVersion: props.application.applicationVersion,
applicationId: props.application.id,
baseApplicationId: props.application.baseId,
},
props.application.pages.map((page) => ({
pageSlug: page.slug,
customSlug: page.customSlug,
pageId: page.id,
basePageId: page.baseId,
})),
);
}
const editModeURL = useMemo(() => {
if (!props.application.defaultPageId) return "";
return builderURL({
pageId: props.application.defaultPageId,
params,
});
}, [props.application.defaultPageId, params]);
const basePageId = props.application.defaultBasePageId;
if (!basePageId) return "";
return builderURL({ basePageId, params });
}, [props.application.defaultBasePageId, params]);
const viewModeURL = useMemo(() => {
if (!props.application.defaultPageId) return "";
return viewerURL({
pageId: props.application.defaultPageId,
params,
});
}, [props.application.defaultPageId, params]);
const basePageId = props.application.defaultBasePageId;
if (!basePageId) return "";
return viewerURL({ basePageId, params });
}, [props.application.defaultBasePageId, params]);
const launchApp = useCallback(() => {
setURLParams();
@ -443,7 +439,7 @@ export function ApplicationCard(props: ApplicationCardProps) {
setURLParams();
history.push(
viewerURL({
pageId: props.application.defaultPageId,
basePageId: props.application.defaultBasePageId,
params,
}),
);

View File

@ -1,6 +1,6 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { getDefaultPageId } from "sagas/selectors";
import { getDefaultBasePageId } from "sagas/selectors";
import { getSettings } from "selectors/settingsSelectors";
import { getCurrentUser } from "selectors/usersSelectors";
import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors";
@ -43,7 +43,7 @@ function useUpdateEmbedSnippet() {
const application = useSelector(getCurrentApplication);
const settings = useSelector(getSettings);
const user = useSelector(getCurrentUser);
const defaultPageId = useSelector(getDefaultPageId);
const defaultBasePageId = useSelector(getDefaultBasePageId);
const featureFlags = useSelector(selectFeatureFlags);
const currentSetting: EmbedSetting = formatEmbedSettings(
settings["APPSMITH_ALLOWED_FRAME_ANCESTORS"] as string,
@ -104,7 +104,7 @@ function useUpdateEmbedSnippet() {
const appViewEndPoint = useMemo(() => {
const url = viewerURL({
pageId: defaultPageId,
basePageId: defaultBasePageId,
});
const allowHidingShareSettingsInEmbedView =
featureFlags.release_embed_hide_share_settings_enabled;
@ -119,7 +119,7 @@ function useUpdateEmbedSnippet() {
fullUrl.searchParams.append("embed", "true");
return fullUrl.toString();
}, [defaultPageId, embedSetting?.showNavigationBar]);
}, [defaultBasePageId, embedSetting?.showNavigationBar]);
const snippet = useMemo(() => {
return `<iframe src="${appViewEndPoint}" width="${embedSetting?.width}" height="${embedSetting?.height}"></iframe>`;

View File

@ -23,7 +23,7 @@ interface ApiRightPaneProps {
actionRightPaneBackLink: React.ReactNode;
applicationId?: string;
currentActionDatasourceId: string;
currentPageId?: string;
currentBasePageId?: string;
datasourceId: string;
datasources: any;
hasResponse: boolean;
@ -290,7 +290,7 @@ function ApiRightPane(props: ApiRightPaneProps) {
e.stopPropagation();
history.push(
datasourcesEditorIdURL({
pageId: props.currentPageId,
basePageId: props.currentBasePageId,
datasourceId: d.id,
params: getQueryParams(),
}),

View File

@ -534,7 +534,7 @@ function CommonEditorForm(props: CommonFormPropsWithExtraParams) {
} = props;
const dispatch = useDispatch();
const params = useParams<{ apiId?: string; queryId?: string }>();
const params = useParams<{ baseApiId?: string; baseQueryId?: string }>();
// passing lodash's equality function to ensure that this selector does not cause a rerender multiple times.
// it checks each value to make sure none has changed before recomputing the actions.
@ -544,7 +544,8 @@ function CommonEditorForm(props: CommonFormPropsWithExtraParams) {
);
const currentActionConfig: Action | undefined = actions.find(
(action) => action.id === params.apiId || action.id === params.queryId,
(action) =>
action.baseId === params.baseApiId || action.id === params.baseQueryId,
);
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const isChangePermitted = getHasManageActionPermission(

View File

@ -11,14 +11,12 @@ import type {
import _ from "lodash";
import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors";
import {
getActionById,
getCurrentApplicationId,
getCurrentPageName,
} from "selectors/editorSelectors";
import type { Plugin } from "api/PluginApi";
import type { Action, PaginationType } from "entities/Action";
import { PluginPackageName } from "entities/Action";
import { getApiName } from "selectors/formSelectors";
import Spinner from "components/editorComponents/Spinner";
import type { CSSProperties } from "styled-components";
import styled from "styled-components";
@ -30,7 +28,11 @@ import PerformanceTracker, {
import * as Sentry from "@sentry/react";
import EntityNotFoundPane from "pages/Editor/EntityNotFoundPane";
import type { ApplicationPayload } from "@appsmith/constants/ReduxActionConstants";
import { getPageList, getPlugins } from "@appsmith/selectors/entitiesSelector";
import {
getActionByBaseId,
getPageList,
getPlugins,
} from "@appsmith/selectors/entitiesSelector";
import history from "utils/history";
import { saasEditorApiIdURL } from "@appsmith/RouteBuilder";
import GraphQLEditorForm from "./GraphQL/GraphQLEditorForm";
@ -46,6 +48,7 @@ interface ReduxStateProps {
isRunning: boolean;
isDeleting: boolean;
isCreating: boolean;
apiId: string;
apiName: string;
currentApplication?: ApplicationPayload;
currentPageName: string | undefined;
@ -85,8 +88,8 @@ class ApiEditor extends React.Component<Props> {
actionType: "API",
});
const type = this.getFormName();
if (this.props.match.params.apiId) {
this.props.changeAPIPage(this.props.match.params.apiId, type === "SAAS");
if (this.props.apiId) {
this.props.changeAPIPage(this.props.apiId, type === "SAAS");
}
}
@ -105,12 +108,9 @@ class ApiEditor extends React.Component<Props> {
if (prevProps.isRunning && !this.props.isRunning) {
PerformanceTracker.stopTracking(PerformanceTransactionName.RUN_API_CLICK);
}
if (prevProps.match.params.apiId !== this.props.match.params.apiId) {
if (prevProps.apiId !== this.props.apiId) {
const type = this.getFormName();
this.props.changeAPIPage(
this.props.match.params.apiId || "",
type === "SAAS",
);
this.props.changeAPIPage(this.props.apiId || "", type === "SAAS");
}
}
@ -138,13 +138,13 @@ class ApiEditor extends React.Component<Props> {
isEditorInitialized,
isRunning,
match: {
params: { apiId },
params: { baseApiId },
},
paginationType,
pluginId,
plugins,
} = this.props;
if (!pluginId && apiId) {
if (!pluginId && baseApiId) {
return <EntityNotFoundPane />;
}
if (isCreating || !isEditorInitialized) {
@ -156,7 +156,7 @@ class ApiEditor extends React.Component<Props> {
}
let formUiComponent: string | undefined;
if (apiId) {
if (baseApiId) {
if (pluginId) {
formUiComponent = this.getPluginUiComponentOfId(pluginId, plugins);
} else {
@ -204,13 +204,13 @@ class ApiEditor extends React.Component<Props> {
{formUiComponent === "SaaSEditorForm" &&
history.push(
saasEditorApiIdURL({
pageId: this.props.match.params.pageId,
basePageId: this.props.match.params.basePageId,
pluginPackageName:
getPackageNameFromPluginId(
this.props.pluginId,
this.props.plugins,
) ?? "",
apiId: this.props.match.params.apiId || "",
baseApiId: this.props.match.params.baseApiId || "",
}),
)}
</div>
@ -226,8 +226,9 @@ const formStyles: CSSProperties = {
};
const mapStateToProps = (state: AppState, props: any): ReduxStateProps => {
const apiAction = getActionById(state, props);
const apiName = getApiName(state, props.match.params.apiId);
const apiAction = getActionByBaseId(state, props?.match?.params?.baseApiId);
const apiName = apiAction?.name ?? "";
const apiId = apiAction?.id ?? "";
const { isCreating, isDeleting, isRunning } = state.ui.apiPane;
const pluginId = _.get(apiAction, "pluginId", "");
return {
@ -235,13 +236,14 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => {
currentApplication: getCurrentApplication(state),
currentPageName: getCurrentPageName(state),
pages: getPageList(state),
apiName: apiName || "",
apiId,
apiName,
plugins: getPlugins(state),
pluginId,
paginationType: _.get(apiAction, "actionConfiguration.paginationType"),
apiAction,
isRunning: isRunning[props.match.params.apiId],
isDeleting: isDeleting[props.match.params.apiId],
isRunning: isRunning[apiId],
isDeleting: isDeleting[apiId],
isCreating: isCreating,
applicationId: getCurrentApplicationId(state),
};

View File

@ -7,12 +7,14 @@ import styled from "styled-components";
import { API_EDITOR_FORM_NAME } from "@appsmith/constants/forms";
import type { Action } from "entities/Action";
import type { AppState } from "@appsmith/reducers";
import { getApiName } from "selectors/formSelectors";
import { EditorTheme } from "components/editorComponents/CodeEditor/EditorConfig";
import useHorizontalResize from "utils/hooks/useHorizontalResize";
import get from "lodash/get";
import type { Datasource } from "entities/Datasource";
import { getAction, getActionData } from "@appsmith/selectors/entitiesSelector";
import {
getActionByBaseId,
getActionData,
} from "@appsmith/selectors/entitiesSelector";
import { isEmpty } from "lodash";
import type { CommonFormProps } from "../CommonEditorForm";
import CommonEditorForm from "../CommonEditorForm";
@ -179,11 +181,11 @@ export default connect(
);
}
// get messages from action itself
const { apiId, queryId } = props.match?.params || {};
const actionId = queryId || apiId;
// const actionId = selector(state, "id");
const action = getAction(state, actionId);
const { baseApiId, baseQueryId } = props.match?.params || {};
const baseActionId = baseQueryId || baseApiId;
const action = getActionByBaseId(state, baseActionId);
const apiId = action?.id ?? "";
const actionName = action?.name ?? "";
const hintMessages = action?.messages;
const datasourceHeaders =
@ -192,10 +194,8 @@ export default connect(
get(datasourceFromAction, "datasourceConfiguration.queryParameters") ||
[];
// const apiId = selector(state, "id");
const currentActionDatasourceId = selector(state, "datasource.id");
const actionName = getApiName(state, apiId) || "";
const headers = selector(state, "actionConfiguration.headers");
let headersCount = 0;

View File

@ -17,7 +17,7 @@ import {
getIsEditorInitialized,
getPagePermissions,
} from "selectors/editorSelectors";
import { getAction } from "@appsmith/selectors/entitiesSelector";
import { getActionByBaseId } from "@appsmith/selectors/entitiesSelector";
import type { APIEditorRouteParams } from "constants/routes";
import {
getHasCreateActionPermission,
@ -44,22 +44,22 @@ import { EditorViewMode } from "@appsmith/entities/IDE/constants";
type ApiEditorWrapperProps = RouteComponentProps<APIEditorRouteParams>;
function getPageName(pages: any, pageId: string) {
const page = pages.find((page: any) => page.pageId === pageId);
function getPageName(pages: any, basePageId: string) {
const page = pages.find((page: any) => page.basePageId === basePageId);
return page ? page.pageName : "";
}
function ApiEditorWrapper(props: ApiEditorWrapperProps) {
const { apiId = "", pageId } = props.match.params;
const { baseApiId = "", basePageId } = props.match.params;
const dispatch = useDispatch();
const isEditorInitialized = useSelector(getIsEditorInitialized);
const action = useSelector((state) => getAction(state, apiId));
const action = useSelector((state) => getActionByBaseId(state, baseApiId));
const apiName = action?.name || "";
const pluginId = get(action, "pluginId", "");
const datasourceId = action?.datasource.id || "";
const plugins = useSelector(getPlugins);
const pages = useSelector(getPageList);
const pageName = getPageName(pages, pageId);
const pageName = getPageName(pages, basePageId);
const settingsConfig = useSelector((state) =>
getPluginSettingConfigs(state, pluginId),
);
@ -106,12 +106,12 @@ function ApiEditorWrapper(props: ApiEditorWrapperProps) {
return (
<>
<MoreActionsMenu
basePageId={basePageId}
className="t--more-action-menu"
id={action?.id || ""}
isChangePermitted={isChangePermitted}
isDeletePermitted={isDeletePermitted}
name={action?.name || ""}
pageId={pageId}
prefixAdditionalMenus={
editorMode === EditorViewMode.SplitScreen && (
<ConvertToModuleInstanceCTA {...convertToModuleProps} />
@ -128,7 +128,7 @@ function ApiEditorWrapper(props: ApiEditorWrapperProps) {
action?.name,
isChangePermitted,
isDeletePermitted,
pageId,
basePageId,
isCreatePermitted,
editorMode,
]);
@ -139,34 +139,42 @@ function ApiEditorWrapper(props: ApiEditorWrapperProps) {
PerformanceTracker.startTracking(
PerformanceTransactionName.RUN_API_CLICK,
{
apiId,
apiId: action?.id,
},
);
AnalyticsUtil.logEvent("RUN_API_CLICK", {
apiName,
apiID: apiId,
apiID: action?.id,
pageName: pageName,
datasourceId,
pluginName: pluginName,
isMock: false, // as mock db exists only for postgres and mongo plugins
});
dispatch(runAction(apiId, paginationField));
dispatch(runAction(action?.id ?? "", paginationField));
},
[apiId, apiName, pageName, getPageName, plugins, pluginId, datasourceId],
[
action?.id,
apiName,
pageName,
getPageName,
plugins,
pluginId,
datasourceId,
],
);
const actionRightPaneBackLink = useMemo(() => {
return <BackToCanvas pageId={pageId} />;
}, [pageId]);
return <BackToCanvas basePageId={basePageId} />;
}, [basePageId]);
const handleDeleteClick = useCallback(() => {
AnalyticsUtil.logEvent("DELETE_API_CLICK", {
apiName,
apiID: apiId,
apiID: action?.id,
pageName,
});
dispatch(deleteAction({ id: apiId, name: apiName }));
}, [getPageName, pages, pageId, apiName]);
dispatch(deleteAction({ id: action?.id ?? "", name: apiName }));
}, [getPageName, pages, basePageId, apiName]);
const notification = useMemo(() => {
if (!isConverting) return null;

Some files were not shown because too many files have changed in this diff Show More