@@ -94,8 +94,8 @@ export default function Settings() {
-
- {currentOrg && currentOrg.name}
+
+ {currentWorkspace && currentWorkspace.name}
history.push(ORG_INVITE_USERS_PAGE_URL)}
+ onClick={() => history.push(WORKSPACE_INVITE_USERS_PAGE_URL)}
text="Invite Users"
/>
);
}
-export default OrgMembers;
+export default WorkspaceMembers;
diff --git a/app/client/src/reducers/index.tsx b/app/client/src/reducers/index.tsx
index 023b55fd0e..6fa5ca373d 100644
--- a/app/client/src/reducers/index.tsx
+++ b/app/client/src/reducers/index.tsx
@@ -19,7 +19,7 @@ import { ApiPaneReduxState } from "./uiReducers/apiPaneReducer";
import { QueryPaneReduxState } from "./uiReducers/queryPaneReducer";
import { PluginDataState } from "reducers/entityReducers/pluginsReducer";
import { AuthState } from "reducers/uiReducers/authReducer";
-import { OrgReduxState } from "reducers/uiReducers/orgReducer";
+import { WorkspaceReduxState } from "reducers/uiReducers/workspaceReducer";
import { UsersReduxState } from "reducers/uiReducers/usersReducer";
import { ThemeState } from "reducers/uiReducers/themeReducer";
import { WidgetDragResizeState } from "reducers/uiReducers/dragResizeReducer";
@@ -83,7 +83,7 @@ export interface AppState {
apiPane: ApiPaneReduxState;
auth: AuthState;
templates: TemplatesReduxState;
- orgs: OrgReduxState;
+ workspaces: WorkspaceReduxState;
users: UsersReduxState;
widgetDragResize: WidgetDragResizeState;
importedCollections: ImportedCollectionsReduxState;
diff --git a/app/client/src/reducers/uiReducers/applicationsReducer.tsx b/app/client/src/reducers/uiReducers/applicationsReducer.tsx
index 292a0f07fb..4191f3c9a4 100644
--- a/app/client/src/reducers/uiReducers/applicationsReducer.tsx
+++ b/app/client/src/reducers/uiReducers/applicationsReducer.tsx
@@ -5,7 +5,7 @@ import {
ReduxActionErrorTypes,
ApplicationPayload,
} from "@appsmith/constants/ReduxActionConstants";
-import { Organization, OrgUser } from "constants/orgConstants";
+import { Workspaces, WorkspaceUser } from "constants/workspaceConstants";
import {
createMessage,
ERROR_MESSAGE_CREATE_APPLICATION,
@@ -26,13 +26,13 @@ const initialState: ApplicationsReduxState = {
deletingApplication: false,
forkingApplication: false,
duplicatingApplication: false,
- userOrgs: [],
- isSavingOrgInfo: false,
+ userWorkspaces: [],
+ isSavingWorkspaceInfo: false,
importingApplication: false,
importedApplication: null,
showAppInviteUsersDialog: false,
isImportAppModalOpen: false,
- organizationIdForImport: null,
+ workspaceIdForImport: null,
};
const applicationsReducer = createReducer(initialState, {
@@ -45,9 +45,9 @@ const applicationsReducer = createReducer(initialState, {
state: ApplicationsReduxState,
action: ReduxAction,
) => {
- const _organizations = state.userOrgs.map((org: Organization) => {
- if (org.organization.id === action.payload.organizationId) {
- let applications = org.applications;
+ const _workspaces = state.userWorkspaces.map((workspace: Workspaces) => {
+ if (workspace.workspace.id === action.payload.workspaceId) {
+ let applications = workspace.applications;
applications = applications.filter(
(application: ApplicationPayload) => {
@@ -56,17 +56,17 @@ const applicationsReducer = createReducer(initialState, {
);
return {
- ...org,
+ ...workspace,
applications,
};
}
- return org;
+ return workspace;
});
return {
...state,
- userOrgs: _organizations,
+ userWorkspaces: _workspaces,
deletingApplication: false,
};
},
@@ -94,24 +94,24 @@ const applicationsReducer = createReducer(initialState, {
[ReduxActionTypes.GET_ALL_APPLICATION_INIT]: (
state: ApplicationsReduxState,
) => ({ ...state, isFetchingApplications: true }),
- [ReduxActionTypes.FETCH_USER_APPLICATIONS_ORGS_SUCCESS]: (
+ [ReduxActionTypes.FETCH_USER_APPLICATIONS_WORKSPACES_SUCCESS]: (
state: ApplicationsReduxState,
action: ReduxAction<{ applicationList: any }>,
) => {
return {
...state,
isFetchingApplications: false,
- userOrgs: action.payload,
+ userWorkspaces: action.payload,
};
},
- [ReduxActionTypes.DELETE_ORG_SUCCESS]: (
+ [ReduxActionTypes.DELETE_WORKSPACE_SUCCESS]: (
state: ApplicationsReduxState,
action: ReduxAction,
) => {
return {
...state,
- userOrgs: state.userOrgs.filter(
- (org: Organization) => org.organization.id !== action.payload,
+ userWorkspaces: state.userWorkspaces.filter(
+ (workspace: Workspaces) => workspace.workspace.id !== action.payload,
),
};
},
@@ -152,7 +152,7 @@ const applicationsReducer = createReducer(initialState, {
action: ReduxAction,
) => {
const updatedCreatingApplication = { ...state.creatingApplication };
- updatedCreatingApplication[action.payload.orgId] = true;
+ updatedCreatingApplication[action.payload.workspaceId] = true;
return {
...state,
@@ -161,56 +161,59 @@ const applicationsReducer = createReducer(initialState, {
},
[ReduxActionTypes.CREATE_APPLICATION_SUCCESS]: (
state: ApplicationsReduxState,
- action: ReduxAction<{ orgId: string; application: ApplicationPayload }>,
+ action: ReduxAction<{
+ workspaceId: string;
+ application: ApplicationPayload;
+ }>,
) => {
- const _organizations = state.userOrgs.map((org: Organization) => {
- if (org.organization.id === action.payload.orgId) {
- const applications = org.applications;
+ const _workspaces = state.userWorkspaces.map((workspace: Workspaces) => {
+ if (workspace.workspace.id === action.payload.workspaceId) {
+ const applications = workspace.applications;
applications.push(action.payload.application);
- org.applications = [...applications];
+ workspace.applications = [...applications];
return {
- ...org,
+ ...workspace,
};
}
- return org;
+ return workspace;
});
const updatedCreatingApplication = { ...state.creatingApplication };
- updatedCreatingApplication[action.payload.orgId] = false;
+ updatedCreatingApplication[action.payload.workspaceId] = false;
return {
...state,
creatingApplication: updatedCreatingApplication,
applicationList: [...state.applicationList, action.payload.application],
- userOrgs: _organizations,
+ userWorkspaces: _workspaces,
};
},
- [ReduxActionTypes.INVITED_USERS_TO_ORGANIZATION]: (
+ [ReduxActionTypes.INVITED_USERS_TO_WORKSPACE]: (
state: ApplicationsReduxState,
- action: ReduxAction<{ orgId: string; users: OrgUser[] }>,
+ action: ReduxAction<{ workspaceId: string; users: WorkspaceUser[] }>,
) => {
- const _organizations = state.userOrgs.map((org: Organization) => {
- if (org.organization.id === action.payload.orgId) {
- const userRoles = org.userRoles;
- org.userRoles = [...userRoles, ...action.payload.users];
+ const _workspaces = state.userWorkspaces.map((workspace: Workspaces) => {
+ if (workspace.workspace.id === action.payload.workspaceId) {
+ const userRoles = workspace.userRoles;
+ workspace.userRoles = [...userRoles, ...action.payload.users];
return {
- ...org,
+ ...workspace,
};
}
- return org;
+ return workspace;
});
return {
...state,
- userOrgs: _organizations,
+ userWorkspaces: _workspaces,
};
},
[ReduxActionErrorTypes.CREATE_APPLICATION_ERROR]: (
state: ApplicationsReduxState,
- action: ReduxAction<{ orgId: string }>,
+ action: ReduxAction<{ workspaceId: string }>,
) => {
const updatedCreatingApplication = { ...state.creatingApplication };
- updatedCreatingApplication[action.payload.orgId] = false;
+ updatedCreatingApplication[action.payload.workspaceId] = false;
return {
...state,
@@ -223,24 +226,27 @@ const applicationsReducer = createReducer(initialState, {
},
[ReduxActionTypes.FORK_APPLICATION_SUCCESS]: (
state: ApplicationsReduxState,
- action: ReduxAction<{ orgId: string; application: ApplicationPayload }>,
+ action: ReduxAction<{
+ workspaceId: string;
+ application: ApplicationPayload;
+ }>,
) => {
- const _organizations = state.userOrgs.map((org: Organization) => {
- if (org.organization.id === action.payload.orgId) {
- const applications = org.applications;
- org.applications = [...applications, action.payload.application];
+ const _workspaces = state.userWorkspaces.map((workspace: Workspaces) => {
+ if (workspace.workspace.id === action.payload.workspaceId) {
+ const applications = workspace.applications;
+ workspace.applications = [...applications, action.payload.application];
return {
- ...org,
+ ...workspace,
};
}
- return org;
+ return workspace;
});
return {
...state,
forkingApplication: false,
applicationList: [...state.applicationList, action.payload.application],
- userOrgs: _organizations,
+ userWorkspaces: _workspaces,
};
},
[ReduxActionErrorTypes.FORK_APPLICATION_ERROR]: (
@@ -276,13 +282,13 @@ const applicationsReducer = createReducer(initialState, {
importingApplication: false,
};
},
- [ReduxActionTypes.SAVING_ORG_INFO]: (state: ApplicationsReduxState) => {
+ [ReduxActionTypes.SAVING_WORKSPACE_INFO]: (state: ApplicationsReduxState) => {
return {
...state,
- isSavingOrgInfo: true,
+ isSavingWorkspaceInfo: true,
};
},
- [ReduxActionTypes.SAVE_ORG_SUCCESS]: (
+ [ReduxActionTypes.SAVE_WORKSPACE_SUCCESS]: (
state: ApplicationsReduxState,
action: ReduxAction<{
id: string;
@@ -292,27 +298,29 @@ const applicationsReducer = createReducer(initialState, {
logoUrl?: string;
}>,
) => {
- const _organizations = state.userOrgs.map((org: Organization) => {
- if (org.organization.id === action.payload.id) {
- org.organization = { ...org.organization, ...action.payload };
+ const _workspaces = state.userWorkspaces.map((workspace: Workspaces) => {
+ if (workspace.workspace.id === action.payload.id) {
+ workspace.workspace = { ...workspace.workspace, ...action.payload };
return {
- ...org,
+ ...workspace,
};
}
- return org;
+ return workspace;
});
return {
...state,
- userOrgs: _organizations,
- isSavingOrgInfo: false,
+ userWorkspaces: _workspaces,
+ isSavingWorkspaceInfo: false,
};
},
- [ReduxActionErrorTypes.SAVE_ORG_ERROR]: (state: ApplicationsReduxState) => {
+ [ReduxActionErrorTypes.SAVE_WORKSPACE_ERROR]: (
+ state: ApplicationsReduxState,
+ ) => {
return {
...state,
- isSavingOrgInfo: false,
+ isSavingWorkspaceInfo: false,
};
},
[ReduxActionTypes.SEARCH_APPLICATIONS]: (
@@ -362,24 +370,24 @@ const applicationsReducer = createReducer(initialState, {
state: ApplicationsReduxState,
action: ReduxAction,
) => {
- // userOrgs data has to be saved to localStorage only if the action is successful
+ // userWorkspaces data has to be saved to localStorage only if the action is successful
// It introduces bug if we prematurely save it during init action.
const { id, ...rest } = action.payload;
- const _organizations = state.userOrgs.map((org: Organization) => {
- const appIndex = org.applications.findIndex((app) => app.id === id);
+ const _workspaces = state.userWorkspaces.map((workspace: Workspaces) => {
+ const appIndex = workspace.applications.findIndex((app) => app.id === id);
if (appIndex !== -1) {
- org.applications[appIndex] = {
- ...org.applications[appIndex],
+ workspace.applications[appIndex] = {
+ ...workspace.applications[appIndex],
...rest,
};
}
- return org;
+ return workspace;
});
return {
...state,
- userOrgs: _organizations,
+ userWorkspaces: _workspaces,
isSavingAppName: false,
isErrorSavingAppName: false,
};
@@ -455,7 +463,7 @@ const applicationsReducer = createReducer(initialState, {
...state,
isDatasourceConfigForImportFetched: false,
}),
- [ReduxActionTypes.SET_ORG_ID_FOR_IMPORT]: (
+ [ReduxActionTypes.SET_WORKSPACE_ID_FOR_IMPORT]: (
state: ApplicationsReduxState,
action: ReduxAction,
) => {
@@ -467,10 +475,10 @@ const applicationsReducer = createReducer(initialState, {
return {
...state,
currentApplication,
- organizationIdForImport: action.payload,
+ workspaceIdForImport: action.payload,
};
},
- [ReduxActionTypes.IMPORT_TEMPLATE_TO_ORGANISATION_SUCCESS]: (
+ [ReduxActionTypes.IMPORT_TEMPLATE_TO_WORKSPACE_SUCCESS]: (
state: ApplicationsReduxState,
action: ReduxAction,
) => {
@@ -497,20 +505,20 @@ export interface ApplicationsReduxState {
forkingApplication: boolean;
duplicatingApplication: boolean;
currentApplication?: ApplicationPayload;
- userOrgs: Organization[];
- isSavingOrgInfo: boolean;
+ userWorkspaces: Workspaces[];
+ isSavingWorkspaceInfo: boolean;
importingApplication: boolean;
showAppInviteUsersDialog: boolean;
importedApplication: any;
isImportAppModalOpen: boolean;
- organizationIdForImport: any;
+ workspaceIdForImport: any;
isDatasourceConfigForImportFetched?: boolean;
}
export interface Application {
id: string;
name: string;
- organizationId: string;
+ workspaceId: string;
isPublic: boolean;
appIsExample: boolean;
new: boolean;
diff --git a/app/client/src/reducers/uiReducers/gitSyncReducer.ts b/app/client/src/reducers/uiReducers/gitSyncReducer.ts
index caddf88947..2f54726077 100644
--- a/app/client/src/reducers/uiReducers/gitSyncReducer.ts
+++ b/app/client/src/reducers/uiReducers/gitSyncReducer.ts
@@ -401,7 +401,9 @@ const gitSyncReducer = createReducer(initialState, {
deployKeyDocUrl: action.payload.docUrl,
};
},
- [ReduxActionTypes.SET_ORG_ID_FOR_IMPORT]: (state: GitSyncReducerState) => {
+ [ReduxActionTypes.SET_WORKSPACE_ID_FOR_IMPORT]: (
+ state: GitSyncReducerState,
+ ) => {
return {
...state,
SSHKeyPair: "",
diff --git a/app/client/src/reducers/uiReducers/index.tsx b/app/client/src/reducers/uiReducers/index.tsx
index 2def5faacb..ec3c59e489 100644
--- a/app/client/src/reducers/uiReducers/index.tsx
+++ b/app/client/src/reducers/uiReducers/index.tsx
@@ -7,7 +7,7 @@ import applicationsReducer from "./applicationsReducer";
import apiPaneReducer from "./apiPaneReducer";
import datasourcePaneReducer from "./datasourcePaneReducer";
import authReducer from "./authReducer";
-import orgReducer from "./orgReducer";
+import workspaceReducer from "./workspaceReducer";
import templateReducer from "./templateReducer";
import usersReducer from "./usersReducer";
import { widgetDraggingReducer } from "./dragResizeReducer";
@@ -52,7 +52,7 @@ const uiReducer = combineReducers({
apiPane: apiPaneReducer,
auth: authReducer,
templates: templateReducer,
- orgs: orgReducer,
+ workspaces: workspaceReducer,
users: usersReducer,
widgetDragResize: widgetDraggingReducer,
importedCollections: importedCollectionsReducer,
diff --git a/app/client/src/reducers/uiReducers/orgReducer.ts b/app/client/src/reducers/uiReducers/orgReducer.ts
deleted file mode 100644
index e373f05736..0000000000
--- a/app/client/src/reducers/uiReducers/orgReducer.ts
+++ /dev/null
@@ -1,156 +0,0 @@
-import { createImmerReducer } from "utils/AppsmithUtils";
-import {
- ReduxAction,
- ReduxActionTypes,
- ReduxActionErrorTypes,
-} from "@appsmith/constants/ReduxActionConstants";
-import { OrgRole, Org, OrgUser } from "constants/orgConstants";
-
-const initialState: OrgReduxState = {
- loadingStates: {
- fetchingRoles: false,
- isFetchAllRoles: false,
- isFetchAllUsers: false,
- isFetchingOrg: false,
- },
- orgUsers: [],
- orgRoles: [],
- currentOrg: {
- id: "",
- name: "",
- },
-};
-
-const orgReducer = createImmerReducer(initialState, {
- [ReduxActionTypes.FETCH_ORG_ROLES_INIT]: (draftState: OrgReduxState) => {
- draftState.loadingStates.isFetchAllRoles = true;
- },
- [ReduxActionTypes.FETCH_ALL_ROLES_INIT]: (draftState: OrgReduxState) => {
- draftState.loadingStates.isFetchAllRoles = true;
- },
- [ReduxActionTypes.FETCH_ALL_USERS_INIT]: (draftState: OrgReduxState) => {
- draftState.loadingStates.isFetchAllUsers = true;
- },
- [ReduxActionTypes.FETCH_ORG_ROLES_SUCCESS]: (
- draftState: OrgReduxState,
- action: ReduxAction,
- ) => {
- draftState.orgRoles = action.payload;
- draftState.loadingStates.fetchingRoles = false;
- },
- [ReduxActionErrorTypes.FETCH_ORG_ROLES_ERROR]: (
- draftState: OrgReduxState,
- ) => {
- draftState.loadingStates.fetchingRoles = false;
- },
- [ReduxActionTypes.FETCH_ALL_USERS_SUCCESS]: (
- draftState: OrgReduxState,
- action: ReduxAction,
- ) => {
- draftState.orgUsers = action.payload;
- draftState.loadingStates.isFetchAllUsers = false;
- },
- [ReduxActionTypes.FETCH_ALL_ROLES_SUCCESS]: (
- draftState: OrgReduxState,
- action: ReduxAction,
- ) => {
- draftState.orgRoles = action.payload;
- draftState.loadingStates.isFetchAllRoles = false;
- },
- [ReduxActionTypes.CHANGE_ORG_USER_ROLE_SUCCESS]: (
- draftState: OrgReduxState,
- action: ReduxAction<{ username: string; roleName: string }>,
- ) => {
- draftState.orgUsers.forEach((user: OrgUser) => {
- if (user.username === action.payload.username) {
- user.roleName = action.payload.roleName;
- user.isChangingRole = false;
- }
- });
- },
- [ReduxActionTypes.CHANGE_ORG_USER_ROLE_INIT]: (
- draftState: OrgReduxState,
- action: ReduxAction<{ username: string }>,
- ) => {
- draftState.orgUsers.forEach((user: OrgUser) => {
- if (user.username === action.payload.username) {
- user.isChangingRole = true;
- }
- });
- },
- [ReduxActionErrorTypes.CHANGE_ORG_USER_ROLE_ERROR]: (
- draftState: OrgReduxState,
- ) => {
- draftState.orgUsers.forEach((user: OrgUser) => {
- //TODO: This will change the status to false even if one role change api fails.
- user.isChangingRole = false;
- });
- },
- [ReduxActionTypes.DELETE_ORG_USER_INIT]: (
- draftState: OrgReduxState,
- action: ReduxAction<{ username: string }>,
- ) => {
- draftState.orgUsers.forEach((user: OrgUser) => {
- if (user.username === action.payload.username) {
- user.isDeleting = true;
- }
- });
- },
- [ReduxActionTypes.DELETE_ORG_USER_SUCCESS]: (
- draftState: OrgReduxState,
- action: ReduxAction<{ username: string }>,
- ) => {
- draftState.orgUsers = draftState.orgUsers.filter(
- (user: OrgUser) => user.username !== action.payload.username,
- );
- },
- [ReduxActionErrorTypes.DELETE_ORG_USER_ERROR]: (
- draftState: OrgReduxState,
- ) => {
- draftState.orgUsers.forEach((user: OrgUser) => {
- //TODO: This will change the status to false even if one delete fails.
- user.isDeleting = false;
- });
- },
- [ReduxActionTypes.SET_CURRENT_ORG_ID]: (
- draftState: OrgReduxState,
- action: ReduxAction<{ orgId: string }>,
- ) => {
- draftState.currentOrg.id = action.payload.orgId;
- },
- [ReduxActionTypes.SET_CURRENT_ORG]: (
- draftState: OrgReduxState,
- action: ReduxAction,
- ) => {
- draftState.currentOrg = action.payload;
- },
- [ReduxActionTypes.FETCH_CURRENT_ORG]: (draftState: OrgReduxState) => {
- draftState.loadingStates.isFetchingOrg = true;
- },
- [ReduxActionTypes.FETCH_ORG_SUCCESS]: (
- draftState: OrgReduxState,
- action: ReduxAction,
- ) => {
- draftState.currentOrg = action.payload;
- draftState.loadingStates.isFetchingOrg = false;
- },
- [ReduxActionErrorTypes.FETCH_ORG_ERROR]: (draftState: OrgReduxState) => {
- draftState.loadingStates.isFetchingOrg = false;
- },
-});
-
-export interface OrgReduxState {
- list?: Org[];
- roles?: OrgRole[];
- loadingStates: {
- fetchingRoles: boolean;
- isFetchAllRoles: boolean;
- isFetchAllUsers: boolean;
- isFetchingOrg: boolean;
- };
- orgUsers: OrgUser[];
- orgRoles: any;
- currentOrg: Org;
-}
-
-export default orgReducer;
diff --git a/app/client/src/reducers/uiReducers/templateReducer.ts b/app/client/src/reducers/uiReducers/templateReducer.ts
index 14603e3234..609bf265a4 100644
--- a/app/client/src/reducers/uiReducers/templateReducer.ts
+++ b/app/client/src/reducers/uiReducers/templateReducer.ts
@@ -72,7 +72,7 @@ const templateReducer = createReducer(initialState, {
templateSearchQuery: action.payload,
};
},
- [ReduxActionTypes.IMPORT_TEMPLATE_TO_ORGANISATION_INIT]: (
+ [ReduxActionTypes.IMPORT_TEMPLATE_TO_WORKSPACE_INIT]: (
state: TemplatesReduxState,
) => {
return {
@@ -80,7 +80,7 @@ const templateReducer = createReducer(initialState, {
isImportingTemplate: true,
};
},
- [ReduxActionTypes.IMPORT_TEMPLATE_TO_ORGANISATION_SUCCESS]: (
+ [ReduxActionTypes.IMPORT_TEMPLATE_TO_WORKSPACE_SUCCESS]: (
state: TemplatesReduxState,
) => {
return {
@@ -88,7 +88,7 @@ const templateReducer = createReducer(initialState, {
isImportingTemplate: false,
};
},
- [ReduxActionErrorTypes.IMPORT_TEMPLATE_TO_ORGANISATION_ERROR]: (
+ [ReduxActionErrorTypes.IMPORT_TEMPLATE_TO_WORKSPACE_ERROR]: (
state: TemplatesReduxState,
) => {
return {
diff --git a/app/client/src/reducers/uiReducers/workspaceReducer.ts b/app/client/src/reducers/uiReducers/workspaceReducer.ts
new file mode 100644
index 0000000000..0c973cc481
--- /dev/null
+++ b/app/client/src/reducers/uiReducers/workspaceReducer.ts
@@ -0,0 +1,170 @@
+import { createImmerReducer } from "utils/AppsmithUtils";
+import {
+ ReduxAction,
+ ReduxActionTypes,
+ ReduxActionErrorTypes,
+} from "@appsmith/constants/ReduxActionConstants";
+import {
+ WorkspaceRole,
+ Workspace,
+ WorkspaceUser,
+} from "constants/workspaceConstants";
+
+const initialState: WorkspaceReduxState = {
+ loadingStates: {
+ fetchingRoles: false,
+ isFetchAllRoles: false,
+ isFetchAllUsers: false,
+ isFetchingWorkspace: false,
+ },
+ workspaceUsers: [],
+ workspaceRoles: [],
+ currentWorkspace: {
+ id: "",
+ name: "",
+ },
+};
+
+const workspaceReducer = createImmerReducer(initialState, {
+ [ReduxActionTypes.FETCH_WORKSPACE_ROLES_INIT]: (
+ draftState: WorkspaceReduxState,
+ ) => {
+ draftState.loadingStates.isFetchAllRoles = true;
+ },
+ [ReduxActionTypes.FETCH_ALL_ROLES_INIT]: (
+ draftState: WorkspaceReduxState,
+ ) => {
+ draftState.loadingStates.isFetchAllRoles = true;
+ },
+ [ReduxActionTypes.FETCH_ALL_USERS_INIT]: (
+ draftState: WorkspaceReduxState,
+ ) => {
+ draftState.loadingStates.isFetchAllUsers = true;
+ },
+ [ReduxActionTypes.FETCH_WORKSPACE_ROLES_SUCCESS]: (
+ draftState: WorkspaceReduxState,
+ action: ReduxAction,
+ ) => {
+ draftState.workspaceRoles = action.payload;
+ draftState.loadingStates.fetchingRoles = false;
+ },
+ [ReduxActionErrorTypes.FETCH_WORKSPACE_ROLES_ERROR]: (
+ draftState: WorkspaceReduxState,
+ ) => {
+ draftState.loadingStates.fetchingRoles = false;
+ },
+ [ReduxActionTypes.FETCH_ALL_USERS_SUCCESS]: (
+ draftState: WorkspaceReduxState,
+ action: ReduxAction,
+ ) => {
+ draftState.workspaceUsers = action.payload;
+ draftState.loadingStates.isFetchAllUsers = false;
+ },
+ [ReduxActionTypes.FETCH_ALL_ROLES_SUCCESS]: (
+ draftState: WorkspaceReduxState,
+ action: ReduxAction,
+ ) => {
+ draftState.workspaceRoles = action.payload;
+ draftState.loadingStates.isFetchAllRoles = false;
+ },
+ [ReduxActionTypes.CHANGE_WORKSPACE_USER_ROLE_SUCCESS]: (
+ draftState: WorkspaceReduxState,
+ action: ReduxAction<{ username: string; roleName: string }>,
+ ) => {
+ draftState.workspaceUsers.forEach((user: WorkspaceUser) => {
+ if (user.username === action.payload.username) {
+ user.roleName = action.payload.roleName;
+ user.isChangingRole = false;
+ }
+ });
+ },
+ [ReduxActionTypes.CHANGE_WORKSPACE_USER_ROLE_INIT]: (
+ draftState: WorkspaceReduxState,
+ action: ReduxAction<{ username: string }>,
+ ) => {
+ draftState.workspaceUsers.forEach((user: WorkspaceUser) => {
+ if (user.username === action.payload.username) {
+ user.isChangingRole = true;
+ }
+ });
+ },
+ [ReduxActionErrorTypes.CHANGE_WORKSPACE_USER_ROLE_ERROR]: (
+ draftState: WorkspaceReduxState,
+ ) => {
+ draftState.workspaceUsers.forEach((user: WorkspaceUser) => {
+ //TODO: This will change the status to false even if one role change api fails.
+ user.isChangingRole = false;
+ });
+ },
+ [ReduxActionTypes.DELETE_WORKSPACE_USER_INIT]: (
+ draftState: WorkspaceReduxState,
+ action: ReduxAction<{ username: string }>,
+ ) => {
+ draftState.workspaceUsers.forEach((user: WorkspaceUser) => {
+ if (user.username === action.payload.username) {
+ user.isDeleting = true;
+ }
+ });
+ },
+ [ReduxActionTypes.DELETE_WORKSPACE_USER_SUCCESS]: (
+ draftState: WorkspaceReduxState,
+ action: ReduxAction<{ username: string }>,
+ ) => {
+ draftState.workspaceUsers = draftState.workspaceUsers.filter(
+ (user: WorkspaceUser) => user.username !== action.payload.username,
+ );
+ },
+ [ReduxActionErrorTypes.DELETE_WORKSPACE_USER_ERROR]: (
+ draftState: WorkspaceReduxState,
+ ) => {
+ draftState.workspaceUsers.forEach((user: WorkspaceUser) => {
+ //TODO: This will change the status to false even if one delete fails.
+ user.isDeleting = false;
+ });
+ },
+ [ReduxActionTypes.SET_CURRENT_WORKSPACE_ID]: (
+ draftState: WorkspaceReduxState,
+ action: ReduxAction<{ workspaceId: string }>,
+ ) => {
+ draftState.currentWorkspace.id = action.payload.workspaceId;
+ },
+ [ReduxActionTypes.SET_CURRENT_WORKSPACE]: (
+ draftState: WorkspaceReduxState,
+ action: ReduxAction,
+ ) => {
+ draftState.currentWorkspace = action.payload;
+ },
+ [ReduxActionTypes.FETCH_CURRENT_WORKSPACE]: (
+ draftState: WorkspaceReduxState,
+ ) => {
+ draftState.loadingStates.isFetchingWorkspace = true;
+ },
+ [ReduxActionTypes.FETCH_WORKSPACE_SUCCESS]: (
+ draftState: WorkspaceReduxState,
+ action: ReduxAction,
+ ) => {
+ draftState.currentWorkspace = action.payload;
+ draftState.loadingStates.isFetchingWorkspace = false;
+ },
+ [ReduxActionErrorTypes.FETCH_WORKSPACE_ERROR]: (
+ draftState: WorkspaceReduxState,
+ ) => {
+ draftState.loadingStates.isFetchingWorkspace = false;
+ },
+});
+
+export interface WorkspaceReduxState {
+ list?: Workspace[];
+ roles?: WorkspaceRole[];
+ loadingStates: {
+ fetchingRoles: boolean;
+ isFetchAllRoles: boolean;
+ isFetchAllUsers: boolean;
+ isFetchingWorkspace: boolean;
+ };
+ workspaceUsers: WorkspaceUser[];
+ workspaceRoles: any;
+ currentWorkspace: Workspace;
+}
+
+export default workspaceReducer;
diff --git a/app/client/src/sagas/ApiPaneSagas.ts b/app/client/src/sagas/ApiPaneSagas.ts
index fea7ca27c7..78cdd6cfa1 100644
--- a/app/client/src/sagas/ApiPaneSagas.ts
+++ b/app/client/src/sagas/ApiPaneSagas.ts
@@ -39,7 +39,7 @@ import {
} from "actions/pluginActionActions";
import { Datasource } from "entities/Datasource";
import { Action, ApiAction, PluginType } from "entities/Action";
-import { getCurrentOrgId } from "@appsmith/selectors/organizationSelectors";
+import { getCurrentWorkspaceId } from "@appsmith/selectors/workspaceSelectors";
import log from "loglevel";
import PerformanceTracker, {
PerformanceTransactionName,
@@ -554,7 +554,7 @@ function* handleDatasourceCreatedSaga(actionPayload: ReduxAction) {
function* handleCreateNewApiActionSaga(
action: ReduxAction<{ pageId: string; from: EventLocation }>,
) {
- const organizationId: string = yield select(getCurrentOrgId);
+ const workspaceId: string = yield select(getCurrentWorkspaceId);
const pluginId: string = yield select(
getPluginIdOfPackageName,
REST_PLUGIN_PACKAGE_NAME,
@@ -575,7 +575,7 @@ function* handleCreateNewApiActionSaga(
datasource: {
name: "DEFAULT_REST_DATASOURCE",
pluginId,
- organizationId,
+ workspaceId,
},
eventData: {
actionType: "API",
diff --git a/app/client/src/sagas/AppThemingSaga.tsx b/app/client/src/sagas/AppThemingSaga.tsx
index c318c36a74..f88ee28696 100644
--- a/app/client/src/sagas/AppThemingSaga.tsx
+++ b/app/client/src/sagas/AppThemingSaga.tsx
@@ -167,7 +167,7 @@ export function* changeSelectedTheme(
// shows toast
Toaster.show({
- text: createMessage(CHANGE_APP_THEME, theme.name),
+ text: createMessage(CHANGE_APP_THEME, theme.displayName),
variant: Variant.success,
actionElement: (
store.dispatch(undoAction())}>Undo
diff --git a/app/client/src/sagas/ApplicationSagas.tsx b/app/client/src/sagas/ApplicationSagas.tsx
index da7a84a544..c7999463c6 100644
--- a/app/client/src/sagas/ApplicationSagas.tsx
+++ b/app/client/src/sagas/ApplicationSagas.tsx
@@ -16,10 +16,10 @@ import ApplicationApi, {
FetchApplicationPayload,
FetchApplicationResponse,
FetchUnconfiguredDatasourceListResponse,
- FetchUsersApplicationsOrgsResponse,
+ FetchUsersApplicationsWorkspacesResponse,
ForkApplicationRequest,
ImportApplicationRequest,
- OrganizationApplicationObject,
+ WorkspaceApplicationObject,
PublishApplicationRequest,
PublishApplicationResponse,
SetDefaultPageRequest,
@@ -28,7 +28,7 @@ import ApplicationApi, {
import { all, call, put, select, takeLatest } from "redux-saga/effects";
import { validateResponse } from "./ErrorSagas";
-import { getUserApplicationsOrgsList } from "selectors/applicationSelectors";
+import { getUserApplicationsWorkspacesList } from "selectors/applicationSelectors";
import { ApiResponse } from "api/ApiResponses";
import history from "utils/history";
import { PLACEHOLDER_APP_SLUG, PLACEHOLDER_PAGE_SLUG } from "constants/routes";
@@ -42,7 +42,7 @@ import {
resetCurrentApplication,
setDefaultApplicationPageSuccess,
setIsReconnectingDatasourcesModalOpen,
- setOrgIdForImport,
+ setWorkspaceIdForImport,
showReconnectDatasourceModal,
} from "actions/applicationActions";
import AnalyticsUtil from "utils/AnalyticsUtil";
@@ -54,7 +54,7 @@ import {
} from "@appsmith/constants/messages";
import { Toaster } from "components/ads/Toast";
import { APP_MODE } from "entities/App";
-import { Org, Organization } from "constants/orgConstants";
+import { Workspace, Workspaces } from "constants/workspaceConstants";
import { Variant } from "components/ads/common";
import { AppIconName } from "components/ads/AppIcon";
import { AppColorCode } from "constants/DefaultTheme";
@@ -72,7 +72,7 @@ import {
reconnectAppLevelWebsocket,
reconnectPageLevelWebsocket,
} from "actions/websocketActions";
-import { getCurrentOrg } from "@appsmith/selectors/organizationSelectors";
+import { getCurrentWorkspace } from "@appsmith/selectors/workspaceSelectors";
import {
getCurrentStep,
@@ -172,29 +172,31 @@ export function* publishApplicationSaga(
export function* getAllApplicationSaga() {
try {
- const response: FetchUsersApplicationsOrgsResponse = yield call(
+ const response: FetchUsersApplicationsWorkspacesResponse = yield call(
ApplicationApi.getAllApplication,
);
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
- const organizationApplication: OrganizationApplicationObject[] = response.data.organizationApplications.map(
- (userOrgs: OrganizationApplicationObject) => ({
- organization: userOrgs.organization,
- userRoles: userOrgs.userRoles,
- applications: !userOrgs.applications
+ const workspaceApplication: WorkspaceApplicationObject[] = response.data.workspaceApplications.map(
+ (userWorkspaces: WorkspaceApplicationObject) => ({
+ workspace: userWorkspaces.workspace,
+ userRoles: userWorkspaces.userRoles,
+ applications: !userWorkspaces.applications
? []
- : userOrgs.applications.map((application: ApplicationObject) => {
- return {
- ...application,
- defaultPageId: getDefaultPageId(application.pages),
- };
- }),
+ : userWorkspaces.applications.map(
+ (application: ApplicationObject) => {
+ return {
+ ...application,
+ defaultPageId: getDefaultPageId(application.pages),
+ };
+ },
+ ),
}),
);
yield put({
- type: ReduxActionTypes.FETCH_USER_APPLICATIONS_ORGS_SUCCESS,
- payload: organizationApplication,
+ type: ReduxActionTypes.FETCH_USER_APPLICATIONS_WORKSPACES_SUCCESS,
+ payload: workspaceApplication,
});
const { newReleasesCount, releaseItems } = response.data || {};
yield put({
@@ -204,7 +206,7 @@ export function* getAllApplicationSaga() {
}
} catch (error) {
yield put({
- type: ReduxActionErrorTypes.FETCH_USER_APPLICATIONS_ORGS_ERROR,
+ type: ReduxActionErrorTypes.FETCH_USER_APPLICATIONS_WORKSPACES_ERROR,
payload: {
error,
},
@@ -247,9 +249,9 @@ export function* fetchAppAndPagesSaga(
});
yield put({
- type: ReduxActionTypes.SET_CURRENT_ORG_ID,
+ type: ReduxActionTypes.SET_CURRENT_WORKSPACE_ID,
payload: {
- orgId: response.data.organizationId,
+ workspaceId: response.data.workspaceId,
},
});
@@ -484,19 +486,19 @@ export function* createApplicationSaga(
applicationName: string;
icon: AppIconName;
color: AppColorCode;
- orgId: string;
+ workspaceId: string;
resolve: any;
reject: any;
}>,
) {
- const { applicationName, color, icon, orgId, reject } = action.payload;
+ const { applicationName, color, icon, reject, workspaceId } = action.payload;
try {
- const userOrgs = yield select(getUserApplicationsOrgsList);
- const existingOrgs = userOrgs.filter(
- (org: Organization) => org.organization.id === orgId,
+ const userWorkspaces = yield select(getUserApplicationsWorkspacesList);
+ const existingWorkspaces = userWorkspaces.filter(
+ (workspace: Workspaces) => workspace.workspace.id === workspaceId,
)[0];
- const existingApplication = existingOrgs
- ? existingOrgs.applications.find(
+ const existingApplication = existingWorkspaces
+ ? existingWorkspaces.applications.find(
(application: ApplicationPayload) =>
application.name === applicationName,
)
@@ -519,7 +521,7 @@ export function* createApplicationSaga(
name: applicationName,
icon: icon,
color: color,
- orgId,
+ workspaceId,
};
const response: CreateApplicationResponse = yield call(
ApplicationApi.createApplication,
@@ -543,7 +545,7 @@ export function* createApplicationSaga(
yield put({
type: ReduxActionTypes.CREATE_APPLICATION_SUCCESS,
payload: {
- orgId,
+ workspaceId,
application,
},
});
@@ -595,7 +597,7 @@ export function* createApplicationSaga(
payload: {
error,
show: false,
- orgId,
+ workspaceId,
},
});
}
@@ -619,7 +621,7 @@ export function* forkApplicationSaga(
yield put({
type: ReduxActionTypes.FORK_APPLICATION_SUCCESS,
payload: {
- orgId: action.payload.organizationId,
+ workspaceId: action.payload.workspaceId,
application,
},
});
@@ -649,19 +651,23 @@ function* showReconnectDatasourcesModalSaga(
action: ReduxAction<{
application: ApplicationResponsePayload;
unConfiguredDatasourceList: Array;
- orgId: string;
+ workspaceId: string;
}>,
) {
- const { application, orgId, unConfiguredDatasourceList } = action.payload;
+ const {
+ application,
+ unConfiguredDatasourceList,
+ workspaceId,
+ } = action.payload;
yield put(getAllApplications());
yield put(importApplicationSuccess(application));
- yield put(fetchPlugins({ orgId }));
+ yield put(fetchPlugins({ workspaceId }));
yield put(
setUnconfiguredDatasourcesDuringImport(unConfiguredDatasourceList || []),
);
- yield put(setOrgIdForImport(orgId));
+ yield put(setWorkspaceIdForImport(workspaceId));
yield put(setIsReconnectingDatasourcesModalOpen({ isOpen: true }));
}
@@ -670,16 +676,16 @@ export function* importApplicationSaga(
) {
try {
const response: ApiResponse = yield call(
- ApplicationApi.importApplicationToOrg,
+ ApplicationApi.importApplicationToWorkspace,
action.payload,
);
const isValidResponse: boolean = yield validateResponse(response);
if (isValidResponse) {
- const allOrgs: Org[] = yield select(getCurrentOrg);
- const currentOrg = allOrgs.filter(
- (el: Org) => el.id === action.payload.orgId,
+ const allWorkspaces: Workspace[] = yield select(getCurrentWorkspace);
+ const currentWorkspace = allWorkspaces.filter(
+ (el: Workspace) => el.id === action.payload.workspaceId,
);
- if (currentOrg.length > 0) {
+ if (currentWorkspace.length > 0) {
const {
application: { applicationVersion, id, pages, slug: applicationSlug },
isPartialImport,
@@ -706,7 +712,7 @@ export function* importApplicationSaga(
application: response.data?.application,
unConfiguredDatasourceList:
response?.data.unConfiguredDatasourceList,
- orgId: action.payload.orgId,
+ workspaceId: action.payload.workspaceId,
}),
);
} else {
@@ -743,7 +749,7 @@ export function* importApplicationSaga(
function* fetchReleases() {
try {
- const response: FetchUsersApplicationsOrgsResponse = yield call(
+ const response: FetchUsersApplicationsWorkspacesResponse = yield call(
ApplicationApi.getAllApplication,
);
const isValidResponse = yield validateResponse(response);
@@ -767,7 +773,7 @@ function* fetchReleases() {
export function* fetchUnconfiguredDatasourceList(
action: ReduxAction<{
applicationId: string;
- orgId: string;
+ workspaceId: string;
}>,
) {
try {
@@ -811,10 +817,10 @@ export function* initializeDatasourceWithDefaultValues(datasource: Datasource) {
}
function* initDatasourceConnectionDuringImport(action: ReduxAction) {
- const orgId = action.payload;
+ const workspaceId = action.payload;
const pluginsAndDatasourcesCalls: boolean = yield failFastApiCalls(
- [fetchPlugins({ orgId }), fetchDatasources({ orgId })],
+ [fetchPlugins({ workspaceId }), fetchDatasources({ workspaceId })],
[
ReduxActionTypes.FETCH_PLUGINS_SUCCESS,
ReduxActionTypes.FETCH_DATASOURCES_SUCCESS,
diff --git a/app/client/src/sagas/CanvasSagas/DraggingCanvasSagas.ts b/app/client/src/sagas/CanvasSagas/DraggingCanvasSagas.ts
index 85eafef20d..5bcbaa4866 100644
--- a/app/client/src/sagas/CanvasSagas/DraggingCanvasSagas.ts
+++ b/app/client/src/sagas/CanvasSagas/DraggingCanvasSagas.ts
@@ -119,7 +119,7 @@ function* addWidgetAndMoveWidgetsSaga(
yield put(updateAndSaveLayout(updatedWidgetsOnAddAndMove));
yield put({
type: ReduxActionTypes.RECORD_RECENTLY_ADDED_WIDGET,
- payload: [newWidget.widgetId],
+ payload: [newWidget.newWidgetId],
});
log.debug("move computations took", performance.now() - start, "ms");
} catch (error) {
diff --git a/app/client/src/sagas/CurlImportSagas.ts b/app/client/src/sagas/CurlImportSagas.ts
index f66357d668..1652329039 100644
--- a/app/client/src/sagas/CurlImportSagas.ts
+++ b/app/client/src/sagas/CurlImportSagas.ts
@@ -12,7 +12,7 @@ import {
createMessage,
CURL_IMPORT_SUCCESS,
} from "@appsmith/constants/messages";
-import { getCurrentOrgId } from "@appsmith/selectors/organizationSelectors";
+import { getCurrentWorkspaceId } from "@appsmith/selectors/workspaceSelectors";
import transformCurlImport from "transformers/CurlImportTransformer";
import history from "utils/history";
import { Toaster } from "components/ads/Toast";
@@ -25,13 +25,13 @@ export function* curlImportSaga(action: ReduxAction) {
let { curl } = action.payload;
try {
curl = transformCurlImport(curl);
- const organizationId: string = yield select(getCurrentOrgId);
+ const workspaceId: string = yield select(getCurrentWorkspaceId);
const request: CurlImportRequest = {
type,
pageId,
name,
curl,
- organizationId,
+ workspaceId,
};
const response: ApiResponse = yield CurlImportApi.curlImport(request);
diff --git a/app/client/src/sagas/DatasourcesSagas.ts b/app/client/src/sagas/DatasourcesSagas.ts
index 700227d7e4..9a4680bbc3 100644
--- a/app/client/src/sagas/DatasourcesSagas.ts
+++ b/app/client/src/sagas/DatasourcesSagas.ts
@@ -51,7 +51,7 @@ import {
import { validateResponse } from "./ErrorSagas";
import AnalyticsUtil from "utils/AnalyticsUtil";
import { getFormData } from "selectors/formSelectors";
-import { getCurrentOrgId } from "@appsmith/selectors/organizationSelectors";
+import { getCurrentWorkspaceId } from "@appsmith/selectors/workspaceSelectors";
import { Variant } from "components/ads/common";
import { Toaster } from "components/ads/Toast";
import { getConfigInitialValues } from "components/formControls/utils";
@@ -85,7 +85,7 @@ import { inGuidedTour } from "selectors/onboardingSelectors";
import { updateReplayEntity } from "actions/pageActions";
import OAuthApi from "api/OAuthApi";
import { AppState } from "reducers";
-import { getOrganizationIdForImport } from "selectors/applicationSelectors";
+import { getWorkspaceIdForImport } from "selectors/applicationSelectors";
import {
apiEditorIdURL,
datasourcesEditorIdURL,
@@ -95,14 +95,14 @@ import {
} from "RouteBuilder";
function* fetchDatasourcesSaga(
- action: ReduxAction<{ orgId?: string } | undefined>,
+ action: ReduxAction<{ workspaceId?: string } | undefined>,
) {
try {
- let orgId = yield select(getCurrentOrgId);
- if (action.payload?.orgId) orgId = action.payload?.orgId;
+ let workspaceId = yield select(getCurrentWorkspaceId);
+ if (action.payload?.workspaceId) workspaceId = action.payload?.workspaceId;
const response: GenericApiResponse = yield DatasourcesApi.fetchDatasources(
- orgId,
+ workspaceId,
);
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
@@ -139,7 +139,7 @@ interface addMockDb
extends ReduxActionWithCallbacks<
{
name: string;
- organizationId: string;
+ workspaceId: string;
pluginId: string;
packageName: string;
},
@@ -151,16 +151,11 @@ interface addMockDb
export function* addMockDbToDatasources(actionPayload: addMockDb) {
try {
- const {
- name,
- organizationId,
- packageName,
- pluginId,
- } = actionPayload.payload;
+ const { name, packageName, pluginId, workspaceId } = actionPayload.payload;
const { isGeneratePageMode } = actionPayload.extraParams;
const response: GenericApiResponse = yield DatasourcesApi.addMockDbToDatasources(
name,
- organizationId,
+ workspaceId,
pluginId,
packageName,
);
@@ -383,7 +378,7 @@ function* redirectAuthorizationCodeSaga(
}>,
) {
const { datasourceId, pageId, pluginType } = actionPayload.payload;
- const isImport: string = yield select(getOrganizationIdForImport);
+ const isImport: string = yield select(getWorkspaceIdForImport);
if (pluginType === PluginType.API) {
window.location.href = `/api/v1/datasources/${datasourceId}/pages/${pageId}/code`;
@@ -488,11 +483,11 @@ function* handleDatasourceNameChangeFailureSaga(
}
function* testDatasourceSaga(actionPayload: ReduxAction) {
- let organizationId = yield select(getCurrentOrgId);
+ let workspaceId = yield select(getCurrentWorkspaceId);
// test button within the import modal
- if (!organizationId) {
- organizationId = yield select(getOrganizationIdForImport);
+ if (!workspaceId) {
+ workspaceId = yield select(getWorkspaceIdForImport);
}
const { initialValues, values } = yield select(
getFormData,
@@ -513,7 +508,7 @@ function* testDatasourceSaga(actionPayload: ReduxAction) {
const response: GenericApiResponse = yield DatasourcesApi.testDatasource(
{
...payload,
- organizationId,
+ workspaceId,
},
);
const isValidResponse = yield validateResponse(response);
@@ -602,7 +597,7 @@ function* createDatasourceFromFormSaga(
actionPayload: ReduxAction,
) {
try {
- const organizationId = yield select(getCurrentOrgId);
+ const workspaceId = yield select(getCurrentWorkspaceId);
yield call(
checkAndGetPluginFormConfigsSaga,
actionPayload.payload.pluginId,
@@ -620,7 +615,7 @@ function* createDatasourceFromFormSaga(
const response: GenericApiResponse = yield DatasourcesApi.createDatasource(
{
...payload,
- organizationId,
+ workspaceId,
},
);
const isValidResponse = yield validateResponse(response);
diff --git a/app/client/src/sagas/GitSyncSagas.ts b/app/client/src/sagas/GitSyncSagas.ts
index 722cbb570a..9dbccf443d 100644
--- a/app/client/src/sagas/GitSyncSagas.ts
+++ b/app/client/src/sagas/GitSyncSagas.ts
@@ -59,7 +59,7 @@ import { Variant } from "components/ads/common";
import {
getCurrentAppGitMetaData,
getCurrentApplication,
- getOrganizationIdForImport,
+ getWorkspaceIdForImport,
} from "selectors/applicationSelectors";
import {
createMessage,
@@ -79,8 +79,8 @@ import {
import { initEditor } from "actions/initActions";
import { fetchPage } from "actions/pageActions";
import { getLogToSentryFromResponse } from "utils/helpers";
-import { getCurrentOrg } from "@appsmith/selectors/organizationSelectors";
-import { Org } from "constants/orgConstants";
+import { getCurrentWorkspace } from "@appsmith/selectors/workspaceSelectors";
+import { Workspace } from "constants/workspaceConstants";
import { log } from "loglevel";
import GIT_ERROR_CODES from "constants/GitErrorCodes";
import { builderURL } from "RouteBuilder";
@@ -639,25 +639,20 @@ function* disconnectGitSaga() {
function* importAppFromGitSaga(action: ConnectToGitReduxAction) {
let response: ApiResponse | undefined;
try {
- const organizationIdForImport: string = yield select(
- getOrganizationIdForImport,
- );
+ const workspaceIdForImport: string = yield select(getWorkspaceIdForImport);
- response = yield GitSyncAPI.importApp(
- action.payload,
- organizationIdForImport,
- );
+ response = yield GitSyncAPI.importApp(action.payload, workspaceIdForImport);
const isValidResponse: boolean = yield validateResponse(
response,
false,
getLogToSentryFromResponse(response),
);
if (isValidResponse) {
- const allOrgs = yield select(getCurrentOrg);
- const currentOrg = allOrgs.filter(
- (el: Org) => el.id === organizationIdForImport,
+ const allWorkspaces = yield select(getCurrentWorkspace);
+ const currentWorkspace = allWorkspaces.filter(
+ (el: Workspace) => el.id === workspaceIdForImport,
);
- if (currentOrg.length > 0) {
+ if (currentWorkspace.length > 0) {
const {
application: app,
isPartialImport,
@@ -679,7 +674,7 @@ function* importAppFromGitSaga(action: ConnectToGitReduxAction) {
application: response?.data?.application,
unConfiguredDatasourceList:
response?.data.unConfiguredDatasourceList,
- orgId: organizationIdForImport,
+ workspaceId: workspaceIdForImport,
}),
);
} else {
@@ -760,7 +755,7 @@ export function* generateSSHKeyPairSaga(action: GenerateSSHKeyPairReduxAction) {
let response: ApiResponse | undefined;
try {
const applicationId: string = yield select(getCurrentApplicationId);
- const isImporting: string = yield select(getOrganizationIdForImport);
+ const isImporting: string = yield select(getWorkspaceIdForImport);
response = yield call(
GitSyncAPI.generateSSHKeyPair,
diff --git a/app/client/src/sagas/JSPaneSagas.ts b/app/client/src/sagas/JSPaneSagas.ts
index 3b0922355f..cb04f96b09 100644
--- a/app/client/src/sagas/JSPaneSagas.ts
+++ b/app/client/src/sagas/JSPaneSagas.ts
@@ -44,7 +44,7 @@ import {
updateJSFunction,
executeJSFunctionInit,
} from "actions/jsPaneActions";
-import { getCurrentOrgId } from "@appsmith/selectors/organizationSelectors";
+import { getCurrentWorkspaceId } from "@appsmith/selectors/workspaceSelectors";
import { getPluginIdOfPackageName } from "sagas/selectors";
import { PluginType } from "entities/Action";
import { Toaster } from "components/ads/Toast";
@@ -77,7 +77,7 @@ import { APP_MODE } from "entities/App";
import { getAppMode } from "selectors/applicationSelectors";
function* handleCreateNewJsActionSaga(action: ReduxAction<{ pageId: string }>) {
- const organizationId: string = yield select(getCurrentOrgId);
+ const workspaceId: string = yield select(getCurrentWorkspaceId);
const applicationId = yield select(getCurrentApplicationId);
const { pageId } = action.payload;
const pluginId: string = yield select(
@@ -92,13 +92,13 @@ function* handleCreateNewJsActionSaga(action: ReduxAction<{ pageId: string }>) {
const newJSCollectionName = createNewJSFunctionName(pageJSActions, pageId);
const { actions, body } = createDummyJSCollectionActions(
pageId,
- organizationId,
+ workspaceId,
);
yield put(
createJSCollectionRequest({
name: newJSCollectionName,
pageId,
- organizationId,
+ workspaceId,
pluginId,
body: body,
variables: [
@@ -135,7 +135,7 @@ function* handleJSCollectionCreatedSaga(
function* handleEachUpdateJSCollection(update: JSUpdate) {
const jsActionId = update.id;
- const organizationId: string = yield select(getCurrentOrgId);
+ const workspaceId: string = yield select(getCurrentWorkspaceId);
if (jsActionId) {
const jsAction: JSCollection = yield select(getJSCollection, jsActionId);
const parsedBody = update.parsedBody;
@@ -173,7 +173,7 @@ function* handleEachUpdateJSCollection(update: JSUpdate) {
for (let i = 0; i < data.newActions.length; i++) {
jsActionTobeUpdated.actions.push({
...data.newActions[i],
- organizationId: organizationId,
+ workspaceId: workspaceId,
});
}
updateCollection = true;
diff --git a/app/client/src/sagas/OnboardingSagas.ts b/app/client/src/sagas/OnboardingSagas.ts
index fee0ff314f..8447229022 100644
--- a/app/client/src/sagas/OnboardingSagas.ts
+++ b/app/client/src/sagas/OnboardingSagas.ts
@@ -25,13 +25,13 @@ import TourApp from "pages/Editor/GuidedTour/app.json";
import {
getFirstTimeUserOnboardingApplicationId,
getHadReachedStep,
- getOnboardingOrganisations,
+ getOnboardingWorkspaces,
getQueryAction,
getTableWidget,
} from "selectors/onboardingSelectors";
import { Toaster } from "components/ads/Toast";
import { Variant } from "components/ads/common";
-import { Organization } from "constants/orgConstants";
+import { Workspaces } from "constants/workspaceConstants";
import {
enableGuidedTour,
focusWidgetProperty,
@@ -74,38 +74,38 @@ import { navigateToCanvas } from "pages/Editor/Explorer/Widgets/utils";
function* createApplication() {
// If we are starting onboarding from the editor wait for the editor to reset.
const isEditorInitialised = yield select(getIsEditorInitialized);
- let userOrgs: Organization[] = yield select(getOnboardingOrganisations);
+ let userWorkspaces: Workspaces[] = yield select(getOnboardingWorkspaces);
if (isEditorInitialised) {
yield take(ReduxActionTypes.RESET_EDITOR_SUCCESS);
- // If we haven't fetched the organisation list yet we wait for it to complete
- // as we need an organisation where we create an application
- if (!userOrgs.length) {
- yield take(ReduxActionTypes.FETCH_USER_APPLICATIONS_ORGS_SUCCESS);
+ // If we haven't fetched the workspace list yet we wait for it to complete
+ // as we need an workspace where we create an application
+ if (!userWorkspaces.length) {
+ yield take(ReduxActionTypes.FETCH_USER_APPLICATIONS_WORKSPACES_SUCCESS);
}
}
- userOrgs = yield select(getOnboardingOrganisations);
+ userWorkspaces = yield select(getOnboardingWorkspaces);
const currentUser = yield select(getCurrentUser);
- const currentOrganizationId = currentUser.currentOrganizationId;
- let organization;
- if (!currentOrganizationId) {
- organization = userOrgs[0];
+ const currentWorkspaceId = currentUser.currentWorkspaceId;
+ let workspace;
+ if (!currentWorkspaceId) {
+ workspace = userWorkspaces[0];
} else {
- const filteredOrganizations = userOrgs.filter(
- (org: any) => org.organization.id === currentOrganizationId,
+ const filteredWorkspaces = userWorkspaces.filter(
+ (workspace: any) => workspace.workspace.id === currentWorkspaceId,
);
- organization = filteredOrganizations[0];
+ workspace = filteredWorkspaces[0];
}
- if (organization) {
+ if (workspace) {
const appFileObject = new File([JSON.stringify(TourApp)], "app.json", {
type: "application/json",
});
yield put(enableGuidedTour(true));
yield put(
importApplication({
- orgId: organization.organization.id,
+ workspaceId: workspace.workspace.id,
applicationFile: appFileObject,
}),
);
diff --git a/app/client/src/sagas/PageSagas.tsx b/app/client/src/sagas/PageSagas.tsx
index d093efd39b..c32e8cee6e 100644
--- a/app/client/src/sagas/PageSagas.tsx
+++ b/app/client/src/sagas/PageSagas.tsx
@@ -138,7 +138,7 @@ export function* fetchPageListSaga(
const response: FetchPageListResponse = yield call(apiCall, applicationId);
const isValidResponse: boolean = yield validateResponse(response);
if (isValidResponse) {
- const orgId = response.data.organizationId;
+ const workspaceId = response.data.workspaceId;
const pages: PageListPayload = response.data.pages.map((page) => ({
pageName: page.name,
pageId: page.id,
@@ -147,9 +147,9 @@ export function* fetchPageListSaga(
slug: page.slug,
}));
yield put({
- type: ReduxActionTypes.SET_CURRENT_ORG_ID,
+ type: ReduxActionTypes.SET_CURRENT_WORKSPACE_ID,
payload: {
- orgId,
+ workspaceId,
},
});
yield put({
diff --git a/app/client/src/sagas/PluginSagas.ts b/app/client/src/sagas/PluginSagas.ts
index e9976717b3..da701afbee 100644
--- a/app/client/src/sagas/PluginSagas.ts
+++ b/app/client/src/sagas/PluginSagas.ts
@@ -6,7 +6,7 @@ import {
} from "@appsmith/constants/ReduxActionConstants";
import PluginsApi, { PluginFormPayload } from "api/PluginApi";
import { validateResponse } from "sagas/ErrorSagas";
-import { getCurrentOrgId } from "@appsmith/selectors/organizationSelectors";
+import { getCurrentWorkspaceId } from "@appsmith/selectors/workspaceSelectors";
import {
getDatasources,
getPlugin,
@@ -38,16 +38,16 @@ import {
} from "utils/DynamicBindingUtils";
function* fetchPluginsSaga(
- action: ReduxAction<{ orgId?: string } | undefined>,
+ action: ReduxAction<{ workspaceId?: string } | undefined>,
) {
try {
- let orgId = yield select(getCurrentOrgId);
- if (action.payload?.orgId) orgId = action.payload?.orgId;
+ let workspaceId = yield select(getCurrentWorkspaceId);
+ if (action.payload?.workspaceId) workspaceId = action.payload?.workspaceId;
- if (!orgId) {
+ if (!workspaceId) {
throw Error("Org id does not exist");
}
- const pluginsResponse = yield call(PluginsApi.fetchPlugins, orgId);
+ const pluginsResponse = yield call(PluginsApi.fetchPlugins, workspaceId);
const isValid = yield validateResponse(pluginsResponse);
if (isValid) {
yield put({
@@ -67,7 +67,7 @@ function* fetchPluginFormConfigsSaga() {
try {
const datasources: Datasource[] = yield select(getDatasources);
const plugins: Plugin[] = yield select(getPlugins);
- // Add plugins of all the datasources of their org
+ // Add plugins of all the datasources of their workspace
const pluginIdFormsToFetch = new Set(
datasources.map((datasource) => datasource.pluginId),
);
diff --git a/app/client/src/sagas/ProvidersSaga.ts b/app/client/src/sagas/ProvidersSaga.ts
index 5a67bc6f0d..b3346284d7 100644
--- a/app/client/src/sagas/ProvidersSaga.ts
+++ b/app/client/src/sagas/ProvidersSaga.ts
@@ -36,7 +36,7 @@ import {
createMessage,
} from "@appsmith/constants/messages";
import AnalyticsUtil from "utils/AnalyticsUtil";
-import { getCurrentOrgId } from "@appsmith/selectors/organizationSelectors";
+import { getCurrentWorkspaceId } from "@appsmith/selectors/workspaceSelectors";
import { Toaster } from "components/ads/Toast";
import { Variant } from "components/ads/common";
@@ -72,10 +72,10 @@ export function* fetchProviderTemplatesSaga(
export function* addApiToPageSaga(
action: ReduxActionWithPromise,
) {
- const organizationId = yield select(getCurrentOrgId);
+ const workspaceId = yield select(getCurrentWorkspaceId);
const request: AddApiToPageRequest = {
...action.payload,
- organizationId,
+ workspaceId,
};
try {
const response: FetchProviderTemplateResponse = yield ProvidersApi.addApiToPage(
diff --git a/app/client/src/sagas/TemplatesSagas.ts b/app/client/src/sagas/TemplatesSagas.ts
index 9668a3f6df..4d5f9c74e0 100644
--- a/app/client/src/sagas/TemplatesSagas.ts
+++ b/app/client/src/sagas/TemplatesSagas.ts
@@ -37,14 +37,14 @@ function* getAllTemplatesSaga() {
}
}
-function* importTemplateToOrganisationSaga(
- action: ReduxAction<{ templateId: string; organizationId: string }>,
+function* importTemplateToWorkspaceSaga(
+ action: ReduxAction<{ templateId: string; workspaceId: string }>,
) {
try {
const response: ImportTemplateResponse = yield call(
TemplatesAPI.importTemplate,
action.payload.templateId,
- action.payload.organizationId,
+ action.payload.workspaceId,
);
const isValid: boolean = yield validateResponse(response);
if (isValid) {
@@ -62,14 +62,14 @@ function* importTemplateToOrganisationSaga(
pageId: application.defaultPageId,
});
yield put({
- type: ReduxActionTypes.IMPORT_TEMPLATE_TO_ORGANISATION_SUCCESS,
+ type: ReduxActionTypes.IMPORT_TEMPLATE_TO_WORKSPACE_SUCCESS,
payload: response.data,
});
history.push(pageURL);
}
} catch (error) {
yield put({
- type: ReduxActionErrorTypes.IMPORT_TEMPLATE_TO_ORGANISATION_ERROR,
+ type: ReduxActionErrorTypes.IMPORT_TEMPLATE_TO_WORKSPACE_ERROR,
payload: {
error,
},
@@ -146,8 +146,8 @@ export default function* watchActionSagas() {
getSimilarTemplatesSaga,
),
takeEvery(
- ReduxActionTypes.IMPORT_TEMPLATE_TO_ORGANISATION_INIT,
- importTemplateToOrganisationSaga,
+ ReduxActionTypes.IMPORT_TEMPLATE_TO_WORKSPACE_INIT,
+ importTemplateToWorkspaceSaga,
),
takeEvery(
ReduxActionTypes.GET_TEMPLATE_NOTIFICATION_SEEN,
diff --git a/app/client/src/sagas/WidgetOperationUtils.test.ts b/app/client/src/sagas/WidgetOperationUtils.test.ts
index 9206598e78..2623f7cd93 100644
--- a/app/client/src/sagas/WidgetOperationUtils.test.ts
+++ b/app/client/src/sagas/WidgetOperationUtils.test.ts
@@ -222,6 +222,57 @@ describe("WidgetOperationSaga", () => {
);
});
+ it("handleSpecificCasesWhilePasting should rename dynamicTriggerPathList template keys for a copied list widget", async () => {
+ const result = handleSpecificCasesWhilePasting(
+ {
+ widgetId: "list2",
+ type: "LIST_WIDGET",
+ widgetName: "List2",
+ parentId: "0",
+ renderMode: "CANVAS",
+ parentColumnSpace: 2,
+ parentRowSpace: 3,
+ leftColumn: 2,
+ rightColumn: 3,
+ topRow: 1,
+ bottomRow: 3,
+ isLoading: false,
+ listData: [],
+ version: 16,
+ disablePropertyPane: false,
+ template: {
+ Image1: {
+ widgetId: "image1",
+ type: "Image_WIDGET",
+ widgetName: "Image1",
+ parentId: "list2",
+ renderMode: "CANVAS",
+ parentColumnSpace: 2,
+ parentRowSpace: 3,
+ leftColumn: 2,
+ rightColumn: 3,
+ topRow: 1,
+ bottomRow: 3,
+ isLoading: false,
+ listData: [],
+ version: 16,
+ disablePropertyPane: false,
+ dynamicTriggerPathList: [{ key: "onClick" }],
+ },
+ },
+ dynamicTriggerPathList: [{ key: "template.Image1.onClick" }],
+ },
+ {},
+ {
+ Image1: "Image1Copy",
+ },
+ [],
+ );
+ expect(get(result, "list2.dynamicTriggerPathList.0.key")).toStrictEqual(
+ "template.Image1Copy.onClick",
+ );
+ });
+
it("should return correct close modal reference name after executing handleSpecificCasesWhilePasting", async () => {
const result = handleSpecificCasesWhilePasting(
{
diff --git a/app/client/src/sagas/WidgetOperationUtils.ts b/app/client/src/sagas/WidgetOperationUtils.ts
index 94d0546d90..cd028f8a70 100644
--- a/app/client/src/sagas/WidgetOperationUtils.ts
+++ b/app/client/src/sagas/WidgetOperationUtils.ts
@@ -208,7 +208,7 @@ export const handleSpecificCasesWhilePasting = (
}
}
- // updating dynamicBindingPath in copied widget if the copied widge thas reference to oldWidgetNames
+ // updating dynamicBindingPath in copied widget if the copied widget thas reference to oldWidgetNames
widget.dynamicBindingPathList = (widget.dynamicBindingPathList || []).map(
(path: any) => {
if (path.key.startsWith(`template.${oldWidgetName}`)) {
@@ -223,6 +223,22 @@ export const handleSpecificCasesWhilePasting = (
return path;
},
);
+
+ // updating dynamicTriggerPath in copied widget if the copied widget thas reference to oldWidgetNames
+ widget.dynamicTriggerPathList = (widget.dynamicTriggerPathList || []).map(
+ (path: any) => {
+ if (path.key.startsWith(`template.${oldWidgetName}`)) {
+ return {
+ key: path.key.replace(
+ `template.${oldWidgetName}`,
+ `template.${newWidgetName}`,
+ ),
+ };
+ }
+
+ return path;
+ },
+ );
});
widgets[widget.widgetId] = widget;
diff --git a/app/client/src/sagas/OrgSagas.ts b/app/client/src/sagas/WorkspaceSagas.ts
similarity index 55%
rename from app/client/src/sagas/OrgSagas.ts
rename to app/client/src/sagas/WorkspaceSagas.ts
index 0703be255a..068eef076e 100644
--- a/app/client/src/sagas/OrgSagas.ts
+++ b/app/client/src/sagas/WorkspaceSagas.ts
@@ -10,49 +10,51 @@ import {
callAPI,
getResponseErrorMessage,
} from "sagas/ErrorSagas";
-import OrgApi, {
- FetchOrgRolesResponse,
- SaveOrgRequest,
- FetchOrgRequest,
- FetchOrgResponse,
- CreateOrgRequest,
+import WorkspaceApi, {
+ FetchWorkspaceRolesResponse,
+ SaveWorkspaceRequest,
+ FetchWorkspaceRequest,
+ FetchWorkspaceResponse,
+ CreateWorkspaceRequest,
FetchAllUsersResponse,
FetchAllUsersRequest,
FetchAllRolesResponse,
- DeleteOrgUserRequest,
+ DeleteWorkspaceUserRequest,
ChangeUserRoleRequest,
FetchAllRolesRequest,
- SaveOrgLogo,
-} from "api/OrgApi";
+ SaveWorkspaceLogo,
+} from "api/WorkspaceApi";
import { ApiResponse } from "api/ApiResponses";
import { Toaster } from "components/ads/Toast";
import { Variant } from "components/ads/common";
-import { getCurrentOrg } from "@appsmith/selectors/organizationSelectors";
+import { getCurrentWorkspace } from "@appsmith/selectors/workspaceSelectors";
import { getCurrentUser } from "selectors/usersSelectors";
-import { Org } from "constants/orgConstants";
+import { Workspace } from "constants/workspaceConstants";
import history from "utils/history";
import { APPLICATIONS_URL } from "constants/routes";
import { getAllApplications } from "actions/applicationActions";
import log from "loglevel";
import {
createMessage,
- DELETE_ORG_SUCCESSFUL,
+ DELETE_WORKSPACE_SUCCESSFUL,
} from "@appsmith/constants/messages";
export function* fetchRolesSaga() {
try {
- const response: FetchOrgRolesResponse = yield call(OrgApi.fetchRoles);
+ const response: FetchWorkspaceRolesResponse = yield call(
+ WorkspaceApi.fetchRoles,
+ );
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
yield put({
- type: ReduxActionTypes.FETCH_ORG_ROLES_SUCCESS,
+ type: ReduxActionTypes.FETCH_WORKSPACE_ROLES_SUCCESS,
payload: response.data,
});
}
} catch (error) {
log.error(error);
yield put({
- type: ReduxActionErrorTypes.FETCH_ORG_ROLES_ERROR,
+ type: ReduxActionErrorTypes.FETCH_WORKSPACE_ROLES_ERROR,
payload: {
error,
},
@@ -60,21 +62,26 @@ export function* fetchRolesSaga() {
}
}
-export function* fetchOrgSaga(action: ReduxAction) {
+export function* fetchWorkspaceSaga(
+ action: ReduxAction,
+) {
try {
- const request: FetchOrgRequest = action.payload;
- const response: FetchOrgResponse = yield call(OrgApi.fetchOrg, request);
+ const request: FetchWorkspaceRequest = action.payload;
+ const response: FetchWorkspaceResponse = yield call(
+ WorkspaceApi.fetchWorkspace,
+ request,
+ );
const isValidResponse = yield request.skipValidation ||
validateResponse(response);
if (isValidResponse) {
yield put({
- type: ReduxActionTypes.FETCH_ORG_SUCCESS,
+ type: ReduxActionTypes.FETCH_WORKSPACE_SUCCESS,
payload: response.data || {},
});
}
} catch (error) {
yield put({
- type: ReduxActionErrorTypes.FETCH_ORG_ERROR,
+ type: ReduxActionErrorTypes.FETCH_WORKSPACE_ERROR,
payload: {
error,
},
@@ -86,7 +93,7 @@ export function* fetchAllUsersSaga(action: ReduxAction) {
try {
const request: FetchAllUsersRequest = action.payload;
const response: FetchAllUsersResponse = yield call(
- OrgApi.fetchAllUsers,
+ WorkspaceApi.fetchAllUsers,
request,
);
const isValidResponse = yield validateResponse(response);
@@ -111,22 +118,25 @@ export function* fetchAllUsersSaga(action: ReduxAction) {
}
}
-export function* changeOrgUserRoleSaga(
+export function* changeWorkspaceUserRoleSaga(
action: ReduxAction,
) {
try {
const request: ChangeUserRoleRequest = action.payload;
- const response: ApiResponse = yield call(OrgApi.changeOrgUserRole, request);
+ const response: ApiResponse = yield call(
+ WorkspaceApi.changeWorkspaceUserRole,
+ request,
+ );
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
yield put({
- type: ReduxActionTypes.CHANGE_ORG_USER_ROLE_SUCCESS,
+ type: ReduxActionTypes.CHANGE_WORKSPACE_USER_ROLE_SUCCESS,
payload: response.data,
});
}
} catch (error) {
yield put({
- type: ReduxActionErrorTypes.CHANGE_ORG_USER_ROLE_ERROR,
+ type: ReduxActionErrorTypes.CHANGE_WORKSPACE_USER_ROLE_ERROR,
payload: {
error,
},
@@ -134,10 +144,15 @@ export function* changeOrgUserRoleSaga(
}
}
-export function* deleteOrgUserSaga(action: ReduxAction) {
+export function* deleteWorkspaceUserSaga(
+ action: ReduxAction,
+) {
try {
- const request: DeleteOrgUserRequest = action.payload;
- const response: ApiResponse = yield call(OrgApi.deleteOrgUser, request);
+ const request: DeleteWorkspaceUserRequest = action.payload;
+ const response: ApiResponse = yield call(
+ WorkspaceApi.deleteWorkspaceUser,
+ request,
+ );
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
const currentUser = yield select(getCurrentUser);
@@ -145,7 +160,7 @@ export function* deleteOrgUserSaga(action: ReduxAction) {
history.replace(APPLICATIONS_URL);
} else {
yield put({
- type: ReduxActionTypes.DELETE_ORG_USER_SUCCESS,
+ type: ReduxActionTypes.DELETE_WORKSPACE_USER_SUCCESS,
payload: {
username: action.payload.username,
},
@@ -158,7 +173,7 @@ export function* deleteOrgUserSaga(action: ReduxAction) {
}
} catch (error) {
yield put({
- type: ReduxActionErrorTypes.DELETE_ORG_USER_ERROR,
+ type: ReduxActionErrorTypes.DELETE_WORKSPACE_USER_ERROR,
payload: {
error,
},
@@ -170,7 +185,7 @@ export function* fetchAllRolesSaga(action: ReduxAction) {
try {
const request: FetchAllRolesRequest = action.payload;
const response: FetchAllRolesResponse = yield call(
- OrgApi.fetchAllRoles,
+ WorkspaceApi.fetchAllRoles,
request,
);
const isValidResponse = yield validateResponse(response);
@@ -187,20 +202,23 @@ export function* fetchAllRolesSaga(action: ReduxAction) {
}
}
-export function* saveOrgSaga(action: ReduxAction) {
+export function* saveWorkspaceSaga(action: ReduxAction) {
try {
- const request: SaveOrgRequest = action.payload;
- const response: ApiResponse = yield call(OrgApi.saveOrg, request);
+ const request: SaveWorkspaceRequest = action.payload;
+ const response: ApiResponse = yield call(
+ WorkspaceApi.saveWorkspace,
+ request,
+ );
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
yield put({
- type: ReduxActionTypes.SAVE_ORG_SUCCESS,
+ type: ReduxActionTypes.SAVE_WORKSPACE_SUCCESS,
payload: request,
});
}
} catch (error) {
yield put({
- type: ReduxActionErrorTypes.SAVE_ORG_ERROR,
+ type: ReduxActionErrorTypes.SAVE_WORKSPACE_ERROR,
payload: {
error: error.message,
},
@@ -208,27 +226,30 @@ export function* saveOrgSaga(action: ReduxAction) {
}
}
-export function* deleteOrgSaga(action: ReduxAction) {
+export function* deleteWorkspaceSaga(action: ReduxAction) {
try {
yield put({
- type: ReduxActionTypes.SAVING_ORG_INFO,
+ type: ReduxActionTypes.SAVING_WORKSPACE_INFO,
});
- const orgId: string = action.payload;
- const response: ApiResponse = yield call(OrgApi.deleteOrg, orgId);
+ const workspaceId: string = action.payload;
+ const response: ApiResponse = yield call(
+ WorkspaceApi.deleteWorkspace,
+ workspaceId,
+ );
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
yield put({
- type: ReduxActionTypes.DELETE_ORG_SUCCESS,
- payload: orgId,
+ type: ReduxActionTypes.DELETE_WORKSPACE_SUCCESS,
+ payload: workspaceId,
});
Toaster.show({
- text: createMessage(DELETE_ORG_SUCCESSFUL),
+ text: createMessage(DELETE_WORKSPACE_SUCCESSFUL),
variant: Variant.success,
});
}
} catch (error) {
yield put({
- type: ReduxActionErrorTypes.DELETE_ORG_ERROR,
+ type: ReduxActionErrorTypes.DELETE_WORKSPACE_ERROR,
payload: {
error: error.message,
},
@@ -236,20 +257,23 @@ export function* deleteOrgSaga(action: ReduxAction) {
}
}
-export function* createOrgSaga(
- action: ReduxActionWithPromise,
+export function* createWorkspaceSaga(
+ action: ReduxActionWithPromise,
) {
const { name, reject, resolve } = action.payload;
try {
- const request: CreateOrgRequest = { name };
- const response: ApiResponse = yield callAPI(OrgApi.createOrg, request);
+ const request: CreateWorkspaceRequest = { name };
+ const response: ApiResponse = yield callAPI(
+ WorkspaceApi.createWorkspace,
+ request,
+ );
const isValidResponse = yield validateResponse(response);
if (!isValidResponse) {
const errorMessage = yield getResponseErrorMessage(response);
yield call(reject, { _error: errorMessage });
} else {
yield put({
- type: ReduxActionTypes.CREATE_ORGANIZATION_SUCCESS,
+ type: ReduxActionTypes.CREATE_WORKSPACE_SUCCESS,
payload: response.data,
});
@@ -257,13 +281,13 @@ export function* createOrgSaga(
yield call(resolve);
}
- // get created org in focus
- const orgId = response.data.id;
- history.push(`${window.location.pathname}#${orgId}`);
+ // get created worskpace in focus
+ const workspaceId = response.data.id;
+ history.push(`${window.location.pathname}#${workspaceId}`);
} catch (error) {
yield call(reject, { _error: error.message });
yield put({
- type: ReduxActionErrorTypes.CREATE_ORGANIZATION_ERROR,
+ type: ReduxActionErrorTypes.CREATE_WORKSPACE_ERROR,
payload: {
error,
},
@@ -271,19 +295,26 @@ export function* createOrgSaga(
}
}
-export function* uploadOrgLogoSaga(action: ReduxAction) {
+export function* uploadWorkspaceLogoSaga(
+ action: ReduxAction,
+) {
try {
const request = action.payload;
- const response: ApiResponse = yield call(OrgApi.saveOrgLogo, request);
+ const response: ApiResponse = yield call(
+ WorkspaceApi.saveWorkspaceLogo,
+ request,
+ );
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
- const allOrgs = yield select(getCurrentOrg);
- const currentOrg = allOrgs.filter((el: Org) => el.id === request.id);
- if (currentOrg.length > 0) {
+ const allWorkspaces = yield select(getCurrentWorkspace);
+ const currentWorkspace = allWorkspaces.filter(
+ (el: Workspace) => el.id === request.id,
+ );
+ if (currentWorkspace.length > 0) {
yield put({
- type: ReduxActionTypes.SAVE_ORG_SUCCESS,
+ type: ReduxActionTypes.SAVE_WORKSPACE_SUCCESS,
payload: {
- id: currentOrg[0].id,
+ id: currentWorkspace[0].id,
logoUrl: response.data.logoUrl,
},
});
@@ -298,19 +329,24 @@ export function* uploadOrgLogoSaga(action: ReduxAction) {
}
}
-export function* deleteOrgLogoSaga(action: ReduxAction<{ id: string }>) {
+export function* deleteWorkspaceLogoSaga(action: ReduxAction<{ id: string }>) {
try {
const request = action.payload;
- const response: ApiResponse = yield call(OrgApi.deleteOrgLogo, request);
+ const response: ApiResponse = yield call(
+ WorkspaceApi.deleteWorkspaceLogo,
+ request,
+ );
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
- const allOrgs = yield select(getCurrentOrg);
- const currentOrg = allOrgs.filter((el: Org) => el.id === request.id);
- if (currentOrg.length > 0) {
+ const allWorkspaces = yield select(getCurrentWorkspace);
+ const currentWorkspace = allWorkspaces.filter(
+ (el: Workspace) => el.id === request.id,
+ );
+ if (currentWorkspace.length > 0) {
yield put({
- type: ReduxActionTypes.SAVE_ORG_SUCCESS,
+ type: ReduxActionTypes.SAVE_WORKSPACE_SUCCESS,
payload: {
- id: currentOrg[0].id,
+ id: currentWorkspace[0].id,
logoUrl: response.data.logoUrl,
},
});
@@ -325,21 +361,24 @@ export function* deleteOrgLogoSaga(action: ReduxAction<{ id: string }>) {
}
}
-export default function* orgSagas() {
+export default function* workspaceSagas() {
yield all([
- takeLatest(ReduxActionTypes.FETCH_ORG_ROLES_INIT, fetchRolesSaga),
- takeLatest(ReduxActionTypes.FETCH_CURRENT_ORG, fetchOrgSaga),
- takeLatest(ReduxActionTypes.SAVE_ORG_INIT, saveOrgSaga),
- takeLatest(ReduxActionTypes.CREATE_ORGANIZATION_INIT, createOrgSaga),
+ takeLatest(ReduxActionTypes.FETCH_WORKSPACE_ROLES_INIT, fetchRolesSaga),
+ takeLatest(ReduxActionTypes.FETCH_CURRENT_WORKSPACE, fetchWorkspaceSaga),
+ takeLatest(ReduxActionTypes.SAVE_WORKSPACE_INIT, saveWorkspaceSaga),
+ takeLatest(ReduxActionTypes.CREATE_WORKSPACE_INIT, createWorkspaceSaga),
takeLatest(ReduxActionTypes.FETCH_ALL_USERS_INIT, fetchAllUsersSaga),
takeLatest(ReduxActionTypes.FETCH_ALL_ROLES_INIT, fetchAllRolesSaga),
- takeLatest(ReduxActionTypes.DELETE_ORG_USER_INIT, deleteOrgUserSaga),
takeLatest(
- ReduxActionTypes.CHANGE_ORG_USER_ROLE_INIT,
- changeOrgUserRoleSaga,
+ ReduxActionTypes.DELETE_WORKSPACE_USER_INIT,
+ deleteWorkspaceUserSaga,
),
- takeLatest(ReduxActionTypes.DELETE_ORG_INIT, deleteOrgSaga),
- takeLatest(ReduxActionTypes.UPLOAD_ORG_LOGO, uploadOrgLogoSaga),
- takeLatest(ReduxActionTypes.REMOVE_ORG_LOGO, deleteOrgLogoSaga),
+ takeLatest(
+ ReduxActionTypes.CHANGE_WORKSPACE_USER_ROLE_INIT,
+ changeWorkspaceUserRoleSaga,
+ ),
+ takeLatest(ReduxActionTypes.DELETE_WORKSPACE_INIT, deleteWorkspaceSaga),
+ takeLatest(ReduxActionTypes.UPLOAD_WORKSPACE_LOGO, uploadWorkspaceLogoSaga),
+ takeLatest(ReduxActionTypes.REMOVE_WORKSPACE_LOGO, deleteWorkspaceLogoSaga),
]);
}
diff --git a/app/client/src/sagas/index.tsx b/app/client/src/sagas/index.tsx
index 4bef0e0edc..ffcb54c1e5 100644
--- a/app/client/src/sagas/index.tsx
+++ b/app/client/src/sagas/index.tsx
@@ -14,7 +14,7 @@ import apiPaneSagas from "./ApiPaneSagas";
import jsPaneSagas from "./JSPaneSagas";
import userSagas from "./userSagas";
import pluginSagas from "./PluginSagas";
-import orgSagas from "./OrgSagas";
+import workspaceSagas from "./WorkspaceSagas";
import importedCollectionsSagas from "./CollectionSagas";
import providersSagas from "./ProvidersSaga";
import curlImportSagas from "./CurlImportSagas";
@@ -62,7 +62,7 @@ const sagas = [
userSagas,
templateSagas,
pluginSagas,
- orgSagas,
+ workspaceSagas,
importedCollectionsSagas,
providersSagas,
curlImportSagas,
diff --git a/app/client/src/sagas/userSagas.tsx b/app/client/src/sagas/userSagas.tsx
index 49fba2b60f..389e05133e 100644
--- a/app/client/src/sagas/userSagas.tsx
+++ b/app/client/src/sagas/userSagas.tsx
@@ -13,7 +13,7 @@ import UserApi, {
VerifyTokenRequest,
TokenPasswordUpdateRequest,
UpdateUserRequest,
- LeaveOrgRequest,
+ LeaveWorkspaceRequest,
} from "@appsmith/api/UserApi";
import { AUTH_LOGIN_URL, SETUP } from "constants/routes";
import history from "utils/history";
@@ -34,7 +34,7 @@ import {
fetchFeatureFlagsError,
} from "actions/userActions";
import AnalyticsUtil from "utils/AnalyticsUtil";
-import { INVITE_USERS_TO_ORG_FORM } from "constants/forms";
+import { INVITE_USERS_TO_WORKSPACE_FORM } from "constants/forms";
import PerformanceTracker, {
PerformanceTransactionName,
} from "utils/PerformanceTracker";
@@ -242,7 +242,7 @@ export function* invitedUserSignupSaga(
type InviteUserPayload = {
email: string;
- orgId: string;
+ workspaceId: string;
roleName: string;
};
@@ -259,14 +259,14 @@ export function* inviteUser(payload: InviteUserPayload, reject: any) {
export function* inviteUsers(
action: ReduxActionWithPromise<{
- data: { usernames: string[]; orgId: string; roleName: string };
+ data: { usernames: string[]; workspaceId: string; roleName: string };
}>,
) {
const { data, reject, resolve } = action.payload;
try {
const response: ApiResponse = yield callAPI(UserApi.inviteUser, {
usernames: data.usernames,
- orgId: data.orgId,
+ workspaceId: data.workspaceId,
roleName: data.roleName,
});
const isValidResponse = yield validateResponse(response);
@@ -278,13 +278,13 @@ export function* inviteUsers(
yield put({
type: ReduxActionTypes.FETCH_ALL_USERS_INIT,
payload: {
- orgId: data.orgId,
+ workspaceId: data.workspaceId,
},
});
yield put({
- type: ReduxActionTypes.INVITED_USERS_TO_ORGANIZATION,
+ type: ReduxActionTypes.INVITED_USERS_TO_WORKSPACE,
payload: {
- orgId: data.orgId,
+ workspaceId: data.workspaceId,
users: data.usernames.map((name: string) => ({
username: name,
roleName: data.roleName,
@@ -292,11 +292,11 @@ export function* inviteUsers(
},
});
yield call(resolve);
- yield put(reset(INVITE_USERS_TO_ORG_FORM));
+ yield put(reset(INVITE_USERS_TO_WORKSPACE_FORM));
} catch (error) {
yield call(reject, { _error: error.message });
yield put({
- type: ReduxActionErrorTypes.INVITE_USERS_TO_ORG_ERROR,
+ type: ReduxActionErrorTypes.INVITE_USERS_TO_WORKSPACE_ERROR,
payload: {
error,
},
@@ -475,7 +475,7 @@ export default function* userSagas() {
ReduxActionTypes.RESET_PASSWORD_VERIFY_TOKEN_INIT,
verifyResetPasswordTokenSaga,
),
- takeLatest(ReduxActionTypes.INVITE_USERS_TO_ORG_INIT, inviteUsers),
+ takeLatest(ReduxActionTypes.INVITE_USERS_TO_WORKSPACE_INIT, inviteUsers),
takeLatest(ReduxActionTypes.LOGOUT_USER_INIT, logoutSaga),
takeLatest(ReduxActionTypes.VERIFY_INVITE_INIT, verifyUserInviteSaga),
takeLatest(
@@ -488,7 +488,7 @@ export default function* userSagas() {
),
takeLatest(ReduxActionTypes.REMOVE_PROFILE_PHOTO, removePhoto),
takeLatest(ReduxActionTypes.UPLOAD_PROFILE_PHOTO, updatePhoto),
- takeLatest(ReduxActionTypes.LEAVE_ORG_INIT, leaveOrgSaga),
+ takeLatest(ReduxActionTypes.LEAVE_WORKSPACE_INIT, leaveWorkspaceSaga),
takeLatest(ReduxActionTypes.FETCH_FEATURE_FLAGS_INIT, fetchFeatureFlags),
takeLatest(
ReduxActionTypes.FETCH_USER_DETAILS_SUCCESS,
@@ -501,10 +501,12 @@ export default function* userSagas() {
]);
}
-export function* leaveOrgSaga(action: ReduxAction) {
+export function* leaveWorkspaceSaga(
+ action: ReduxAction,
+) {
try {
- const request: LeaveOrgRequest = action.payload;
- const response: ApiResponse = yield call(UserApi.leaveOrg, request);
+ const request: LeaveWorkspaceRequest = action.payload;
+ const response: ApiResponse = yield call(UserApi.leaveWorkspace, request);
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
yield put({
diff --git a/app/client/src/selectors/applicationSelectors.tsx b/app/client/src/selectors/applicationSelectors.tsx
index c0b81b6b8f..989d874199 100644
--- a/app/client/src/selectors/applicationSelectors.tsx
+++ b/app/client/src/selectors/applicationSelectors.tsx
@@ -6,10 +6,10 @@ import {
} from "reducers/uiReducers/applicationsReducer";
import {
ApplicationPayload,
- OrganizationDetails,
+ WorkspaceDetails,
} from "@appsmith/constants/ReduxActionConstants";
import Fuse from "fuse.js";
-import { Organization } from "constants/orgConstants";
+import { Workspaces } from "constants/workspaceConstants";
import { GitApplicationMetadata } from "api/ApplicationApi";
import {
isPermitted,
@@ -17,7 +17,7 @@ import {
} from "pages/Applications/permissionHelpers";
const fuzzySearchOptions = {
- keys: ["applications.name", "organization.name"],
+ keys: ["applications.name", "workspace.name"],
shouldSort: true,
threshold: 0.5,
location: 0,
@@ -43,8 +43,8 @@ export const getIsSavingAppName = (state: AppState) =>
state.ui.applications.isSavingAppName;
export const getIsErroredSavingAppName = (state: AppState) =>
state.ui.applications.isErrorSavingAppName;
-export const getUserApplicationsOrgs = (state: AppState) => {
- return state.ui.applications.userOrgs;
+export const getUserApplicationsWorkspaces = (state: AppState) => {
+ return state.ui.applications.userWorkspaces;
};
export const getImportedCollections = (state: AppState) =>
@@ -83,40 +83,40 @@ export const getApplicationList = createSelector(
},
);
-export const getUserApplicationsOrgsList = createSelector(
- getUserApplicationsOrgs,
+export const getUserApplicationsWorkspacesList = createSelector(
+ getUserApplicationsWorkspaces,
getApplicationSearchKeyword,
(
- applicationsOrgs?: Organization[],
+ applicationsWorkspaces?: Workspaces[],
keyword?: string,
- ): OrganizationDetails[] => {
+ ): WorkspaceDetails[] => {
if (
- applicationsOrgs &&
- applicationsOrgs.length > 0 &&
+ applicationsWorkspaces &&
+ applicationsWorkspaces.length > 0 &&
keyword &&
keyword.trim().length > 0
) {
- const fuzzy = new Fuse(applicationsOrgs, fuzzySearchOptions);
- let organizationList = fuzzy.search(keyword) as OrganizationDetails[];
- organizationList = organizationList.map((org) => {
- const applicationFuzzy = new Fuse(org.applications, {
+ const fuzzy = new Fuse(applicationsWorkspaces, fuzzySearchOptions);
+ let workspaceList = fuzzy.search(keyword) as WorkspaceDetails[];
+ workspaceList = workspaceList.map((workspace) => {
+ const applicationFuzzy = new Fuse(workspace.applications, {
...fuzzySearchOptions,
keys: ["name"],
});
const applications = applicationFuzzy.search(keyword) as any[];
return {
- ...org,
+ ...workspace,
applications,
};
});
- return organizationList;
+ return workspaceList;
} else if (
- applicationsOrgs &&
+ applicationsWorkspaces &&
(keyword === undefined || keyword.trim().length === 0)
) {
- return applicationsOrgs;
+ return applicationsWorkspaces;
}
return [];
},
@@ -152,8 +152,8 @@ export const getCurrentAppGitMetaData = createSelector(
currentApplication?.gitApplicationMetadata,
);
-export const getIsSavingOrgInfo = (state: AppState) =>
- state.ui.applications.isSavingOrgInfo;
+export const getIsSavingWorkspaceInfo = (state: AppState) =>
+ state.ui.applications.isSavingWorkspaceInfo;
export const showAppInviteUsersDialogSelector = (state: AppState) =>
state.ui.applications.showAppInviteUsersDialog;
@@ -164,19 +164,19 @@ export const getIsDatasourceConfigForImportFetched = (state: AppState) =>
export const getIsImportingApplication = (state: AppState) =>
state.ui.applications.importingApplication;
-export const getOrganizationIdForImport = (state: AppState) =>
- state.ui.applications.organizationIdForImport;
+export const getWorkspaceIdForImport = (state: AppState) =>
+ state.ui.applications.workspaceIdForImport;
export const getImportedApplication = (state: AppState) =>
state.ui.applications.importedApplication;
-// Get organization list where user can create applications
-export const getOrganizationCreateApplication = createSelector(
- getUserApplicationsOrgs,
- (userOrgs) => {
- return userOrgs.filter((userOrg) =>
+// Get workspace list where user can create applications
+export const getWorkspaceCreateApplication = createSelector(
+ getUserApplicationsWorkspaces,
+ (userWorkspaces) => {
+ return userWorkspaces.filter((userWorkspace) =>
isPermitted(
- userOrg.organization.userPermissions || [],
+ userWorkspace.workspace.userPermissions || [],
PERMISSION_TYPE.CREATE_APPLICATION,
),
);
diff --git a/app/client/src/selectors/editorSelectors.tsx b/app/client/src/selectors/editorSelectors.tsx
index fc434306e3..f246b308de 100644
--- a/app/client/src/selectors/editorSelectors.tsx
+++ b/app/client/src/selectors/editorSelectors.tsx
@@ -2,7 +2,7 @@ import { createSelector } from "reselect";
import { AppState } from "reducers";
import { WidgetConfigReducerState } from "reducers/entityReducers/widgetConfigReducer";
-import { WidgetProps } from "widgets/BaseWidget";
+import { WidgetCardProps, WidgetProps } from "widgets/BaseWidget";
import {
CanvasWidgetsReduxState,
FlattenedWidgetProps,
@@ -206,7 +206,7 @@ export const getWidgetCards = createSelector(
(config) => !config.hideCard,
);
- const _cards = cards.map((config) => {
+ const _cards: WidgetCardProps[] = cards.map((config) => {
const {
columns,
detachFromLayout = false,
@@ -214,6 +214,7 @@ export const getWidgetCards = createSelector(
iconSVG,
key,
rows,
+ searchTags,
type,
} = config;
return {
@@ -224,6 +225,7 @@ export const getWidgetCards = createSelector(
detachFromLayout,
displayName,
icon: iconSVG,
+ searchTags,
};
});
const sortedCards = sortBy(_cards, ["displayName"]);
diff --git a/app/client/src/selectors/entitiesSelector.ts b/app/client/src/selectors/entitiesSelector.ts
index f389a1753d..6abc345791 100644
--- a/app/client/src/selectors/entitiesSelector.ts
+++ b/app/client/src/selectors/entitiesSelector.ts
@@ -795,7 +795,9 @@ export const getJSActions = (
(jsCollectionData) => jsCollectionData.config.id === JSCollectionId,
);
- return jsCollection?.config.actions ?? [];
+ return jsCollection?.config.actions
+ ? sortBy(jsCollection?.config.actions, ["name"])
+ : [];
};
export const getActiveJSActionId = (
diff --git a/app/client/src/selectors/onboardingSelectors.tsx b/app/client/src/selectors/onboardingSelectors.tsx
index f04993394e..05383c8b29 100644
--- a/app/client/src/selectors/onboardingSelectors.tsx
+++ b/app/client/src/selectors/onboardingSelectors.tsx
@@ -4,7 +4,7 @@ import {
} from "pages/Applications/permissionHelpers";
import { AppState } from "reducers";
import { createSelector } from "reselect";
-import { getUserApplicationsOrgs } from "./applicationSelectors";
+import { getUserApplicationsWorkspaces } from "./applicationSelectors";
import { getWidgets } from "sagas/selectors";
import { getActionResponses, getActions } from "./entitiesSelector";
import { getSelectedWidget } from "./ui";
@@ -310,14 +310,14 @@ export const showInfoMessageSelector = (state: AppState) =>
export const loading = (state: AppState) => state.ui.onBoarding.loading;
-// To find an organisation where the user has permission to create an
+// To find an workspace where the user has permission to create an
// application
-export const getOnboardingOrganisations = createSelector(
- getUserApplicationsOrgs,
- (userOrgs) => {
- return userOrgs.filter((userOrg) =>
+export const getOnboardingWorkspaces = createSelector(
+ getUserApplicationsWorkspaces,
+ (userWorkspaces) => {
+ return userWorkspaces.filter((userWorkspace) =>
isPermitted(
- userOrg.organization.userPermissions || [],
+ userWorkspace.workspace.userPermissions || [],
PERMISSION_TYPE.CREATE_APPLICATION,
),
);
diff --git a/app/client/src/selectors/templatesSelectors.tsx b/app/client/src/selectors/templatesSelectors.tsx
index 31cf42f875..f8df41f227 100644
--- a/app/client/src/selectors/templatesSelectors.tsx
+++ b/app/client/src/selectors/templatesSelectors.tsx
@@ -2,7 +2,7 @@ import { FilterKeys, Template } from "api/TemplatesApi";
import Fuse from "fuse.js";
import { AppState } from "reducers";
import { createSelector } from "reselect";
-import { getOrganizationCreateApplication } from "./applicationSelectors";
+import { getWorkspaceCreateApplication } from "./applicationSelectors";
import { getWidgetCards } from "./editorSelectors";
import { getDefaultPlugins } from "./entitiesSelector";
import { Filter } from "pages/Templates/Filters";
@@ -22,11 +22,11 @@ export const isImportingTemplateSelector = (state: AppState) =>
export const showTemplateNotificationSelector = (state: AppState) =>
state.ui.templates.templateNotificationSeen;
-export const getOrganizationForTemplates = createSelector(
- getOrganizationCreateApplication,
- (organizationList) => {
- if (organizationList.length) {
- return organizationList[0];
+export const getWorkspaceForTemplates = createSelector(
+ getWorkspaceCreateApplication,
+ (workspaceList) => {
+ if (workspaceList.length) {
+ return workspaceList[0];
}
return null;
@@ -169,13 +169,13 @@ export const getFilterListSelector = createSelector(
},
);
-export const getForkableOrganizations = createSelector(
- getOrganizationCreateApplication,
- (organisations) => {
- return organisations.map((organization) => {
+export const getForkableWorkspaces = createSelector(
+ getWorkspaceCreateApplication,
+ (workspaces) => {
+ return workspaces.map((workspace) => {
return {
- label: organization.organization.name,
- value: organization.organization.id,
+ label: workspace.workspace.name,
+ value: workspace.workspace.id,
};
});
},
diff --git a/app/client/src/selectors/workspaceSelectors.tsx b/app/client/src/selectors/workspaceSelectors.tsx
new file mode 100644
index 0000000000..0ad3fdcb99
--- /dev/null
+++ b/app/client/src/selectors/workspaceSelectors.tsx
@@ -0,0 +1,68 @@
+import { createSelector } from "reselect";
+import { AppState } from "reducers";
+import { WorkspaceRole } from "constants/workspaceConstants";
+
+export const getRolesFromState = (state: AppState) => {
+ return state.ui.workspaces.roles;
+};
+
+export const getWorkspaceLoadingStates = (state: AppState) => {
+ return {
+ isFetchingWorkspace: state.ui.workspaces.loadingStates.isFetchingWorkspace,
+ isFetchingAllUsers: state.ui.workspaces.loadingStates.isFetchAllUsers,
+ isFetchingAllRoles: state.ui.workspaces.loadingStates.isFetchAllRoles,
+ deletingUserInfo: state.ui.workspaces.workspaceUsers.filter(
+ (el) => el.isDeleting,
+ )[0],
+ roleChangingUserInfo: state.ui.workspaces.workspaceUsers.filter(
+ (el) => el.isChangingRole,
+ )[0],
+ };
+};
+
+export const getCurrentWorkspaceId = (state: AppState) =>
+ state.ui.workspaces.currentWorkspace.id;
+export const getWorkspaces = (state: AppState) => {
+ return state.ui.applications.userWorkspaces;
+};
+export const getCurrentWorkspace = (state: AppState) => {
+ return state.ui.applications.userWorkspaces.map((el) => el.workspace);
+};
+export const getCurrentAppWorkspace = (state: AppState) => {
+ return state.ui.workspaces.currentWorkspace;
+};
+export const getAllUsers = (state: AppState) =>
+ state.ui.workspaces.workspaceUsers;
+export const getAllRoles = (state: AppState) =>
+ state.ui.workspaces.workspaceRoles;
+
+export const getRoles = createSelector(
+ getRolesFromState,
+ (roles?: WorkspaceRole[]): WorkspaceRole[] | undefined => {
+ return roles?.map((role) => ({
+ id: role.id,
+ name: role.displayName || role.name,
+ isDefault: role.isDefault,
+ }));
+ },
+);
+
+export const getRolesForField = createSelector(getAllRoles, (roles?: any) => {
+ return Object.entries(roles).map((role) => {
+ return {
+ id: role[0],
+ name: role[0],
+ description: role[1],
+ };
+ });
+});
+
+export const getDefaultRole = createSelector(
+ getRoles,
+ (roles?: WorkspaceRole[]) => {
+ return roles?.find((role) => role.isDefault);
+ },
+);
+export const getCurrentError = (state: AppState) => {
+ return state.ui.errors.currentError;
+};
diff --git a/app/client/src/serviceWorker.js b/app/client/src/serviceWorker.js
index ff3c789eca..2f7e5312ac 100644
--- a/app/client/src/serviceWorker.js
+++ b/app/client/src/serviceWorker.js
@@ -22,7 +22,7 @@ const regexMap = {
/(tiny.cloud|googleapis|gstatic|cloudfront).*.(js|css|woff2)/,
),
shims: new RegExp(/shims\/.*.js/),
- profile: new RegExp(/v1\/(users\/profile|organizations)/),
+ profile: new RegExp(/v1\/(users\/profile|workspaces)/),
providers: new RegExp(/v1\/marketplace\/(providers|templates)/),
};
diff --git a/app/client/src/transformers/RestAPIDatasourceFormTransformer.ts b/app/client/src/transformers/RestAPIDatasourceFormTransformer.ts
index 838f475bf4..c7d6ba9ee9 100644
--- a/app/client/src/transformers/RestAPIDatasourceFormTransformer.ts
+++ b/app/client/src/transformers/RestAPIDatasourceFormTransformer.ts
@@ -37,7 +37,7 @@ export const datasourceToFormValues = (
: "";
return {
datasourceId: datasource.id,
- organizationId: datasource.organizationId,
+ workspaceId: datasource.workspaceId,
pluginId: datasource.pluginId,
isValid: datasource.isValid,
url: datasource.datasourceConfiguration?.url,
diff --git a/app/client/src/transformers/RestActionTransformers.test.ts b/app/client/src/transformers/RestActionTransformers.test.ts
index 3ceb666524..f712a0e7e8 100644
--- a/app/client/src/transformers/RestActionTransformers.test.ts
+++ b/app/client/src/transformers/RestActionTransformers.test.ts
@@ -14,7 +14,7 @@ const BASE_ACTION: ApiAction = {
executeOnLoad: false,
invalids: [],
isValid: false,
- organizationId: "",
+ workspaceId: "",
pageId: "",
pluginId: "",
id: "testId",
diff --git a/app/client/src/utils/DynamicBindingUtils.test.ts b/app/client/src/utils/DynamicBindingUtils.test.ts
index e875eb1f0c..c2b9670650 100644
--- a/app/client/src/utils/DynamicBindingUtils.test.ts
+++ b/app/client/src/utils/DynamicBindingUtils.test.ts
@@ -65,7 +65,7 @@ describe("DynamicBindingPathlist", () => {
const action: Action = {
cacheResponse: "",
id: "61810f59a0f5113e30ba72ac",
- organizationId: "61800c6bd504bf710747bf9a",
+ workspaceId: "61800c6bd504bf710747bf9a",
pluginType: PluginType.API,
pluginId: "5ca385dc81b37f0004b4db85",
name: "Api1",
@@ -73,7 +73,7 @@ describe("DynamicBindingPathlist", () => {
// userPermissions: [],
name: "DEFAULT_REST_DATASOURCE",
pluginId: "5ca385dc81b37f0004b4db85",
- organizationId: "61800c6bd504bf710747bf9a",
+ workspaceId: "61800c6bd504bf710747bf9a",
datasourceConfiguration: {
url: "https://thatcopy.pw",
},
diff --git a/app/client/src/utils/JSPaneUtils.test.ts b/app/client/src/utils/JSPaneUtils.test.ts
index b8da5c0bf7..1c6435c251 100644
--- a/app/client/src/utils/JSPaneUtils.test.ts
+++ b/app/client/src/utils/JSPaneUtils.test.ts
@@ -5,7 +5,7 @@ import { getDifferenceInJSCollection, ParsedBody } from "./JSPaneUtils";
const JSObject1: JSCollection = {
id: "1234",
applicationId: "app123",
- organizationId: "org123",
+ workspaceId: "workspace123",
name: "JSObject2",
pageId: "page123",
pluginId: "plugin123",
@@ -16,7 +16,7 @@ const JSObject1: JSCollection = {
{
id: "fun2",
applicationId: "app123",
- organizationId: "org123",
+ workspaceId: "workspace123",
pluginType: "JS",
pluginId: "plugin123",
name: "myFun2",
@@ -25,7 +25,7 @@ const JSObject1: JSCollection = {
userPermissions: [],
name: "UNUSED_DATASOURCE",
pluginId: "plugin123",
- organizationId: "org123",
+ workspaceId: "workspace123",
messages: [],
isValid: true,
new: true,
@@ -58,7 +58,7 @@ const JSObject1: JSCollection = {
{
id: "fun1",
applicationId: "app123",
- organizationId: "org123",
+ workspaceId: "workspace123",
pluginType: "JS",
pluginId: "plugin123",
name: "myFun1",
@@ -67,7 +67,7 @@ const JSObject1: JSCollection = {
userPermissions: [],
name: "UNUSED_DATASOURCE",
pluginId: "plugin123",
- organizationId: "org123",
+ workspaceId: "workspace123",
messages: [],
isValid: true,
new: true,
@@ -116,7 +116,7 @@ const JSObject1: JSCollection = {
const JSObject2: JSCollection = {
id: "1234",
applicationId: "app123",
- organizationId: "org123",
+ workspaceId: "workspace123",
name: "JSObject2",
pageId: "page123",
pluginId: "plugin123",
@@ -127,7 +127,7 @@ const JSObject2: JSCollection = {
{
id: "fun1",
applicationId: "app123",
- organizationId: "org123",
+ workspaceId: "workspace123",
pluginType: "JS",
pluginId: "plugin123",
name: "myFun1",
@@ -136,7 +136,7 @@ const JSObject2: JSCollection = {
userPermissions: [],
name: "UNUSED_DATASOURCE",
pluginId: "plugin123",
- organizationId: "org123",
+ workspaceId: "workspace123",
messages: [],
isValid: true,
new: true,
@@ -169,7 +169,7 @@ const JSObject2: JSCollection = {
{
id: "fun2",
applicationId: "app123",
- organizationId: "org123",
+ workspaceId: "workspace123",
pluginType: "JS",
pluginId: "plugin123",
name: "myFun2",
@@ -178,7 +178,7 @@ const JSObject2: JSCollection = {
userPermissions: [],
name: "UNUSED_DATASOURCE",
pluginId: "plugin123",
- organizationId: "org123",
+ workspaceId: "workspace123",
messages: [],
isValid: true,
new: true,
@@ -257,7 +257,7 @@ const resultRenamedActions = {
{
id: "fun1",
applicationId: "app123",
- organizationId: "org123",
+ workspaceId: "workspace123",
pluginType: "JS",
pluginId: "plugin123",
name: "myFun11",
@@ -266,7 +266,7 @@ const resultRenamedActions = {
userPermissions: [],
name: "UNUSED_DATASOURCE",
pluginId: "plugin123",
- organizationId: "org123",
+ workspaceId: "workspace123",
messages: [],
isValid: true,
new: true,
@@ -338,7 +338,7 @@ const resultDeletedActions = {
{
id: "fun2",
applicationId: "app123",
- organizationId: "org123",
+ workspaceId: "workspace123",
pluginType: "JS",
pluginId: "plugin123",
name: "myFun2",
@@ -347,7 +347,7 @@ const resultDeletedActions = {
userPermissions: [],
name: "UNUSED_DATASOURCE",
pluginId: "plugin123",
- organizationId: "org123",
+ workspaceId: "workspace123",
messages: [],
isValid: true,
new: true,
@@ -455,7 +455,7 @@ const resultChangedBody = {
{
id: "fun2",
applicationId: "app123",
- organizationId: "org123",
+ workspaceId: "workspace123",
pluginType: "JS",
pluginId: "plugin123",
name: "myFun2",
@@ -464,7 +464,7 @@ const resultChangedBody = {
userPermissions: [],
name: "UNUSED_DATASOURCE",
pluginId: "plugin123",
- organizationId: "org123",
+ workspaceId: "workspace123",
messages: [],
isValid: true,
new: true,
@@ -536,7 +536,7 @@ const resultChangedParameters = {
{
id: "fun2",
applicationId: "app123",
- organizationId: "org123",
+ workspaceId: "workspace123",
pluginType: "JS",
pluginId: "plugin123",
name: "myFun2",
@@ -545,7 +545,7 @@ const resultChangedParameters = {
userPermissions: [],
name: "UNUSED_DATASOURCE",
pluginId: "plugin123",
- organizationId: "org123",
+ workspaceId: "workspace123",
messages: [],
isValid: true,
new: true,
@@ -617,7 +617,7 @@ const resultRemovedAsync = {
{
id: "fun2",
applicationId: "app123",
- organizationId: "org123",
+ workspaceId: "workspace123",
pluginType: "JS",
pluginId: "plugin123",
name: "myFun2",
@@ -626,7 +626,7 @@ const resultRemovedAsync = {
userPermissions: [],
name: "UNUSED_DATASOURCE",
pluginId: "plugin123",
- organizationId: "org123",
+ workspaceId: "workspace123",
messages: [],
isValid: true,
new: true,
@@ -695,7 +695,7 @@ const resultAddedAsync = {
{
id: "fun1",
applicationId: "app123",
- organizationId: "org123",
+ workspaceId: "workspace123",
pluginType: "JS",
pluginId: "plugin123",
name: "myFun1",
@@ -704,7 +704,7 @@ const resultAddedAsync = {
userPermissions: [],
name: "UNUSED_DATASOURCE",
pluginId: "plugin123",
- organizationId: "org123",
+ workspaceId: "workspace123",
messages: [],
isValid: true,
new: true,
@@ -780,7 +780,7 @@ const resultAddedAction = {
executeOnLoad: false,
pageId: "page123",
collectionId: "1234",
- organizationId: "org123",
+ workspaceId: "workspace123",
actionConfiguration: {
body: "async () => {\n\t\t//use async-await or promises\n\t}",
isAsync: true,
diff --git a/app/client/src/utils/JSPaneUtils.tsx b/app/client/src/utils/JSPaneUtils.tsx
index f4eeb58e15..1aeddab0ad 100644
--- a/app/client/src/utils/JSPaneUtils.tsx
+++ b/app/client/src/utils/JSPaneUtils.tsx
@@ -111,7 +111,7 @@ export const getDifferenceInJSCollection = (
collectionId: jsAction.id,
executeOnLoad: false,
pageId: jsAction.pageId,
- organizationId: jsAction.organizationId,
+ workspaceId: jsAction.workspaceId,
actionConfiguration: {
body: action.body,
isAsync: action.isAsync,
@@ -184,7 +184,7 @@ export const pushLogsForObjectUpdate = (
export const createDummyJSCollectionActions = (
pageId: string,
- organizationId: string,
+ workspaceId: string,
) => {
const body =
"export default {\n\tmyVar1: [],\n\tmyVar2: {},\n\tmyFun1: () => {\n\t\t//write code here\n\t},\n\tmyFun2: async () => {\n\t\t//use async-await or promises\n\t}\n}";
@@ -193,7 +193,7 @@ export const createDummyJSCollectionActions = (
{
name: "myFun1",
pageId,
- organizationId,
+ workspaceId,
executeOnLoad: false,
actionConfiguration: {
body: "() => {\n\t\t//write code here\n\t}",
@@ -206,7 +206,7 @@ export const createDummyJSCollectionActions = (
{
name: "myFun2",
pageId,
- organizationId,
+ workspaceId,
executeOnLoad: false,
actionConfiguration: {
body: "async () => {\n\t\t//use async-await or promises\n\t}",
diff --git a/app/client/src/utils/WidgetRegisterHelpers.tsx b/app/client/src/utils/WidgetRegisterHelpers.tsx
index 1ca1a8efd1..75a759c929 100644
--- a/app/client/src/utils/WidgetRegisterHelpers.tsx
+++ b/app/client/src/utils/WidgetRegisterHelpers.tsx
@@ -52,6 +52,7 @@ export const configureWidget = (config: WidgetConfiguration) => {
const _config = {
...features,
...config.defaults,
+ searchTags: config.searchTags,
type: config.type,
hideCard: !!config.hideCard || !config.iconSVG,
isDeprecated: !!config.isDeprecated,
diff --git a/app/client/src/utils/autocomplete/EntityDefinitions.test.ts b/app/client/src/utils/autocomplete/EntityDefinitions.test.ts
index 0bd95a8c65..76655c8685 100644
--- a/app/client/src/utils/autocomplete/EntityDefinitions.test.ts
+++ b/app/client/src/utils/autocomplete/EntityDefinitions.test.ts
@@ -61,7 +61,7 @@ const jsObject: JSCollectionData = {
config: {
id: "1234",
applicationId: "app123",
- organizationId: "org123",
+ workspaceId: "workspace123",
name: "JSObject3",
pageId: "page123",
pluginId: "plugin123",
@@ -72,7 +72,7 @@ const jsObject: JSCollectionData = {
{
id: "fun1",
applicationId: "app123",
- organizationId: "org123",
+ workspaceId: "workspace123",
pluginType: "JS",
pluginId: "plugin123",
name: "myFun1",
@@ -81,7 +81,7 @@ const jsObject: JSCollectionData = {
userPermissions: [],
name: "UNUSED_DATASOURCE",
pluginId: "plugin123",
- organizationId: "org123",
+ workspaceId: "workspace123",
messages: [],
isValid: true,
new: true,
@@ -114,7 +114,7 @@ const jsObject: JSCollectionData = {
{
id: "fun2",
applicationId: "app123",
- organizationId: "org123",
+ workspaceId: "workspace123",
pluginType: PluginType.JS,
pluginId: "plugin123",
name: "myFun2",
@@ -123,7 +123,7 @@ const jsObject: JSCollectionData = {
userPermissions: [],
name: "UNUSED_DATASOURCE",
pluginId: "plugin123",
- organizationId: "org123",
+ workspaceId: "workspace123",
messages: [],
isValid: true,
new: true,
diff --git a/app/client/src/utils/helpers.tsx b/app/client/src/utils/helpers.tsx
index 1d95c7d3f0..f342e63d23 100644
--- a/app/client/src/utils/helpers.tsx
+++ b/app/client/src/utils/helpers.tsx
@@ -12,7 +12,7 @@ import {
} from "constants/WidgetValidation";
import { GLOBAL_FUNCTIONS } from "./autocomplete/EntityDefinitions";
import { get, set, isNil } from "lodash";
-import { Org } from "constants/orgConstants";
+import { Workspace } from "constants/workspaceConstants";
import {
isPermitted,
PERMISSION_TYPE,
@@ -469,11 +469,11 @@ export const renameKeyInObject = (object: any, key: string, newKey: string) => {
return object;
};
-// Can be used to check if the user has developer role access to org
-export const getCanCreateApplications = (currentOrg: Org) => {
- const userOrgPermissions = currentOrg.userPermissions || [];
+// Can be used to check if the user has developer role access to workspace
+export const getCanCreateApplications = (currentWorkspace: Workspace) => {
+ const userWorkspacePermissions = currentWorkspace.userPermissions || [];
const canManage = isPermitted(
- userOrgPermissions,
+ userWorkspacePermissions,
PERMISSION_TYPE.CREATE_APPLICATION,
);
return canManage;
diff --git a/app/client/src/utils/hooks/useOrg.tsx b/app/client/src/utils/hooks/useOrg.tsx
deleted file mode 100644
index af52899b7d..0000000000
--- a/app/client/src/utils/hooks/useOrg.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { fetchOrg } from "actions/orgActions";
-import { useEffect } from "react";
-import { useSelector, useDispatch } from "react-redux";
-import { getCurrentUser } from "selectors/usersSelectors";
-
-import { getCurrentAppOrg } from "@appsmith/selectors/organizationSelectors";
-import { ANONYMOUS_USERNAME } from "constants/userConstants";
-
-const useOrg = (orgId: string) => {
- const dispatch = useDispatch();
- const org = useSelector(getCurrentAppOrg);
- const currentUser = useSelector(getCurrentUser);
-
- useEffect(() => {
- if (!currentUser || currentUser.username === ANONYMOUS_USERNAME) return;
-
- if ((!org || !org.userPermissions) && orgId) {
- dispatch(fetchOrg(orgId, true));
- }
- }, [orgId, currentUser && currentUser.username]);
-
- return org;
-};
-
-export default useOrg;
diff --git a/app/client/src/utils/hooks/useWorkspace.tsx b/app/client/src/utils/hooks/useWorkspace.tsx
new file mode 100644
index 0000000000..0b360d2006
--- /dev/null
+++ b/app/client/src/utils/hooks/useWorkspace.tsx
@@ -0,0 +1,25 @@
+import { fetchWorkspace } from "actions/workspaceActions";
+import { useEffect } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import { getCurrentUser } from "selectors/usersSelectors";
+
+import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors";
+import { ANONYMOUS_USERNAME } from "constants/userConstants";
+
+const useWorkspace = (workspaceId: string) => {
+ const dispatch = useDispatch();
+ const workspace = useSelector(getCurrentAppWorkspace);
+ const currentUser = useSelector(getCurrentUser);
+
+ useEffect(() => {
+ if (!currentUser || currentUser.username === ANONYMOUS_USERNAME) return;
+
+ if ((!workspace || !workspace.userPermissions) && workspaceId) {
+ dispatch(fetchWorkspace(workspaceId, true));
+ }
+ }, [workspaceId, currentUser && currentUser.username]);
+
+ return workspace;
+};
+
+export default useWorkspace;
diff --git a/app/client/src/widgets/AudioRecorderWidget/index.ts b/app/client/src/widgets/AudioRecorderWidget/index.ts
index d4d32166fe..fd362b35f1 100644
--- a/app/client/src/widgets/AudioRecorderWidget/index.ts
+++ b/app/client/src/widgets/AudioRecorderWidget/index.ts
@@ -6,6 +6,7 @@ export const CONFIG = {
name: "Audio Recorder",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["sound recorder", "voice recorder"],
defaults: {
iconColor: "white",
isDisabled: false,
diff --git a/app/client/src/widgets/AudioWidget/index.tsx b/app/client/src/widgets/AudioWidget/index.tsx
index 547c8f854f..b2c592e7c8 100644
--- a/app/client/src/widgets/AudioWidget/index.tsx
+++ b/app/client/src/widgets/AudioWidget/index.tsx
@@ -6,6 +6,7 @@ export const CONFIG = {
name: "Audio",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["mp3", "sound", "wave", "player"],
defaults: {
rows: 4,
columns: 28,
diff --git a/app/client/src/widgets/ButtonGroupWidget/index.ts b/app/client/src/widgets/ButtonGroupWidget/index.ts
index d63a69e632..d7e52e9673 100644
--- a/app/client/src/widgets/ButtonGroupWidget/index.ts
+++ b/app/client/src/widgets/ButtonGroupWidget/index.ts
@@ -12,6 +12,7 @@ export const CONFIG = {
iconSVG: IconSVG,
needsMeta: false, // Defines if this widget adds any meta properties
isCanvas: false, // Defines if this widget has a canvas within in which we can drop other widgets
+ searchTags: ["click", "submit"],
defaults: {
rows: 4,
columns: 24,
diff --git a/app/client/src/widgets/ButtonWidget/index.ts b/app/client/src/widgets/ButtonWidget/index.ts
index 01e032dd4a..59aed7fc31 100644
--- a/app/client/src/widgets/ButtonWidget/index.ts
+++ b/app/client/src/widgets/ButtonWidget/index.ts
@@ -11,6 +11,7 @@ export const CONFIG = {
name: "Button",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["click", "submit"],
defaults: {
animateLoading: true,
text: "Submit",
diff --git a/app/client/src/widgets/CameraWidget/index.ts b/app/client/src/widgets/CameraWidget/index.ts
index 1db67bd358..ed20b6f4b6 100644
--- a/app/client/src/widgets/CameraWidget/index.ts
+++ b/app/client/src/widgets/CameraWidget/index.ts
@@ -8,6 +8,7 @@ export const CONFIG = {
iconSVG: IconSVG,
needsMeta: true, // Defines if this widget adds any meta properties
isCanvas: false, // Defines if this widget has a canvas within in which we can drop other widgets
+ searchTags: ["photo", "video recorder"],
defaults: {
widgetName: "Camera",
rows: 33,
diff --git a/app/client/src/widgets/ChartWidget/index.ts b/app/client/src/widgets/ChartWidget/index.ts
index 7b23bbfa23..0969bad061 100644
--- a/app/client/src/widgets/ChartWidget/index.ts
+++ b/app/client/src/widgets/ChartWidget/index.ts
@@ -8,6 +8,7 @@ export const CONFIG = {
name: "Chart",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["graph", "visuals", "visualisations"],
defaults: {
rows: 32,
columns: 24,
diff --git a/app/client/src/widgets/CheckboxWidget/index.ts b/app/client/src/widgets/CheckboxWidget/index.ts
index ff3dd1531b..f1468597aa 100644
--- a/app/client/src/widgets/CheckboxWidget/index.ts
+++ b/app/client/src/widgets/CheckboxWidget/index.ts
@@ -8,6 +8,7 @@ export const CONFIG = {
name: "Checkbox",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["boolean"],
defaults: {
rows: 4,
columns: 7,
diff --git a/app/client/src/widgets/ContainerWidget/index.ts b/app/client/src/widgets/ContainerWidget/index.ts
index 03fbb3a9d3..cb924867ef 100644
--- a/app/client/src/widgets/ContainerWidget/index.ts
+++ b/app/client/src/widgets/ContainerWidget/index.ts
@@ -7,6 +7,7 @@ export const CONFIG = {
name: "Container",
iconSVG: IconSVG,
isCanvas: true,
+ searchTags: ["div", "parent", "group"],
defaults: {
backgroundColor: "#FFFFFF",
rows: 40,
diff --git a/app/client/src/widgets/CurrencyInputWidget/index.ts b/app/client/src/widgets/CurrencyInputWidget/index.ts
index 0a6100301e..c8154fef82 100644
--- a/app/client/src/widgets/CurrencyInputWidget/index.ts
+++ b/app/client/src/widgets/CurrencyInputWidget/index.ts
@@ -8,6 +8,7 @@ export const CONFIG = {
name: "Currency Input",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["amount", "total"],
defaults: {
...BaseConfig.defaults,
widgetName: "CurrencyInput",
diff --git a/app/client/src/widgets/DatePickerWidget2/index.ts b/app/client/src/widgets/DatePickerWidget2/index.ts
index 106c9b2929..ad961402f4 100644
--- a/app/client/src/widgets/DatePickerWidget2/index.ts
+++ b/app/client/src/widgets/DatePickerWidget2/index.ts
@@ -10,6 +10,7 @@ export const CONFIG = {
name: "DatePicker",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["calendar"],
defaults: {
isDisabled: false,
datePickerType: "DATE_PICKER",
diff --git a/app/client/src/widgets/DividerWidget/index.ts b/app/client/src/widgets/DividerWidget/index.ts
index fe058115a2..520f013fa5 100644
--- a/app/client/src/widgets/DividerWidget/index.ts
+++ b/app/client/src/widgets/DividerWidget/index.ts
@@ -6,6 +6,7 @@ export const CONFIG = {
type: Widget.getWidgetType(),
name: "Divider",
iconSVG: IconSVG,
+ searchTags: ["line"],
defaults: {
rows: 4,
columns: 20,
diff --git a/app/client/src/widgets/DocumentViewerWidget/index.ts b/app/client/src/widgets/DocumentViewerWidget/index.ts
index ab9e2eb211..337f96bd31 100644
--- a/app/client/src/widgets/DocumentViewerWidget/index.ts
+++ b/app/client/src/widgets/DocumentViewerWidget/index.ts
@@ -7,6 +7,7 @@ export const CONFIG = {
iconSVG: IconSVG,
needsMeta: false, // Defines if this widget adds any meta properties
isCanvas: false, // Defines if this widget has a canvas within in which we can drop other widgets
+ searchTags: ["pdf"],
defaults: {
widgetName: "DocumentViewer",
docUrl:
diff --git a/app/client/src/widgets/FilePickerWidgetV2/index.ts b/app/client/src/widgets/FilePickerWidgetV2/index.ts
index 843212db07..5cf23797e8 100644
--- a/app/client/src/widgets/FilePickerWidgetV2/index.ts
+++ b/app/client/src/widgets/FilePickerWidgetV2/index.ts
@@ -7,6 +7,7 @@ export const CONFIG = {
name: "FilePicker",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["upload"],
defaults: {
rows: 4,
files: [],
diff --git a/app/client/src/widgets/FormWidget/index.ts b/app/client/src/widgets/FormWidget/index.ts
index 5713ca2dec..dec3702900 100644
--- a/app/client/src/widgets/FormWidget/index.ts
+++ b/app/client/src/widgets/FormWidget/index.ts
@@ -9,6 +9,7 @@ export const CONFIG = {
iconSVG: IconSVG,
needsMeta: true,
isCanvas: true,
+ searchTags: ["group"],
defaults: {
rows: 40,
columns: 24,
diff --git a/app/client/src/widgets/IconButtonWidget/index.ts b/app/client/src/widgets/IconButtonWidget/index.ts
index 01d1795c79..4ac60a62e8 100644
--- a/app/client/src/widgets/IconButtonWidget/index.ts
+++ b/app/client/src/widgets/IconButtonWidget/index.ts
@@ -7,6 +7,7 @@ export const CONFIG = {
type: Widget.getWidgetType(),
name: "Icon Button",
iconSVG: IconSVG,
+ searchTags: ["click", "submit"],
defaults: {
iconName: IconNames.PLUS,
buttonVariant: ButtonVariantTypes.PRIMARY,
diff --git a/app/client/src/widgets/IframeWidget/index.ts b/app/client/src/widgets/IframeWidget/index.ts
index 033eee741c..388ba8782d 100644
--- a/app/client/src/widgets/IframeWidget/index.ts
+++ b/app/client/src/widgets/IframeWidget/index.ts
@@ -6,6 +6,7 @@ export const CONFIG = {
name: "Iframe",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["embed"],
defaults: {
source: "https://www.example.com",
borderOpacity: 100,
diff --git a/app/client/src/widgets/InputWidgetV2/index.ts b/app/client/src/widgets/InputWidgetV2/index.ts
index 8b0c99c80c..b345eff0c8 100644
--- a/app/client/src/widgets/InputWidgetV2/index.ts
+++ b/app/client/src/widgets/InputWidgetV2/index.ts
@@ -7,6 +7,7 @@ export const CONFIG = {
name: "Input",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["form", "text input", "number", "textarea"],
defaults: {
...BaseConfig.defaults,
inputType: "TEXT",
diff --git a/app/client/src/widgets/MapChartWidget/index.ts b/app/client/src/widgets/MapChartWidget/index.ts
index b6c031ef19..99c230d59a 100644
--- a/app/client/src/widgets/MapChartWidget/index.ts
+++ b/app/client/src/widgets/MapChartWidget/index.ts
@@ -8,6 +8,7 @@ export const CONFIG = {
iconSVG: IconSVG,
needsMeta: true, // Defines if this widget adds any meta properties
isCanvas: false, // Defines if this widget has a canvas within in which we can drop other widgets
+ searchTags: ["graph", "visuals", "visualisations"],
defaults: {
rows: 32,
columns: 24,
diff --git a/app/client/src/widgets/ModalWidget/index.ts b/app/client/src/widgets/ModalWidget/index.ts
index 6bbafb3bbd..b3b4cde5cc 100644
--- a/app/client/src/widgets/ModalWidget/index.ts
+++ b/app/client/src/widgets/ModalWidget/index.ts
@@ -20,6 +20,7 @@ export const CONFIG = {
iconSVG: IconSVG,
needsMeta: true,
isCanvas: true,
+ searchTags: ["dialog", "popup", "notification"],
defaults: {
rows: 24,
columns: 24,
diff --git a/app/client/src/widgets/MultiSelectTreeWidget/index.ts b/app/client/src/widgets/MultiSelectTreeWidget/index.ts
index be39dde30c..2bbd7adccf 100644
--- a/app/client/src/widgets/MultiSelectTreeWidget/index.ts
+++ b/app/client/src/widgets/MultiSelectTreeWidget/index.ts
@@ -8,6 +8,7 @@ export const CONFIG = {
name: "Multi TreeSelect",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["dropdown"],
defaults: {
rows: 4,
columns: 20,
diff --git a/app/client/src/widgets/MultiSelectWidgetV2/index.ts b/app/client/src/widgets/MultiSelectWidgetV2/index.ts
index 90d3a18f78..a25a8fb635 100644
--- a/app/client/src/widgets/MultiSelectWidgetV2/index.ts
+++ b/app/client/src/widgets/MultiSelectWidgetV2/index.ts
@@ -8,6 +8,7 @@ export const CONFIG = {
name: "MultiSelect",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["dropdown", "tags"],
defaults: {
rows: 4,
columns: 20,
diff --git a/app/client/src/widgets/PhoneInputWidget/index.ts b/app/client/src/widgets/PhoneInputWidget/index.ts
index fcda29881c..72baef92a3 100644
--- a/app/client/src/widgets/PhoneInputWidget/index.ts
+++ b/app/client/src/widgets/PhoneInputWidget/index.ts
@@ -8,6 +8,7 @@ export const CONFIG = {
name: "Phone Input",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["call"],
defaults: {
...BaseConfig.defaults,
widgetName: "PhoneInput",
diff --git a/app/client/src/widgets/ProgressWidget/index.ts b/app/client/src/widgets/ProgressWidget/index.ts
index 48396b190f..b97212d180 100644
--- a/app/client/src/widgets/ProgressWidget/index.ts
+++ b/app/client/src/widgets/ProgressWidget/index.ts
@@ -9,6 +9,7 @@ export const CONFIG = {
iconSVG: IconSVG,
needsMeta: false, // Defines if this widget adds any meta properties
isCanvas: false, // Defines if this widget has a canvas within in which we can drop other widgets
+ searchTags: ["percent"],
defaults: {
widgetName: "Progress",
rows: 4,
diff --git a/app/client/src/widgets/RadioGroupWidget/index.ts b/app/client/src/widgets/RadioGroupWidget/index.ts
index 8dded249fe..cf64e9f869 100644
--- a/app/client/src/widgets/RadioGroupWidget/index.ts
+++ b/app/client/src/widgets/RadioGroupWidget/index.ts
@@ -8,6 +8,7 @@ export const CONFIG = {
name: "Radio Group",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["choice"],
defaults: {
rows: 8,
columns: 20,
diff --git a/app/client/src/widgets/RateWidget/index.ts b/app/client/src/widgets/RateWidget/index.ts
index 48f1aff9b1..5a9dea34aa 100644
--- a/app/client/src/widgets/RateWidget/index.ts
+++ b/app/client/src/widgets/RateWidget/index.ts
@@ -7,6 +7,7 @@ export const CONFIG = {
name: "Rating",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["stars"],
defaults: {
rows: 4,
columns: 10,
diff --git a/app/client/src/widgets/RichTextEditorWidget/index.ts b/app/client/src/widgets/RichTextEditorWidget/index.ts
index cacbee6602..de253f67f4 100644
--- a/app/client/src/widgets/RichTextEditorWidget/index.ts
+++ b/app/client/src/widgets/RichTextEditorWidget/index.ts
@@ -8,6 +8,7 @@ export const CONFIG = {
name: "Rich Text Editor",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["input", "rte"],
defaults: {
defaultText: "This is the initial content of the editor",
rows: 20,
diff --git a/app/client/src/widgets/SelectWidget/index.ts b/app/client/src/widgets/SelectWidget/index.ts
index 4dc37b5778..32ca54c64c 100644
--- a/app/client/src/widgets/SelectWidget/index.ts
+++ b/app/client/src/widgets/SelectWidget/index.ts
@@ -8,6 +8,7 @@ export const CONFIG = {
name: "Select",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["dropdown"],
defaults: {
rows: 4,
columns: 20,
diff --git a/app/client/src/widgets/SingleSelectTreeWidget/index.ts b/app/client/src/widgets/SingleSelectTreeWidget/index.ts
index a7a740d608..5e00d936e4 100644
--- a/app/client/src/widgets/SingleSelectTreeWidget/index.ts
+++ b/app/client/src/widgets/SingleSelectTreeWidget/index.ts
@@ -6,6 +6,7 @@ import Widget from "./widget";
export const CONFIG = {
type: Widget.getWidgetType(),
name: "TreeSelect",
+ searchTags: ["dropdown"],
iconSVG: IconSVG,
needsMeta: true,
defaults: {
diff --git a/app/client/src/widgets/SwitchWidget/index.ts b/app/client/src/widgets/SwitchWidget/index.ts
index e39d316b60..9b94ec470f 100644
--- a/app/client/src/widgets/SwitchWidget/index.ts
+++ b/app/client/src/widgets/SwitchWidget/index.ts
@@ -8,6 +8,7 @@ export const CONFIG = {
name: "Switch",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["boolean"],
defaults: {
label: "Label",
rows: 4,
diff --git a/app/client/src/widgets/TableWidget/index.ts b/app/client/src/widgets/TableWidget/index.ts
index 34bb036303..c19d23f8e7 100644
--- a/app/client/src/widgets/TableWidget/index.ts
+++ b/app/client/src/widgets/TableWidget/index.ts
@@ -14,6 +14,7 @@ export const CONFIG = {
name: "Table",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["datagrid"],
defaults: {
rows: 28,
columns: 34,
diff --git a/app/client/src/widgets/TableWidget/widget/propertyConfig.ts b/app/client/src/widgets/TableWidget/widget/propertyConfig.ts
index 7564680aba..a4a835b669 100644
--- a/app/client/src/widgets/TableWidget/widget/propertyConfig.ts
+++ b/app/client/src/widgets/TableWidget/widget/propertyConfig.ts
@@ -736,7 +736,7 @@ export default [
{
propertyName: "textColor",
label: "Text Color",
- controlType: "COLOR_PICKER",
+ controlType: "PRIMARY_COLUMNS_COLOR_PICKER",
isJSConvertible: true,
customJSControl: "COMPUTE_VALUE",
updateHook: updateDerivedColumnsHook,
@@ -760,7 +760,7 @@ export default [
{
propertyName: "cellBackground",
label: "Cell Background",
- controlType: "COLOR_PICKER",
+ controlType: "PRIMARY_COLUMNS_COLOR_PICKER",
isJSConvertible: true,
customJSControl: "COMPUTE_VALUE",
updateHook: updateDerivedColumnsHook,
@@ -906,7 +906,7 @@ export default [
propertyName: "buttonColor",
getStylesheetValue,
label: "Button Color",
- controlType: "COLOR_PICKER",
+ controlType: "PRIMARY_COLUMNS_COLOR_PICKER",
helpText: "Changes the color of the button",
isJSConvertible: true,
customJSControl: "COMPUTE_VALUE",
@@ -1048,7 +1048,7 @@ export default [
helpText:
"Sets the custom color preset based on the menu button variant",
label: "Menu Color",
- controlType: "COLOR_PICKER",
+ controlType: "PRIMARY_COLUMNS_COLOR_PICKER",
customJSControl: "COMPUTE_VALUE",
isJSConvertible: true,
isBindProperty: true,
@@ -1207,7 +1207,7 @@ export default [
helpText:
"Sets the background color of a menu item",
label: "Background color",
- controlType: "COLOR_PICKER",
+ controlType: "PRIMARY_COLUMNS_COLOR_PICKER",
isJSConvertible: true,
isBindProperty: true,
isTriggerProperty: false,
@@ -1224,7 +1224,7 @@ export default [
propertyName: "textColor",
helpText: "Sets the text color of a menu item",
label: "Text color",
- controlType: "COLOR_PICKER",
+ controlType: "PRIMARY_COLUMNS_COLOR_PICKER",
isBindProperty: false,
isTriggerProperty: false,
updateHook: updateDerivedColumnsHook,
@@ -1294,7 +1294,7 @@ export default [
propertyName: "iconColor",
helpText: "Sets the icon color of a menu item",
label: "Icon color",
- controlType: "COLOR_PICKER",
+ controlType: "PRIMARY_COLUMNS_COLOR_PICKER",
isBindProperty: false,
isTriggerProperty: false,
updateHook: updateDerivedColumnsHook,
diff --git a/app/client/src/widgets/TextWidget/index.ts b/app/client/src/widgets/TextWidget/index.ts
index c6de20ffdb..c675710c74 100644
--- a/app/client/src/widgets/TextWidget/index.ts
+++ b/app/client/src/widgets/TextWidget/index.ts
@@ -7,6 +7,7 @@ export const CONFIG = {
type: Widget.getWidgetType(),
name: "Text",
iconSVG: IconSVG,
+ searchTags: ["typography", "paragraph"],
defaults: {
text: "Label",
fontSize: DEFAULT_FONT_SIZE,
diff --git a/app/client/src/widgets/VideoWidget/index.ts b/app/client/src/widgets/VideoWidget/index.ts
index 74960b1dc6..e3885baaf2 100644
--- a/app/client/src/widgets/VideoWidget/index.ts
+++ b/app/client/src/widgets/VideoWidget/index.ts
@@ -6,6 +6,7 @@ export const CONFIG = {
name: "Video",
iconSVG: IconSVG,
needsMeta: true,
+ searchTags: ["youtube"],
defaults: {
rows: 28,
columns: 24,
diff --git a/app/client/src/widgets/constants.ts b/app/client/src/widgets/constants.ts
index dd9adf1feb..392a3e1b74 100644
--- a/app/client/src/widgets/constants.ts
+++ b/app/client/src/widgets/constants.ts
@@ -14,6 +14,7 @@ export interface WidgetConfiguration {
isCanvas?: boolean;
needsMeta?: boolean;
features?: WidgetFeatures;
+ searchTags?: string[];
properties: {
config: PropertyPaneConfig[];
default: Record;
diff --git a/app/client/src/workers/DataTreeEvaluator/test/DataTreeEvaluator.test.ts b/app/client/src/workers/DataTreeEvaluator/test/DataTreeEvaluator.test.ts
index 8c08ede2f5..293f2bf004 100644
--- a/app/client/src/workers/DataTreeEvaluator/test/DataTreeEvaluator.test.ts
+++ b/app/client/src/workers/DataTreeEvaluator/test/DataTreeEvaluator.test.ts
@@ -1,8 +1,10 @@
import DataTreeEvaluator from "../DataTreeEvaluator";
-import { asyncTagUnevalTree, unEvalTree } from "./mockUnEvalTree";
+import { asyncTagUnevalTree, unEvalTree } from "./mockData/mockUnEvalTree";
import { DataTree } from "entities/DataTree/dataTreeFactory";
import { DataTreeDiff } from "workers/evaluationUtils";
import { ALL_WIDGETS_AND_CONFIG } from "utils/WidgetRegistry";
+import { arrayAccessorCyclicDependency } from "./mockData/ArrayAccessorTree";
+import { nestedArrayAccessorCyclicDependency } from "./mockData/NestedArrayAccessorTree";
const widgetConfigMap = {};
ALL_WIDGETS_AND_CONFIG.map(([, config]) => {
@@ -201,4 +203,173 @@ describe("DataTreeEvaluator", () => {
).toBe(true);
});
});
+
+ describe("array accessor dependency handling", () => {
+ const dataTreeEvaluator = new DataTreeEvaluator(widgetConfigMap);
+ beforeEach(() => {
+ dataTreeEvaluator.createFirstTree(
+ nestedArrayAccessorCyclicDependency.initUnEvalTree,
+ );
+ });
+ describe("array of objects", () => {
+ // when Text1.text has a binding Api1.data[2].id
+ it("on consequent API failures", () => {
+ // cyclic dependency case
+ for (let i = 0; i < 2; i++) {
+ // success: response -> [{...}, {...}, {...}]
+ dataTreeEvaluator.updateDataTree(
+ arrayAccessorCyclicDependency.apiSuccessUnEvalTree,
+ );
+ expect(dataTreeEvaluator.dependencyMap["Api1"]).toStrictEqual([
+ "Api1.data",
+ ]);
+ expect(dataTreeEvaluator.dependencyMap["Api1.data"]).toStrictEqual([
+ "Api1.data[2]",
+ ]);
+ expect(
+ dataTreeEvaluator.dependencyMap["Api1.data[2]"],
+ ).toStrictEqual(["Api1.data[2].id"]);
+ expect(dataTreeEvaluator.dependencyMap["Text1.text"]).toStrictEqual([
+ "Api1.data[2].id",
+ ]);
+
+ // failure: response -> {}
+ dataTreeEvaluator.updateDataTree(
+ arrayAccessorCyclicDependency.apiFailureUnEvalTree,
+ );
+ expect(dataTreeEvaluator.dependencyMap["Api1"]).toStrictEqual([
+ "Api1.data",
+ ]);
+ expect(dataTreeEvaluator.dependencyMap["Api1.data"]).toStrictEqual(
+ [],
+ );
+ expect(dataTreeEvaluator.dependencyMap["Api1.data[2]"]).toStrictEqual(
+ undefined,
+ );
+ expect(dataTreeEvaluator.dependencyMap["Text1.text"]).toStrictEqual(
+ [],
+ );
+ }
+ });
+
+ // when Text1.text has a binding Api1.data[2].id
+ it("on API response array length change", () => {
+ // success: response -> [{...}, {...}, {...}]
+ dataTreeEvaluator.updateDataTree(
+ arrayAccessorCyclicDependency.apiSuccessUnEvalTree,
+ );
+
+ // success: response -> [{...}, {...}]
+ dataTreeEvaluator.updateDataTree(
+ arrayAccessorCyclicDependency.apiSuccessUnEvalTree2,
+ );
+ expect(dataTreeEvaluator.dependencyMap["Api1"]).toStrictEqual([
+ "Api1.data",
+ ]);
+ expect(dataTreeEvaluator.dependencyMap["Api1.data"]).toStrictEqual([]);
+ expect(dataTreeEvaluator.dependencyMap["Api1.data[2]"]).toStrictEqual(
+ undefined,
+ );
+ expect(dataTreeEvaluator.dependencyMap["Text1.text"]).toStrictEqual([]);
+ });
+ });
+
+ describe("nested array of objects", () => {
+ // when Text1.text has a binding Api1.data[2][2].id
+ it("on consequent API failures", () => {
+ // cyclic dependency case
+ for (let i = 0; i < 2; i++) {
+ // success: response -> [ [{...}, {...}, {...}], [{...}, {...}, {...}], [{...}, {...}, {...}] ]
+ dataTreeEvaluator.updateDataTree(
+ nestedArrayAccessorCyclicDependency.apiSuccessUnEvalTree,
+ );
+ expect(dataTreeEvaluator.dependencyMap["Api1"]).toStrictEqual([
+ "Api1.data",
+ ]);
+ expect(dataTreeEvaluator.dependencyMap["Api1.data"]).toStrictEqual([
+ "Api1.data[2]",
+ ]);
+ expect(
+ dataTreeEvaluator.dependencyMap["Api1.data[2]"],
+ ).toStrictEqual(["Api1.data[2][2]"]);
+ expect(
+ dataTreeEvaluator.dependencyMap["Api1.data[2][2]"],
+ ).toStrictEqual(["Api1.data[2][2].id"]);
+ expect(dataTreeEvaluator.dependencyMap["Text1.text"]).toStrictEqual([
+ "Api1.data[2][2].id",
+ ]);
+
+ // failure: response -> {}
+ dataTreeEvaluator.updateDataTree(
+ nestedArrayAccessorCyclicDependency.apiFailureUnEvalTree,
+ );
+ expect(dataTreeEvaluator.dependencyMap["Api1"]).toStrictEqual([
+ "Api1.data",
+ ]);
+ expect(dataTreeEvaluator.dependencyMap["Api1.data"]).toStrictEqual(
+ [],
+ );
+ expect(dataTreeEvaluator.dependencyMap["Api1.data[2]"]).toStrictEqual(
+ undefined,
+ );
+ expect(
+ dataTreeEvaluator.dependencyMap["Api1.data[2][2]"],
+ ).toStrictEqual(undefined);
+ expect(dataTreeEvaluator.dependencyMap["Text1.text"]).toStrictEqual(
+ [],
+ );
+ }
+ });
+
+ // when Text1.text has a binding Api1.data[2][2].id
+ it("on API response array length change", () => {
+ // success: response -> [ [{...}, {...}, {...}], [{...}, {...}, {...}], [{...}, {...}, {...}] ]
+ dataTreeEvaluator.updateDataTree(
+ nestedArrayAccessorCyclicDependency.apiSuccessUnEvalTree,
+ );
+
+ // success: response -> [ [{...}, {...}, {...}], [{...}, {...}, {...}] ]
+ dataTreeEvaluator.updateDataTree(
+ nestedArrayAccessorCyclicDependency.apiSuccessUnEvalTree2,
+ );
+ expect(dataTreeEvaluator.dependencyMap["Api1"]).toStrictEqual([
+ "Api1.data",
+ ]);
+ expect(dataTreeEvaluator.dependencyMap["Api1.data"]).toStrictEqual([]);
+ expect(dataTreeEvaluator.dependencyMap["Api1.data[2]"]).toStrictEqual(
+ undefined,
+ );
+ expect(
+ dataTreeEvaluator.dependencyMap["Api1.data[2][2]"],
+ ).toStrictEqual(undefined);
+ expect(dataTreeEvaluator.dependencyMap["Text1.text"]).toStrictEqual([]);
+ });
+
+ // when Text1.text has a binding Api1.data[2][2].id
+ it("on API response nested array length change", () => {
+ // success: response -> [ [{...}, {...}, {...}], [{...}, {...}, {...}], [{...}, {...}, {...}] ]
+ dataTreeEvaluator.updateDataTree(
+ nestedArrayAccessorCyclicDependency.apiSuccessUnEvalTree,
+ );
+
+ // success: response -> [ [{...}, {...}, {...}], [{...}, {...}, {...}], [] ]
+ dataTreeEvaluator.updateDataTree(
+ nestedArrayAccessorCyclicDependency.apiSuccessUnEvalTree3,
+ );
+ expect(dataTreeEvaluator.dependencyMap["Api1"]).toStrictEqual([
+ "Api1.data",
+ ]);
+ expect(dataTreeEvaluator.dependencyMap["Api1.data"]).toStrictEqual([
+ "Api1.data[2]",
+ ]);
+ expect(dataTreeEvaluator.dependencyMap["Api1.data[2]"]).toStrictEqual(
+ [],
+ );
+ expect(
+ dataTreeEvaluator.dependencyMap["Api1.data[2][2]"],
+ ).toStrictEqual(undefined);
+ expect(dataTreeEvaluator.dependencyMap["Text1.text"]).toStrictEqual([]);
+ });
+ });
+ });
});
diff --git a/app/client/src/workers/DataTreeEvaluator/test/mockData/ArrayAccessorTree.ts b/app/client/src/workers/DataTreeEvaluator/test/mockData/ArrayAccessorTree.ts
new file mode 100644
index 0000000000..9663fa75ee
--- /dev/null
+++ b/app/client/src/workers/DataTreeEvaluator/test/mockData/ArrayAccessorTree.ts
@@ -0,0 +1,916 @@
+import { PluginType, PaginationType } from "entities/Action";
+import {
+ DataTree,
+ EvaluationSubstitutionType,
+ DataTreeAction,
+ DataTreeWidget,
+ ENTITY_TYPE,
+} from "entities/DataTree/dataTreeFactory";
+
+export const arrayAccessorCyclicDependency: Record = {
+ initUnEvalTree: {
+ Api1: ({
+ run: {},
+ clear: {},
+ actionId: "6285d928db0f9c6e620d454a",
+ name: "Api1",
+ pluginId: "5ca385dc81b37f0004b4db85",
+ pluginType: PluginType.API,
+ config: {
+ timeoutInMillisecond: 10000,
+ paginationType: PaginationType.NONE,
+ path: "/posts",
+ queryParameters: [
+ {
+ key: "",
+ value: "",
+ },
+ {
+ key: "",
+ value: "",
+ },
+ ],
+ pluginSpecifiedTemplates: [
+ {
+ value: true,
+ },
+ ],
+ formData: {
+ apiContentType: "none",
+ },
+ },
+ dynamicBindingPathList: [],
+ responseMeta: {
+ isExecutionSuccess: false,
+ },
+ ENTITY_TYPE: ENTITY_TYPE.ACTION,
+ isLoading: false,
+ bindingPaths: {
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ "config.queryParameters[0].key": EvaluationSubstitutionType.TEMPLATE,
+ "config.queryParameters[0].value": EvaluationSubstitutionType.TEMPLATE,
+ "config.queryParameters[1].key": EvaluationSubstitutionType.TEMPLATE,
+ "config.queryParameters[1].value": EvaluationSubstitutionType.TEMPLATE,
+ },
+ reactivePaths: {
+ data: EvaluationSubstitutionType.TEMPLATE,
+ isLoading: EvaluationSubstitutionType.TEMPLATE,
+ datasourceUrl: EvaluationSubstitutionType.TEMPLATE,
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ "config.queryParameters[0].key": EvaluationSubstitutionType.TEMPLATE,
+ "config.queryParameters[0].value": EvaluationSubstitutionType.TEMPLATE,
+ "config.queryParameters[1].key": EvaluationSubstitutionType.TEMPLATE,
+ "config.queryParameters[1].value": EvaluationSubstitutionType.TEMPLATE,
+ },
+ dependencyMap: {
+ "config.body": ["config.pluginSpecifiedTemplates[0].value"],
+ },
+ logBlackList: {},
+ datasourceUrl: "https://jsonplaceholder.typicode.com",
+ } as unknown) as DataTreeAction,
+ Text1: ({
+ widgetName: "Text1",
+ displayName: "Text",
+ iconSVG: "/static/media/icon.97c59b52.svg",
+ topRow: 14,
+ bottomRow: 18,
+ parentRowSpace: 10,
+ type: "TEXT_WIDGET",
+ hideCard: false,
+ animateLoading: true,
+ overflow: "NONE",
+ fontFamily: "{{appsmith.theme.fontFamily.appFont}}",
+ parentColumnSpace: 11.796875,
+ dynamicTriggerPathList: [],
+ leftColumn: 21,
+ dynamicBindingPathList: [
+ {
+ key: "fontFamily",
+ },
+ {
+ key: "borderRadius",
+ },
+ {
+ key: "text",
+ },
+ {
+ key: "value",
+ },
+ ],
+ shouldTruncate: false,
+ truncateButtonColor: "#FFC13D",
+ text: "{{\nApi1.data[2].id\n}}",
+ key: "ljtoov0cml",
+ rightColumn: 37,
+ textAlign: "LEFT",
+ widgetId: "1p9hcl50i8",
+ isVisible: true,
+ fontStyle: "BOLD",
+ textColor: "#231F20",
+ version: 1,
+ parentId: "0",
+ renderMode: "CANVAS",
+ isLoading: false,
+ borderRadius: "{{appsmith.theme.borderRadius.appBorderRadius}}",
+ fontSize: "1rem",
+ value: "{{ Text1.text }}",
+ defaultProps: {},
+ defaultMetaProps: [],
+ logBlackList: {
+ value: true,
+ },
+ propertyOverrideDependency: {},
+ overridingPropertyPaths: {},
+ bindingPaths: {
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ reactivePaths: {
+ value: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ borderRadius: EvaluationSubstitutionType.TEMPLATE,
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ triggerPaths: {},
+ validationPaths: {
+ text: {
+ type: "TEXT",
+ params: {
+ limitLineBreaks: true,
+ },
+ },
+ isVisible: {
+ type: "BOOLEAN",
+ },
+ animateLoading: {
+ type: "BOOLEAN",
+ },
+ disableLink: {
+ type: "BOOLEAN",
+ },
+ backgroundColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ expected: {
+ type: "string (HTML color name or HEX value)",
+ example: "red | #9C0D38",
+ autocompleteDataType: "STRING",
+ },
+ },
+ },
+ textColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ },
+ },
+ borderColor: {
+ type: "TEXT",
+ },
+ borderWidth: {
+ type: "NUMBER",
+ },
+ fontSize: {
+ type: "TEXT",
+ },
+ fontFamily: {
+ type: "TEXT",
+ },
+ fontStyle: {
+ type: "TEXT",
+ },
+ textAlign: {
+ type: "TEXT",
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.WIDGET,
+ privateWidgets: {},
+ meta: {},
+ } as unknown) as DataTreeWidget,
+ },
+ apiSuccessUnEvalTree: {
+ // success: response -> [{...}, {...}, {...}]
+ Api1: {
+ run: {},
+ clear: {},
+ actionId: "6285d928db0f9c6e620d454a",
+ name: "Api1",
+ pluginId: "5ca385dc81b37f0004b4db85",
+ pluginType: PluginType.API,
+ config: {
+ timeoutInMillisecond: 10000,
+ paginationType: PaginationType.NONE,
+ path: "/posts",
+ queryParameters: [],
+ pluginSpecifiedTemplates: [
+ {
+ value: true,
+ },
+ ],
+ formData: {
+ apiContentType: "none",
+ },
+ },
+ dynamicBindingPathList: [],
+ data: [
+ {
+ userId: 1,
+ id: 1,
+ title:
+ "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
+ body:
+ "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
+ },
+ {
+ userId: 1,
+ id: 2,
+ title: "qui est esse",
+ body:
+ "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla",
+ },
+ {
+ userId: 1,
+ id: 3,
+ title: "ea molestias quasi exercitationem repellat qui ipsa sit aut",
+ body:
+ "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut",
+ },
+ ],
+ responseMeta: {
+ statusCode: "200 OK",
+ isExecutionSuccess: true,
+ headers: {
+ Date: ["Fri, 20 May 2022 09:18:48 GMT"],
+ "Content-Type": ["application/json; charset=utf-8"],
+ "Transfer-Encoding": ["chunked"],
+ Connection: ["keep-alive"],
+ "X-Powered-By": ["Express"],
+ "X-Ratelimit-Limit": ["1000"],
+ "X-Ratelimit-Remaining": ["999"],
+ "X-Ratelimit-Reset": ["1652916230"],
+ Vary: ["Origin, Accept-Encoding"],
+ "Access-Control-Allow-Credentials": ["true"],
+ "Cache-Control": ["max-age=43200"],
+ Pragma: ["no-cache"],
+ Expires: ["-1"],
+ "X-Content-Type-Options": ["nosniff"],
+ Etag: ['W/"6b80-Ybsq/K6GwwqrYkAsFxqDXGC7DoM"'],
+ Via: ["1.1 vegur"],
+ "CF-Cache-Status": ["HIT"],
+ Age: ["6791"],
+ "Expect-CT": [
+ 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"',
+ ],
+ "Report-To": [
+ '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=mL80WXGZevCRJ%2BH3N6Uq0dvpeHk%2BFLrmzIZMCcTnH10LlRna45sxEdLPMELrTur3z3Tr8ucgNQ7X%2FuIhNRTRj00%2FvML3zxIkOIZsrKf3iTIeQDts3oFwUg9b51xg0IDoperi1JchNq5muJETOeT%2B"}],"group":"cf-nel","max_age":604800}',
+ ],
+ NEL: ['{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'],
+ Server: ["cloudflare"],
+ "CF-RAY": ["70e3fcb39dde18ce-SIN"],
+ "alt-svc": ['h3=":443"; ma=86400, h3-29=":443"; ma=86400'],
+ "X-APPSMITH-DATATYPE": ["JSON"],
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.ACTION,
+ isLoading: false,
+ bindingPaths: {
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ },
+ reactivePaths: {
+ data: EvaluationSubstitutionType.TEMPLATE,
+ isLoading: EvaluationSubstitutionType.TEMPLATE,
+ datasourceUrl: EvaluationSubstitutionType.TEMPLATE,
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ },
+ dependencyMap: {
+ "config.body": ["config.pluginSpecifiedTemplates[0].value"],
+ },
+ logBlackList: {},
+ datasourceUrl: "https://jsonplaceholder.typicode.com",
+ },
+ // Text1.text binding Api1.data[2].id
+ Text1: ({
+ widgetName: "Text1",
+ displayName: "Text",
+ iconSVG: "/static/media/icon.97c59b52.svg",
+ topRow: 14,
+ bottomRow: 18,
+ parentRowSpace: 10,
+ type: "TEXT_WIDGET",
+ hideCard: false,
+ animateLoading: true,
+ overflow: "NONE",
+ fontFamily: "{{appsmith.theme.fontFamily.appFont}}",
+ parentColumnSpace: 11.796875,
+ dynamicTriggerPathList: [],
+ leftColumn: 21,
+ dynamicBindingPathList: [
+ {
+ key: "fontFamily",
+ },
+ {
+ key: "borderRadius",
+ },
+ {
+ key: "text",
+ },
+ {
+ key: "value",
+ },
+ ],
+ shouldTruncate: false,
+ truncateButtonColor: "#FFC13D",
+ text: "{{\nApi1.data[2].id\n}}",
+ key: "ljtoov0cml",
+ rightColumn: 37,
+ textAlign: "LEFT",
+ widgetId: "1p9hcl50i8",
+ isVisible: true,
+ fontStyle: "BOLD",
+ textColor: "#231F20",
+ version: 1,
+ parentId: "0",
+ renderMode: "CANVAS",
+ isLoading: false,
+ borderRadius: "{{appsmith.theme.borderRadius.appBorderRadius}}",
+ fontSize: "1rem",
+ value: "{{ Text1.text }}",
+ defaultProps: {},
+ defaultMetaProps: [],
+ logBlackList: {
+ value: true,
+ },
+ propertyOverrideDependency: {},
+ overridingPropertyPaths: {},
+ bindingPaths: {
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ reactivePaths: {
+ value: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ borderRadius: EvaluationSubstitutionType.TEMPLATE,
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ triggerPaths: {},
+ validationPaths: {
+ text: {
+ type: "TEXT",
+ params: {
+ limitLineBreaks: true,
+ },
+ },
+ isVisible: {
+ type: "BOOLEAN",
+ },
+ animateLoading: {
+ type: "BOOLEAN",
+ },
+ disableLink: {
+ type: "BOOLEAN",
+ },
+ backgroundColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ expected: {
+ type: "string (HTML color name or HEX value)",
+ example: "red | #9C0D38",
+ autocompleteDataType: "STRING",
+ },
+ },
+ },
+ textColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ },
+ },
+ borderColor: {
+ type: "TEXT",
+ },
+ borderWidth: {
+ type: "NUMBER",
+ },
+ fontSize: {
+ type: "TEXT",
+ },
+ fontFamily: {
+ type: "TEXT",
+ },
+ fontStyle: {
+ type: "TEXT",
+ },
+ textAlign: {
+ type: "TEXT",
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.WIDGET,
+ privateWidgets: {},
+ meta: {},
+ } as unknown) as DataTreeWidget,
+ },
+ apiFailureUnEvalTree: {
+ // failure: response -> {}
+ Api1: {
+ run: {},
+ clear: {},
+ actionId: "6285d928db0f9c6e620d454a",
+ name: "Api1",
+ pluginId: "5ca385dc81b37f0004b4db85",
+ pluginType: PluginType.API,
+ config: {
+ timeoutInMillisecond: 10000,
+ paginationType: PaginationType.NONE,
+ path: "/pos",
+ queryParameters: [],
+ pluginSpecifiedTemplates: [
+ {
+ value: true,
+ },
+ ],
+ formData: {
+ apiContentType: "none",
+ },
+ },
+ dynamicBindingPathList: [],
+ data: {},
+ responseMeta: {
+ statusCode: "404 NOT_FOUND",
+ isExecutionSuccess: false,
+ headers: {
+ Date: ["Fri, 20 May 2022 09:20:01 GMT"],
+ "Content-Type": ["application/json; charset=utf-8"],
+ Connection: ["keep-alive"],
+ "X-Powered-By": ["Express"],
+ "X-Ratelimit-Limit": ["1000"],
+ "X-Ratelimit-Remaining": ["999"],
+ "X-Ratelimit-Reset": ["1653038437"],
+ Vary: ["Origin, Accept-Encoding"],
+ "Access-Control-Allow-Credentials": ["true"],
+ "Cache-Control": ["max-age=43200"],
+ Pragma: ["no-cache"],
+ Expires: ["-1"],
+ "X-Content-Type-Options": ["nosniff"],
+ Etag: ['W/"2-vyGp6PvFo4RvsFtPoIWeCReyIC8"'],
+ Via: ["1.1 vegur"],
+ "CF-Cache-Status": ["EXPIRED"],
+ "Expect-CT": [
+ 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"',
+ ],
+ "Report-To": [
+ '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=UkqmMMihJpG%2BIoEcVub10200FpqRPQDDipw0gOy%2B5nYRyuF6NZ4X1CoNEXk2YLHb%2FLkt%2F1rXFAJJq5xwJtRgb6%2BsXwWEAqWi5vSP5D6DMhVyP%2Fyr5Q5FQc3dfILZfmeEoCWKxlEq0AfhOOKThz%2BK"}],"group":"cf-nel","max_age":604800}',
+ ],
+ NEL: ['{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'],
+ Server: ["cloudflare"],
+ "CF-RAY": ["70e3fe76b80d9f86-SIN"],
+ "alt-svc": ['h3=":443"; ma=86400, h3-29=":443"; ma=86400'],
+ "content-length": ["2"],
+ "X-APPSMITH-DATATYPE": ["JSON"],
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.ACTION,
+ isLoading: false,
+ bindingPaths: {
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ },
+ reactivePaths: {
+ data: EvaluationSubstitutionType.TEMPLATE,
+ isLoading: EvaluationSubstitutionType.TEMPLATE,
+ datasourceUrl: EvaluationSubstitutionType.TEMPLATE,
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ },
+ dependencyMap: {
+ "config.body": ["config.pluginSpecifiedTemplates[0].value"],
+ },
+ logBlackList: {},
+ datasourceUrl: "https://jsonplaceholder.typicode.com",
+ },
+ // Text1.text binding Api1.data[2].id
+ Text1: ({
+ widgetName: "Text1",
+ displayName: "Text",
+ iconSVG: "/static/media/icon.97c59b52.svg",
+ topRow: 14,
+ bottomRow: 18,
+ parentRowSpace: 10,
+ type: "TEXT_WIDGET",
+ hideCard: false,
+ animateLoading: true,
+ overflow: "NONE",
+ fontFamily: "{{appsmith.theme.fontFamily.appFont}}",
+ parentColumnSpace: 11.796875,
+ dynamicTriggerPathList: [],
+ leftColumn: 21,
+ dynamicBindingPathList: [
+ {
+ key: "fontFamily",
+ },
+ {
+ key: "borderRadius",
+ },
+ {
+ key: "text",
+ },
+ {
+ key: "value",
+ },
+ ],
+ shouldTruncate: false,
+ truncateButtonColor: "#FFC13D",
+ text: "{{\nApi1.data[2].id\n}}",
+ key: "ljtoov0cml",
+ rightColumn: 37,
+ textAlign: "LEFT",
+ widgetId: "1p9hcl50i8",
+ isVisible: true,
+ fontStyle: "BOLD",
+ textColor: "#231F20",
+ version: 1,
+ parentId: "0",
+ renderMode: "CANVAS",
+ isLoading: false,
+ borderRadius: "{{appsmith.theme.borderRadius.appBorderRadius}}",
+ fontSize: "1rem",
+ value: "{{ Text1.text }}",
+ defaultProps: {},
+ defaultMetaProps: [],
+ logBlackList: {
+ value: true,
+ },
+ propertyOverrideDependency: {},
+ overridingPropertyPaths: {},
+ bindingPaths: {
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ reactivePaths: {
+ value: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ borderRadius: EvaluationSubstitutionType.TEMPLATE,
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ triggerPaths: {},
+ validationPaths: {
+ text: {
+ type: "TEXT",
+ params: {
+ limitLineBreaks: true,
+ },
+ },
+ isVisible: {
+ type: "BOOLEAN",
+ },
+ animateLoading: {
+ type: "BOOLEAN",
+ },
+ disableLink: {
+ type: "BOOLEAN",
+ },
+ backgroundColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ expected: {
+ type: "string (HTML color name or HEX value)",
+ example: "red | #9C0D38",
+ autocompleteDataType: "STRING",
+ },
+ },
+ },
+ textColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ },
+ },
+ borderColor: {
+ type: "TEXT",
+ },
+ borderWidth: {
+ type: "NUMBER",
+ },
+ fontSize: {
+ type: "TEXT",
+ },
+ fontFamily: {
+ type: "TEXT",
+ },
+ fontStyle: {
+ type: "TEXT",
+ },
+ textAlign: {
+ type: "TEXT",
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.WIDGET,
+ privateWidgets: {},
+ meta: {},
+ } as unknown) as DataTreeWidget,
+ },
+ apiSuccessUnEvalTree2: {
+ // success: response -> [{...}, {...}]
+ Api1: {
+ run: {},
+ clear: {},
+ actionId: "6285d928db0f9c6e620d454a",
+ name: "Api1",
+ pluginId: "5ca385dc81b37f0004b4db85",
+ pluginType: PluginType.API,
+ config: {
+ timeoutInMillisecond: 10000,
+ paginationType: PaginationType.NONE,
+ path: "/posts",
+ queryParameters: [],
+ pluginSpecifiedTemplates: [
+ {
+ value: true,
+ },
+ ],
+ formData: {
+ apiContentType: "none",
+ },
+ },
+ dynamicBindingPathList: [],
+ data: [
+ {
+ userId: 1,
+ id: 1,
+ title:
+ "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
+ body:
+ "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
+ },
+ {
+ userId: 1,
+ id: 2,
+ title:
+ "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
+ body:
+ "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
+ },
+ ],
+ responseMeta: {
+ statusCode: "200 OK",
+ isExecutionSuccess: true,
+ headers: {
+ Date: ["Fri, 20 May 2022 09:18:48 GMT"],
+ "Content-Type": ["application/json; charset=utf-8"],
+ "Transfer-Encoding": ["chunked"],
+ Connection: ["keep-alive"],
+ "X-Powered-By": ["Express"],
+ "X-Ratelimit-Limit": ["1000"],
+ "X-Ratelimit-Remaining": ["999"],
+ "X-Ratelimit-Reset": ["1652916230"],
+ Vary: ["Origin, Accept-Encoding"],
+ "Access-Control-Allow-Credentials": ["true"],
+ "Cache-Control": ["max-age=43200"],
+ Pragma: ["no-cache"],
+ Expires: ["-1"],
+ "X-Content-Type-Options": ["nosniff"],
+ Etag: ['W/"6b80-Ybsq/K6GwwqrYkAsFxqDXGC7DoM"'],
+ Via: ["1.1 vegur"],
+ "CF-Cache-Status": ["HIT"],
+ Age: ["6791"],
+ "Expect-CT": [
+ 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"',
+ ],
+ "Report-To": [
+ '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=mL80WXGZevCRJ%2BH3N6Uq0dvpeHk%2BFLrmzIZMCcTnH10LlRna45sxEdLPMELrTur3z3Tr8ucgNQ7X%2FuIhNRTRj00%2FvML3zxIkOIZsrKf3iTIeQDts3oFwUg9b51xg0IDoperi1JchNq5muJETOeT%2B"}],"group":"cf-nel","max_age":604800}',
+ ],
+ NEL: ['{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'],
+ Server: ["cloudflare"],
+ "CF-RAY": ["70e3fcb39dde18ce-SIN"],
+ "alt-svc": ['h3=":443"; ma=86400, h3-29=":443"; ma=86400'],
+ "X-APPSMITH-DATATYPE": ["JSON"],
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.ACTION,
+ isLoading: false,
+ bindingPaths: {
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ },
+ reactivePaths: {
+ data: EvaluationSubstitutionType.TEMPLATE,
+ isLoading: EvaluationSubstitutionType.TEMPLATE,
+ datasourceUrl: EvaluationSubstitutionType.TEMPLATE,
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ },
+ dependencyMap: {
+ "config.body": ["config.pluginSpecifiedTemplates[0].value"],
+ },
+ logBlackList: {},
+ datasourceUrl: "https://jsonplaceholder.typicode.com",
+ },
+ // Text1.text binding Api1.data[2].id
+ Text1: ({
+ widgetName: "Text1",
+ displayName: "Text",
+ iconSVG: "/static/media/icon.97c59b52.svg",
+ topRow: 14,
+ bottomRow: 18,
+ parentRowSpace: 10,
+ type: "TEXT_WIDGET",
+ hideCard: false,
+ animateLoading: true,
+ overflow: "NONE",
+ fontFamily: "{{appsmith.theme.fontFamily.appFont}}",
+ parentColumnSpace: 11.796875,
+ dynamicTriggerPathList: [],
+ leftColumn: 21,
+ dynamicBindingPathList: [
+ {
+ key: "fontFamily",
+ },
+ {
+ key: "borderRadius",
+ },
+ {
+ key: "text",
+ },
+ {
+ key: "value",
+ },
+ ],
+ shouldTruncate: false,
+ truncateButtonColor: "#FFC13D",
+ text: "{{\nApi1.data[2].id\n}}",
+ key: "ljtoov0cml",
+ rightColumn: 37,
+ textAlign: "LEFT",
+ widgetId: "1p9hcl50i8",
+ isVisible: true,
+ fontStyle: "BOLD",
+ textColor: "#231F20",
+ version: 1,
+ parentId: "0",
+ renderMode: "CANVAS",
+ isLoading: false,
+ borderRadius: "{{appsmith.theme.borderRadius.appBorderRadius}}",
+ fontSize: "1rem",
+ value: "{{ Text1.text }}",
+ defaultProps: {},
+ defaultMetaProps: [],
+ logBlackList: {
+ value: true,
+ },
+ propertyOverrideDependency: {},
+ overridingPropertyPaths: {},
+ bindingPaths: {
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ reactivePaths: {
+ value: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ borderRadius: EvaluationSubstitutionType.TEMPLATE,
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ triggerPaths: {},
+ validationPaths: {
+ text: {
+ type: "TEXT",
+ params: {
+ limitLineBreaks: true,
+ },
+ },
+ isVisible: {
+ type: "BOOLEAN",
+ },
+ animateLoading: {
+ type: "BOOLEAN",
+ },
+ disableLink: {
+ type: "BOOLEAN",
+ },
+ backgroundColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ expected: {
+ type: "string (HTML color name or HEX value)",
+ example: "red | #9C0D38",
+ autocompleteDataType: "STRING",
+ },
+ },
+ },
+ textColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ },
+ },
+ borderColor: {
+ type: "TEXT",
+ },
+ borderWidth: {
+ type: "NUMBER",
+ },
+ fontSize: {
+ type: "TEXT",
+ },
+ fontFamily: {
+ type: "TEXT",
+ },
+ fontStyle: {
+ type: "TEXT",
+ },
+ textAlign: {
+ type: "TEXT",
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.WIDGET,
+ privateWidgets: {},
+ meta: {},
+ } as unknown) as DataTreeWidget,
+ },
+};
diff --git a/app/client/src/workers/DataTreeEvaluator/test/mockData/NestedArrayAccessorTree.ts b/app/client/src/workers/DataTreeEvaluator/test/mockData/NestedArrayAccessorTree.ts
new file mode 100644
index 0000000000..9def250bed
--- /dev/null
+++ b/app/client/src/workers/DataTreeEvaluator/test/mockData/NestedArrayAccessorTree.ts
@@ -0,0 +1,1275 @@
+import { PluginType, PaginationType } from "entities/Action";
+import {
+ DataTree,
+ EvaluationSubstitutionType,
+ DataTreeAction,
+ DataTreeWidget,
+ ENTITY_TYPE,
+} from "entities/DataTree/dataTreeFactory";
+
+export const nestedArrayAccessorCyclicDependency: Record = {
+ initUnEvalTree: {
+ Api1: ({
+ run: {},
+ clear: {},
+ actionId: "6285d928db0f9c6e620d454a",
+ name: "Api1",
+ pluginId: "5ca385dc81b37f0004b4db85",
+ pluginType: PluginType.API,
+ config: {
+ timeoutInMillisecond: 10000,
+ paginationType: PaginationType.NONE,
+ path: "/posts",
+ queryParameters: [
+ {
+ key: "",
+ value: "",
+ },
+ {
+ key: "",
+ value: "",
+ },
+ ],
+ pluginSpecifiedTemplates: [
+ {
+ value: true,
+ },
+ ],
+ formData: {
+ apiContentType: "none",
+ },
+ },
+ dynamicBindingPathList: [],
+ responseMeta: {
+ isExecutionSuccess: false,
+ },
+ ENTITY_TYPE: ENTITY_TYPE.ACTION,
+ isLoading: false,
+ bindingPaths: {
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ "config.queryParameters[0].key": EvaluationSubstitutionType.TEMPLATE,
+ "config.queryParameters[0].value": EvaluationSubstitutionType.TEMPLATE,
+ "config.queryParameters[1].key": EvaluationSubstitutionType.TEMPLATE,
+ "config.queryParameters[1].value": EvaluationSubstitutionType.TEMPLATE,
+ },
+ reactivePaths: {
+ data: EvaluationSubstitutionType.TEMPLATE,
+ isLoading: EvaluationSubstitutionType.TEMPLATE,
+ datasourceUrl: EvaluationSubstitutionType.TEMPLATE,
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ "config.queryParameters[0].key": EvaluationSubstitutionType.TEMPLATE,
+ "config.queryParameters[0].value": EvaluationSubstitutionType.TEMPLATE,
+ "config.queryParameters[1].key": EvaluationSubstitutionType.TEMPLATE,
+ "config.queryParameters[1].value": EvaluationSubstitutionType.TEMPLATE,
+ },
+ dependencyMap: {
+ "config.body": ["config.pluginSpecifiedTemplates[0].value"],
+ },
+ logBlackList: {},
+ datasourceUrl: "https://jsonplaceholder.typicode.com",
+ } as unknown) as DataTreeAction,
+ Text1: ({
+ widgetName: "Text1",
+ displayName: "Text",
+ iconSVG: "/static/media/icon.97c59b52.svg",
+ topRow: 14,
+ bottomRow: 18,
+ parentRowSpace: 10,
+ type: "TEXT_WIDGET",
+ hideCard: false,
+ animateLoading: true,
+ overflow: "NONE",
+ fontFamily: "{{appsmith.theme.fontFamily.appFont}}",
+ parentColumnSpace: 11.796875,
+ dynamicTriggerPathList: [],
+ leftColumn: 21,
+ dynamicBindingPathList: [
+ {
+ key: "fontFamily",
+ },
+ {
+ key: "borderRadius",
+ },
+ {
+ key: "text",
+ },
+ {
+ key: "value",
+ },
+ ],
+ shouldTruncate: false,
+ truncateButtonColor: "#FFC13D",
+ text: "{{\nApi1.data[2][2].id\n}}",
+ key: "ljtoov0cml",
+ rightColumn: 37,
+ textAlign: "LEFT",
+ widgetId: "1p9hcl50i8",
+ isVisible: true,
+ fontStyle: "BOLD",
+ textColor: "#231F20",
+ version: 1,
+ parentId: "0",
+ renderMode: "CANVAS",
+ isLoading: false,
+ borderRadius: "{{appsmith.theme.borderRadius.appBorderRadius}}",
+ fontSize: "1rem",
+ value: "{{ Text1.text }}",
+ defaultProps: {},
+ defaultMetaProps: [],
+ logBlackList: {
+ value: true,
+ },
+ propertyOverrideDependency: {},
+ overridingPropertyPaths: {},
+ bindingPaths: {
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ reactivePaths: {
+ value: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ borderRadius: EvaluationSubstitutionType.TEMPLATE,
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ triggerPaths: {},
+ validationPaths: {
+ text: {
+ type: "TEXT",
+ params: {
+ limitLineBreaks: true,
+ },
+ },
+ isVisible: {
+ type: "BOOLEAN",
+ },
+ animateLoading: {
+ type: "BOOLEAN",
+ },
+ disableLink: {
+ type: "BOOLEAN",
+ },
+ backgroundColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ expected: {
+ type: "string (HTML color name or HEX value)",
+ example: "red | #9C0D38",
+ autocompleteDataType: "STRING",
+ },
+ },
+ },
+ textColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ },
+ },
+ borderColor: {
+ type: "TEXT",
+ },
+ borderWidth: {
+ type: "NUMBER",
+ },
+ fontSize: {
+ type: "TEXT",
+ },
+ fontFamily: {
+ type: "TEXT",
+ },
+ fontStyle: {
+ type: "TEXT",
+ },
+ textAlign: {
+ type: "TEXT",
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.WIDGET,
+ privateWidgets: {},
+ meta: {},
+ } as unknown) as DataTreeWidget,
+ },
+ apiSuccessUnEvalTree: {
+ // success: response -> [ [{...}, {...}, {...}], [{...}, {...}, {...}], [{...}, {...}, {...}] ]
+ Api1: {
+ run: {},
+ clear: {},
+ actionId: "6285d928db0f9c6e620d454a",
+ name: "Api1",
+ pluginId: "5ca385dc81b37f0004b4db85",
+ pluginType: PluginType.API,
+ config: {
+ timeoutInMillisecond: 10000,
+ paginationType: PaginationType.NONE,
+ path: "/posts",
+ queryParameters: [],
+ pluginSpecifiedTemplates: [
+ {
+ value: true,
+ },
+ ],
+ formData: {
+ apiContentType: "none",
+ },
+ },
+ dynamicBindingPathList: [],
+ data: [
+ [
+ {
+ userId: 1,
+ id: 1,
+ title:
+ "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
+ body:
+ "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
+ },
+ {
+ userId: 1,
+ id: 2,
+ title: "qui est esse",
+ body:
+ "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla",
+ },
+ {
+ userId: 1,
+ id: 3,
+ title:
+ "ea molestias quasi exercitationem repellat qui ipsa sit aut",
+ body:
+ "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut",
+ },
+ ],
+ [
+ {
+ userId: 1,
+ id: 1,
+ title:
+ "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
+ body:
+ "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
+ },
+ {
+ userId: 1,
+ id: 2,
+ title: "qui est esse",
+ body:
+ "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla",
+ },
+ {
+ userId: 1,
+ id: 3,
+ title:
+ "ea molestias quasi exercitationem repellat qui ipsa sit aut",
+ body:
+ "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut",
+ },
+ ],
+ [
+ {
+ userId: 1,
+ id: 1,
+ title:
+ "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
+ body:
+ "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
+ },
+ {
+ userId: 1,
+ id: 2,
+ title: "qui est esse",
+ body:
+ "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla",
+ },
+ {
+ userId: 1,
+ id: 3,
+ title:
+ "ea molestias quasi exercitationem repellat qui ipsa sit aut",
+ body:
+ "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut",
+ },
+ ],
+ ],
+ responseMeta: {
+ statusCode: "200 OK",
+ isExecutionSuccess: true,
+ headers: {
+ Date: ["Fri, 20 May 2022 09:18:48 GMT"],
+ "Content-Type": ["application/json; charset=utf-8"],
+ "Transfer-Encoding": ["chunked"],
+ Connection: ["keep-alive"],
+ "X-Powered-By": ["Express"],
+ "X-Ratelimit-Limit": ["1000"],
+ "X-Ratelimit-Remaining": ["999"],
+ "X-Ratelimit-Reset": ["1652916230"],
+ Vary: ["Origin, Accept-Encoding"],
+ "Access-Control-Allow-Credentials": ["true"],
+ "Cache-Control": ["max-age=43200"],
+ Pragma: ["no-cache"],
+ Expires: ["-1"],
+ "X-Content-Type-Options": ["nosniff"],
+ Etag: ['W/"6b80-Ybsq/K6GwwqrYkAsFxqDXGC7DoM"'],
+ Via: ["1.1 vegur"],
+ "CF-Cache-Status": ["HIT"],
+ Age: ["6791"],
+ "Expect-CT": [
+ 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"',
+ ],
+ "Report-To": [
+ '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=mL80WXGZevCRJ%2BH3N6Uq0dvpeHk%2BFLrmzIZMCcTnH10LlRna45sxEdLPMELrTur3z3Tr8ucgNQ7X%2FuIhNRTRj00%2FvML3zxIkOIZsrKf3iTIeQDts3oFwUg9b51xg0IDoperi1JchNq5muJETOeT%2B"}],"group":"cf-nel","max_age":604800}',
+ ],
+ NEL: ['{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'],
+ Server: ["cloudflare"],
+ "CF-RAY": ["70e3fcb39dde18ce-SIN"],
+ "alt-svc": ['h3=":443"; ma=86400, h3-29=":443"; ma=86400'],
+ "X-APPSMITH-DATATYPE": ["JSON"],
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.ACTION,
+ isLoading: false,
+ bindingPaths: {
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ },
+ reactivePaths: {
+ data: EvaluationSubstitutionType.TEMPLATE,
+ isLoading: EvaluationSubstitutionType.TEMPLATE,
+ datasourceUrl: EvaluationSubstitutionType.TEMPLATE,
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ },
+ dependencyMap: {
+ "config.body": ["config.pluginSpecifiedTemplates[0].value"],
+ },
+ logBlackList: {},
+ datasourceUrl: "https://jsonplaceholder.typicode.com",
+ },
+ // Text1.text binding Api1.data[2][2].id
+ Text1: ({
+ widgetName: "Text1",
+ displayName: "Text",
+ iconSVG: "/static/media/icon.97c59b52.svg",
+ topRow: 14,
+ bottomRow: 18,
+ parentRowSpace: 10,
+ type: "TEXT_WIDGET",
+ hideCard: false,
+ animateLoading: true,
+ overflow: "NONE",
+ fontFamily: "{{appsmith.theme.fontFamily.appFont}}",
+ parentColumnSpace: 11.796875,
+ dynamicTriggerPathList: [],
+ leftColumn: 21,
+ dynamicBindingPathList: [
+ {
+ key: "fontFamily",
+ },
+ {
+ key: "borderRadius",
+ },
+ {
+ key: "text",
+ },
+ {
+ key: "value",
+ },
+ ],
+ shouldTruncate: false,
+ truncateButtonColor: "#FFC13D",
+ text: "{{\nApi1.data[2][2].id\n}}",
+ key: "ljtoov0cml",
+ rightColumn: 37,
+ textAlign: "LEFT",
+ widgetId: "1p9hcl50i8",
+ isVisible: true,
+ fontStyle: "BOLD",
+ textColor: "#231F20",
+ version: 1,
+ parentId: "0",
+ renderMode: "CANVAS",
+ isLoading: false,
+ borderRadius: "{{appsmith.theme.borderRadius.appBorderRadius}}",
+ fontSize: "1rem",
+ value: "{{ Text1.text }}",
+ defaultProps: {},
+ defaultMetaProps: [],
+ logBlackList: {
+ value: true,
+ },
+ propertyOverrideDependency: {},
+ overridingPropertyPaths: {},
+ bindingPaths: {
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ reactivePaths: {
+ value: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ borderRadius: EvaluationSubstitutionType.TEMPLATE,
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ triggerPaths: {},
+ validationPaths: {
+ text: {
+ type: "TEXT",
+ params: {
+ limitLineBreaks: true,
+ },
+ },
+ isVisible: {
+ type: "BOOLEAN",
+ },
+ animateLoading: {
+ type: "BOOLEAN",
+ },
+ disableLink: {
+ type: "BOOLEAN",
+ },
+ backgroundColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ expected: {
+ type: "string (HTML color name or HEX value)",
+ example: "red | #9C0D38",
+ autocompleteDataType: "STRING",
+ },
+ },
+ },
+ textColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ },
+ },
+ borderColor: {
+ type: "TEXT",
+ },
+ borderWidth: {
+ type: "NUMBER",
+ },
+ fontSize: {
+ type: "TEXT",
+ },
+ fontFamily: {
+ type: "TEXT",
+ },
+ fontStyle: {
+ type: "TEXT",
+ },
+ textAlign: {
+ type: "TEXT",
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.WIDGET,
+ privateWidgets: {},
+ meta: {},
+ } as unknown) as DataTreeWidget,
+ },
+ apiFailureUnEvalTree: {
+ // failure: response -> {}
+ Api1: {
+ run: {},
+ clear: {},
+ actionId: "6285d928db0f9c6e620d454a",
+ name: "Api1",
+ pluginId: "5ca385dc81b37f0004b4db85",
+ pluginType: PluginType.API,
+ config: {
+ timeoutInMillisecond: 10000,
+ paginationType: PaginationType.NONE,
+ path: "/pos",
+ queryParameters: [],
+ pluginSpecifiedTemplates: [
+ {
+ value: true,
+ },
+ ],
+ formData: {
+ apiContentType: "none",
+ },
+ },
+ dynamicBindingPathList: [],
+ data: {},
+ responseMeta: {
+ statusCode: "404 NOT_FOUND",
+ isExecutionSuccess: false,
+ headers: {
+ Date: ["Fri, 20 May 2022 09:20:01 GMT"],
+ "Content-Type": ["application/json; charset=utf-8"],
+ Connection: ["keep-alive"],
+ "X-Powered-By": ["Express"],
+ "X-Ratelimit-Limit": ["1000"],
+ "X-Ratelimit-Remaining": ["999"],
+ "X-Ratelimit-Reset": ["1653038437"],
+ Vary: ["Origin, Accept-Encoding"],
+ "Access-Control-Allow-Credentials": ["true"],
+ "Cache-Control": ["max-age=43200"],
+ Pragma: ["no-cache"],
+ Expires: ["-1"],
+ "X-Content-Type-Options": ["nosniff"],
+ Etag: ['W/"2-vyGp6PvFo4RvsFtPoIWeCReyIC8"'],
+ Via: ["1.1 vegur"],
+ "CF-Cache-Status": ["EXPIRED"],
+ "Expect-CT": [
+ 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"',
+ ],
+ "Report-To": [
+ '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=UkqmMMihJpG%2BIoEcVub10200FpqRPQDDipw0gOy%2B5nYRyuF6NZ4X1CoNEXk2YLHb%2FLkt%2F1rXFAJJq5xwJtRgb6%2BsXwWEAqWi5vSP5D6DMhVyP%2Fyr5Q5FQc3dfILZfmeEoCWKxlEq0AfhOOKThz%2BK"}],"group":"cf-nel","max_age":604800}',
+ ],
+ NEL: ['{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'],
+ Server: ["cloudflare"],
+ "CF-RAY": ["70e3fe76b80d9f86-SIN"],
+ "alt-svc": ['h3=":443"; ma=86400, h3-29=":443"; ma=86400'],
+ "content-length": ["2"],
+ "X-APPSMITH-DATATYPE": ["JSON"],
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.ACTION,
+ isLoading: false,
+ bindingPaths: {
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ },
+ reactivePaths: {
+ data: EvaluationSubstitutionType.TEMPLATE,
+ isLoading: EvaluationSubstitutionType.TEMPLATE,
+ datasourceUrl: EvaluationSubstitutionType.TEMPLATE,
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ },
+ dependencyMap: {
+ "config.body": ["config.pluginSpecifiedTemplates[0].value"],
+ },
+ logBlackList: {},
+ datasourceUrl: "https://jsonplaceholder.typicode.com",
+ },
+ // Text1.text binding Api1.data[2][2].id
+ Text1: ({
+ widgetName: "Text1",
+ displayName: "Text",
+ iconSVG: "/static/media/icon.97c59b52.svg",
+ topRow: 14,
+ bottomRow: 18,
+ parentRowSpace: 10,
+ type: "TEXT_WIDGET",
+ hideCard: false,
+ animateLoading: true,
+ overflow: "NONE",
+ fontFamily: "{{appsmith.theme.fontFamily.appFont}}",
+ parentColumnSpace: 11.796875,
+ dynamicTriggerPathList: [],
+ leftColumn: 21,
+ dynamicBindingPathList: [
+ {
+ key: "fontFamily",
+ },
+ {
+ key: "borderRadius",
+ },
+ {
+ key: "text",
+ },
+ {
+ key: "value",
+ },
+ ],
+ shouldTruncate: false,
+ truncateButtonColor: "#FFC13D",
+ text: "{{\nApi1.data[2][2].id\n}}",
+ key: "ljtoov0cml",
+ rightColumn: 37,
+ textAlign: "LEFT",
+ widgetId: "1p9hcl50i8",
+ isVisible: true,
+ fontStyle: "BOLD",
+ textColor: "#231F20",
+ version: 1,
+ parentId: "0",
+ renderMode: "CANVAS",
+ isLoading: false,
+ borderRadius: "{{appsmith.theme.borderRadius.appBorderRadius}}",
+ fontSize: "1rem",
+ value: "{{ Text1.text }}",
+ defaultProps: {},
+ defaultMetaProps: [],
+ logBlackList: {
+ value: true,
+ },
+ propertyOverrideDependency: {},
+ overridingPropertyPaths: {},
+ bindingPaths: {
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ reactivePaths: {
+ value: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ borderRadius: EvaluationSubstitutionType.TEMPLATE,
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ triggerPaths: {},
+ validationPaths: {
+ text: {
+ type: "TEXT",
+ params: {
+ limitLineBreaks: true,
+ },
+ },
+ isVisible: {
+ type: "BOOLEAN",
+ },
+ animateLoading: {
+ type: "BOOLEAN",
+ },
+ disableLink: {
+ type: "BOOLEAN",
+ },
+ backgroundColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ expected: {
+ type: "string (HTML color name or HEX value)",
+ example: "red | #9C0D38",
+ autocompleteDataType: "STRING",
+ },
+ },
+ },
+ textColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ },
+ },
+ borderColor: {
+ type: "TEXT",
+ },
+ borderWidth: {
+ type: "NUMBER",
+ },
+ fontSize: {
+ type: "TEXT",
+ },
+ fontFamily: {
+ type: "TEXT",
+ },
+ fontStyle: {
+ type: "TEXT",
+ },
+ textAlign: {
+ type: "TEXT",
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.WIDGET,
+ privateWidgets: {},
+ meta: {},
+ } as unknown) as DataTreeWidget,
+ },
+ apiSuccessUnEvalTree2: {
+ // success: response -> [ [{...}, {...}, {...}], [{...}, {...}, {...}] ]
+ Api1: {
+ run: {},
+ clear: {},
+ actionId: "6285d928db0f9c6e620d454a",
+ name: "Api1",
+ pluginId: "5ca385dc81b37f0004b4db85",
+ pluginType: PluginType.API,
+ config: {
+ timeoutInMillisecond: 10000,
+ paginationType: PaginationType.NONE,
+ path: "/posts",
+ queryParameters: [],
+ pluginSpecifiedTemplates: [
+ {
+ value: true,
+ },
+ ],
+ formData: {
+ apiContentType: "none",
+ },
+ },
+ dynamicBindingPathList: [],
+ data: [
+ [
+ {
+ userId: 1,
+ id: 1,
+ title:
+ "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
+ body:
+ "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
+ },
+ {
+ userId: 1,
+ id: 2,
+ title: "qui est esse",
+ body:
+ "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla",
+ },
+ {
+ userId: 1,
+ id: 3,
+ title:
+ "ea molestias quasi exercitationem repellat qui ipsa sit aut",
+ body:
+ "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut",
+ },
+ ],
+ [
+ {
+ userId: 1,
+ id: 1,
+ title:
+ "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
+ body:
+ "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
+ },
+ {
+ userId: 1,
+ id: 2,
+ title: "qui est esse",
+ body:
+ "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla",
+ },
+ {
+ userId: 1,
+ id: 3,
+ title:
+ "ea molestias quasi exercitationem repellat qui ipsa sit aut",
+ body:
+ "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut",
+ },
+ ],
+ ],
+ responseMeta: {
+ statusCode: "200 OK",
+ isExecutionSuccess: true,
+ headers: {
+ Date: ["Fri, 20 May 2022 09:18:48 GMT"],
+ "Content-Type": ["application/json; charset=utf-8"],
+ "Transfer-Encoding": ["chunked"],
+ Connection: ["keep-alive"],
+ "X-Powered-By": ["Express"],
+ "X-Ratelimit-Limit": ["1000"],
+ "X-Ratelimit-Remaining": ["999"],
+ "X-Ratelimit-Reset": ["1652916230"],
+ Vary: ["Origin, Accept-Encoding"],
+ "Access-Control-Allow-Credentials": ["true"],
+ "Cache-Control": ["max-age=43200"],
+ Pragma: ["no-cache"],
+ Expires: ["-1"],
+ "X-Content-Type-Options": ["nosniff"],
+ Etag: ['W/"6b80-Ybsq/K6GwwqrYkAsFxqDXGC7DoM"'],
+ Via: ["1.1 vegur"],
+ "CF-Cache-Status": ["HIT"],
+ Age: ["6791"],
+ "Expect-CT": [
+ 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"',
+ ],
+ "Report-To": [
+ '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=mL80WXGZevCRJ%2BH3N6Uq0dvpeHk%2BFLrmzIZMCcTnH10LlRna45sxEdLPMELrTur3z3Tr8ucgNQ7X%2FuIhNRTRj00%2FvML3zxIkOIZsrKf3iTIeQDts3oFwUg9b51xg0IDoperi1JchNq5muJETOeT%2B"}],"group":"cf-nel","max_age":604800}',
+ ],
+ NEL: ['{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'],
+ Server: ["cloudflare"],
+ "CF-RAY": ["70e3fcb39dde18ce-SIN"],
+ "alt-svc": ['h3=":443"; ma=86400, h3-29=":443"; ma=86400'],
+ "X-APPSMITH-DATATYPE": ["JSON"],
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.ACTION,
+ isLoading: false,
+ bindingPaths: {
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ },
+ reactivePaths: {
+ data: EvaluationSubstitutionType.TEMPLATE,
+ isLoading: EvaluationSubstitutionType.TEMPLATE,
+ datasourceUrl: EvaluationSubstitutionType.TEMPLATE,
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ },
+ dependencyMap: {
+ "config.body": ["config.pluginSpecifiedTemplates[0].value"],
+ },
+ logBlackList: {},
+ datasourceUrl: "https://jsonplaceholder.typicode.com",
+ },
+ Text1: ({
+ widgetName: "Text1",
+ displayName: "Text",
+ iconSVG: "/static/media/icon.97c59b52.svg",
+ topRow: 14,
+ bottomRow: 18,
+ parentRowSpace: 10,
+ type: "TEXT_WIDGET",
+ hideCard: false,
+ animateLoading: true,
+ overflow: "NONE",
+ fontFamily: "{{appsmith.theme.fontFamily.appFont}}",
+ parentColumnSpace: 11.796875,
+ dynamicTriggerPathList: [],
+ leftColumn: 21,
+ dynamicBindingPathList: [
+ {
+ key: "fontFamily",
+ },
+ {
+ key: "borderRadius",
+ },
+ {
+ key: "text",
+ },
+ {
+ key: "value",
+ },
+ ],
+ shouldTruncate: false,
+ truncateButtonColor: "#FFC13D",
+ text: "{{\nApi1.data[2][2].id\n}}",
+ key: "ljtoov0cml",
+ rightColumn: 37,
+ textAlign: "LEFT",
+ widgetId: "1p9hcl50i8",
+ isVisible: true,
+ fontStyle: "BOLD",
+ textColor: "#231F20",
+ version: 1,
+ parentId: "0",
+ renderMode: "CANVAS",
+ isLoading: false,
+ borderRadius: "{{appsmith.theme.borderRadius.appBorderRadius}}",
+ fontSize: "1rem",
+ value: "{{ Text1.text }}",
+ defaultProps: {},
+ defaultMetaProps: [],
+ logBlackList: {
+ value: true,
+ },
+ propertyOverrideDependency: {},
+ overridingPropertyPaths: {},
+ bindingPaths: {
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ reactivePaths: {
+ value: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ borderRadius: EvaluationSubstitutionType.TEMPLATE,
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ triggerPaths: {},
+ validationPaths: {
+ text: {
+ type: "TEXT",
+ params: {
+ limitLineBreaks: true,
+ },
+ },
+ isVisible: {
+ type: "BOOLEAN",
+ },
+ animateLoading: {
+ type: "BOOLEAN",
+ },
+ disableLink: {
+ type: "BOOLEAN",
+ },
+ backgroundColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ expected: {
+ type: "string (HTML color name or HEX value)",
+ example: "red | #9C0D38",
+ autocompleteDataType: "STRING",
+ },
+ },
+ },
+ textColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ },
+ },
+ borderColor: {
+ type: "TEXT",
+ },
+ borderWidth: {
+ type: "NUMBER",
+ },
+ fontSize: {
+ type: "TEXT",
+ },
+ fontFamily: {
+ type: "TEXT",
+ },
+ fontStyle: {
+ type: "TEXT",
+ },
+ textAlign: {
+ type: "TEXT",
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.WIDGET,
+ privateWidgets: {},
+ meta: {},
+ } as unknown) as DataTreeWidget,
+ },
+ apiSuccessUnEvalTree3: {
+ // success: response -> [ [{...}, {...}, {...}], [{...}, {...}, {...}], [] ]
+ Api1: {
+ run: {},
+ clear: {},
+ actionId: "6285d928db0f9c6e620d454a",
+ name: "Api1",
+ pluginId: "5ca385dc81b37f0004b4db85",
+ pluginType: PluginType.API,
+ config: {
+ timeoutInMillisecond: 10000,
+ paginationType: PaginationType.NONE,
+ path: "/posts",
+ queryParameters: [],
+ pluginSpecifiedTemplates: [
+ {
+ value: true,
+ },
+ ],
+ formData: {
+ apiContentType: "none",
+ },
+ },
+ dynamicBindingPathList: [],
+ data: [
+ [
+ {
+ userId: 1,
+ id: 1,
+ title:
+ "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
+ body:
+ "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
+ },
+ {
+ userId: 1,
+ id: 2,
+ title: "qui est esse",
+ body:
+ "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla",
+ },
+ {
+ userId: 1,
+ id: 3,
+ title:
+ "ea molestias quasi exercitationem repellat qui ipsa sit aut",
+ body:
+ "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut",
+ },
+ ],
+ [
+ {
+ userId: 1,
+ id: 1,
+ title:
+ "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
+ body:
+ "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
+ },
+ {
+ userId: 1,
+ id: 2,
+ title: "qui est esse",
+ body:
+ "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla",
+ },
+ {
+ userId: 1,
+ id: 3,
+ title:
+ "ea molestias quasi exercitationem repellat qui ipsa sit aut",
+ body:
+ "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut",
+ },
+ ],
+ [],
+ ],
+ responseMeta: {
+ statusCode: "200 OK",
+ isExecutionSuccess: true,
+ headers: {
+ Date: ["Fri, 20 May 2022 09:18:48 GMT"],
+ "Content-Type": ["application/json; charset=utf-8"],
+ "Transfer-Encoding": ["chunked"],
+ Connection: ["keep-alive"],
+ "X-Powered-By": ["Express"],
+ "X-Ratelimit-Limit": ["1000"],
+ "X-Ratelimit-Remaining": ["999"],
+ "X-Ratelimit-Reset": ["1652916230"],
+ Vary: ["Origin, Accept-Encoding"],
+ "Access-Control-Allow-Credentials": ["true"],
+ "Cache-Control": ["max-age=43200"],
+ Pragma: ["no-cache"],
+ Expires: ["-1"],
+ "X-Content-Type-Options": ["nosniff"],
+ Etag: ['W/"6b80-Ybsq/K6GwwqrYkAsFxqDXGC7DoM"'],
+ Via: ["1.1 vegur"],
+ "CF-Cache-Status": ["HIT"],
+ Age: ["6791"],
+ "Expect-CT": [
+ 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"',
+ ],
+ "Report-To": [
+ '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=mL80WXGZevCRJ%2BH3N6Uq0dvpeHk%2BFLrmzIZMCcTnH10LlRna45sxEdLPMELrTur3z3Tr8ucgNQ7X%2FuIhNRTRj00%2FvML3zxIkOIZsrKf3iTIeQDts3oFwUg9b51xg0IDoperi1JchNq5muJETOeT%2B"}],"group":"cf-nel","max_age":604800}',
+ ],
+ NEL: ['{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'],
+ Server: ["cloudflare"],
+ "CF-RAY": ["70e3fcb39dde18ce-SIN"],
+ "alt-svc": ['h3=":443"; ma=86400, h3-29=":443"; ma=86400'],
+ "X-APPSMITH-DATATYPE": ["JSON"],
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.ACTION,
+ isLoading: false,
+ bindingPaths: {
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ },
+ reactivePaths: {
+ data: EvaluationSubstitutionType.TEMPLATE,
+ isLoading: EvaluationSubstitutionType.TEMPLATE,
+ datasourceUrl: EvaluationSubstitutionType.TEMPLATE,
+ "config.path": EvaluationSubstitutionType.TEMPLATE,
+ "config.body": EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ },
+ dependencyMap: {
+ "config.body": ["config.pluginSpecifiedTemplates[0].value"],
+ },
+ logBlackList: {},
+ datasourceUrl: "https://jsonplaceholder.typicode.com",
+ },
+ // Text1.text binding Api1.data[2][2].id
+ Text1: ({
+ widgetName: "Text1",
+ displayName: "Text",
+ iconSVG: "/static/media/icon.97c59b52.svg",
+ topRow: 14,
+ bottomRow: 18,
+ parentRowSpace: 10,
+ type: "TEXT_WIDGET",
+ hideCard: false,
+ animateLoading: true,
+ overflow: "NONE",
+ fontFamily: "{{appsmith.theme.fontFamily.appFont}}",
+ parentColumnSpace: 11.796875,
+ dynamicTriggerPathList: [],
+ leftColumn: 21,
+ dynamicBindingPathList: [
+ {
+ key: "fontFamily",
+ },
+ {
+ key: "borderRadius",
+ },
+ {
+ key: "text",
+ },
+ {
+ key: "value",
+ },
+ ],
+ shouldTruncate: false,
+ truncateButtonColor: "#FFC13D",
+ text: "{{\nApi1.data[2][2].id\n}}",
+ key: "ljtoov0cml",
+ rightColumn: 37,
+ textAlign: "LEFT",
+ widgetId: "1p9hcl50i8",
+ isVisible: true,
+ fontStyle: "BOLD",
+ textColor: "#231F20",
+ version: 1,
+ parentId: "0",
+ renderMode: "CANVAS",
+ isLoading: false,
+ borderRadius: "{{appsmith.theme.borderRadius.appBorderRadius}}",
+ fontSize: "1rem",
+ value: "{{ Text1.text }}",
+ defaultProps: {},
+ defaultMetaProps: [],
+ logBlackList: {
+ value: true,
+ },
+ propertyOverrideDependency: {},
+ overridingPropertyPaths: {},
+ bindingPaths: {
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ reactivePaths: {
+ value: EvaluationSubstitutionType.TEMPLATE,
+ fontFamily: EvaluationSubstitutionType.TEMPLATE,
+ borderRadius: EvaluationSubstitutionType.TEMPLATE,
+ text: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ disableLink: EvaluationSubstitutionType.TEMPLATE,
+ backgroundColor: EvaluationSubstitutionType.TEMPLATE,
+ textColor: EvaluationSubstitutionType.TEMPLATE,
+ borderColor: EvaluationSubstitutionType.TEMPLATE,
+ borderWidth: EvaluationSubstitutionType.TEMPLATE,
+ fontSize: EvaluationSubstitutionType.TEMPLATE,
+ fontStyle: EvaluationSubstitutionType.TEMPLATE,
+ textAlign: EvaluationSubstitutionType.TEMPLATE,
+ },
+ triggerPaths: {},
+ validationPaths: {
+ text: {
+ type: "TEXT",
+ params: {
+ limitLineBreaks: true,
+ },
+ },
+ isVisible: {
+ type: "BOOLEAN",
+ },
+ animateLoading: {
+ type: "BOOLEAN",
+ },
+ disableLink: {
+ type: "BOOLEAN",
+ },
+ backgroundColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ expected: {
+ type: "string (HTML color name or HEX value)",
+ example: "red | #9C0D38",
+ autocompleteDataType: "STRING",
+ },
+ },
+ },
+ textColor: {
+ type: "TEXT",
+ params: {
+ regex: {},
+ },
+ },
+ borderColor: {
+ type: "TEXT",
+ },
+ borderWidth: {
+ type: "NUMBER",
+ },
+ fontSize: {
+ type: "TEXT",
+ },
+ fontFamily: {
+ type: "TEXT",
+ },
+ fontStyle: {
+ type: "TEXT",
+ },
+ textAlign: {
+ type: "TEXT",
+ },
+ },
+ ENTITY_TYPE: ENTITY_TYPE.WIDGET,
+ privateWidgets: {},
+ meta: {},
+ } as unknown) as DataTreeWidget,
+ },
+};
diff --git a/app/client/src/workers/DataTreeEvaluator/test/mockUnEvalTree.ts b/app/client/src/workers/DataTreeEvaluator/test/mockData/mockUnEvalTree.ts
similarity index 91%
rename from app/client/src/workers/DataTreeEvaluator/test/mockUnEvalTree.ts
rename to app/client/src/workers/DataTreeEvaluator/test/mockData/mockUnEvalTree.ts
index 4f60f6eee4..42e6c1fb4a 100644
--- a/app/client/src/workers/DataTreeEvaluator/test/mockUnEvalTree.ts
+++ b/app/client/src/workers/DataTreeEvaluator/test/mockData/mockUnEvalTree.ts
@@ -37,7 +37,7 @@ export const unEvalTree = {
reactivePaths: {},
triggerPaths: {},
validationPaths: {},
- ENTITY_TYPE: "WIDGET",
+ ENTITY_TYPE: ENTITY_TYPE.WIDGET,
privateWidgets: {},
},
Button1: {
@@ -76,16 +76,16 @@ export const unEvalTree = {
propertyOverrideDependency: {},
overridingPropertyPaths: {},
reactivePaths: {
- recaptchaToken: "TEMPLATE",
- text: "TEMPLATE",
- tooltip: "TEMPLATE",
- googleRecaptchaKey: "TEMPLATE",
- recaptchaType: "TEMPLATE",
- isVisible: "TEMPLATE",
- isDisabled: "TEMPLATE",
- animateLoading: "TEMPLATE",
- buttonVariant: "TEMPLATE",
- placement: "TEMPLATE",
+ recaptchaToken: EvaluationSubstitutionType.TEMPLATE,
+ text: EvaluationSubstitutionType.TEMPLATE,
+ tooltip: EvaluationSubstitutionType.TEMPLATE,
+ googleRecaptchaKey: EvaluationSubstitutionType.TEMPLATE,
+ recaptchaType: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ isDisabled: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ buttonVariant: EvaluationSubstitutionType.TEMPLATE,
+ placement: EvaluationSubstitutionType.TEMPLATE,
},
triggerPaths: {
onClick: true,
@@ -131,7 +131,7 @@ export const unEvalTree = {
},
},
},
- ENTITY_TYPE: "WIDGET",
+ ENTITY_TYPE: ENTITY_TYPE.WIDGET,
privateWidgets: {},
},
Button2: {
@@ -174,16 +174,16 @@ export const unEvalTree = {
propertyOverrideDependency: {},
overridingPropertyPaths: {},
reactivePaths: {
- recaptchaToken: "TEMPLATE",
- text: "TEMPLATE",
- tooltip: "TEMPLATE",
- googleRecaptchaKey: "TEMPLATE",
- recaptchaType: "TEMPLATE",
- isVisible: "TEMPLATE",
- isDisabled: "TEMPLATE",
- animateLoading: "TEMPLATE",
- buttonVariant: "TEMPLATE",
- placement: "TEMPLATE",
+ recaptchaToken: EvaluationSubstitutionType.TEMPLATE,
+ text: EvaluationSubstitutionType.TEMPLATE,
+ tooltip: EvaluationSubstitutionType.TEMPLATE,
+ googleRecaptchaKey: EvaluationSubstitutionType.TEMPLATE,
+ recaptchaType: EvaluationSubstitutionType.TEMPLATE,
+ isVisible: EvaluationSubstitutionType.TEMPLATE,
+ isDisabled: EvaluationSubstitutionType.TEMPLATE,
+ animateLoading: EvaluationSubstitutionType.TEMPLATE,
+ buttonVariant: EvaluationSubstitutionType.TEMPLATE,
+ placement: EvaluationSubstitutionType.TEMPLATE,
},
triggerPaths: {
onClick: true,
@@ -229,7 +229,7 @@ export const unEvalTree = {
},
},
},
- ENTITY_TYPE: "WIDGET",
+ ENTITY_TYPE: ENTITY_TYPE.WIDGET,
privateWidgets: {},
},
pageList: [
@@ -255,7 +255,7 @@ export const unEvalTree = {
appsmith: {
user: {
email: "rathod@appsmith.com",
- organizationIds: [
+ workspaceIds: [
"6218a61972ccd9145ec78c57",
"621913df0276eb01d22fec44",
"60caf8edb1e47a1315f0c48f",
@@ -297,7 +297,7 @@ export const unEvalTree = {
canBeRequested: true,
},
mode: "EDIT",
- ENTITY_TYPE: "APPSMITH",
+ ENTITY_TYPE: ENTITY_TYPE.APPSMITH,
},
};
@@ -517,7 +517,7 @@ export const asyncTagUnevalTree: DataTree = {
appsmith: ({
user: {
email: "anand@appsmith.com",
- organizationIds: [
+ workspaceIds: [
"61431979a67ce2289d3c7c6d",
"61431a95a67ce2289d3c7c74",
"5f7add8687af934ed846dd6a",
diff --git a/app/client/src/workers/evaluationUtils.test.ts b/app/client/src/workers/evaluationUtils.test.ts
index 4fcdfdeb70..36ae4efa43 100644
--- a/app/client/src/workers/evaluationUtils.test.ts
+++ b/app/client/src/workers/evaluationUtils.test.ts
@@ -447,6 +447,70 @@ describe("translateDiffEvent", () => {
expect(expectedTranslations).toStrictEqual(actualTranslations);
});
+
+ it("lists array accessors when object is replaced by an array", () => {
+ const diffs: Diff[] = [
+ {
+ kind: "E",
+ path: ["Api1", "data"],
+ lhs: {},
+ rhs: [{ id: 1 }, { id: 2 }],
+ },
+ ];
+
+ const expectedTranslations: DataTreeDiff[] = [
+ {
+ payload: {
+ propertyPath: "Api1.data[0]",
+ },
+ event: DataTreeDiffEvent.NEW,
+ },
+ {
+ payload: {
+ propertyPath: "Api1.data[1]",
+ },
+ event: DataTreeDiffEvent.NEW,
+ },
+ ];
+
+ const actualTranslations = flatten(
+ diffs.map((diff) => translateDiffEventToDataTreeDiffEvent(diff, {})),
+ );
+
+ expect(expectedTranslations).toStrictEqual(actualTranslations);
+ });
+
+ it("lists array accessors when array is replaced by an object", () => {
+ const diffs: Diff[] = [
+ {
+ kind: "E",
+ path: ["Api1", "data"],
+ lhs: [{ id: 1 }, { id: 2 }],
+ rhs: {},
+ },
+ ];
+
+ const expectedTranslations: DataTreeDiff[] = [
+ {
+ payload: {
+ propertyPath: "Api1.data[0]",
+ },
+ event: DataTreeDiffEvent.DELETE,
+ },
+ {
+ payload: {
+ propertyPath: "Api1.data[1]",
+ },
+ event: DataTreeDiffEvent.DELETE,
+ },
+ ];
+
+ const actualTranslations = flatten(
+ diffs.map((diff) => translateDiffEventToDataTreeDiffEvent(diff, {})),
+ );
+
+ expect(expectedTranslations).toStrictEqual(actualTranslations);
+ });
});
describe("overrideWidgetProperties", () => {
diff --git a/app/client/src/workers/evaluationUtils.ts b/app/client/src/workers/evaluationUtils.ts
index 17ea67a2d6..0145fe9a2b 100644
--- a/app/client/src/workers/evaluationUtils.ts
+++ b/app/client/src/workers/evaluationUtils.ts
@@ -222,6 +222,19 @@ export const translateDiffEventToDataTreeDiffEvent = (
},
};
});
+
+ // when an object is being replaced by an array
+ // list all new array accessors that are being added
+ // so dependencies will be created based on existing bindings
+ if (Array.isArray(difference.rhs)) {
+ result = result.concat(
+ translateDiffArrayIndexAccessors(
+ propertyPath,
+ difference.rhs,
+ DataTreeDiffEvent.NEW,
+ ),
+ );
+ }
} else if (
!isTrueObject(difference.lhs) &&
isTrueObject(difference.rhs)
@@ -239,6 +252,19 @@ export const translateDiffEventToDataTreeDiffEvent = (
},
};
});
+
+ // when an array is being replaced by an object
+ // remove all array accessors that are deleted
+ // so dependencies by existing bindings are removed
+ if (Array.isArray(difference.lhs)) {
+ result = result.concat(
+ translateDiffArrayIndexAccessors(
+ propertyPath,
+ difference.lhs,
+ DataTreeDiffEvent.DELETE,
+ ),
+ );
+ }
}
break;
}
@@ -258,6 +284,23 @@ export const translateDiffEventToDataTreeDiffEvent = (
return result;
};
+export const translateDiffArrayIndexAccessors = (
+ propertyPath: string,
+ array: unknown[],
+ event: DataTreeDiffEvent,
+) => {
+ const result: DataTreeDiff[] = [];
+ array.forEach((data, index) => {
+ const path = `${propertyPath}[${index}]`;
+ result.push({
+ event,
+ payload: {
+ propertyPath: path,
+ },
+ });
+ });
+ return result;
+};
/*
Table1.selectedRow
Table1.selectedRow.email: ["Input1.defaultText"]
diff --git a/app/client/test/__mocks__/apiHandlers.ts b/app/client/test/__mocks__/apiHandlers.ts
index b58e7ff091..39dbd14a31 100644
--- a/app/client/test/__mocks__/apiHandlers.ts
+++ b/app/client/test/__mocks__/apiHandlers.ts
@@ -4,7 +4,7 @@ import {
fetchApplicationThreadsMockResponse,
createNewThreadMockResponse,
} from "mockResponses/CommentApiMockResponse";
-import CreateOrganisationMockResponse from "mockResponses/CreateOrganisationMockResponse.json";
+import CreateWorkspaceMockResponse from "mockResponses/CreateWorkspaceMockResponse.json";
import ApplicationsNewMockResponse from "mockResponses/ApplicationsNewMockResponse.json";
const mockSuccessRes = {
@@ -14,8 +14,8 @@ const mockSuccessRes = {
export const handlers = [
// mock apis here
- rest.post("/api/v1/organizations", (req, res, ctx) => {
- return res(ctx.status(200), ctx.json(CreateOrganisationMockResponse));
+ rest.post("/api/v1/workspaces", (req, res, ctx) => {
+ return res(ctx.status(200), ctx.json(CreateWorkspaceMockResponse));
}),
rest.get("/api/v1/applications/new", (req, res, ctx) => {
return res(ctx.status(200), ctx.json(ApplicationsNewMockResponse));
diff --git a/app/client/test/sagas.ts b/app/client/test/sagas.ts
index a9189f3baa..65cb4cbf0b 100644
--- a/app/client/test/sagas.ts
+++ b/app/client/test/sagas.ts
@@ -3,7 +3,7 @@ import apiPaneSagas from "../src/sagas/ApiPaneSagas";
import jsPaneSagas from "../src/sagas/JSPaneSagas";
import userSagas from "../src/sagas/userSagas";
import pluginSagas from "../src/sagas/PluginSagas";
-import orgSagas from "../src/sagas/OrgSagas";
+import workspaceSagas from "../src/sagas/WorkspaceSagas";
import importedCollectionsSagas from "../src/sagas/CollectionSagas";
import providersSagas from "../src/sagas/ProvidersSaga";
import curlImportSagas from "../src/sagas/CurlImportSagas";
@@ -43,7 +43,7 @@ export const sagasToRunForTests = [
jsPaneSagas,
userSagas,
pluginSagas,
- orgSagas,
+ workspaceSagas,
importedCollectionsSagas,
providersSagas,
curlImportSagas,
diff --git a/app/client/test/testCommon.ts b/app/client/test/testCommon.ts
index 1a5a2be648..dd7765cc67 100644
--- a/app/client/test/testCommon.ts
+++ b/app/client/test/testCommon.ts
@@ -100,7 +100,7 @@ export function MockApplication({ children }: any) {
const dispatch = useDispatch();
dispatch(initEditor({ pageId: "page_id", mode: APP_MODE.EDIT }));
const mockResp: any = {
- organizationId: "org_id",
+ workspaceId: "workspace_id",
pages: [{ id: "page_id", name: "Page1", isDefault: true }],
id: "app_id",
isDefault: true,
diff --git a/app/server/appsmith-git/src/main/java/com/appsmith/git/helpers/FileUtilsImpl.java b/app/server/appsmith-git/src/main/java/com/appsmith/git/helpers/FileUtilsImpl.java
index dc6cc63200..88a6d9f845 100644
--- a/app/server/appsmith-git/src/main/java/com/appsmith/git/helpers/FileUtilsImpl.java
+++ b/app/server/appsmith-git/src/main/java/com/appsmith/git/helpers/FileUtilsImpl.java
@@ -1,5 +1,6 @@
package com.appsmith.git.helpers;
+import com.appsmith.external.converters.GsonISOStringToInstantConverter;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
import com.appsmith.external.git.FileInterface;
@@ -42,6 +43,7 @@ import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.time.Instant;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
@@ -123,7 +125,7 @@ public class FileUtilsImpl implements FileInterface {
/**
* This method will save the complete application in the local repo directory.
- * Path to repo will be : ./container-volumes/git-repo/organizationId/defaultApplicationId/repoName/{application_data}
+ * Path to repo will be : ./container-volumes/git-repo/workspaceId/defaultApplicationId/repoName/{application_data}
* @param baseRepoSuffix path suffix used to create a repo path
* @param applicationGitReference application reference object from which entire application can be rehydrated
* @param branchName name of the branch for the current application
@@ -149,6 +151,7 @@ public class FileUtilsImpl implements FileInterface {
.registerTypeAdapter(Double.class, new GsonDoubleToLongConverter())
.registerTypeAdapter(Set.class, new GsonUnorderedToOrderedConverter())
.registerTypeAdapter(Map.class, new GsonUnorderedToOrderedConverter())
+ .registerTypeAdapter(Instant.class, new GsonISOStringToInstantConverter())
.disableHtmlEscaping()
.setPrettyPrinting()
.create();
@@ -229,7 +232,7 @@ public class FileUtilsImpl implements FileInterface {
}
}
// Save JSObjects
- for (Map.Entry resource : applicationGitReference.getActionsCollections().entrySet()) {
+ for (Map.Entry resource : applicationGitReference.getActionCollections().entrySet()) {
// JSObjectName_pageName => nomenclature for the keys
// TODO
// JSObjectName => for app level JSObjects, this is not implemented yet
@@ -383,7 +386,7 @@ public class FileUtilsImpl implements FileInterface {
@Override
public Mono deleteLocalRepo(Path baseRepoSuffix) {
- // Remove the complete directory from path: baseRepo/organizationId/defaultApplicationId
+ // Remove the complete directory from path: baseRepo/workspaceId/defaultApplicationId
File file = Paths.get(gitServiceConfig.getGitRootPath()).resolve(baseRepoSuffix).getParent().toFile();
while (file.exists()) {
FileSystemUtils.deleteRecursively(file);
@@ -466,7 +469,7 @@ public class FileUtilsImpl implements FileInterface {
// Extract actions
applicationGitReference.setActions(readFiles(baseRepoPath.resolve(ACTION_DIRECTORY), gson, ""));
// Extract actionCollections
- applicationGitReference.setActionsCollections(readFiles(baseRepoPath.resolve(ACTION_COLLECTION_DIRECTORY), gson, ""));
+ applicationGitReference.setActionCollections(readFiles(baseRepoPath.resolve(ACTION_COLLECTION_DIRECTORY), gson, ""));
// Extract pages
applicationGitReference.setPages(readFiles(pageDirectory, gson, ""));
// Extract datasources
@@ -490,7 +493,7 @@ public class FileUtilsImpl implements FileInterface {
}
}
applicationGitReference.setActions(actionMap);
- applicationGitReference.setActionsCollections(actionCollectionMap);
+ applicationGitReference.setActionCollections(actionCollectionMap);
applicationGitReference.setPages(pageMap);
// Extract datasources
applicationGitReference.setDatasources(readFiles(baseRepoPath.resolve(DATASOURCE_DIRECTORY), gson, ""));
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/converters/GsonISOStringToInstantConverter.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/converters/GsonISOStringToInstantConverter.java
new file mode 100644
index 0000000000..a3768eb119
--- /dev/null
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/converters/GsonISOStringToInstantConverter.java
@@ -0,0 +1,43 @@
+package com.appsmith.external.converters;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+
+import java.lang.reflect.Type;
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+
+public class GsonISOStringToInstantConverter implements JsonSerializer, JsonDeserializer {
+ private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssX").withZone(ZoneOffset.UTC);
+
+ @Override
+ public Instant deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
+ if(jsonElement.isJsonNull()) {
+ return null;
+ }
+ if (jsonElement.isJsonPrimitive()) {
+ String jsonString = jsonElement.getAsJsonPrimitive().getAsString();
+ if (jsonString.length() == 0) {
+ return null;
+ }
+ try {
+ Double aDouble = Double.parseDouble(jsonString);
+ return Instant.ofEpochSecond(aDouble.longValue());
+ } catch (NumberFormatException e) {
+ // do nothing, let's try to parse with Instant.parse assuming it's in ISO format
+ }
+ }
+ return Instant.parse(jsonElement.getAsString());
+ }
+
+ @Override
+ public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) {
+ return new JsonPrimitive(formatter.format(src));
+ }
+}
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/FileInterface.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/FileInterface.java
index 9214876d9d..dc2c66be2f 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/FileInterface.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/FileInterface.java
@@ -10,7 +10,7 @@ import java.nio.file.Path;
public interface FileInterface {
/**
* This method is use to store the serialised application to git repo, directory path structure we are going to follow :
- * ./container-volumes/git-repo/organizationId/defaultApplicationId/repoName/{application_data}
+ * ./container-volumes/git-repo/workspaceId/defaultApplicationId/repoName/{application_data}
* @param baseRepoSuffix path suffix used to create a repo path
* @param applicationGitReference application reference object from which entire application can be rehydrated
* @return Path to where the application is stored
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ApplicationGitReference.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ApplicationGitReference.java
index 95f150f32a..6b6f022040 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ApplicationGitReference.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ApplicationGitReference.java
@@ -17,7 +17,7 @@ public class ApplicationGitReference {
Object metadata;
Object theme;
Map actions;
- Map actionsCollections;
+ Map actionCollections;
Map pages;
Map datasources;
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/BaseDomain.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/BaseDomain.java
index 5f2d37f2c1..e00edc1c43 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/BaseDomain.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/BaseDomain.java
@@ -79,4 +79,14 @@ public abstract class BaseDomain implements Persistable, AppsmithDomain
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
@JsonIgnore
String gitSyncId;
+
+ public void sanitiseToExportBaseObject() {
+ this.setDefaultResources(null);
+ this.setCreatedAt(null);
+ this.setUpdatedAt(null);
+ this.setUserPermissions(null);
+ this.setPolicies(null);
+ this.setCreatedBy(null);
+ this.setModifiedBy(null);
+ }
}
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Datasource.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Datasource.java
index e39c662143..18850f6bd2 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Datasource.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Datasource.java
@@ -12,6 +12,7 @@ import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.util.CollectionUtils;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
@Getter
@@ -32,9 +33,13 @@ public class Datasource extends BaseDomain {
// It'll be null if not set
@Transient
String pluginName;
-
+
+ //Organizations migrated to workspaces, kept the field as deprecated to support the old migration
+ @Deprecated
String organizationId;
+ String workspaceId;
+
String templateName;
DatasourceConfiguration datasourceConfiguration;
@@ -103,4 +108,18 @@ public class Datasource extends BaseDomain {
.isEquals();
}
+ public void sanitiseToExportResource(Map pluginMap) {
+ this.setPolicies(null);
+ this.setStructure(null);
+ this.setUpdatedAt(null);
+ this.setCreatedAt(null);
+ this.setUserPermissions(null);
+ this.setIsConfigured(null);
+ this.setInvalids(null);
+ this.setId(null);
+ this.setWorkspaceId(null);
+ this.setOrganizationId(null);
+ this.setPluginId(pluginMap.get(this.getPluginId()));
+ }
+
}
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/PluginExecutor.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/PluginExecutor.java
index 8af499afd9..cd892a4ef0 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/PluginExecutor.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/PluginExecutor.java
@@ -219,7 +219,6 @@ public interface PluginExecutor extends ExtensionPoint {
* @param actionConfiguration
* @return modified actionConfiguration object after setting the two keys mentioned above in `formData`.
*/
- default ActionConfiguration extractAndSetNativeQueryFromFormData(ActionConfiguration actionConfiguration) {
- return actionConfiguration;
+ default void extractAndSetNativeQueryFromFormData(ActionConfiguration actionConfiguration) {
}
}
diff --git a/app/server/appsmith-plugins/mongoPlugin/src/main/java/com/external/plugins/MongoPlugin.java b/app/server/appsmith-plugins/mongoPlugin/src/main/java/com/external/plugins/MongoPlugin.java
index 9be97a133d..31c329b56e 100644
--- a/app/server/appsmith-plugins/mongoPlugin/src/main/java/com/external/plugins/MongoPlugin.java
+++ b/app/server/appsmith-plugins/mongoPlugin/src/main/java/com/external/plugins/MongoPlugin.java
@@ -877,7 +877,7 @@ public class MongoPlugin extends BasePlugin {
* @return Mongo's native/raw query set at path `formData.formToNativeQuery.data`
*/
@Override
- public ActionConfiguration extractAndSetNativeQueryFromFormData(ActionConfiguration actionConfiguration) {
+ public void extractAndSetNativeQueryFromFormData(ActionConfiguration actionConfiguration) {
Map formData = actionConfiguration.getFormData();
if (formData != null && !formData.isEmpty()) {
/* If it is not raw command, then it must be one of the mongo form commands */
@@ -903,8 +903,6 @@ public class MongoPlugin extends BasePlugin {
}
}
}
-
- return actionConfiguration;
}
}
diff --git a/app/server/appsmith-server/pom.xml b/app/server/appsmith-server/pom.xml
index 25fbb8e2af..19cc1673d0 100644
--- a/app/server/appsmith-server/pom.xml
+++ b/app/server/appsmith-server/pom.xml
@@ -120,6 +120,7 @@
de.flapdoodle.embed
de.flapdoodle.embed.mongo
test
+ 3.4.6
com.google.guava
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AclPermission.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AclPermission.java
index 43994838e4..d05051b0c4 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AclPermission.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AclPermission.java
@@ -17,7 +17,7 @@ public enum AclPermission {
/**
* Notes :
* 1. Composite permissions are more often than not used in the generation of the hierarchical graphs.
- * For example, USER_MANAGE_ORGANIZATIONS, ORGANIZATION_MANAGE_APPLICATIONS, etc.
+ * For example, USER_MANAGE_WORKSPACES, WORKSPACE_MANAGE_APPLICATIONS, etc.
*/
// These are generic permissions created to make the transition to the new ACL format easy. They must be removed
@@ -27,38 +27,38 @@ public enum AclPermission {
UPDATE("update", null),
DELETE("delete", null),
- // Does the user have manage organization permission
- USER_MANAGE_ORGANIZATIONS("manage:userOrganization", User.class),
- //Does the user have read organization permissions
- USER_READ_ORGANIZATIONS("read:userOrganization", User.class),
+ // Does the user have manage workspace permission
+ USER_MANAGE_WORKSPACES("manage:userWorkspace", User.class),
+ //Does the user have read workspace permissions
+ USER_READ_WORKSPACES("read:userWorkspace", User.class),
// Does this user have permission to access Instance Config UI?
MANAGE_INSTANCE_ENV("manage:instanceEnv", User.class),
// TODO: Add these permissions to PolicyGenerator to assign them to the user when they sign up
- // The following should be applied to Organization and not User
+ // The following should be applied to Workspace and not User
READ_USERS("read:users", User.class),
MANAGE_USERS("manage:users", User.class),
RESET_PASSWORD_USERS("resetPassword:users", User.class),
- MANAGE_ORGANIZATIONS("manage:organizations", Workspace.class),
- READ_ORGANIZATIONS("read:organizations", Workspace.class),
+ MANAGE_WORKSPACES("manage:workspaces", Workspace.class),
+ READ_WORKSPACES("read:workspaces", Workspace.class),
- // Was the user assigned a global permission at the organization level to manage applications?
- ORGANIZATION_MANAGE_APPLICATIONS("manage:orgApplications", Workspace.class),
- ORGANIZATION_READ_APPLICATIONS("read:orgApplications", Workspace.class),
- ORGANIZATION_PUBLISH_APPLICATIONS("publish:orgApplications", Workspace.class),
- ORGANIZATION_EXPORT_APPLICATIONS("export:orgApplications", Workspace.class),
+ // Was the user assigned a global permission at the workspace level to manage applications?
+ WORKSPACE_MANAGE_APPLICATIONS("manage:workspaceApplications", Workspace.class),
+ WORKSPACE_READ_APPLICATIONS("read:workspaceApplications", Workspace.class),
+ WORKSPACE_PUBLISH_APPLICATIONS("publish:workspaceApplications", Workspace.class),
+ WORKSPACE_EXPORT_APPLICATIONS("export:workspaceApplications", Workspace.class),
// Invitation related permissions
- ORGANIZATION_INVITE_USERS("inviteUsers:organization", Workspace.class),
+ WORKSPACE_INVITE_USERS("inviteUsers:workspace", Workspace.class),
MANAGE_APPLICATIONS("manage:applications", Application.class),
READ_APPLICATIONS("read:applications", Application.class),
PUBLISH_APPLICATIONS("publish:applications", Application.class),
EXPORT_APPLICATIONS("export:applications", Application.class),
- // Making an application public permission at Organization level
+ // Making an application public permission at Workspace level
MAKE_PUBLIC_APPLICATIONS("makePublic:applications", Application.class),
// Can the user create a comment thread on a given application?
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AppsmithRole.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AppsmithRole.java
index 7138666b93..25ee08253d 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AppsmithRole.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AppsmithRole.java
@@ -7,14 +7,14 @@ import java.util.List;
import java.util.Set;
import static com.appsmith.server.acl.AclPermission.MANAGE_APPLICATIONS;
-import static com.appsmith.server.acl.AclPermission.MANAGE_ORGANIZATIONS;
-import static com.appsmith.server.acl.AclPermission.ORGANIZATION_EXPORT_APPLICATIONS;
-import static com.appsmith.server.acl.AclPermission.ORGANIZATION_INVITE_USERS;
-import static com.appsmith.server.acl.AclPermission.ORGANIZATION_MANAGE_APPLICATIONS;
-import static com.appsmith.server.acl.AclPermission.ORGANIZATION_PUBLISH_APPLICATIONS;
-import static com.appsmith.server.acl.AclPermission.ORGANIZATION_READ_APPLICATIONS;
+import static com.appsmith.server.acl.AclPermission.MANAGE_WORKSPACES;
+import static com.appsmith.server.acl.AclPermission.WORKSPACE_EXPORT_APPLICATIONS;
+import static com.appsmith.server.acl.AclPermission.WORKSPACE_INVITE_USERS;
+import static com.appsmith.server.acl.AclPermission.WORKSPACE_MANAGE_APPLICATIONS;
+import static com.appsmith.server.acl.AclPermission.WORKSPACE_PUBLISH_APPLICATIONS;
+import static com.appsmith.server.acl.AclPermission.WORKSPACE_READ_APPLICATIONS;
import static com.appsmith.server.acl.AclPermission.READ_APPLICATIONS;
-import static com.appsmith.server.acl.AclPermission.READ_ORGANIZATIONS;
+import static com.appsmith.server.acl.AclPermission.READ_WORKSPACES;
@Getter
public enum AppsmithRole {
@@ -22,15 +22,14 @@ public enum AppsmithRole {
APPLICATION_VIEWER("Application Viewer", "", Set.of(READ_APPLICATIONS)),
ORGANIZATION_ADMIN("Administrator", "Can modify all organization settings including editing applications, " +
"inviting other users to the organization and exporting applications from the organization",
- Set.of(MANAGE_ORGANIZATIONS, ORGANIZATION_INVITE_USERS, ORGANIZATION_EXPORT_APPLICATIONS)),
+ Set.of(MANAGE_WORKSPACES, WORKSPACE_INVITE_USERS, WORKSPACE_EXPORT_APPLICATIONS)),
ORGANIZATION_DEVELOPER("Developer", "Can edit and view applications along with inviting other users to the organization",
- Set.of(READ_ORGANIZATIONS, ORGANIZATION_MANAGE_APPLICATIONS, ORGANIZATION_READ_APPLICATIONS,
- ORGANIZATION_PUBLISH_APPLICATIONS, ORGANIZATION_INVITE_USERS)),
+ Set.of(READ_WORKSPACES, WORKSPACE_MANAGE_APPLICATIONS, WORKSPACE_READ_APPLICATIONS,
+ WORKSPACE_PUBLISH_APPLICATIONS, WORKSPACE_INVITE_USERS)),
ORGANIZATION_VIEWER(
- "App Viewer",
- "Can view applications and invite other users to view applications",
- Set.of(READ_ORGANIZATIONS, ORGANIZATION_READ_APPLICATIONS, ORGANIZATION_INVITE_USERS)
- ),
+ "App Viewer",
+ "Can view applications and invite other users to view applications",
+ Set.of(READ_WORKSPACES, WORKSPACE_READ_APPLICATIONS, WORKSPACE_INVITE_USERS)),
;
private Set permissions;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/ce/PolicyGeneratorCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/ce/PolicyGeneratorCE.java
index dfc1ee6ccd..2e809d0a9b 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/ce/PolicyGeneratorCE.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/ce/PolicyGeneratorCE.java
@@ -28,26 +28,26 @@ import static com.appsmith.server.acl.AclPermission.MAKE_PUBLIC_APPLICATIONS;
import static com.appsmith.server.acl.AclPermission.MANAGE_ACTIONS;
import static com.appsmith.server.acl.AclPermission.MANAGE_APPLICATIONS;
import static com.appsmith.server.acl.AclPermission.MANAGE_DATASOURCES;
-import static com.appsmith.server.acl.AclPermission.MANAGE_ORGANIZATIONS;
+import static com.appsmith.server.acl.AclPermission.MANAGE_WORKSPACES;
import static com.appsmith.server.acl.AclPermission.MANAGE_PAGES;
import static com.appsmith.server.acl.AclPermission.MANAGE_THEMES;
import static com.appsmith.server.acl.AclPermission.MANAGE_USERS;
-import static com.appsmith.server.acl.AclPermission.ORGANIZATION_EXPORT_APPLICATIONS;
-import static com.appsmith.server.acl.AclPermission.ORGANIZATION_MANAGE_APPLICATIONS;
-import static com.appsmith.server.acl.AclPermission.ORGANIZATION_PUBLISH_APPLICATIONS;
-import static com.appsmith.server.acl.AclPermission.ORGANIZATION_READ_APPLICATIONS;
+import static com.appsmith.server.acl.AclPermission.WORKSPACE_EXPORT_APPLICATIONS;
+import static com.appsmith.server.acl.AclPermission.WORKSPACE_MANAGE_APPLICATIONS;
+import static com.appsmith.server.acl.AclPermission.WORKSPACE_PUBLISH_APPLICATIONS;
+import static com.appsmith.server.acl.AclPermission.WORKSPACE_READ_APPLICATIONS;
import static com.appsmith.server.acl.AclPermission.PUBLISH_APPLICATIONS;
import static com.appsmith.server.acl.AclPermission.READ_ACTIONS;
import static com.appsmith.server.acl.AclPermission.READ_APPLICATIONS;
import static com.appsmith.server.acl.AclPermission.READ_COMMENTS;
import static com.appsmith.server.acl.AclPermission.READ_DATASOURCES;
-import static com.appsmith.server.acl.AclPermission.READ_ORGANIZATIONS;
+import static com.appsmith.server.acl.AclPermission.READ_WORKSPACES;
import static com.appsmith.server.acl.AclPermission.READ_PAGES;
import static com.appsmith.server.acl.AclPermission.READ_THEMES;
import static com.appsmith.server.acl.AclPermission.READ_THREADS;
import static com.appsmith.server.acl.AclPermission.READ_USERS;
-import static com.appsmith.server.acl.AclPermission.USER_MANAGE_ORGANIZATIONS;
-import static com.appsmith.server.acl.AclPermission.USER_READ_ORGANIZATIONS;
+import static com.appsmith.server.acl.AclPermission.USER_MANAGE_WORKSPACES;
+import static com.appsmith.server.acl.AclPermission.USER_READ_WORKSPACES;
@Getter
@@ -77,7 +77,7 @@ public class PolicyGeneratorCE {
});
createUserPolicyGraph();
- createOrganizationPolicyGraph();
+ createWorkspacePolicyGraph();
createDatasourcePolicyGraph();
createApplicationPolicyGraph();
createPagePolicyGraph();
@@ -87,27 +87,27 @@ public class PolicyGeneratorCE {
}
/**
- * In this, we add permissions for a user to interact with organizations and other users inside the said organizations
+ * In this, we add permissions for a user to interact with workspaces and other users inside the said workspaces
*/
private void createUserPolicyGraph() {
- hierarchyGraph.addEdge(USER_MANAGE_ORGANIZATIONS, MANAGE_ORGANIZATIONS);
- hierarchyGraph.addEdge(USER_READ_ORGANIZATIONS, READ_ORGANIZATIONS);
+ hierarchyGraph.addEdge(USER_MANAGE_WORKSPACES, MANAGE_WORKSPACES);
+ hierarchyGraph.addEdge(USER_READ_WORKSPACES, READ_WORKSPACES);
- // If user is given manageOrg permission, they must also be able to read organizations
- lateralGraph.addEdge(USER_MANAGE_ORGANIZATIONS, USER_READ_ORGANIZATIONS);
+ // If user is given manageOrg permission, they must also be able to read workspaces
+ lateralGraph.addEdge(USER_MANAGE_WORKSPACES, USER_READ_WORKSPACES);
lateralGraph.addEdge(MANAGE_USERS, READ_USERS);
}
- private void createOrganizationPolicyGraph() {
- lateralGraph.addEdge(MANAGE_ORGANIZATIONS, READ_ORGANIZATIONS);
- lateralGraph.addEdge(MANAGE_ORGANIZATIONS, ORGANIZATION_MANAGE_APPLICATIONS);
- lateralGraph.addEdge(MANAGE_ORGANIZATIONS, ORGANIZATION_READ_APPLICATIONS);
- lateralGraph.addEdge(MANAGE_ORGANIZATIONS, ORGANIZATION_PUBLISH_APPLICATIONS);
+ private void createWorkspacePolicyGraph() {
+ lateralGraph.addEdge(MANAGE_WORKSPACES, READ_WORKSPACES);
+ lateralGraph.addEdge(MANAGE_WORKSPACES, WORKSPACE_MANAGE_APPLICATIONS);
+ lateralGraph.addEdge(MANAGE_WORKSPACES, WORKSPACE_READ_APPLICATIONS);
+ lateralGraph.addEdge(MANAGE_WORKSPACES, WORKSPACE_PUBLISH_APPLICATIONS);
}
private void createDatasourcePolicyGraph() {
- hierarchyGraph.addEdge(ORGANIZATION_MANAGE_APPLICATIONS, MANAGE_DATASOURCES);
- hierarchyGraph.addEdge(ORGANIZATION_READ_APPLICATIONS, READ_DATASOURCES);
+ hierarchyGraph.addEdge(WORKSPACE_MANAGE_APPLICATIONS, MANAGE_DATASOURCES);
+ hierarchyGraph.addEdge(WORKSPACE_READ_APPLICATIONS, READ_DATASOURCES);
lateralGraph.addEdge(MANAGE_DATASOURCES, READ_DATASOURCES);
lateralGraph.addEdge(MANAGE_DATASOURCES, EXECUTE_DATASOURCES);
@@ -115,11 +115,11 @@ public class PolicyGeneratorCE {
}
private void createApplicationPolicyGraph() {
- hierarchyGraph.addEdge(ORGANIZATION_MANAGE_APPLICATIONS, MANAGE_APPLICATIONS);
- hierarchyGraph.addEdge(ORGANIZATION_READ_APPLICATIONS, READ_APPLICATIONS);
- hierarchyGraph.addEdge(ORGANIZATION_PUBLISH_APPLICATIONS, PUBLISH_APPLICATIONS);
- hierarchyGraph.addEdge(MANAGE_ORGANIZATIONS, MAKE_PUBLIC_APPLICATIONS);
- hierarchyGraph.addEdge(ORGANIZATION_EXPORT_APPLICATIONS, EXPORT_APPLICATIONS);
+ hierarchyGraph.addEdge(WORKSPACE_MANAGE_APPLICATIONS, MANAGE_APPLICATIONS);
+ hierarchyGraph.addEdge(WORKSPACE_READ_APPLICATIONS, READ_APPLICATIONS);
+ hierarchyGraph.addEdge(WORKSPACE_PUBLISH_APPLICATIONS, PUBLISH_APPLICATIONS);
+ hierarchyGraph.addEdge(MANAGE_WORKSPACES, MAKE_PUBLIC_APPLICATIONS);
+ hierarchyGraph.addEdge(WORKSPACE_EXPORT_APPLICATIONS, EXPORT_APPLICATIONS);
// If the user is being given MANAGE_APPLICATION permission, they must also be given READ_APPLICATION perm
lateralGraph.addEdge(MANAGE_APPLICATIONS, READ_APPLICATIONS);
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java
index 8dd1e8386b..7ffce1602a 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java
@@ -154,10 +154,10 @@ public class AuthenticationSuccessHandlerCE implements ServerAuthenticationSucce
private Mono createDefaultApplication(User user) {
// need to create default application
- String workspaceId = user.getOrganizationIds().iterator().next();
+ String workspaceId = user.getWorkspaceIds().iterator().next();
Application application = new Application();
- application.setOrganizationId(workspaceId);
+ application.setWorkspaceId(workspaceId);
application.setName("My first application");
return applicationPageService.createApplication(application);
}
@@ -181,11 +181,10 @@ public class AuthenticationSuccessHandlerCE implements ServerAuthenticationSucce
ServerWebExchange exchange = webFilterExchange.getExchange();
String state = exchange.getRequest().getQueryParams().getFirst(Security.QUERY_PARAMETER_STATE);
String redirectUrl = RedirectHelper.DEFAULT_REDIRECT_URL;
- String prefix = Security.STATE_PARAMETER_ORIGIN + "=";
if (state != null && !state.isEmpty()) {
String[] stateArray = state.split(",");
for (String stateVar : stateArray) {
- if (stateVar != null && stateVar.startsWith(prefix)) {
+ if (stateVar != null && stateVar.startsWith(Security.STATE_PARAMETER_ORIGIN)) {
// This is the origin of the request that we want to redirect to
redirectUrl = stateVar.split("=", 2)[1];
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java
index 5eb92e7d96..d571888a22 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java
@@ -173,8 +173,8 @@ public class SecurityConfig {
User user = new User();
user.setName(FieldName.ANONYMOUS_USER);
user.setEmail(FieldName.ANONYMOUS_USER);
- user.setCurrentOrganizationId("");
- user.setOrganizationIds(new HashSet<>());
+ user.setCurrentWorkspaceId("");
+ user.setWorkspaceIds(new HashSet<>());
user.setIsAnonymous(true);
return user;
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/FieldName.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/FieldName.java
index e69772e890..4059f9504e 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/FieldName.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/FieldName.java
@@ -3,7 +3,9 @@ package com.appsmith.server.constants;
public class FieldName {
public static final String EMAIL = "email";
public static final String PASSWORD = "password";
+ @Deprecated
public static final String ORGANIZATION_ID = "organizationId";
+ public static final String WORKSPACE_ID = "workspaceId";
public static final String DELETED = "deleted";
public static final String CREATED_AT = "createdAt";
public static final String DELETED_AT = "deletedAt";
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/ResourceModes.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/ResourceModes.java
new file mode 100644
index 0000000000..384c5f5934
--- /dev/null
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/ResourceModes.java
@@ -0,0 +1,5 @@
+package com.appsmith.server.constants;
+
+public enum ResourceModes {
+ EDIT, VIEW
+}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/Url.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/Url.java
index 7e9984090e..954c6637f2 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/Url.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/Url.java
@@ -6,7 +6,7 @@ public interface Url {
String LOGIN_URL = BASE_URL + VERSION + "/login";
String LOGOUT_URL = BASE_URL + VERSION + "/logout";
String WIDGET_URL = BASE_URL + VERSION + "/widgets";
- String ORGANIZATION_URL = BASE_URL + VERSION + "/organizations";
+ String WORKSPACE_URL = BASE_URL + VERSION + "/workspaces";
String LAYOUT_URL = BASE_URL + VERSION + "/layouts";
String PLUGIN_URL = BASE_URL + VERSION + "/plugins";
String SETTING_URL = BASE_URL + VERSION + "/settings";
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/WorkspaceController.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/WorkspaceController.java
index 8e16f0b4ae..b9574d395d 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/WorkspaceController.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/WorkspaceController.java
@@ -8,7 +8,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
-@RequestMapping(Url.ORGANIZATION_URL)
+@RequestMapping(Url.WORKSPACE_URL)
public class WorkspaceController extends WorkspaceControllerCE {
public WorkspaceController(WorkspaceService workspaceService,
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationControllerCE.java
index f0fef61039..cf1af1dd6e 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationControllerCE.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationControllerCE.java
@@ -4,7 +4,6 @@ import com.appsmith.external.models.Datasource;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.constants.Url;
import com.appsmith.server.domains.Application;
-import com.appsmith.server.domains.ApplicationJson;
import com.appsmith.server.domains.GitAuth;
import com.appsmith.server.domains.Theme;
import com.appsmith.server.dtos.ApplicationAccessDTO;
@@ -23,7 +22,6 @@ import com.appsmith.server.solutions.ApplicationForkingService;
import com.appsmith.server.solutions.ImportExportApplicationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@@ -45,7 +43,6 @@ import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import javax.validation.Valid;
-import java.nio.charset.StandardCharsets;
import java.util.List;
@Slf4j
@@ -76,13 +73,13 @@ public class ApplicationControllerCE extends BaseController> create(@Valid @RequestBody Application resource,
- @RequestParam String orgId,
+ @RequestParam String workspaceId,
ServerWebExchange exchange) {
- if (orgId == null) {
- return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, "organization id"));
+ if (workspaceId == null) {
+ return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, "workspace id"));
}
- log.debug("Going to create application in org {}", orgId);
- return applicationPageService.createApplication(resource, orgId)
+ log.debug("Going to create application in workspace {}", workspaceId);
+ return applicationPageService.createApplication(resource, workspaceId)
.map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null));
}
@@ -160,22 +157,15 @@ public class ApplicationControllerCE extends BaseController> getApplicationFile(@PathVariable String id,
- @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) {
+ public Mono> getApplicationFile(@PathVariable String id,
+ @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) {
log.debug("Going to export application with id: {}, branch: {}", id, branchName);
- return importExportApplicationService.exportApplicationById(id, branchName)
+ return importExportApplicationService.getApplicationFile(id, branchName)
.map(fetchedResource -> {
- String applicationName = fetchedResource.getExportedApplication().getName();
- HttpHeaders responseHeaders = new HttpHeaders();
- ContentDisposition contentDisposition = ContentDisposition
- .builder("attachment")
- .filename(applicationName + ".json", StandardCharsets.UTF_8)
- .build();
- responseHeaders.setContentDisposition(contentDisposition);
- responseHeaders.setContentType(MediaType.APPLICATION_JSON);
-
- return new ResponseEntity<>(fetchedResource, responseHeaders, HttpStatus.OK);
+ HttpHeaders responseHeaders = fetchedResource.getHttpHeaders();
+ Object applicationResource = fetchedResource.getApplicationResource();
+ return new ResponseEntity<>(applicationResource, responseHeaders, HttpStatus.OK);
});
}
@@ -217,9 +207,9 @@ public class ApplicationControllerCE extends BaseController new ResponseDTO<>(HttpStatus.OK.value(), theme, null));
}
- @GetMapping("/import/{orgId}/datasources")
- public Mono>> getUnConfiguredDatasource(@PathVariable String orgId, @RequestParam String defaultApplicationId) {
- return importExportApplicationService.findDatasourceByApplicationId(defaultApplicationId, orgId)
+ @GetMapping("/import/{workspaceId}/datasources")
+ public Mono>> getUnConfiguredDatasource(@PathVariable String workspaceId, @RequestParam String defaultApplicationId) {
+ return importExportApplicationService.findDatasourceByApplicationId(defaultApplicationId, workspaceId)
.map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null));
}
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/RestApiImportControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/RestApiImportControllerCE.java
index 77ae5025cc..ba37f7c681 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/RestApiImportControllerCE.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/RestApiImportControllerCE.java
@@ -44,7 +44,7 @@ public class RestApiImportControllerCE {
@RequestParam RestApiImporterType type,
@RequestParam String pageId,
@RequestParam String name,
- @RequestParam String organizationId,
+ @RequestParam String workspaceId,
@RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName,
@RequestHeader(name = "Origin", required = false) String originHeader
) {
@@ -59,7 +59,7 @@ public class RestApiImportControllerCE {
throw new IllegalStateException("Unexpected value: " + type);
}
- return service.importAction(input, pageId, name, organizationId, branchName)
+ return service.importAction(input, pageId, name, workspaceId, branchName)
.map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null));
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/UserControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/UserControllerCE.java
index 486ba41140..46671ba5b0 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/UserControllerCE.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/UserControllerCE.java
@@ -97,19 +97,19 @@ public class UserControllerCE extends BaseController
.map(updatedUser -> new ResponseDTO<>(HttpStatus.OK.value(), updatedUser, null));
}
- @PutMapping("/switchOrganization/{workspaceId}")
- public Mono> setCurrentOrganization(@PathVariable String workspaceId) {
+ @PutMapping("/switchWorkspace/{workspaceId}")
+ public Mono> setCurrentWorkspace(@PathVariable String workspaceId) {
return service.switchCurrentWorkspace(workspaceId)
.map(user -> new ResponseDTO<>(HttpStatus.OK.value(), user, null));
}
- @PutMapping("/addOrganization/{workspaceId}")
+ @PutMapping("/addWorkspace/{workspaceId}")
public Mono> addUserToWorkspace(@PathVariable String workspaceId) {
return userWorkspaceService.addUserToWorkspace(workspaceId, null)
.map(user -> new ResponseDTO<>(HttpStatus.OK.value(), user, null));
}
- @PutMapping("/leaveOrganization/{workspaceId}")
+ @PutMapping("/leaveWorkspace/{workspaceId}")
public Mono> leaveWorkspace(@PathVariable String workspaceId) {
return userWorkspaceService.leaveWorkspace(workspaceId)
.map(user -> new ResponseDTO<>(HttpStatus.OK.value(), user, null));
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/WorkspaceControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/WorkspaceControllerCE.java
index 66e5defab7..6d82da5f7f 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/WorkspaceControllerCE.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/WorkspaceControllerCE.java
@@ -25,7 +25,7 @@ import java.util.List;
import java.util.Map;
-@RequestMapping(Url.ORGANIZATION_URL)
+@RequestMapping(Url.WORKSPACE_URL)
public class WorkspaceControllerCE extends BaseController {
private final UserWorkspaceService userWorkspaceService;
@@ -41,8 +41,8 @@ public class WorkspaceControllerCE extends BaseController>> getUserRolesForWorkspace(@RequestParam String organizationId) {
- return service.getUserRolesForWorkspace(organizationId)
+ public Mono>> getUserRolesForWorkspace(@RequestParam String workspaceId) {
+ return service.getUserRolesForWorkspace(workspaceId)
.map(permissions -> new ResponseDTO<>(HttpStatus.OK.value(), permissions, null));
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/converters/GsonISOStringToInstantConverter.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/converters/GsonISOStringToInstantConverter.java
deleted file mode 100644
index f8fe47ff4b..0000000000
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/converters/GsonISOStringToInstantConverter.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.appsmith.server.converters;
-
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParseException;
-
-import java.lang.reflect.Type;
-import java.time.Instant;
-
-public class GsonISOStringToInstantConverter implements JsonDeserializer {
- @Override
- public Instant deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
- if(jsonElement.isJsonNull()) {
- return null;
- }
- String jsonString = jsonElement.getAsJsonPrimitive().getAsString();
- if(jsonString.length() == 0) {
- return null;
- }
- try {
- Double aDouble = Double.parseDouble(jsonString);
- return Instant.ofEpochSecond(aDouble.longValue());
- } catch (NumberFormatException e) {
- // do nothing, let's try to parse with Instant.parse assuming it's in ISO format
- }
- return Instant.parse(jsonString);
- }
-}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/AbstractCommentDomain.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/AbstractCommentDomain.java
index 50d01d7ed2..45836a506a 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/AbstractCommentDomain.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/AbstractCommentDomain.java
@@ -18,8 +18,13 @@ public abstract class AbstractCommentDomain extends BaseDomain {
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
String authorUsername; // username i.e. email of the user, who authored this comment or thread.
+
+ //Organizations migrated to workspaces, kept the field as deprecated to support the old migration
+ @Deprecated
String orgId;
+ String workspaceId;
+
/** Edit/Published Mode */
ApplicationMode mode;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Action.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Action.java
index 14d2fe9605..82cd30675e 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Action.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Action.java
@@ -28,8 +28,12 @@ public class Action extends BaseDomain {
Datasource datasource;
+ //Organizations migrated to workspaces, kept the field as depricated to support the old migration
+ @Deprecated
String organizationId;
+ String workspaceId;
+
String pageId;
String collectionId;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ActionCollection.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ActionCollection.java
index b60d561950..ebc2f76141 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ActionCollection.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ActionCollection.java
@@ -23,9 +23,27 @@ public class ActionCollection extends BaseDomain {
String applicationId;
+ //Organizations migrated to workspaces, kept the field as depricated to support the old migration
+ @Deprecated
String organizationId;
+ String workspaceId;
+
ActionCollectionDTO unpublishedCollection;
ActionCollectionDTO publishedCollection;
+
+ public void sanitiseToExportDBObject() {
+ this.setDefaultResources(null);
+ ActionCollectionDTO unpublishedCollection = this.getUnpublishedCollection();
+ if (unpublishedCollection != null) {
+ unpublishedCollection.sanitiseForExport();
+ }
+ ActionCollectionDTO publishedCollection = this.getPublishedCollection();
+ if (publishedCollection != null) {
+ publishedCollection.sanitiseForExport();
+ }
+ this.sanitiseToExportBaseObject();
+ this.setOrganizationId(null);
+ }
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Application.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Application.java
index 87e72843c2..2519f6fb73 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Application.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Application.java
@@ -18,7 +18,10 @@ import java.io.Serializable;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import static com.appsmith.server.constants.ResourceModes.EDIT;
+import static com.appsmith.server.constants.ResourceModes.VIEW;
import static com.appsmith.server.helpers.DateUtils.ISO_FORMATTER;
@Getter
@@ -32,8 +35,12 @@ public class Application extends BaseDomain {
@NotNull
String name;
+ //Organizations migrated to workspaces, kept the field as deprecated to support the old migration
+ @Deprecated
String organizationId;
+ String workspaceId;
+
/*
TODO: remove default values from application.
*/
@@ -147,7 +154,7 @@ public class Application extends BaseDomain {
// initialized newly or is left up to the calling function to set.
public Application(Application application) {
super();
- this.organizationId = application.getOrganizationId();
+ this.workspaceId = application.getWorkspaceId();
this.pages = new ArrayList<>();
this.publishedPages = new ArrayList<>();
this.clonedFromApplicationId = application.getId();
@@ -157,6 +164,33 @@ public class Application extends BaseDomain {
this.publishedAppLayout = application.getPublishedAppLayout() == null ? null : new AppLayout(application.getPublishedAppLayout().type);
}
+ public void exportApplicationPages(final Map pageIdToNameMap) {
+ for (ApplicationPage applicationPage : this.getPages()) {
+ applicationPage.setId(pageIdToNameMap.get(applicationPage.getId() + EDIT));
+ applicationPage.setDefaultPageId(null);
+ }
+ for (ApplicationPage applicationPage : this.getPublishedPages()) {
+ applicationPage.setId(pageIdToNameMap.get(applicationPage.getId() + VIEW));
+ applicationPage.setDefaultPageId(null);
+ }
+ }
+
+ public void sanitiseToExportDBObject() {
+ this.setWorkspaceId(null);
+ this.setOrganizationId(null);
+ this.setModifiedBy(null);
+ this.setCreatedBy(null);
+ this.setLastDeployedAt(null);
+ this.setLastEditedAt(null);
+ this.setGitApplicationMetadata(null);
+ this.setEditModeThemeId(null);
+ this.setPublishedModeThemeId(null);
+ this.setClientSchemaVersion(null);
+ this.setServerSchemaVersion(null);
+ this.setIsManualUpdate(false);
+ this.sanitiseToExportBaseObject();
+ }
+
public List getPages() {
return Boolean.TRUE.equals(viewMode) ? publishedPages : pages;
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Collection.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Collection.java
index deda3c443e..790bcf1b26 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Collection.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Collection.java
@@ -20,8 +20,12 @@ public class Collection extends BaseDomain {
String applicationId;
+ //Organizations migrated to workspaces, kept the field as depricated to support the old migration
+ @Deprecated
String organizationId;
+ String workspaceId;
+
Boolean shared;
//To save space, when creating/updating collection, only add Action's id field instead of the entire action.
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/GitApplicationMetadata.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/GitApplicationMetadata.java
index e4a05891b4..656ee6b635 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/GitApplicationMetadata.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/GitApplicationMetadata.java
@@ -29,7 +29,7 @@ public class GitApplicationMetadata implements AppsmithDomain {
String repoName;
// Default application id used for storing the application files in local volume :
- // container-volumes/git_repo/organizationId/defaultApplicationId/branchName/applicationDirectoryStructure...
+ // container-volumes/git_repo/workspaceId/defaultApplicationId/branchName/applicationDirectoryStructure...
String defaultApplicationId;
// Git credentials used to push changes to remote repo and will be stored with default application only to optimise
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Group.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Group.java
index 209d8a1f91..776512c834 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Group.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Group.java
@@ -21,9 +21,14 @@ public class Group extends BaseDomain {
private String displayName;
+ //Organizations migrated to workspaces, kept the field as deprecated to support the old migration
+ @Deprecated
@NotNull
private String organizationId;
+ @NotNull
+ String workspaceId;
+
/**
* This is a list of name of permissions. We will query with permission collection by name
* This is because permissions are global in nature. They are not specific to a particular org/team.
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Layout.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Layout.java
index fc1338a7ac..a23b636c35 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Layout.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Layout.java
@@ -2,6 +2,8 @@ package com.appsmith.server.domains;
import com.appsmith.external.models.BaseDomain;
import com.appsmith.server.dtos.DslActionDTO;
+import com.appsmith.server.helpers.CollectionUtils;
+import com.appsmith.server.helpers.CompareDslActionDTO;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.NoArgsConstructor;
@@ -11,6 +13,7 @@ import net.minidev.json.JSONObject;
import java.util.List;
import java.util.Set;
+import java.util.TreeSet;
import static java.lang.Boolean.TRUE;
@@ -76,4 +79,23 @@ public class Layout extends BaseDomain {
public List> getLayoutOnLoadActions() {
return viewMode ? publishedLayoutOnLoadActions : layoutOnLoadActions;
}
+
+ public void sanitiseToExportDBObject() {
+ this.setAllOnPageLoadActionNames(null);
+ this.setCreatedAt(null);
+ this.setUpdatedAt(null);
+ this.setAllOnPageLoadActionEdges(null);
+ this.setActionsUsedInDynamicBindings(null);
+ this.setWidgetNames(null);
+ List> layoutOnLoadActions = this.getLayoutOnLoadActions();
+ if (!CollectionUtils.isNullOrEmpty(layoutOnLoadActions)) {
+ // Sort actions based on id to commit to git in ordered manner
+ for (int dslActionIndex = 0; dslActionIndex < layoutOnLoadActions.size(); dslActionIndex++) {
+ TreeSet sortedActions = new TreeSet<>(new CompareDslActionDTO());
+ sortedActions.addAll(layoutOnLoadActions.get(dslActionIndex));
+ sortedActions.forEach(DslActionDTO::sanitiseForExport);
+ layoutOnLoadActions.set(dslActionIndex, sortedActions);
+ }
+ }
+ }
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/NewAction.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/NewAction.java
index f41c8c24c3..eaa93ebacc 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/NewAction.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/NewAction.java
@@ -18,8 +18,12 @@ public class NewAction extends BaseDomain {
// Fields in action that are not allowed to change between published and unpublished versions
String applicationId;
+ //Organizations migrated to workspaces, kept the field as deprecated to support the old migration
+ @Deprecated
String organizationId;
+ String workspaceId;
+
PluginType pluginType;
String pluginId;
@@ -35,4 +39,22 @@ public class NewAction extends BaseDomain {
ActionDTO publishedAction;
+ public void sanitiseToExportDBObject() {
+ this.setTemplateId(null);
+ this.setApplicationId(null);
+ this.setOrganizationId(null);
+ this.setWorkspaceId(null);
+ this.setProviderId(null);
+ this.setDocumentation(null);
+ ActionDTO unpublishedAction = this.getUnpublishedAction();
+ if (unpublishedAction != null) {
+ unpublishedAction.sanitiseToExportDBObject();
+ }
+ ActionDTO publishedAction = this.getPublishedAction();
+ if (publishedAction != null) {
+ publishedAction.sanitiseToExportDBObject();
+ }
+ this.sanitiseToExportBaseObject();
+ }
+
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/NewPage.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/NewPage.java
index 7091919805..6dbef3f5e7 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/NewPage.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/NewPage.java
@@ -18,4 +18,16 @@ public class NewPage extends BaseDomain {
PageDTO unpublishedPage;
PageDTO publishedPage;
+
+ public void sanitiseToExportDBObject() {
+ this.setApplicationId(null);
+ this.setId(null);
+ if (this.getUnpublishedPage() != null) {
+ this.getUnpublishedPage().sanitiseToExportDBObject();
+ }
+ if (this.getPublishedPage() != null) {
+ this.getPublishedPage().sanitiseToExportDBObject();
+ }
+ this.sanitiseToExportBaseObject();
+ }
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Plugin.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Plugin.java
index f1d579e6b8..f136981f57 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Plugin.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Plugin.java
@@ -65,7 +65,7 @@ public class Plugin extends BaseDomain {
String generateCRUDPageComponent;
// Marking it as JsonIgnore because we don't want other users to be able to set this property. Only admins
- // must be able to mark a plugin for defaultInstall on all organization creations
+ // must be able to mark a plugin for defaultInstall on all workspace creations
@JsonIgnore
Boolean defaultInstall;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Theme.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Theme.java
index a93f7ba8d8..838301ed82 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Theme.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Theme.java
@@ -26,7 +26,13 @@ public class Theme extends BaseDomain {
private String displayName;
private String applicationId;
+
+ //Organizations migrated to workspaces, kept the field as deprecated to support the old migration
+ @Deprecated
private String organizationId;
+
+ String workspaceId;
+
private Object config;
private Object properties;
private Map stylesheet;
@@ -41,4 +47,16 @@ public class Theme extends BaseDomain {
private String primaryColor;
private String backgroundColor;
}
+
+ public void sanitiseToExportDBObject() {
+ this.setId(null);
+ if(this.isSystemTheme()) {
+ // for system theme, we only need theme name and isSystemTheme properties so set null to others
+ this.setProperties(null);
+ this.setConfig(null);
+ this.setStylesheet(null);
+ }
+ // set null to base domain properties also
+ this.sanitiseToExportBaseObject();
+ }
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/User.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/User.java
index 6a08285d3e..a48e976dad 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/User.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/User.java
@@ -47,11 +47,23 @@ public class User extends BaseDomain implements UserDetails, OidcUser {
private Boolean isEnabled = true;
+ //Organizations migrated to workspaces, kept the field as depricated to support the old migration
+ @Deprecated
private String currentOrganizationId;
+
+ private String currentWorkspaceId;
+ //Organizations migrated to workspaces, kept the field as depricated to support the old migration
+ @Deprecated
private Set organizationIds;
+
+ private Set workspaceIds;
+ //Organizations migrated to workspaces, kept the field as depricated to support the old migration
+ @Deprecated
private String examplesOrganizationId;
+
+ private String examplesWorkspaceId;
// There is a many-to-many relationship with groups. If this value is modified, please also modify the list of
// users in that particular group document as well.
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/UserData.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/UserData.java
index e9cfeb3111..77c4fd34fd 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/UserData.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/UserData.java
@@ -30,7 +30,7 @@ public class UserData extends BaseDomain {
@JsonIgnore
String userId;
- // Role of the user in their organization, example, Designer, Developer, Product Lead etc.
+ // Role of the user in their workspace, example, Designer, Developer, Product Lead etc.
private String role;
// The goal the user is trying to solve with Appsmith.
@@ -42,9 +42,13 @@ public class UserData extends BaseDomain {
// The version where this user has last viewed the release notes.
private String releaseNotesViewedVersion;
- // list of organisation ids that were recently accessed by the user
+ //Organizations migrated to workspaces, kept the field as deprecated to support the old migration
+ @Deprecated
private List recentlyUsedOrgIds;
+ // list of workspace ids that were recently accessed by the user
+ private List recentlyUsedWorkspaceIds;
+
// list of application ids that were recently accessed by the user
private List recentlyUsedAppIds;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Workspace.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Workspace.java
index 92e8047d85..2194585fe6 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Workspace.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Workspace.java
@@ -34,7 +34,11 @@ public class Workspace extends BaseDomain {
private String slug;
+ //Organizations migrated to workspaces, kept the field as deprecated to support the old migration
+ @Deprecated
private Boolean isAutoGeneratedOrganization;
+
+ private Boolean isAutoGeneratedWorkspace;
@JsonIgnore
private List userRoles;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ActionCollectionDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ActionCollectionDTO.java
index eef0da3107..77e3d8c6e8 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ActionCollectionDTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ActionCollectionDTO.java
@@ -35,7 +35,7 @@ public class ActionCollectionDTO {
String applicationId;
@Transient
- String organizationId;
+ String workspaceId;
String name;
@@ -91,8 +91,8 @@ public class ActionCollectionDTO {
public Set validate() {
Set validationErrors = new HashSet<>();
- if (this.organizationId == null) {
- validationErrors.add(AppsmithError.INVALID_PARAMETER.getMessage(FieldName.ORGANIZATION_ID));
+ if (this.workspaceId == null) {
+ validationErrors.add(AppsmithError.INVALID_PARAMETER.getMessage(FieldName.WORKSPACE_ID));
}
if (this.applicationId == null) {
validationErrors.add(AppsmithError.INVALID_PARAMETER.getMessage(FieldName.APPLICATION_ID));
@@ -112,7 +112,15 @@ public class ActionCollectionDTO {
public void populateTransientFields(ActionCollection actionCollection) {
this.setId(actionCollection.getId());
this.setApplicationId(actionCollection.getApplicationId());
- this.setOrganizationId(actionCollection.getOrganizationId());
+ this.setWorkspaceId(actionCollection.getWorkspaceId());
copyNewFieldValuesIntoOldObject(actionCollection.getDefaultResources(), this.getDefaultResources());
}
+
+ public void sanitiseForExport() {
+ this.setDefaultResources(null);
+ this.setDefaultToBranchedActionIdsMap(null);
+ this.setDefaultToBranchedArchivedActionIdsMap(null);
+ this.setActionIds(null);
+ this.setArchivedActionIds(null);
+ }
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ActionDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ActionDTO.java
index ef73f00f6c..12ab3a43d3 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ActionDTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ActionDTO.java
@@ -2,10 +2,10 @@ package com.appsmith.server.dtos;
import com.appsmith.external.models.ActionConfiguration;
import com.appsmith.external.models.Datasource;
+import com.appsmith.external.models.DefaultResources;
import com.appsmith.external.models.Policy;
import com.appsmith.external.models.Property;
import com.appsmith.server.domains.ActionProvider;
-import com.appsmith.external.models.DefaultResources;
import com.appsmith.server.domains.Documentation;
import com.appsmith.server.domains.PluginType;
import com.fasterxml.jackson.annotation.JsonFormat;
@@ -35,7 +35,7 @@ public class ActionDTO {
String applicationId;
@Transient
- String organizationId;
+ String workspaceId;
@Transient
PluginType pluginType;
@@ -148,4 +148,17 @@ public class ActionDTO {
return this.fullyQualifiedName;
}
}
+ public void sanitiseToExportDBObject() {
+ this.setDefaultResources(null);
+ this.setCacheResponse(null);
+ if (this.getDatasource() != null) {
+ this.getDatasource().setCreatedAt(null);
+ }
+ if (this.getUserPermissions() != null) {
+ this.getUserPermissions().clear();
+ }
+ if (this.getPolicies() != null) {
+ this.getPolicies().clear();
+ }
+ }
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/AddItemToPageDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/AddItemToPageDTO.java
index ca13cea62a..b7299d33a7 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/AddItemToPageDTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/AddItemToPageDTO.java
@@ -10,6 +10,6 @@ import lombok.Setter;
public class AddItemToPageDTO {
String name;
String pageId;
- String organizationId;
+ String workspaceId;
ItemDTO marketplaceElement;
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ApplicationJson.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ApplicationJson.java
similarity index 73%
rename from app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ApplicationJson.java
rename to app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ApplicationJson.java
index 2f6e8bd9f7..371f3477ce 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ApplicationJson.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ApplicationJson.java
@@ -1,13 +1,17 @@
-package com.appsmith.server.domains;
+package com.appsmith.server.dtos;
import com.appsmith.external.models.Datasource;
-import com.appsmith.external.models.InvisibleActionFields;
import com.appsmith.external.models.DecryptedSensitiveFields;
+import com.appsmith.external.models.InvisibleActionFields;
+import com.appsmith.server.domains.ActionCollection;
+import com.appsmith.server.domains.Application;
+import com.appsmith.server.domains.NewAction;
+import com.appsmith.server.domains.NewPage;
+import com.appsmith.server.domains.Theme;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.Transient;
-import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -36,20 +40,26 @@ public class ApplicationJson {
List pageList;
- List pageOrder = new ArrayList<>();
+ @Deprecated
+ List pageOrder;
- List publishedPageOrder = new ArrayList<>();
+ @Deprecated
+ List publishedPageOrder;
+ @Deprecated
String publishedDefaultPageName;
-
+
+ @Deprecated
String unpublishedDefaultPageName;
List actionList;
List actionCollectionList;
+ // TODO remove the plain text fields during the export once we have a way to address sample apps DB authentication
Map decryptedFields;
+ @Deprecated
Map invisibleActionFields;
Theme editModeTheme;
@@ -58,6 +68,9 @@ public class ApplicationJson {
/**
* Mapping mongoEscapedWidgets with layoutId
*/
+ @Deprecated
Map> publishedLayoutmongoEscapedWidgets;
+
+ @Deprecated
Map> unpublishedLayoutmongoEscapedWidgets;
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ApplicationPagesDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ApplicationPagesDTO.java
index 3fc8563612..58cd5bd40b 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ApplicationPagesDTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ApplicationPagesDTO.java
@@ -10,7 +10,7 @@ import java.util.List;
@Setter
public class ApplicationPagesDTO {
- String organizationId;
+ String workspaceId;
Application application;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/DslActionDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/DslActionDTO.java
index dd42ee027f..07402c803b 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/DslActionDTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/DslActionDTO.java
@@ -28,4 +28,9 @@ public class DslActionDTO {
PluginType pluginType;
Set jsonPathKeys;
Integer timeoutInMillisecond = DEFAULT_ACTION_EXECUTION_TIMEOUT_MS;
+
+ public void sanitiseForExport() {
+ this.setDefaultActionId(null);
+ this.setDefaultCollectionId(null);
+ }
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ExportFileDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ExportFileDTO.java
new file mode 100644
index 0000000000..a5ae30e6ae
--- /dev/null
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ExportFileDTO.java
@@ -0,0 +1,11 @@
+package com.appsmith.server.dtos;
+
+import lombok.Data;
+import org.springframework.http.HttpHeaders;
+
+
+@Data
+public class ExportFileDTO {
+ HttpHeaders httpHeaders;
+ Object applicationResource;
+}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/InstallPluginRedisDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/InstallPluginRedisDTO.java
index 652a99042d..ccce06916c 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/InstallPluginRedisDTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/InstallPluginRedisDTO.java
@@ -6,6 +6,6 @@ import lombok.Setter;
@Getter
@Setter
public class InstallPluginRedisDTO {
- String organizationId;
- PluginWorkspaceDTO pluginOrgDTO;
+ String workspaceId;
+ PluginWorkspaceDTO pluginWorkspaceDTO;
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/InviteUsersDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/InviteUsersDTO.java
index bf9467040e..591f3f9635 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/InviteUsersDTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/InviteUsersDTO.java
@@ -17,5 +17,5 @@ public class InviteUsersDTO {
String roleName;
@NotNull
- String orgId;
+ String workspaceId;
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/MockDataSource.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/MockDataSource.java
index bba97c5ba4..d073cdcccd 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/MockDataSource.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/MockDataSource.java
@@ -9,7 +9,7 @@ public class MockDataSource {
String name;
- String organizationId;
+ String workspaceId;
String pluginId;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/PageDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/PageDTO.java
index 180d6bac25..0c26b15045 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/PageDTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/PageDTO.java
@@ -55,4 +55,8 @@ public class PageDTO {
// connected applications and will be used to connect actions across the branches
@Transient
DefaultResources defaultResources;
+
+ public void sanitiseToExportDBObject() {
+ this.getLayouts().forEach(Layout::sanitiseToExportDBObject);
+ }
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/PluginWorkspaceDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/PluginWorkspaceDTO.java
index 3654001bb0..15efc99bb4 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/PluginWorkspaceDTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/PluginWorkspaceDTO.java
@@ -9,7 +9,7 @@ public class PluginWorkspaceDTO {
String pluginId;
- String organizationId;
+ String workspaceId;
WorkspacePluginStatus status;
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserHomepageDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserHomepageDTO.java
index b5aed72afd..4c4173937a 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserHomepageDTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserHomepageDTO.java
@@ -16,7 +16,7 @@ public class UserHomepageDTO {
User user;
- List organizationApplications;
+ List workspaceApplications;
// This is a string so that it can hold values like `10+` if there's more than 10 new versions, for example.
String newReleasesCount;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserProfileDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserProfileDTO.java
index 0d6fc83a97..77adcfab7e 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserProfileDTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserProfileDTO.java
@@ -13,7 +13,7 @@ public class UserProfileDTO {
String email;
- Set organizationIds;
+ Set workspaceIds;
String username;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserSignupDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserSignupDTO.java
index 953ca92003..3f95f9f039 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserSignupDTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserSignupDTO.java
@@ -6,5 +6,5 @@ import lombok.Data;
@Data
public class UserSignupDTO {
private User user;
- private String defaultOrganizationId;
+ private String defaultWorkspaceId;
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/WorkspaceApplicationsDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/WorkspaceApplicationsDTO.java
index 89d6905874..b26cc074d2 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/WorkspaceApplicationsDTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/WorkspaceApplicationsDTO.java
@@ -15,7 +15,7 @@ import java.util.List;
@NoArgsConstructor
@ToString
public class WorkspaceApplicationsDTO {
- Workspace organization;
+ Workspace workspace;
List applications;
List userRoles;
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/events/AbstractCommentEvent.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/events/AbstractCommentEvent.java
index 431125dc23..287a4ce11d 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/events/AbstractCommentEvent.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/events/AbstractCommentEvent.java
@@ -7,7 +7,7 @@ import lombok.Data;
@Data
public abstract class AbstractCommentEvent {
private final String authorUserName;
- private final Workspace organization;
+ private final Workspace workspace;
private final Application application;
private final String originHeader;
private final String pageName;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/events/CommentAddedEvent.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/events/CommentAddedEvent.java
index ac5ace8925..862a4f70f8 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/events/CommentAddedEvent.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/events/CommentAddedEvent.java
@@ -12,9 +12,9 @@ public class CommentAddedEvent extends AbstractCommentEvent {
private final Comment comment;
private final Set subscribers;
- public CommentAddedEvent(Workspace organization, Application application,
+ public CommentAddedEvent(Workspace workspace, Application application,
String originHeader, Comment comment, Set subscribers, String pageName) {
- super(comment.getAuthorUsername(), organization, application, originHeader, pageName);
+ super(comment.getAuthorUsername(), workspace, application, originHeader, pageName);
this.comment = comment;
this.subscribers = subscribers;
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/events/CommentThreadClosedEvent.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/events/CommentThreadClosedEvent.java
index 058d5fc171..ae2e458d3e 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/events/CommentThreadClosedEvent.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/events/CommentThreadClosedEvent.java
@@ -9,8 +9,8 @@ import lombok.Getter;
public class CommentThreadClosedEvent extends AbstractCommentEvent {
private final CommentThread commentThread;
- public CommentThreadClosedEvent(String authorUserName, Workspace organization, Application application, String originHeader, CommentThread commentThread, String pagename) {
- super(authorUserName, organization, application, originHeader, pagename);
+ public CommentThreadClosedEvent(String authorUserName, Workspace workspace, Application application, String originHeader, CommentThread commentThread, String pagename) {
+ super(authorUserName, workspace, application, originHeader, pagename);
this.commentThread = commentThread;
}
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java
index 7d3a21025f..c7c9c98350 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java
@@ -86,7 +86,7 @@ public enum AppsmithError {
AppsmithErrorAction.LOG_EXTERNALLY, null, ErrorType.BAD_REQUEST, null),
GIT_MERGE_FAILED_REMOTE_CHANGES(406, 4036, "Remote is ahead of local by {0} commits on branch {1}. Please pull remote changes first and try again.", AppsmithErrorAction.DEFAULT, null, ErrorType.GIT_ACTION_EXECUTION_ERROR, ErrorReferenceDocUrl.GIT_UPSTREAM_CHANGES),
GIT_MERGE_FAILED_LOCAL_CHANGES(406, 4037, "There are uncommitted changes present in your local branch {0}. Please commit them first and try again", AppsmithErrorAction.DEFAULT, null, ErrorType.GIT_ACTION_EXECUTION_ERROR, null),
- REMOVE_LAST_ORG_ADMIN_ERROR(400, 4038, "The last admin can not be removed from an organization", AppsmithErrorAction.DEFAULT, null, ErrorType.INTERNAL_ERROR, null),
+ REMOVE_LAST_WORKSPACE_ADMIN_ERROR(400, 4038, "The last admin can not be removed from an organization", AppsmithErrorAction.DEFAULT, null, ErrorType.INTERNAL_ERROR, null),
INVALID_CRUD_PAGE_REQUEST(400, 4039, "Unable to process page generation request, {0}", AppsmithErrorAction.DEFAULT, null, ErrorType.BAD_REQUEST, null),
UNSUPPORTED_OPERATION_FOR_REMOTE_BRANCH(400, 4040, "This operation is not supported for remote branch {0}. Please use local branches only to proceed", AppsmithErrorAction.DEFAULT, "Unsupported Operation!", ErrorType.BAD_REQUEST, null),
INTERNAL_SERVER_ERROR(500, 5000, "Internal server error while processing request", AppsmithErrorAction.LOG_EXTERNALLY, null, ErrorType.INTERNAL_ERROR, null),
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/CompareDslActionDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/CompareDslActionDTO.java
index 6afe8b58c0..b3592481f3 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/CompareDslActionDTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/CompareDslActionDTO.java
@@ -10,9 +10,9 @@ public class CompareDslActionDTO implements Comparator, Serializab
// Method to compare DslActionDTO based on id
@Override
public int compare(DslActionDTO action1, DslActionDTO action2) {
- if (action1 != null && !StringUtils.isEmpty(action1.getId())
- && action2 != null && !StringUtils.isEmpty(action2.getId())) {
- return action1.getId().compareTo(action2.getId());
+ if (action1 != null && !StringUtils.isEmpty(action1.getName())
+ && action2 != null && !StringUtils.isEmpty(action2.getName())) {
+ return action1.getName().compareTo(action2.getName());
}
return 1;
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitCloudServicesUtils.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitCloudServicesUtils.java
index 79bc149374..6def85fefb 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitCloudServicesUtils.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitCloudServicesUtils.java
@@ -28,11 +28,11 @@ public class GitCloudServicesUtils {
private final static Map gitLimitCache = new HashMap<>();
- public Mono getPrivateRepoLimitForOrg(String orgId, boolean isClearCache) {
+ public Mono getPrivateRepoLimitForOrg(String workspaceId, boolean isClearCache) {
final String baseUrl = cloudServicesConfig.getBaseUrl();
return configService.getInstanceId().map(instanceId -> {
if (commonConfig.isCloudHosting()) {
- return instanceId + "_" + orgId;
+ return instanceId + "_" + workspaceId;
} else {
return instanceId;
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitFileUtils.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitFileUtils.java
index 4f05212b2f..d20ef0dbad 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitFileUtils.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitFileUtils.java
@@ -1,22 +1,21 @@
package com.appsmith.server.helpers;
+import com.appsmith.external.constants.AnalyticsEvents;
import com.appsmith.external.git.FileInterface;
import com.appsmith.external.helpers.Stopwatch;
import com.appsmith.external.models.ApplicationGitReference;
import com.appsmith.external.models.Datasource;
import com.appsmith.git.helpers.FileUtilsImpl;
-import com.appsmith.external.constants.AnalyticsEvents;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.ActionCollection;
import com.appsmith.server.domains.Application;
-import com.appsmith.server.domains.ApplicationJson;
-import com.appsmith.server.domains.Layout;
+import com.appsmith.server.domains.ApplicationPage;
import com.appsmith.server.domains.NewAction;
import com.appsmith.server.domains.NewPage;
import com.appsmith.server.domains.Theme;
import com.appsmith.server.dtos.ActionCollectionDTO;
import com.appsmith.server.dtos.ActionDTO;
-import com.appsmith.server.dtos.DslActionDTO;
+import com.appsmith.server.dtos.ApplicationJson;
import com.appsmith.server.dtos.PageDTO;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
@@ -39,11 +38,9 @@ import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.TreeSet;
import java.util.stream.Collectors;
import static com.appsmith.external.constants.GitConstants.NAME_SEPARATOR;
@@ -72,7 +69,7 @@ public class GitFileUtils {
= Set.of(EXPORTED_APPLICATION, DATASOURCE_LIST, PAGE_LIST, ACTION_LIST, ACTION_COLLECTION_LIST, DECRYPTED_FIELDS, EDIT_MODE_THEME);
/**
* This method will save the complete application in the local repo directory.
- * Path to repo will be : ./container-volumes/git-repo/organizationId/defaultApplicationId/repoName/{application_data}
+ * Path to repo will be : ./container-volumes/git-repo/workspaceId/defaultApplicationId/repoName/{application_data}
* @param baseRepoSuffix path suffix used to create a local repo path
* @param applicationJson application reference object from which entire application can be rehydrated
* @param branchName name of the branch for the current application
@@ -96,7 +93,7 @@ public class GitFileUtils {
.map(tuple -> {
stopwatch.stopTimer();
Path repoPath = tuple.getT1();
- // Path to repo will be : ./container-volumes/git-repo/organizationId/defaultApplicationId/repoName/
+ // Path to repo will be : ./container-volumes/git-repo/workspaceId/defaultApplicationId/repoName/
final Map data = Map.of(
FieldName.APPLICATION_ID, repoPath.getParent().getFileName().toString(),
FieldName.ORGANIZATION_ID, repoPath.getParent().getParent().getFileName().toString(),
@@ -205,14 +202,13 @@ public class GitFileUtils {
resourceMap.put(prefix, actionCollection);
});
- applicationReference.setActionsCollections(new HashMap<>(resourceMap));
+ applicationReference.setActionCollections(new HashMap<>(resourceMap));
resourceMap.clear();
// Send datasources
applicationJson
.getDatasourceList()
.forEach(datasource -> {
- removeUnwantedFieldsFromDatasource(datasource);
resourceMap.put(datasource.getName(), datasource);
});
applicationReference.setDatasources(new HashMap<>(resourceMap));
@@ -224,18 +220,18 @@ public class GitFileUtils {
/**
* Method to reconstruct the application from the local git repo
*
- * @param organizationId To which organisation application needs to be rehydrated
+ * @param workspaceId To which workspace application needs to be rehydrated
* @param defaultApplicationId Root application for the current branched application
* @param branchName for which branch the application needs to rehydrate
* @return application reference from which entire application can be rehydrated
*/
- public Mono reconstructApplicationJsonFromGitRepo(String organizationId,
+ public Mono reconstructApplicationJsonFromGitRepo(String workspaceId,
String defaultApplicationId,
String repoName,
String branchName) {
Stopwatch stopwatch = new Stopwatch(AnalyticsEvents.GIT_DESERIALIZE_APP_RESOURCES_FROM_FILE.getEventName());
Mono appReferenceMono = fileUtils
- .reconstructApplicationReferenceFromGitRepo(organizationId, defaultApplicationId, repoName, branchName);
+ .reconstructApplicationReferenceFromGitRepo(workspaceId, defaultApplicationId, repoName, branchName);
return Mono.zip(appReferenceMono, sessionUserService.getCurrentUser())
.map(tuple -> {
ApplicationGitReference applicationReference = tuple.getT1();
@@ -246,7 +242,7 @@ public class GitFileUtils {
stopwatch.stopTimer();
final Map data = Map.of(
FieldName.APPLICATION_ID, defaultApplicationId,
- FieldName.ORGANIZATION_ID, organizationId,
+ FieldName.ORGANIZATION_ID, workspaceId,
FieldName.FLOW_NAME, stopwatch.getFlow(),
"executionTime", stopwatch.getExecutionTime()
);
@@ -308,19 +304,9 @@ public class GitFileUtils {
}
private void removeUnwantedFieldsFromPage(NewPage page) {
- page.setDefaultResources(null);
- page.setCreatedAt(null);
- page.setUpdatedAt(null);
// As we are publishing the app and then committing to git we expect the published and unpublished PageDTO will
// be same, so we only commit unpublished PageDTO.
page.setPublishedPage(null);
- page.setUserPermissions(null);
- PageDTO unpublishedPage = page.getUnpublishedPage();
- if (unpublishedPage != null) {
- unpublishedPage
- .getLayouts()
- .forEach(this::removeUnwantedFieldsFromLayout);
- }
}
private void removeUnwantedFieldsFromApplication(Application application) {
@@ -331,83 +317,40 @@ public class GitFileUtils {
application.setSlug(null);
}
- private void removeUnwantedFieldsFromDatasource(Datasource datasource) {
- datasource.setPolicies(new HashSet<>());
- datasource.setStructure(null);
- datasource.setUpdatedAt(null);
- datasource.setCreatedAt(null);
- datasource.setUserPermissions(null);
- datasource.setIsConfigured(null);
- datasource.setInvalids(null);
- }
-
private void removeUnwantedFieldFromAction(NewAction action) {
- action.setDefaultResources(null);
- action.setCreatedAt(null);
- action.setUpdatedAt(null);
// As we are publishing the app and then committing to git we expect the published and unpublished ActionDTO will
// be same, so we only commit unpublished ActionDTO.
action.setPublishedAction(null);
- action.setUserPermissions(null);
- ActionDTO unpublishedAction = action.getUnpublishedAction();
- if (unpublishedAction != null) {
- unpublishedAction.setDefaultResources(null);
- if (unpublishedAction.getDatasource() != null) {
- unpublishedAction.getDatasource().setCreatedAt(null);
- }
- }
}
private void removeUnwantedFieldFromActionCollection(ActionCollection actionCollection) {
- actionCollection.setDefaultResources(null);
- actionCollection.setCreatedAt(null);
- actionCollection.setUpdatedAt(null);
// As we are publishing the app and then committing to git we expect the published and unpublished
// ActionCollectionDTO will be same, so we only commit unpublished ActionCollectionDTO.
actionCollection.setPublishedCollection(null);
- actionCollection.setUserPermissions(null);
- ActionCollectionDTO unpublishedCollection = actionCollection.getUnpublishedCollection();
- if (unpublishedCollection != null) {
- unpublishedCollection.setDefaultResources(null);
- unpublishedCollection.setDefaultToBranchedActionIdsMap(null);
- unpublishedCollection.setDefaultToBranchedArchivedActionIdsMap(null);
- unpublishedCollection.setActionIds(null);
- unpublishedCollection.setArchivedActionIds(null);
- }
- }
-
- private void removeUnwantedFieldsFromLayout(Layout layout) {
- layout.setAllOnPageLoadActionNames(null);
- layout.setCreatedAt(null);
- layout.setUpdatedAt(null);
- layout.setAllOnPageLoadActionEdges(null);
- layout.setActionsUsedInDynamicBindings(null);
- layout.setMongoEscapedWidgetNames(null);
- List> layoutOnLoadActions = layout.getLayoutOnLoadActions();
- if (!CollectionUtils.isNullOrEmpty(layout.getLayoutOnLoadActions())) {
- // Sort actions based on id to commit to git in ordered manner
- for (int dslActionIndex = 0; dslActionIndex < layoutOnLoadActions.size(); dslActionIndex++) {
- TreeSet sortedActions = new TreeSet<>(new CompareDslActionDTO());
- sortedActions.addAll(layoutOnLoadActions.get(dslActionIndex));
- sortedActions
- .forEach(actionDTO -> {
- actionDTO.setDefaultActionId(null);
- actionDTO.setDefaultCollectionId(null);
- });
- layoutOnLoadActions.set(dslActionIndex, sortedActions);
- }
- }
}
private ApplicationJson getApplicationJsonFromGitReference(ApplicationGitReference applicationReference) {
ApplicationJson applicationJson = new ApplicationJson();
// Extract application data from the json
- applicationJson.setExportedApplication(getApplicationResource(applicationReference.getApplication(), Application.class));
+ Application application = getApplicationResource(applicationReference.getApplication(), Application.class);
+ applicationJson.setExportedApplication(application);
applicationJson.setEditModeTheme(getApplicationResource(applicationReference.getTheme(), Theme.class));
// Clone the edit mode theme to published theme as both should be same for git connected application because we
// do deploy and push as a single operation
applicationJson.setPublishedTheme(applicationJson.getEditModeTheme());
Gson gson = new Gson();
+
+ if (application != null && !CollectionUtils.isNullOrEmpty(application.getPages())) {
+ // Remove null values
+ org.apache.commons.collections.CollectionUtils.filter(application.getPages(), PredicateUtils.notNullPredicate());
+ // Create a deep clone of application pages to update independently
+ application.setViewMode(false);
+ final List applicationPages = new ArrayList<>(application.getPages().size());
+ application.getPages()
+ .forEach(applicationPage -> applicationPages.add(gson.fromJson(gson.toJson(applicationPage), ApplicationPage.class)));
+ application.setPublishedPages(applicationPages);
+ }
+
// Extract pages
List pages = getApplicationResource(applicationReference.getPages(), NewPage.class);
// Remove null values
@@ -436,10 +379,10 @@ public class GitFileUtils {
}
// Extract actionCollection
- if (CollectionUtils.isNullOrEmpty(applicationReference.getActionsCollections())) {
+ if (CollectionUtils.isNullOrEmpty(applicationReference.getActionCollections())) {
applicationJson.setActionCollectionList(new ArrayList<>());
} else {
- List actionCollections = getApplicationResource(applicationReference.getActionsCollections(), ActionCollection.class);
+ List actionCollections = getApplicationResource(applicationReference.getActionCollections(), ActionCollection.class);
// Remove null values if present
org.apache.commons.collections.CollectionUtils.filter(actionCollections, PredicateUtils.notNullPredicate());
actionCollections.forEach(actionCollection -> {
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/PolicyUtils.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/PolicyUtils.java
index f681a49818..7517c909d5 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/PolicyUtils.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/PolicyUtils.java
@@ -162,7 +162,7 @@ public class PolicyUtils {
return datasourceRepository
// fetch datasources with execute permissions so that app viewers can invite other app viewers
- .findAllByOrganizationId(workspaceId, AclPermission.EXECUTE_DATASOURCES)
+ .findAllByWorkspaceId(workspaceId, AclPermission.EXECUTE_DATASOURCES)
// In case we have come across a datasource for this workspace that the current user is not allowed to manage, move on.
.switchIfEmpty(Mono.empty())
.map(datasource -> {
@@ -200,7 +200,7 @@ public class PolicyUtils {
return applicationRepository
// fetch applications with read permissions so that app viewers can invite other app viewers
- .findByOrganizationId(workspaceId, AclPermission.READ_APPLICATIONS)
+ .findByWorkspaceId(workspaceId, AclPermission.READ_APPLICATIONS)
// In case we have come across an application for this workspace that the current user is not allowed to manage, move on.
.switchIfEmpty(Mono.empty())
.map(application -> {
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog.java
index f9510074f2..33a755ff70 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog.java
@@ -133,8 +133,8 @@ import static com.appsmith.external.helpers.PluginUtils.setValueSafelyInFormData
import static com.appsmith.server.acl.AclPermission.EXECUTE_ACTIONS;
import static com.appsmith.server.acl.AclPermission.EXPORT_APPLICATIONS;
import static com.appsmith.server.acl.AclPermission.MAKE_PUBLIC_APPLICATIONS;
-import static com.appsmith.server.acl.AclPermission.ORGANIZATION_EXPORT_APPLICATIONS;
-import static com.appsmith.server.acl.AclPermission.ORGANIZATION_INVITE_USERS;
+import static com.appsmith.server.acl.AclPermission.WORKSPACE_EXPORT_APPLICATIONS;
+import static com.appsmith.server.acl.AclPermission.WORKSPACE_INVITE_USERS;
import static com.appsmith.server.acl.AclPermission.READ_ACTIONS;
import static com.appsmith.server.acl.AclPermission.READ_THEMES;
import static com.appsmith.server.constants.FieldName.DEFAULT_RESOURCES;
@@ -729,13 +729,13 @@ public class DatabaseChangelog {
policies = new HashSet<>();
}
- Optional inviteUsersOptional = policies.stream().filter(policy -> policy.getPermission().equals(ORGANIZATION_INVITE_USERS.getValue())).findFirst();
+ Optional inviteUsersOptional = policies.stream().filter(policy -> policy.getPermission().equals(WORKSPACE_INVITE_USERS.getValue())).findFirst();
if (inviteUsersOptional.isPresent()) {
Policy inviteUserPolicy = inviteUsersOptional.get();
inviteUserPolicy.getUsers().addAll(invitePermissionUsernames);
} else {
// this policy doesnt exist. create and add this to the policy set
- Policy inviteUserPolicy = Policy.builder().permission(ORGANIZATION_INVITE_USERS.getValue())
+ Policy inviteUserPolicy = Policy.builder().permission(WORKSPACE_INVITE_USERS.getValue())
.users(invitePermissionUsernames).build();
organization.getPolicies().add(inviteUserPolicy);
}
@@ -1704,7 +1704,7 @@ public class DatabaseChangelog {
mongoTemplate.updateFirst(
query(new Criteria().andOperator(
where(fieldName(QOrganization.organization.id)).is(org.getId()),
- where(fieldName(QOrganization.organization.policies) + ".permission").is(ORGANIZATION_INVITE_USERS.getValue())
+ where(fieldName(QOrganization.organization.policies) + ".permission").is(WORKSPACE_INVITE_USERS.getValue())
)),
new Update().addToSet("policies.$.users").each(viewers.toArray()),
Organization.class
@@ -2468,14 +2468,14 @@ public class DatabaseChangelog {
}
Optional exportAppOrgLevelOptional = policies.stream()
- .filter(policy -> policy.getPermission().equals(ORGANIZATION_EXPORT_APPLICATIONS.getValue())).findFirst();
+ .filter(policy -> policy.getPermission().equals(WORKSPACE_EXPORT_APPLICATIONS.getValue())).findFirst();
if (exportAppOrgLevelOptional.isPresent()) {
Policy exportApplicationPolicy = exportAppOrgLevelOptional.get();
exportApplicationPolicy.getUsers().addAll(exportApplicationPermissionUsernames);
} else {
// this policy doesnt exist. create and add this to the policy set
- Policy inviteUserPolicy = Policy.builder().permission(ORGANIZATION_EXPORT_APPLICATIONS.getValue())
+ Policy inviteUserPolicy = Policy.builder().permission(WORKSPACE_EXPORT_APPLICATIONS.getValue())
.users(exportApplicationPermissionUsernames).build();
organization.getPolicies().add(inviteUserPolicy);
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java
index 41522dce14..df5f2dbc3d 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java
@@ -1,37 +1,90 @@
package com.appsmith.server.migrations;
+import com.appsmith.external.models.ApiTemplate;
+import com.appsmith.external.models.BaseDomain;
+import com.appsmith.external.models.Category;
import com.appsmith.external.models.Datasource;
import com.appsmith.external.models.Property;
+import com.appsmith.external.models.Provider;
import com.appsmith.external.models.QBaseDomain;
import com.appsmith.external.models.QDatasource;
+import com.appsmith.server.acl.AppsmithRole;
import com.appsmith.server.constants.FieldName;
+import com.appsmith.server.domains.Action;
import com.appsmith.server.domains.ActionCollection;
import com.appsmith.server.domains.Application;
import com.appsmith.server.domains.ApplicationPage;
+import com.appsmith.server.domains.Asset;
+import com.appsmith.server.domains.Collection;
+import com.appsmith.server.domains.Comment;
+import com.appsmith.server.domains.CommentNotification;
+import com.appsmith.server.domains.CommentThread;
+import com.appsmith.server.domains.CommentThreadNotification;
+import com.appsmith.server.domains.Config;
+import com.appsmith.server.domains.GitDeployKeys;
+import com.appsmith.server.domains.Group;
+import com.appsmith.server.domains.InviteUser;
+import com.appsmith.server.domains.Layout;
import com.appsmith.server.domains.NewAction;
import com.appsmith.server.domains.NewPage;
+import com.appsmith.server.domains.Notification;
import com.appsmith.server.domains.Organization;
+import com.appsmith.server.domains.Page;
+import com.appsmith.server.domains.PasswordResetToken;
import com.appsmith.server.domains.Plugin;
+import com.appsmith.server.domains.QAction;
+import com.appsmith.server.domains.QActionCollection;
import com.appsmith.server.domains.PricingPlan;
import com.appsmith.server.domains.QApplication;
+import com.appsmith.server.domains.QCollection;
+import com.appsmith.server.domains.QComment;
+import com.appsmith.server.domains.QCommentThread;
+import com.appsmith.server.domains.QConfig;
+import com.appsmith.server.domains.QGroup;
+import com.appsmith.server.domains.QInviteUser;
import com.appsmith.server.domains.QNewAction;
import com.appsmith.server.domains.QNewPage;
import com.appsmith.server.domains.QOrganization;
import com.appsmith.server.domains.QPlugin;
+import com.appsmith.server.domains.QTheme;
+import com.appsmith.server.domains.QUser;
+import com.appsmith.server.domains.QUserData;
+import com.appsmith.server.domains.QWorkspace;
+import com.appsmith.server.domains.Role;
+import com.appsmith.server.domains.Sequence;
+import com.appsmith.server.domains.Theme;
+import com.appsmith.server.domains.UsagePulse;
+import com.appsmith.server.domains.User;
+import com.appsmith.server.domains.UserData;
import com.appsmith.server.domains.QTenant;
import com.appsmith.server.domains.Sequence;
import com.appsmith.server.domains.Tenant;
import com.appsmith.server.domains.User;
import com.appsmith.server.domains.Workspace;
+import com.appsmith.server.domains.WorkspacePlugin;
import com.appsmith.server.dtos.ActionDTO;
+import com.appsmith.server.dtos.ApplicationTemplate;
+import com.appsmith.server.dtos.ResetUserPasswordDTO;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.helpers.TextUtils;
+import com.appsmith.server.services.ce.ConfigServiceCE;
+import com.appsmith.server.services.ce.ConfigServiceCEImpl;
import com.github.cloudyrock.mongock.ChangeLog;
import com.github.cloudyrock.mongock.ChangeSet;
import com.github.cloudyrock.mongock.driver.mongodb.springdata.v3.decorator.impl.MongockTemplate;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
+import reactor.core.publisher.Flux;
+
+import org.bson.BsonArray;
+import org.bson.Document;
+import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
+import org.springframework.data.mongodb.core.aggregation.AggregationPipeline;
+import org.springframework.data.mongodb.core.aggregation.AggregationUpdate;
+import org.springframework.data.mongodb.core.aggregation.Fields;
+import org.springframework.data.mongodb.core.aggregation.SetOperation;
+import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.ReactiveRedisOperations;
@@ -41,13 +94,14 @@ import org.springframework.util.StringUtils;
import reactor.core.publisher.Flux;
import java.time.Instant;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.HashSet;
+import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -789,12 +843,14 @@ public class DatabaseChangelog2 {
@ChangeSet(order = "009", id = "copy-organization-to-workspaces", author = "")
public void copyOrganizationToWorkspaces(MongockTemplate mongockTemplate) {
+ // Drop the workspace collection in case it has been partially run, otherwise it has no effect
+ mongockTemplate.dropCollection(Workspace.class);
Gson gson = new Gson();
//Memory optimization note:
//Call stream instead of findAll to avoid out of memory if the collection is big
//stream implementation lazy loads the data using underlying cursor open on the collection
- //the data is loaded as and when needed by the pipeline
- try(Stream stream = mongockTemplate.stream(new Query(), Organization.class)
+ //the data is loaded as as and when needed by the pipeline
+ try(Stream stream = mongockTemplate.stream(new Query().cursorBatchSize(10000), Organization.class)
.stream()) {
stream.forEach((organization) -> {
Workspace workspace = gson.fromJson(gson.toJson(organization), Workspace.class);
@@ -891,6 +947,136 @@ public class DatabaseChangelog2 {
final Flux