Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat: Made changes to support datasources configuration page for workspace#41324

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
tomjose92 wants to merge14 commits intorelease
base:release
Choose a base branch
Loading
fromfeat/issue-35669/workspace-datasources

Conversation

@tomjose92
Copy link
Contributor

@tomjose92tomjose92 commentedOct 27, 2025
edited by coderabbitaibot
Loading

Description

Made changes to show datasources settings page at a workspace level.
This allows an administrator to see all the datasources being used on the workspace from a page without the need to go to App Editor.

Datasource.config.page.mov

Fixes35669

Automation

/ok-to-test tags="@tag.All"

🔍 Cypress test results

Warning

Tests have not run on the HEAD9caf3ed yet


Sat, 29 Nov 2025 06:18:52 UTC

Communication

Should the DevRel and Marketing teams inform users about this change?

  • Yes
  • No

Summary by CodeRabbit

  • New Features

    • Workspace datasources page, editor, header and sidebar for viewing, creating, and editing workspace-scoped datasources
    • "Datasources" added to the workspace menu and workspace-scoped routes
  • Enhancements

    • Routing, URL handling and IDE header updated for workspace context and navigation
    • Datasource creation options and add-button behavior adjusted when in workspace view; workspace init/loading UI added
    • REST/GraphQL creation options hidden on workspace datasources page
  • Tests

    • Cypress end-to-end tests covering workspace datasource flows (blank state, create, edit, delete)

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitaibot commentedOct 27, 2025
edited
Loading

Walkthrough

Adds Workspace IDE support: new IDE type, workspace-scoped routes and URL builders, workspace context in URL assembly, Redux actions/reducer and sagas to initialize a WorkspaceEditorEngine, new workspace datasources UI (pages, header, side pane, editor), permission/plugin filter adjustments, and e2e tests.

Changes

Cohort / File(s)Summary
IDE Type Definition
app/client/src/ce/IDE/Interfaces/IDETypes.ts
AddedWorkspace member toIDE_TYPE, updatingIDEType union.
Routing Constants
app/client/src/constants/routes/baseRoutes.ts,app/client/src/ce/IDE/constants/routes.ts
AddedWORKSPACE_DATASOURCES_PAGE_URL andWORKSPACE_DATASOURCE_EDITOR_PAGE_URL; mappedIDEBasePaths[IDE_TYPE.Workspace] to those routes.
URL Builders & Assembly
app/client/src/ce/RouteBuilder.ts,app/client/src/ce/entities/URLRedirect/URLAssembly.ts
AddedworkspaceDatasourcesURL andworkspaceDatasourceEditorURL; extendedURLBuilderParams withworkspaceId?; introduced workspace context detection, workspace-specific base path/entity resolution, and datasource suffix normalization.
Redux: Actions & Constants
app/client/src/ce/actions/workspaceIDEActions.ts,app/client/src/ee/actions/workspaceIDEActions.ts,app/client/src/ce/constants/ReduxActionConstants.tsx
NewInitWorkspaceIDEPayload andinitWorkspaceIDE action; addedINITIALIZE_WORKSPACE_IDE,INITIALIZE_WORKSPACE_IDE_SUCCESS, andINITIALIZE_WORKSPACE_IDE_ERROR; EE module re-exports CE actions.
Redux: Reducer State
app/client/src/ce/reducers/uiReducers/editorReducer.tsx
AddedisWorkspaceEditorInitialized toEditorReduxState, initial state, and handlers forINITIALIZE_WORKSPACE_IDE andINITIALIZE_WORKSPACE_IDE_SUCCESS.
Sagas
app/client/src/ce/sagas/workspaceIDESagas.ts,app/client/src/ee/sagas/workspaceIDESagas.ts,app/client/src/ce/sagas/index.tsx
NewstartWorkspaceIDE saga (CE), EE saga wiringtakeLatest onINITIALIZE_WORKSPACE_IDE, and registration ofworkspaceIDESagas in CE saga index.
Workspace Editor Engine
app/client/src/entities/Engine/WorkspaceEditorEngine.ts
New saga-drivenWorkspaceEditorEngine with methods to load workspace, fetch envs/plugins/datasources, setup engine, complete initialization, and domain-specific error handling.
Workspace UI: Pages & Components
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx,app/client/src/pages/workspace/WorkspaceDataSidePane.tsx,app/client/src/pages/workspace/WorkspaceDatasourceEditor.tsx,app/client/src/pages/workspace/WorkspaceDatasourceHeader.tsx,app/client/src/pages/workspace/index.tsx
Added two-pane datasources page, side pane, editor wrapper, header, and routing updates;Workspace also exported as default.
App Header & Menu
app/client/src/ce/pages/common/AppHeader.tsx,app/client/src/pages/AppIDE/layouts/components/Header/index.tsx,app/client/src/ce/pages/Applications/WorkspaceMenu.tsx
Added workspace datasource header routes, render workspace name link withworkspaceId query param in header, and added "Datasources" item to workspace menu.
Editor Plugin Filters & Permissions
app/client/src/pages/Editor/IntegrationEditor/APIOrSaasPlugins.tsx,app/client/src/pages/Editor/IntegrationEditor/DBOrMostPopularPlugins.tsx,app/client/src/ce/utils/BusinessFeatures/permissionPageHelpers.tsx
Added workspace context checks to hide REST/GraphQL creation options and to block create-datasource permission whenideType isWorkspace.
Tests
app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
Added e2e tests covering workspace datasource blank-state flows, add/edit/delete scenarios and navigation.

Sequence Diagram(s)

sequenceDiagram    participant User    participant Router    participant WorkspacePage as WorkspaceDatasourcesPage    participant Redux    participant Saga as workspaceIDESaga    participant Engine as WorkspaceEditorEngine    participant API    User->>Router: GET /workspace/:id/datasources    Router->>WorkspacePage: render(workspaceId)    WorkspacePage->>Redux: select isWorkspaceEditorInitialized    alt not initialized        WorkspacePage->>Redux: dispatch initWorkspaceIDE({workspaceId})        Redux->>Saga: middleware handles action        activate Saga        Saga->>Engine: new WorkspaceEditorEngine()        Saga->>Engine: call loadWorkspace(workspaceId)        activate Engine        Engine->>API: fetch workspace environments        API-->>Engine: environments        Engine->>API: fetch plugins & datasources        API-->>Engine: plugins & datasources        Engine->>Redux: put INITIALIZE_WORKSPACE_IDE_SUCCESS        deactivate Engine        deactivate Saga        Redux->>WorkspacePage: isWorkspaceEditorInitialized = true    end    WorkspacePage->>WorkspacePage: render side pane + editor routes
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Areas needing extra attention:
    • WorkspaceEditorEngine async flows and error types.
    • startWorkspaceIDE saga ordering (reset, init, load sequence).
    • URLAssembly workspace detection and datasource suffix normalization.
    • useEffect dependencies and init races in WorkspaceDatasourcesPage.
    • Permission gating changes that may hide creation options unexpectedly.

Poem

🌱 A workspace blooms with datasources bright,
Sagas hum softly to set up the light,
Routes align and headers find their place,
Editors wake in a scoped little space,
Tests stroll in to prove the new embrace.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.You can run@coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Title check✅ PassedTitle describes the main feature (workspace-level datasources configuration page) and aligns with the substantial changes across multiple files adding this capability.
Description check✅ PassedDescription includes motivation, issue reference (#35669), relevant video context, and automation tags; meets template requirements despite communication checkbox not being selected.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branchfeat/issue-35669/workspace-datasources

Thanks for usingCodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment@coderabbitai help to get the list of available commands and usage tips.

@tomjose92tomjose92 changed the titlefeat - Made changes to support datasources configuration page for workspacefeat: Made changes to support datasources configuration page for workspaceOct 27, 2025
@tomjose92
Copy link
ContributorAuthor

/build-deploy-preview skip-tests=true

github-actions[bot] reacted with rocket emojigithub-actions[bot] reacted with eyes emoji

@github-actionsgithub-actionsbot added the EnhancementNew feature or request labelOct 27, 2025
@github-actions
Copy link

Deploying Your Preview:https://github.com/appsmithorg/appsmith/actions/runs/18841755423.
Workflow:On demand build Docker image and deploy preview.
skip-tests:true.
env: ``.
PR: 41324.
recreate: .

Copy link
Contributor

@coderabbitaicoderabbitaibot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (14)
app/client/src/ce/pages/Applications/WorkspaceMenu.tsx (1)

169-181:Use RouteBuilder + add test id/a11y role.

  • Prefer central URL helper to avoid hard-coded paths.
  • Add data-testid and role="menuitem" for QA/a11y parity with other items.

Apply within this block:

-  <CustomMenuItem-    className="workspace-menu-item"+  <CustomMenuItem+    className="workspace-menu-item"+    data-testid="t--workspace-datasources"+    role="menuitem"     onClick={() =>-      getOnSelectAction(DropdownOnSelectActions.REDIRECT, {-        path: `/workspace/${workspace.id}/datasources`,-      })+      getOnSelectAction(DropdownOnSelectActions.REDIRECT, {+        path: workspaceDatasourcesURL({ workspaceId: workspace.id }),+      })     }   >

And add import at top:

+import { workspaceDatasourcesURL } from "ce/RouteBuilder";
app/client/src/pages/workspace/index.tsx (1)

20-29:Prefer Route.render to avoid remounts and re-created component functions.
Keeps props typing simple and avoids new component identity per render.

-        <SentryRoute-          component={({-            match,-          }: {-            match: { params: { workspaceId: string } };-          }) => (-            <WorkspaceDatasourcesPage workspaceId={match.params.workspaceId} />-          )}-          path={`${path}/:workspaceId/datasources`}-        />+        <SentryRoute+          path={`${path}/:workspaceId/datasources`}+          render={({ match }: { match: { params: { workspaceId: string } } }) => (+            <WorkspaceDatasourcesPage workspaceId={match.params.workspaceId} />+          )}+        />
app/client/src/ce/RouteBuilder.ts (1)

200-206:Consider aligning with the existing URL building pattern.

These functions use template literals directly, while most other URL builders in this file useurlBuilder.build(). For consistency and to leverage any URL handling logic (encoding, normalization) thaturlBuilder provides, consider using the established pattern.

Apply this diff to align with existing patterns:

-export const workspaceDatasourcesURL = (workspaceId: string): string =>-  `/workspace/${workspaceId}/datasources`;--export const workspaceDatasourceEditorURL = (-  workspaceId: string,-  datasourceId: string,-): string => `/workspace/${workspaceId}/datasources/${datasourceId}`;+export const workspaceDatasourcesURL = (workspaceId: string): string =>+  urlBuilder.build({+    suffix: `workspace/${workspaceId}/datasources`,+  });++export const workspaceDatasourceEditorURL = (+  workspaceId: string,+  datasourceId: string,+): string =>+  urlBuilder.build({+    suffix: `workspace/${workspaceId}/datasources/${datasourceId}`,+  });

Note: Review urlBuilder.build implementation to ensure it handles absolute paths starting with "workspace" correctly, or adjust the pattern accordingly.

app/client/src/ce/sagas/workspaceIDESagas.ts (2)

24-28:Await editor reset before initialization to avoid race conditions.

RESET_EDITOR_REQUEST may have async side-effects. Wait for RESET_EDITOR_SUCCESS before proceeding.

-import { all, put, call, takeLatest } from "redux-saga/effects";+import { all, put, call, take, takeLatest } from "redux-saga/effects";...   yield put(resetEditorRequest());+  yield take(ReduxActionTypes.RESET_EDITOR_SUCCESS);   yield call(workspaceEngine.setupEngine);

39-43:Simplify watcher.

all([...]) with a single effect is unnecessary. Yield takeLatest directly.

-export default function* watchWorkspaceIDESagas() {-  yield all([-    takeLatest(ReduxActionTypes.INITIALIZE_WORKSPACE_IDE, startWorkspaceIDE),-  ]);-}+export default function* watchWorkspaceIDESagas() {+  yield takeLatest(ReduxActionTypes.INITIALIZE_WORKSPACE_IDE, startWorkspaceIDE);+}
app/client/src/ce/reducers/uiReducers/editorReducer.tsx (1)

45-62:Reset workspace IDE flag on RESET_EDITOR_REQUEST.

Keeps flags consistent across editor switches.

 [ReduxActionTypes.RESET_EDITOR_REQUEST]: (state: EditorReduxState) => {   return {     ...state,+    isWorkspaceEditorInitialized: false,     currentPageId: undefined,
app/client/src/ce/actions/workspaceIDEActions.ts (1)

7-10:LGTM. Consider typing the action.

Optionally return ReduxAction for stricter typing.

app/client/src/pages/workspace/WorkspaceDatasourceEditor.tsx (1)

16-24:Guard selector result and avoid magic string.

  • Use optional chaining to avoid reading id from undefined.
  • Replace "unused_env" with a shared constant.
 useEffect(() => {-  if (-    currentEnvironmentDetails.id &&-    currentEnvironmentDetails.id !== "unused_env"-  ) {-    dispatch(setCurrentEditingEnvironmentID(currentEnvironmentDetails.id));-  }-}, [dispatch, currentEnvironmentDetails.id]);+  const envId = currentEnvironmentDetails?.id;+  if (envId && envId !== UNUSED_ENV_ID) {+    dispatch(setCurrentEditingEnvironmentID(envId));+  }+}, [dispatch, currentEnvironmentDetails?.id]);

Add/import:const UNUSED_ENV_ID = "unused_env"; (or import an existing constant).

app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1)

95-106:Add error fallback UI.

Show an error state if initialization fails (pair with reducer error flag).

-if (!isWorkspaceEditorInitialized) {+const initError = useSelector(+  (state: DefaultRootState) => state.ui.editor.workspaceEditorInitError,+);+if (initError) {+  return (+    <PageContainer>+      <CenteredWrapper style={{ height: `calc(100vh - ${IDE_HEADER_HEIGHT}px)` }}>+        <div>Failed to initialize Workspace Datasources. Please retry.</div>+      </CenteredWrapper>+    </PageContainer>+  );+}+if (!isWorkspaceEditorInitialized) {   return (
app/client/src/ce/entities/Engine/WorkspaceEditorEngine.ts (1)

104-108:Optional: include workspaceId in SUCCESS payload.

Helps consumers correlate which workspace initialized (useful for telemetry or race-proofing).

   *completeChore() {     yield put({-      type: ReduxActionTypes.INITIALIZE_WORKSPACE_IDE_SUCCESS,+      type: ReduxActionTypes.INITIALIZE_WORKSPACE_IDE_SUCCESS,+      // payload: { workspaceId }, // if you propagate it here     });   }
app/client/src/pages/workspace/WorkspaceDataSidePane.tsx (4)

170-179:Add alt text to datasource icons (a11y).

Provide meaningful alt; fallback to plugin or datasource name.

-  startIcon: (-    <DatasourceIcon-      src={getAssetUrl(pluginImages[data.pluginId])}-    />-  ),+  startIcon: (+    <DatasourceIcon+      alt={`${data.name} icon`}+      src={getAssetUrl(pluginImages[data.pluginId])}+    />+  ),

36-40:Optional: avoid magic numbers in heights.

Use a shared header height token to compute PaneBody height for consistency with IDE.

-  height: calc(100vh - 120px);+  /* import { IDE_HEADER_HEIGHT } from "@appsmith/ads"; */+  height: calc(100vh - var(--ide-header-height, 120px));

And set the CSS variable at a higher container if available.


70-75:useCallback deps completeness.

goToDatasource depends on history. It’s stable, but include it to silence exhaustive-deps lint (if enabled).

-  const goToDatasource = useCallback(+  const goToDatasource = useCallback(     (id: string) => {       history.push(workspaceDatasourceEditorURL(workspaceId, id));     },-    [workspaceId],+    [workspaceId, history],   );

124-137:Show spinner copy via i18n message key.

Replace hardcoded “Loading workspace permissions...” with a messages constant for consistency.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between15113b4 and228474d.

📒 Files selected for processing (20)
  • app/client/src/ce/IDE/Interfaces/IDETypes.ts (1 hunks)
  • app/client/src/ce/IDE/constants/routes.ts (1 hunks)
  • app/client/src/ce/RouteBuilder.ts (1 hunks)
  • app/client/src/ce/actions/workspaceIDEActions.ts (1 hunks)
  • app/client/src/ce/constants/ReduxActionConstants.tsx (2 hunks)
  • app/client/src/ce/entities/Engine/WorkspaceEditorEngine.ts (1 hunks)
  • app/client/src/ce/entities/URLRedirect/URLAssembly.ts (7 hunks)
  • app/client/src/ce/pages/Applications/WorkspaceMenu.tsx (1 hunks)
  • app/client/src/ce/reducers/uiReducers/editorReducer.tsx (3 hunks)
  • app/client/src/ce/sagas/index.tsx (2 hunks)
  • app/client/src/ce/sagas/workspaceIDESagas.ts (1 hunks)
  • app/client/src/constants/routes/baseRoutes.ts (1 hunks)
  • app/client/src/ee/actions/workspaceIDEActions.ts (1 hunks)
  • app/client/src/ee/entities/Engine/WorkspaceEditorEngine.ts (1 hunks)
  • app/client/src/ee/sagas/workspaceIDESagas.ts (1 hunks)
  • app/client/src/pages/workspace/WorkspaceCreateNewDatasourceTab.tsx (1 hunks)
  • app/client/src/pages/workspace/WorkspaceDataSidePane.tsx (1 hunks)
  • app/client/src/pages/workspace/WorkspaceDatasourceEditor.tsx (1 hunks)
  • app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1 hunks)
  • app/client/src/pages/workspace/index.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (11)
app/client/src/ce/actions/workspaceIDEActions.ts (1)
app/client/src/ce/constants/ReduxActionConstants.tsx (1)
  • ReduxActionTypes (1302-1346)
app/client/src/ce/IDE/constants/routes.ts (1)
app/client/src/ce/IDE/Interfaces/IDETypes.ts (1)
  • IDE_TYPE (1-6)
app/client/src/ce/sagas/workspaceIDESagas.ts (4)
app/client/src/actions/ReduxActionTypes.ts (1)
  • ReduxAction (9-12)
app/client/src/ce/actions/workspaceIDEActions.ts (1)
  • InitWorkspaceIDEPayload (3-5)
app/client/src/ce/entities/Engine/WorkspaceEditorEngine.ts (1)
  • WorkspaceEditorEngine (22-109)
app/client/src/actions/initActions.ts (1)
  • resetEditorRequest (51-53)
app/client/src/ce/reducers/uiReducers/editorReducer.tsx (1)
app/client/src/ce/constants/ReduxActionConstants.tsx (1)
  • ReduxActionTypes (1302-1346)
app/client/src/pages/workspace/WorkspaceDatasourceEditor.tsx (1)
app/client/src/ce/actions/environmentAction.ts (1)
  • setCurrentEditingEnvironmentID (7-10)
app/client/src/pages/workspace/WorkspaceDataSidePane.tsx (6)
app/client/src/ce/selectors/entitiesSelector.ts (4)
  • getDatasources (86-88)
  • getDatasourcesGroupedByPluginCategory (114-144)
  • getPluginImages (605-623)
  • getPlugins (90-91)
app/client/src/ce/entities/FeatureFlag.ts (1)
  • FEATURE_FLAG (2-67)
app/client/src/ce/RouteBuilder.ts (1)
  • workspaceDatasourceEditorURL (203-206)
app/client/src/ce/utils/BusinessFeatures/permissionPageHelpers.tsx (1)
  • getHasCreateDatasourcePermission (56-62)
app/client/src/ce/constants/messages.ts (3)
  • DATASOURCE_BLANK_STATE_CTA (2360-2360)
  • DATA_PANE_TITLE (2356-2356)
  • DATASOURCE_LIST_BLANK_DESCRIPTION (2357-2358)
app/client/src/entities/Datasource/index.ts (1)
  • Datasource (154-162)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (5)
app/client/src/ce/selectors/entitiesSelector.ts (1)
  • getDatasourceUsageCountForApp (1769-1787)
app/client/src/ce/IDE/Interfaces/IDETypes.ts (1)
  • IDE_TYPE (1-6)
app/client/src/ce/actions/workspaceIDEActions.ts (1)
  • initWorkspaceIDE (7-10)
app/client/src/pages/workspace/WorkspaceDataSidePane.tsx (1)
  • WorkspaceDataSidePane (52-197)
app/client/src/components/SentryRoute.tsx (1)
  • SentryRoute (3-3)
app/client/src/ce/RouteBuilder.ts (1)
app/client/cypress/support/commands.js (1)
  • workspaceId (396-396)
app/client/src/ce/entities/URLRedirect/URLAssembly.ts (1)
app/client/cypress/support/commands.js (1)
  • workspaceId (396-396)
app/client/src/ce/entities/Engine/WorkspaceEditorEngine.ts (5)
app/client/src/ce/actions/environmentAction.ts (1)
  • fetchingEnvironmentConfigs (13-26)
app/client/src/actions/ReduxActionTypes.ts (1)
  • ReduxAction (9-12)
app/client/src/sagas/InitSagas.ts (1)
  • failFastApiCalls (147-167)
app/client/src/entities/Engine/index.ts (2)
  • PluginsNotFoundError (61-61)
  • PluginFormConfigsNotFoundError (62-62)
app/client/src/actions/pluginActions.ts (1)
  • fetchPluginFormConfigs (22-29)
app/client/src/pages/workspace/index.tsx (2)
app/client/src/components/SentryRoute.tsx (1)
  • SentryRoute (3-3)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1)
  • WorkspaceDatasourcesPage (59-145)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: client-prettier / prettier-check
  • GitHub Check: client-lint / client-lint
  • GitHub Check: client-check-cyclic-deps / check-cyclic-dependencies
  • GitHub Check: client-unit-tests / client-unit-tests
  • GitHub Check: client-build / client-build
🔇 Additional comments (12)
app/client/src/ce/sagas/index.tsx (1)

60-60:Saga wiring looks good.
Placement alongside workspaceSagas is reasonable. No changes needed.

Also applies to: 79-79

app/client/src/ce/entities/URLRedirect/URLAssembly.ts (1)

245-252:Workspace URL resolution needs refinement, but proposed fixes require design clarification.

The concerns about empty workspaceId and context-coupled suffix rewriting are valid. However, the proposed diffs have structural issues that need addressing:

Confirmed issues:

  • resolveEntityIdForWorkspace() returns"" instead of throwing—creates/workspace//datasources risk
  • Suffix rewrite gates onisWorkspaceContext() only, not explicitworkspaceId intent

Issues with proposed solution:

  • generateBasePath() receives onlybasePageId andmode; diffs assume it receivesbuilderParams—misaligned with actual signature
  • No evidence ofdatasource/ suffix pattern in RouteBuilder (uses"datasource","datasources","datasource/{id}")
  • Diff E duplicates suffix logic; unclear whethergenerateBasePath() should make the workspace vs. app decision

Recommended approach:

  1. FixresolveEntityIdForWorkspace() to throw on missing ID (align withresolveEntityIdForApp())
  2. Clarify method responsibilities: ShouldgenerateBasePath() be refactored to receivebuilderParams and handle the workspace/app decision, or shouldbuild() handle routing logic?
  3. Unify suffix handling: Gate on!!builderParams.workspaceId || isWorkspaceContext() consistently—not just in one location

Redesign the routing layer to pass explicit intent (workspaceId) through method calls rather than relying on URL parsing alone.

app/client/src/constants/routes/baseRoutes.ts (1)

31-31:LGTM!

The new workspace datasources route constant follows the established naming pattern and integrates cleanly with existing workspace routes.

app/client/src/ce/IDE/constants/routes.ts (1)

45-45:LGTM!

Adding the Workspace IDE type to the IDEBasePaths mapping is consistent with the existing pattern for None and UIPackage types.

app/client/src/ee/actions/workspaceIDEActions.ts (1)

1-1:LGTM!

Standard EE/CE facade pattern that allows for potential future extensions while maintaining a clean architecture boundary.

app/client/src/ee/entities/Engine/WorkspaceEditorEngine.ts (1)

1-1:LGTM!

The EE facade for WorkspaceEditorEngine follows the established pattern and maintains clean architectural boundaries.

app/client/src/ee/sagas/workspaceIDESagas.ts (1)

1-2:LGTM!

The EE saga facade follows the established pattern and properly re-exports both named and default exports from the CE layer.

app/client/src/ce/constants/ReduxActionConstants.tsx (2)

414-415:LGTM!

The new workspace IDE action constants follow the established naming convention and are consistent with existing IDE initialization patterns (e.g., INITIALIZE_EDITOR).


483-483:LGTM!

The error action constant is properly placed in IDEActionErrorTypes and follows the naming pattern.

app/client/src/pages/workspace/WorkspaceCreateNewDatasourceTab.tsx (1)

4-6:No issues found. CreateNewDatasourceTab properly accesses workspace context via Redux.

The component is Redux-connected throughconnect(mapStateToProps), which automatically injects workspace data (viagetCurrentAppWorkspace,getCurrentPageId, and other selectors) as props. The wrapper component correctly omits props since the child component obtains all required context from Redux state.

app/client/src/ce/entities/Engine/WorkspaceEditorEngine.ts (1)

40-47:No action required—empty type is intentional.

Thetype property in thefetchingEnvironmentConfigs action creator is intentionally left as an empty string to imitate the functionality of the enterprise edition. The action properly propagates through sagas that handle environment configuration fetching. The code at lines 40–47 is correct as written.

app/client/src/pages/workspace/WorkspaceDatasourceEditor.tsx (1)

5-5:Fix empty Redux action type in setCurrentEditingEnvironmentID.

The action type is confirmed empty inapp/client/src/ce/actions/environmentAction.ts line 8. Redux actions require a non-emptytype property for proper routing and reducer handling. Replace the empty string with a descriptive action type constant.

⛔ Skipped due to learnings
Learnt from: AmanAgarwal041PR: appsmithorg/appsmith#29266File: app/client/src/ce/actions/environmentAction.ts:15-16Timestamp: 2024-07-26T21:12:57.228ZLearning: The `type` property in the `fetchingEnvironmentConfigs` action creator is intentionally left as an empty string to imitate the functionality of the enterprise edition, as per the user's clarification.

None:"None",
App:"App",
UIPackage:"UIPackage",
Workspace:"Workspace",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

⚠️ Potential issue |🔴 Critical

🧩 Analysis chain

LGTM — new IDE type addition is consistent.
No concerns here. Please ensure downstream switch/route maps cover IDE_TYPE.Workspace.

Run to spot any missing cases:


🏁 Script executed:

#!/bin/bashrg -nP --type=ts'\bIDE_TYPE\.Workspace\b|:\s*IDEType\b' -C2

Length of output: 8283


---🏁 Script executed:```shell#!/bin/bash# Find switch statements handling IDE_TYPErg -nP --type=ts 'switch\s*\(\s*(type|ideType|.*IDE_TYPE)' -A 15 | head -100

Length of output: 8750


🏁 Script executed:

#!/bin/bash# Find other enum-like mappings that use IDE_TYPE keysrg -nP --type=ts'\[IDE_TYPE\.' -C 1| head -150

Length of output: 498


🏁 Script executed:

#!/bin/bash# Check if there are any references to IDE_TYPE.Workspace that might be missingrg -nP --type=ts'IDE_TYPE\.Workspace' -C 3

Length of output: 386


🏁 Script executed:

#!/bin/bash# Get full getIDEFocusStrategy function to check if Workspace case is handledcat app/client/src/ce/navigation/FocusStrategy/index.ts

Length of output: 528


🏁 Script executed:

#!/bin/bash# Search for getIDETypeByUrl to see if it handles Workspacecat app/client/src/ce/entities/IDE/utils/getIDETypeByUrl.ts

Length of output: 434


🏁 Script executed:

#!/bin/bash# Search for EE FocusStrategy implementationsfd -t f'FocusStrategy' -path'*/ee/*'

Length of output: 168


🏁 Script executed:

#!/bin/bash# Check if UIPackageFocusStrategy or WorkspaceFocusStrategy existsrg -nP --type=ts'UIPackageFocusStrategy|WorkspaceFocusStrategy' -l

Length of output: 0


🏁 Script executed:

#!/bin/bash# Find AppIDEFocusStrategy to understand implementation patternrg -nP --type=ts'class AppIDEFocusStrategy|export.*AppIDEFocusStrategy' -C 3

Length of output: 784


🏁 Script executed:

#!/bin/bash# Search more broadly for strategy files in EE folderfind. -path"*/ee/*" -name"*FocusStrategy*"2>/dev/null| head -20

Length of output: 179


🏁 Script executed:

#!/bin/bash# Check if there's an EE version of the focus strategy indexfind. -path"*/ee/*" -name"index.ts"| xargs grep -l"getIDEFocusStrategy\|FocusStrategy"2>/dev/null| head -10

Length of output: 53


🏁 Script executed:

#!/bin/bash# Check the EE version of getIDEFocusStrategycat app/client/src/ee/navigation/FocusStrategy/index.ts

Length of output: 44


🏁 Script executed:

#!/bin/bash# Check if getIDEFocusStrategy is called with Workspace anywhererg -nP --type=ts'getIDEFocusStrategy' -C 3

Length of output: 2489


Add case for IDE_TYPE.Workspace in getIDEFocusStrategy or update default handler.

The switch statement inapp/client/src/ce/navigation/FocusStrategy/index.ts only handlesIDE_TYPE.None andIDE_TYPE.App, butIDE_TYPE.Workspace is now inIDEBasePaths. SinceFocusRetentionSaga callsgetIDEFocusStrategy(ideType) whereideType comes fromgetIDETypeByUrl(), this will throw an error if Workspace paths are configured.

Currently,IDE_TYPE.Workspace has an empty path array, so it won't trigger at runtime yet—but this is a latent bug waiting to happen.

🤖 Prompt for AI Agents
In app/client/src/ce/IDE/Interfaces/IDETypes.ts around line 5,IDE_TYPE.Workspace was added but getIDEFocusStrategy (inapp/client/src/ce/navigation/FocusStrategy/index.ts) only handles IDE_TYPE.Noneand IDE_TYPE.App; add a case for IDE_TYPE.Workspace to the switch ingetIDEFocusStrategy (or update the switch default to handle unknown/added IDEtypes safely) so FocusRetentionSaga won't throw when getIDETypeByUrl() returnsWorkspace; implement the Workspace case to return the appropriate focus strategy(match App behavior or a no-op strategy) and ensure the default branch logs awarning and returns a safe fallback strategy.

Comment on lines +69 to +76
[ReduxActionTypes.INITIALIZE_WORKSPACE_IDE]:(state:EditorReduxState)=>{
return{ ...state,isWorkspaceEditorInitialized:false};
},
[ReduxActionTypes.INITIALIZE_WORKSPACE_IDE_SUCCESS]:(
state:EditorReduxState,
)=>{
return{ ...state,isWorkspaceEditorInitialized:true};
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

⚠️ Potential issue |🟠 Major

Handle initialization error to avoid infinite spinner.

Add INITIALIZE_WORKSPACE_IDE_ERROR handler and store the error so UI can show a fallback.

   [ReduxActionTypes.INITIALIZE_WORKSPACE_IDE]: (state: EditorReduxState) => {     return { ...state, isWorkspaceEditorInitialized: false };   },   [ReduxActionTypes.INITIALIZE_WORKSPACE_IDE_SUCCESS]: (     state: EditorReduxState,   ) => {     return { ...state, isWorkspaceEditorInitialized: true };   },+  [ReduxActionErrorTypes.INITIALIZE_WORKSPACE_IDE_ERROR]: (+    state: EditorReduxState,+    action: ReduxAction<{ error: unknown }>,+  ) => {+    return {+      ...state,+      isWorkspaceEditorInitialized: false,+      workspaceEditorInitError: action.payload?.error,+    };+  },

Additionally add the field to state shape and initial state:

 // initialState   onLoadActionExecution: false,+  workspaceEditorInitError: undefined,
 export interface EditorReduxState { ...   onLoadActionExecution?: boolean;+  workspaceEditorInitError?: unknown;
📝 Committable suggestion

‼️IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[ReduxActionTypes.INITIALIZE_WORKSPACE_IDE]:(state:EditorReduxState)=>{
return{ ...state,isWorkspaceEditorInitialized:false};
},
[ReduxActionTypes.INITIALIZE_WORKSPACE_IDE_SUCCESS]:(
state:EditorReduxState,
)=>{
return{ ...state,isWorkspaceEditorInitialized:true};
},
[ReduxActionTypes.INITIALIZE_WORKSPACE_IDE]:(state:EditorReduxState)=>{
return{ ...state,isWorkspaceEditorInitialized:false};
},
[ReduxActionTypes.INITIALIZE_WORKSPACE_IDE_SUCCESS]:(
state:EditorReduxState,
)=>{
return{ ...state,isWorkspaceEditorInitialized:true};
},
[ReduxActionErrorTypes.INITIALIZE_WORKSPACE_IDE_ERROR]:(
state:EditorReduxState,
action:ReduxAction<{error:unknown}>,
)=>{
return{
...state,
isWorkspaceEditorInitialized:false,
workspaceEditorInitError:action.payload?.error,
};
},
🤖 Prompt for AI Agents
In app/client/src/ce/reducers/uiReducers/editorReducer.tsx around lines 69 to76, add a new ReduxActionTypes.INITIALIZE_WORKSPACE_IDE_ERROR case that setsisWorkspaceEditorInitialized to false and stores the error payload on state(e.g., workspaceInitError or initializeWorkspaceError) so the UI can stop thespinner and show a fallback; also add that error field to the EditorReduxStatetype/shape and initialize it in the reducer's initial state (null or undefinedby default), and ensure the SUCCESS and INITIALIZE handlers clear/reset theerror.

Comment on lines +30 to +36
yieldput({
type:ReduxActionErrorTypes.INITIALIZE_WORKSPACE_IDE_ERROR,
payload:{
error,
},
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

⚠️ Potential issue |🟠 Major

Surface error state for UI.

INITIALIZE_WORKSPACE_IDE_ERROR is dispatched, but there’s no reducer handling to unblock or show an error. Pair this with a reducer flag and UI fallback. See reducer comment for concrete diff.

🤖 Prompt for AI Agents
In app/client/src/ce/sagas/workspaceIDESagas.ts around lines 30 to 36, the sagadispatches INITIALIZE_WORKSPACE_IDE_ERROR but the app has no reducer or stateflag to surface this error to the UI; add a reducer case and state flag (e.g.,workspaceIDEInitializationError or isWorkspaceIDEInitError) to store the errorpayload and clear any "initializing" flag, update the reducer's initial stateaccordingly, and ensure components read this flag to show a fallback/error UIand stop loading spinners; also add an action handler to clear the error whenretrying or on successful init.

Comment on lines +31 to +38
return(
<DataSourceEditor
applicationId={workspaceApplicationId}
datasourceId={datasourceId}
isWorkspaceContext
pageId={workspacePageId}
/>
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

⚠️ Potential issue |🔴 Critical

🧩 Analysis chain

Verify DataSourceEditor workspace mode assumptions.

We pass synthetic applicationId/pageId with isWorkspaceContext. Confirm DataSourceEditor suppresses app/page fetches in this mode.


🏁 Script executed:

#!/bin/bash# Ensure DataSourceEditor gates app/page dependent fetches behind `isWorkspaceContext`.rg -nP --type=ts --type=tsx -C3'\bfunction\s+DataSourceEditor\b|\bconst\s+DataSourceEditor\b' app/client/src \| sed -n'1,120p'rg -nP --type=ts --type=tsx -C3'isWorkspaceContext' app/client/src/pages/Editor/DataSourceEditor*

Length of output: 55


🏁 Script executed:

#!/bin/bash# Find DataSourceEditor component filesfd -e ts -e tsx'DataSourceEditor' app/client/src# Search for DataSourceEditor definition without type flagrg -n'function DataSourceEditor|const DataSourceEditor' app/client/src -A 5# Search for isWorkspaceContext usage in Editor directoryrg -n'isWorkspaceContext' app/client/src/pages/Editor -C 3

Length of output: 0


🏁 Script executed:

#!/bin/bash# Broader search for DataSource-related filesfind app/client/src -type f -name"*DataSource*"2>/dev/null| head -20# List structure of app/client/src if it existsls -la app/client/src/2>/dev/null| head -20# Search broadly for isWorkspaceContext across entire codebaserg'isWorkspaceContext' -n2>/dev/null| head -30# Search for any Editor directoryfind app/client -type d -name"Editor"2>/dev/null

Length of output: 2312


🏁 Script executed:

#!/bin/bash# Check what WorkspaceDatasourceEditor imports and usescat app/client/src/pages/workspace/WorkspaceDatasourceEditor.tsx# Search for component definitions accepting isWorkspaceContextrg'isWorkspaceContext' app/client/src/pages/Editor -B 5 -A 10# Look for Datasource related components in Editor directoriesfind app/client/src/pages/Editor -type f\( -name"*.tsx" -o -name"*.ts"\)| xargs grep -l"Datasource"2>/dev/null

Length of output: 5898


🏁 Script executed:

#!/bin/bash# View DataSourceEditor component definitioncat app/client/src/pages/Editor/DataSourceEditor/index.tsx# Search for isWorkspaceContext usage in DataSourceEditor directoryrg'isWorkspaceContext' app/client/src/pages/Editor/DataSourceEditor -B 3 -A 3# Look for useEffect and fetch patterns in the directoryrg'useEffect|fetch|applicationId|pageId' app/client/src/pages/Editor/DataSourceEditor/index.tsx -n

Length of output: 40922


DataSourceEditor must handle isWorkspaceContext to suppress app/page dependency fetches.

TheisWorkspaceContext prop passed from WorkspaceDatasourceEditor is never declared in the component'sReduxStateProps interface and never checked. The component unconditionally callsgetApplicationByIdFromWorkspaces(state, applicationId) and passes bothapplicationId andpageId to subforms without guarding based on workspace context. This means synthetic IDs intended to avoid unnecessary API calls are still processed as legitimate application/page references, potentially triggering fetches.

AddisWorkspaceContext to theReduxStateProps interface, extract it inmapStateToProps, and conditionally skip app/page lookups when true. Alternatively, prevent the synthetic IDs from reaching selectors that trigger API calls by gating the affected logic.

@tomjose92
Copy link
ContributorAuthor

/build-deploy-preview skip-tests=true

github-actions[bot] reacted with rocket emojigithub-actions[bot] reacted with eyes emoji

@github-actions
Copy link

Deploying Your Preview:https://github.com/appsmithorg/appsmith/actions/runs/18842120808.
Workflow:On demand build Docker image and deploy preview.
skip-tests:true.
env: ``.
PR: 41324.
recreate: .

Copy link
Contributor

@coderabbitaicoderabbitaibot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (3)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (3)

71-73:Pass IDE_TYPE.Workspace for correct usage labels.

The selector generates usage strings like "N queries in this app" when passedIDE_TYPE.App. Since this is a workspace context, passIDE_TYPE.Workspace so labels read "…in this workspace".

-const dsUsageMap = useSelector((state) =>-  getDatasourceUsageCountForApp(state, IDE_TYPE.App),-);+const dsUsageMap = useSelector((state) =>+  getDatasourceUsageCountForApp(state, IDE_TYPE.Workspace),+);

81-86:Initialization won't re-run when switching workspaces.

The!isWorkspaceEditorInitialized guard prevents re-initialization when navigating from one workspace to another. The flag stays true from the first workspace, so workspace B never initializes.

-useEffect(() => {-  if (workspaceId && !isWorkspaceEditorInitialized) {-    dispatch(initWorkspaceIDE({ workspaceId }));-  }-}, [dispatch, workspaceId, isWorkspaceEditorInitialized]);+useEffect(() => {+  if (workspaceId) {+    dispatch(initWorkspaceIDE({ workspaceId }));+  }+}, [dispatch, workspaceId]);

120-124:Route path case mismatch with navigation calls.

This route uses "/new" (lowercase), but WorkspaceDataSidePane pushes "/NEW" (uppercase) on lines 43 and 102. Navigation will fail. Standardize on lowercase "/new" in WorkspaceDataSidePane.tsx.

🧹 Nitpick comments (2)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (2)

89-106:Consider adding error handling for failed initialization.

Currently there's no feedback if workspace fetch or IDE initialization fails. Users might see an indefinite spinner. Consider adding error boundaries or timeout handling.


123-135:Inconsistent workspaceId prop.

Line 123 rendersWorkspaceCreateNewDatasourceTab without passingworkspaceId, but line 135 passes it explicitly. If the component extracts it from route params, the explicit prop is redundant. If not, line 123 is missing it.

For consistency, either remove the explicit prop on line 135:

-<WorkspaceCreateNewDatasourceTab workspaceId={workspaceId} />+<WorkspaceCreateNewDatasourceTab />

Or add it to line 123:

-render={() => <WorkspaceCreateNewDatasourceTab />}+render={() => <WorkspaceCreateNewDatasourceTab workspaceId={workspaceId} />}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between228474d andad664c8.

📒 Files selected for processing (1)
  • app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (5)
app/client/src/ce/selectors/entitiesSelector.ts (1)
  • getDatasourceUsageCountForApp (1769-1787)
app/client/src/ce/IDE/Interfaces/IDETypes.ts (1)
  • IDE_TYPE (1-6)
app/client/src/ce/actions/workspaceIDEActions.ts (1)
  • initWorkspaceIDE (7-10)
app/client/src/pages/workspace/WorkspaceDataSidePane.tsx (1)
  • WorkspaceDataSidePane (52-197)
app/client/src/components/SentryRoute.tsx (1)
  • SentryRoute (3-3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: client-check-cyclic-deps / check-cyclic-dependencies
  • GitHub Check: client-prettier / prettier-check
  • GitHub Check: client-unit-tests / client-unit-tests
  • GitHub Check: client-lint / client-lint
  • GitHub Check: client-build / client-build

Copy link
Contributor

@coderabbitaicoderabbitaibot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (2)

70-73:Use Workspace context for usage strings.

Pass IDE_TYPE.Workspace so labels read “…in this workspace”.

-  const dsUsageMap = useSelector((state) =>-    getDatasourceUsageCountForApp(state, IDE_TYPE.App),-  );+  const dsUsageMap = useSelector((state) =>+    getDatasourceUsageCountForApp(state, IDE_TYPE.Workspace),+  );

81-86:Re-initialize IDE on workspace change.

The guard can skip init when switching workspaces. Dispatch on every workspaceId change.

-useEffect(() => {-  if (workspaceId && !isWorkspaceEditorInitialized) {-    dispatch(initWorkspaceIDE({ workspaceId }));-  }-}, [dispatch, workspaceId, isWorkspaceEditorInitialized]);+useEffect(() => {+  if (workspaceId) {+    dispatch(initWorkspaceIDE({ workspaceId }));+  }+}, [dispatch, workspaceId]);
🧹 Nitpick comments (6)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (2)

132-135:Make the default list route exact.

Prevents accidental matches if route order shifts.

-            <SentryRoute-              path="/workspace/:workspaceId/datasources"-              render={() => <WorkspaceCreateNewDatasourceTab />}-            />+            <SentryRoute+              exact+              path="/workspace/:workspaceId/datasources"+              render={() => <WorkspaceCreateNewDatasourceTab />}+            />

121-124:Avoid magic “NEW” segment.

Extract to a constant or reuse a RouteBuilder helper to keep callers and routes in sync.

-              path="/workspace/:workspaceId/datasources/NEW"+              path={`/workspace/:workspaceId/datasources/${NEW_SEGMENT}`}

Consider adding workspaceDatasourceNewURL(workspaceId) in RouteBuilder and using it here.

app/client/src/ce/entities/URLRedirect/URLAssembly.ts (3)

254-263:Don’t infer context from window.location. Prefer explicit params.

Coupling to window pathname makes URL building dependent on the current page and breaks SSR/tests. Consider treating presence of builderParams.workspaceId as the workspace context switch, falling back to location only if absent.

Minimal approach: add an optional parameter or internal flag set in build():

  • Determineconst inWorkspace = !!builderParams.workspaceId || this.isWorkspaceContext();
  • Pass workspaceId explicitly to generateBasePathForWorkspace rather than re-parsing location.

341-349:Suffix rewrite for “datasource/” is brittle.

This special-case logic is easy to miss for other workspace routes and mixes concerns. Prefer dedicated helpers or route constants for workspace URLs and keep URLBuilder generic.

  • Move workspace-datasource path assembly to RouteBuilder (already added) and remove this special-case.
  • If retained, also handle exact "datasource" (no trailing slash) to avoid edge cases.

30-32:Document workspaceId usage.

Clarify that providing workspaceId opts into workspace routing so callers aren’t surprised.

Add JSDoc on URLBuilderParams.workspaceId explaining precedence over window location and expected consumers.

app/client/src/ce/RouteBuilder.ts (1)

200-207:Unify with route constants and add a helper for "NEW".

  • ConstantsWORKSPACE_URL andWORKSPACE_DATASOURCES_PAGE_URL exist in baseRoutes and should be imported to avoid drift.
  • AddworkspaceDatasourceNewURL helper to consolidate the three hardcoded/datasources/NEW strings currently in WorkspaceDatasourcesPage.tsx and WorkspaceDataSidePane.tsx.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and betweenad664c8 ande4c0ba2.

📒 Files selected for processing (4)
  • app/client/src/ce/RouteBuilder.ts (1 hunks)
  • app/client/src/ce/entities/URLRedirect/URLAssembly.ts (6 hunks)
  • app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1 hunks)
  • app/client/src/pages/workspace/index.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/client/src/pages/workspace/index.tsx
🧰 Additional context used
🧬 Code graph analysis (3)
app/client/src/ce/RouteBuilder.ts (1)
app/client/cypress/support/commands.js (1)
  • workspaceId (396-396)
app/client/src/ce/entities/URLRedirect/URLAssembly.ts (1)
app/client/cypress/support/commands.js (1)
  • workspaceId (396-396)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (5)
app/client/src/ce/selectors/entitiesSelector.ts (1)
  • getDatasourceUsageCountForApp (1769-1787)
app/client/src/ce/IDE/Interfaces/IDETypes.ts (1)
  • IDE_TYPE (1-6)
app/client/src/ce/actions/workspaceIDEActions.ts (1)
  • initWorkspaceIDE (7-10)
app/client/src/pages/workspace/WorkspaceDataSidePane.tsx (1)
  • WorkspaceDataSidePane (52-197)
app/client/src/components/SentryRoute.tsx (1)
  • SentryRoute (3-3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: client-unit-tests / client-unit-tests
  • GitHub Check: client-build / client-build
  • GitHub Check: client-prettier / prettier-check
  • GitHub Check: client-check-cyclic-deps / check-cyclic-dependencies
  • GitHub Check: client-lint / client-lint

Comment on lines +312 to +323
resolveEntityIdForWorkspace(builderParams:URLBuilderParams):string{
// Extract workspaceId from current URL if not provided
if(builderParams?.workspaceId){
returnbuilderParams.workspaceId;
}

constcurrentUrl=window.location.pathname;
constworkspaceMatch=currentUrl.match(/^\/workspace\/([^\/]+)/);

returnworkspaceMatch ?workspaceMatch[1] :"";
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

⚠️ Potential issue |🟠 Major

Validate workspaceId; don’t fall back to empty string.

Returning "" yields “/workspace//…” URLs. Align with app path behavior and throw.

-    const workspaceMatch = currentUrl.match(/^\/workspace\/([^\/]+)/);--    return workspaceMatch ? workspaceMatch[1] : "";+    const workspaceMatch = currentUrl.match(/^\/workspace\/([^\/]+)/);+    const id = workspaceMatch ? workspaceMatch[1] : "";+    if (!id) {+      throw new URIError("Missing workspaceId. Provide builderParams.workspaceId or navigate under /workspace/:workspaceId.");+    }+    return id;
🤖 Prompt for AI Agents
In app/client/src/ce/entities/URLRedirect/URLAssembly.ts around lines 312 to323, the resolver returns an empty string when no workspaceId is found whichproduces malformed paths like "/workspace//…"; change the logic to validate andrequire a workspaceId: if builderParams.workspaceId is present return it;otherwise attempt to extract from window.location.pathname and if extractionfails throw a clear Error (or assert) indicating missing workspaceId instead ofreturning ""; ensure the thrown error message includes context (e.g., "MissingworkspaceId in URL or builderParams") so callers can handle or surface it.

@tomjose92
Copy link
ContributorAuthor

/build-deploy-preview skip-tests=true

github-actions[bot] reacted with rocket emojigithub-actions[bot] reacted with eyes emoji

@github-actions
Copy link

Deploying Your Preview:https://github.com/appsmithorg/appsmith/actions/runs/18848305560.
Workflow:On demand build Docker image and deploy preview.
skip-tests:true.
env: ``.
PR: 41324.
recreate: .

@github-actions
Copy link

Deploy-Preview-URL:https://ce-41324.dp.appsmith.com

…components. Also handled the header for WorkspaceDatasources. Also hiding REST API and GRAPHQL API from datasources list on workspaces page
Copy link
Contributor

@coderabbitaicoderabbitaibot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (2)

75-78:Use Workspace context for usage strings.

As previously noted, passingIDE_TYPE.App causes usage labels to read "in this app". Update toIDE_TYPE.Workspace so the UI displays "in this workspace" for consistency with the workspace context.

-  const dsUsageMap = useSelector((state) =>-    getDatasourceUsageCountForApp(state, IDE_TYPE.App),-  );+  const dsUsageMap = useSelector((state) =>+    getDatasourceUsageCountForApp(state, IDE_TYPE.Workspace),+  );

86-91:Re-initialize when workspaceId changes.

As previously noted, the current guard prevents re-initialization when navigating between different workspaces. TheisWorkspaceEditorInitialized flag remains true after the first workspace is loaded, so switching to a different workspace won't trigger initialization.

-  useEffect(() => {-    if (workspaceId && !isWorkspaceEditorInitialized) {-      dispatch(initWorkspaceIDE({ workspaceId }));-    }-  }, [dispatch, workspaceId, isWorkspaceEditorInitialized]);+  useEffect(() => {+    if (workspaceId) {+      dispatch(initWorkspaceIDE({ workspaceId }));+    }+  }, [dispatch, workspaceId]);
🧹 Nitpick comments (3)
app/client/src/pages/Editor/IntegrationEditor/DBOrMostPopularPlugins.tsx (1)

330-335:Optional: Consider removing unnecessary optional chaining.

The Plugin interface (fromentities/Plugin/index.ts) showspackageName is a required field, so the optional chainingplugin?.packageName is unnecessary. The variable namefinalFilteredMostPopularPlugins could be more descriptive (e.g.,workspaceFilteredPlugins), though the current name is acceptable.

-  // Filter out REST API from most popular plugins when on workspace datasources page-  const finalFilteredMostPopularPlugins = isWorkspaceDatasourcesPage-    ? filteredMostPopularPlugins.filter(-        (plugin: Plugin) => plugin?.packageName !== PluginPackageName.REST_API,-      )-    : filteredMostPopularPlugins;+  // Filter out REST API from most popular plugins when on workspace datasources page+  const workspaceFilteredPlugins = isWorkspaceDatasourcesPage+    ? filteredMostPopularPlugins.filter(+        (plugin: Plugin) => plugin.packageName !== PluginPackageName.REST_API,+      )+    : filteredMostPopularPlugins;
app/client/src/pages/Editor/IntegrationEditor/APIOrSaasPlugins.tsx (1)

368-371:Consider using route matching utilities for robustness.

The current implementation usingincludes() will work for the expected paths but could theoretically match unintended URLs. For more robust path matching, consider using React Router'smatchPath or theuseLocation hook with explicit path comparison.

Example refactor:

+import { useLocation, matchPath } from "react-router";+import { WORKSPACE_DATASOURCES_PAGE_URL, WORKSPACE_DATASOURCE_EDITOR_PAGE_URL } from "constants/routes";...-  // Check if we're on workspace datasources page-  const isWorkspaceDatasourcesPage =-    window.location.pathname.includes("/workspace/") &&-    window.location.pathname.includes("/datasources");+  const location = useLocation();+  const isWorkspaceDatasourcesPage = Boolean(+    matchPath(location.pathname, { path: WORKSPACE_DATASOURCES_PAGE_URL }) ||+    matchPath(location.pathname, { path: WORKSPACE_DATASOURCE_EDITOR_PAGE_URL })+  );
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1)

123-141:Consider using lowercase "new" for route consistency.

The route uses/NEW (uppercase), which matches the navigation inWorkspaceDataSidePane. While this works, the convention in web routing typically favors lowercase path segments. Consider standardizing on/new across both the route definition and all navigation calls for better consistency with common web practices.

-            path={`${WORKSPACE_DATASOURCES_PAGE_URL}/NEW`}+            path={`${WORKSPACE_DATASOURCES_PAGE_URL}/new`}

And update navigation calls inWorkspaceDataSidePane.tsx:

-history.push(`/workspace/${workspaceId}/datasources/NEW`);+history.push(`/workspace/${workspaceId}/datasources/new`);
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and betweene4c0ba2 and5aa777b.

📒 Files selected for processing (7)
  • app/client/src/ce/pages/common/AppHeader.tsx (2 hunks)
  • app/client/src/constants/routes/baseRoutes.ts (1 hunks)
  • app/client/src/pages/Editor/IntegrationEditor/APIOrSaasPlugins.tsx (1 hunks)
  • app/client/src/pages/Editor/IntegrationEditor/DBOrMostPopularPlugins.tsx (1 hunks)
  • app/client/src/pages/workspace/WorkspaceDatasourceHeader.tsx (1 hunks)
  • app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1 hunks)
  • app/client/src/pages/workspace/index.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/client/src/constants/routes/baseRoutes.ts
🧰 Additional context used
🧬 Code graph analysis (6)
app/client/src/pages/Editor/IntegrationEditor/APIOrSaasPlugins.tsx (2)
app/client/src/pages/Editor/IntegrationEditor/util.ts (1)
  • filterSearch (11-20)
app/client/src/ce/constants/messages.ts (1)
  • CREATE_NEW_DATASOURCE_REST_API (402-402)
app/client/src/pages/workspace/WorkspaceDatasourceHeader.tsx (2)
app/client/src/pages/Editor/AppsmithLink.tsx (1)
  • AppsmithLink (29-67)
app/client/src/constants/routes/baseRoutes.ts (1)
  • APPLICATIONS_URL (8-8)
app/client/src/pages/Editor/IntegrationEditor/DBOrMostPopularPlugins.tsx (1)
app/client/src/entities/Plugin/index.ts (1)
  • Plugin (71-87)
app/client/src/pages/workspace/index.tsx (3)
app/client/src/components/SentryRoute.tsx (1)
  • SentryRoute (3-3)
app/client/src/pages/common/PageWrapper.tsx (1)
  • PageWrapper (63-89)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1)
  • WorkspaceDatasourcesPage (64-146)
app/client/src/ce/pages/common/AppHeader.tsx (1)
app/client/src/constants/routes/baseRoutes.ts (2)
  • WORKSPACE_DATASOURCES_PAGE_URL (31-31)
  • WORKSPACE_DATASOURCE_EDITOR_PAGE_URL (32-32)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (6)
app/client/src/ce/selectors/entitiesSelector.ts (1)
  • getDatasourceUsageCountForApp (1769-1787)
app/client/src/ce/IDE/Interfaces/IDETypes.ts (1)
  • IDE_TYPE (1-6)
app/client/src/ce/actions/workspaceIDEActions.ts (1)
  • initWorkspaceIDE (7-10)
app/client/src/pages/workspace/WorkspaceDataSidePane.tsx (1)
  • WorkspaceDataSidePane (52-197)
app/client/src/components/SentryRoute.tsx (1)
  • SentryRoute (3-3)
app/client/src/constants/routes/baseRoutes.ts (2)
  • WORKSPACE_DATASOURCES_PAGE_URL (31-31)
  • WORKSPACE_DATASOURCE_EDITOR_PAGE_URL (32-32)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: client-check-cyclic-deps / check-cyclic-dependencies
  • GitHub Check: client-lint / client-lint
  • GitHub Check: client-prettier / prettier-check
  • GitHub Check: client-unit-tests / client-unit-tests
  • GitHub Check: client-build / client-build
🔇 Additional comments (15)
app/client/src/pages/Editor/IntegrationEditor/DBOrMostPopularPlugins.tsx (1)

338-338:LGTM!

The plugin selection correctly uses the workspace-filtered plugin list when displaying most popular plugins.

app/client/src/ce/pages/common/AppHeader.tsx (2)

19-20:LGTM!

The new imports for workspace datasource routes and header component are correctly placed and follow the existing import patterns.

Also applies to: 25-25


49-56:LGTM!

The new workspace datasource routes are properly integrated into the Switch statement and follow the existing routing patterns.

app/client/src/pages/Editor/IntegrationEditor/APIOrSaasPlugins.tsx (1)

373-386:LGTM!

The visibility conditions correctly hide REST and GraphQL API creation options when on workspace datasources pages. The logic is consistently applied to both API types.

app/client/src/pages/workspace/WorkspaceDatasourceHeader.tsx (3)

1-7:LGTM!

All imports are correctly placed and necessary for the component implementation.


9-16:LGTM!

The fixed header styling is appropriate and uses the correct CSS variables for z-index and background color.


18-38:LGTM!

The header component is well-structured and correctly implements the IDEHeader pattern with appropriate conditional rendering for the workspace name.

app/client/src/pages/workspace/index.tsx (4)

6-6:LGTM!

The import for WorkspaceDatasourcesPage is correctly placed.


15-22:LGTM!

The Settings route maintains the existing PageWrapper pattern and is correctly structured.


23-42:LGTM!

The workspace datasources routes are correctly configured. Both routes properly extractworkspaceId from route parameters and pass it toWorkspaceDatasourcesPage. The component handles its own layout, so not wrapping it inPageWrapper is appropriate.


43-49:LGTM!

The default workspace page route maintains the existing PageWrapper pattern and is correctly positioned as the catch-all route.

app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (4)

1-24:LGTM!

All imports are appropriately organized and necessary for the component implementation.


27-58:LGTM!

The styled components create an appropriate two-pane IDE layout that mirrors the AppIDE structure.


80-84:LGTM!

The workspace selector correctly retrieves the current workspace by ID.


93-98:LGTM!

The workspace fetching logic correctly ensures workspace data is loaded when needed.

Copy link
Contributor

@coderabbitaicoderabbitaibot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
app/client/src/pages/workspace/WorkspaceDatasourceHeader.tsx (2)

34-36:Remove or clarify the empty div.

The empty div in IDEHeader.Right serves no clear purpose. Either remove it if IDEHeader.Right can be empty, or add a comment if it's a placeholder for future functionality.

         <IDEHeader.Right>-          <div />         </IDEHeader.Right>

9-16:WorkspaceDatasourceHeader height should be explicitly set to match padding-top.

The page correctly appliespadding-top: ${IDE_HEADER_HEIGHT}px onPageContainer to offset the fixed header. However,WorkspaceDatasourceHeader doesn't explicitly set its own height property. For alignment consistency, addheight: ${IDE_HEADER_HEIGHT}px; toStyledWorkspaceHeader to ensure the header and content spacing remain in sync ifIDE_HEADER_HEIGHT changes.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between5aa777b and1a30e1b.

📒 Files selected for processing (1)
  • app/client/src/pages/workspace/WorkspaceDatasourceHeader.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
app/client/src/pages/workspace/WorkspaceDatasourceHeader.tsx (2)
app/client/src/pages/Editor/AppsmithLink.tsx (1)
  • AppsmithLink (29-67)
app/client/src/constants/routes/baseRoutes.ts (1)
  • APPLICATIONS_URL (8-8)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: client-unit-tests / client-unit-tests
  • GitHub Check: client-prettier / prettier-check
  • GitHub Check: client-lint / client-lint
  • GitHub Check: client-build / client-build
  • GitHub Check: client-check-cyclic-deps / check-cyclic-dependencies
🔇 Additional comments (1)
app/client/src/pages/workspace/WorkspaceDatasourceHeader.tsx (1)

1-7:LGTM!

Imports are clean and all used.

…age, it takes the user to the workspace on the applications page.
Copy link
Contributor

@coderabbitaicoderabbitaibot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
app/client/src/pages/AppIDE/layouts/components/Header/index.tsx (2)

165-168:Consider adding a defensive check forcurrentWorkspace.id.

The code checkscurrentWorkspace.name on line 163 but directly accessescurrentWorkspace.id without validation. If the id is undefined, the URL becomes malformed (/applications?workspaceId=undefined).

Consider either:

  1. AddingcurrentWorkspace.id to the condition on line 163
  2. Using optional chaining with a fallback
-            <>-              <Link-                className="mr-1.5"-                to={`${APPLICATIONS_URL}?workspaceId=${currentWorkspace.id}`}-              >+            {currentWorkspace.id ? (+              <>+                <Link+                  className="mr-1.5"+                  to={`${APPLICATIONS_URL}?workspaceId=${currentWorkspace.id}`}+                >+                  {currentWorkspace.name}+                </Link>+                {"/"}+                <EditorName+                  applicationId={applicationId}+                  className="t--application-name editable-application-name max-w-48"+                  defaultSavingState={+                    isSavingName ? SavingState.STARTED : SavingState.NOT_STARTED+                  }+                  defaultValue={currentApplication?.name || ""}+                  editInteractionKind={EditInteractionKind.SINGLE}+                  editorName="Application"+                  fill+                  getNavigationMenu={useNavigationMenuData}+                  isError={isErroredSavingName}+                  isNewEditor={+                    applicationList.filter((el) => el.id === applicationId)+                      .length > 0+                  }+                  isPopoverOpen={isPopoverOpen}+                  onBlur={(value: string) =>+                    updateApplicationDispatch(applicationId || "", {+                      name: value,+                      currentApp: true,+                    })+                  }+                  setIsPopoverOpen={setIsPopoverOpen}+                />+              </>+            ) : null}-                {currentWorkspace.name}-              </Link>-              {"/"}-              <EditorName-                applicationId={applicationId}-                className="t--application-name editable-application-name max-w-48"-                defaultSavingState={-                  isSavingName ? SavingState.STARTED : SavingState.NOT_STARTED-                }-                defaultValue={currentApplication?.name || ""}-                editInteractionKind={EditInteractionKind.SINGLE}-                editorName="Application"-                fill-                getNavigationMenu={useNavigationMenuData}-                isError={isErroredSavingName}-                isNewEditor={-                  applicationList.filter((el) => el.id === applicationId)-                    .length > 0-                }-                isPopoverOpen={isPopoverOpen}-                onBlur={(value: string) =>-                  updateApplicationDispatch(applicationId || "", {-                    name: value,-                    currentApp: true,-                  })-                }-                setIsPopoverOpen={setIsPopoverOpen}-              />-            </>

167-167:Consider using a URL builder utility for query parameter construction.

Manually constructing query parameters via template literals lacks type safety and proper URL encoding. Consider usingURLSearchParams or a URL builder utility consistent with patterns elsewhere in the codebase (e.g.,viewerURL on line 144).

Example withURLSearchParams:

constapplicationsUrl=`${APPLICATIONS_URL}?${newURLSearchParams({workspaceId:currentWorkspace.id}).toString()}`;

Or define a URL builder function similar to other route builders in the codebase.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between1a30e1b and3f3d190.

📒 Files selected for processing (2)
  • app/client/src/pages/AppIDE/layouts/components/Header/index.tsx (1 hunks)
  • app/client/src/pages/workspace/WorkspaceDatasourceHeader.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/client/src/pages/workspace/WorkspaceDatasourceHeader.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
app/client/src/pages/AppIDE/layouts/components/Header/index.tsx (1)
app/client/src/constants/routes/baseRoutes.ts (1)
  • APPLICATIONS_URL (8-8)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: client-check-cyclic-deps / check-cyclic-dependencies
  • GitHub Check: client-unit-tests / client-unit-tests
  • GitHub Check: client-build / client-build
  • GitHub Check: client-prettier / prettier-check
  • GitHub Check: client-lint / client-lint

@github-actions
Copy link

This PR has not seen activitiy for a while. It will be closed in 7 days unless further activity is detected.

Copy link
Contributor

@coderabbitaicoderabbitaibot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1)

78-83:Re-initialize when workspaceId changes.

The!isWorkspaceEditorInitialized guard prevents re-initialization when navigating between different workspaces. Once initialized for workspace A, switching to workspace B will skip initialization because the flag is already true.

Apply this diff to ensure initialization occurs for each workspace:

 useEffect(() => {-  if (workspaceId && !isWorkspaceEditorInitialized) {+  if (workspaceId) {     dispatch(initWorkspaceIDE({ workspaceId }));   }-}, [dispatch, workspaceId, isWorkspaceEditorInitialized]);+}, [dispatch, workspaceId]);

Note: If initialization should only occur once per workspace, track the initialized workspaceId separately rather than using a boolean flag.

🧹 Nitpick comments (1)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1)

114-118:Consider lowercase route convention.

The route uses uppercase/NEW, which is unconventional (most routes use lowercase/new). While this is consistent with the navigation inWorkspaceDataSidePane.tsx, lowercase is the standard convention for URLs.

To align with web conventions, consider refactoring to lowercase:

-            path={`${WORKSPACE_DATASOURCES_PAGE_URL}/NEW`}+            path={`${WORKSPACE_DATASOURCES_PAGE_URL}/new`}

And update the corresponding navigation inWorkspaceDataSidePane.tsx:

history.push(`/workspace/${workspaceId}/datasources/new`)

Alternatively, extract to a shared constant to prevent future mismatches:

// In constants/routes.tsexportconstDATASOURCE_NEW_PATH='/new';// Usagepath={`${WORKSPACE_DATASOURCES_PAGE_URL}${DATASOURCE_NEW_PATH}`}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between3f3d190 and9698179.

📒 Files selected for processing (3)
  • app/client/src/ce/IDE/constants/routes.ts (1 hunks)
  • app/client/src/pages/workspace/WorkspaceDataSidePane.tsx (1 hunks)
  • app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/client/src/ce/IDE/constants/routes.ts
  • app/client/src/pages/workspace/WorkspaceDataSidePane.tsx
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: Aishwarya-U-RRepo: appsmithorg/appsmith PR: 29405File: app/client/cypress/e2e/Regression/ClientSide/Binding/TableV2_Widget_API_Pagination_spec.js:37-41Timestamp: 2024-10-08T15:32:39.374ZLearning: The pull request titled "test: Cypress | Replace static with Dynamic waits - Part 1" is part of a phased approach where only certain test specifications are targeted for static wait removal in the initial phase. Future phases will address additional specs.
Learnt from: Aishwarya-U-RRepo: appsmithorg/appsmith PR: 29405File: app/client/cypress/e2e/Regression/ClientSide/Binding/TableV2_Widget_API_Pagination_spec.js:37-41Timestamp: 2024-07-26T21:12:57.228ZLearning: The pull request titled "test: Cypress | Replace static with Dynamic waits - Part 1" is part of a phased approach where only certain test specifications are targeted for static wait removal in the initial phase. Future phases will address additional specs.
📚 Learning: 2024-12-16T19:43:14.764Z
Learnt from: brayn003Repo: appsmithorg/appsmith PR: 38171File: app/client/src/git/components/GitContextProvider/index.tsx:60-70Timestamp: 2024-12-16T19:43:14.764ZLearning: Prefer not to throw errors when dispatching actions in the `setImportWorkspaceId` function in `app/client/src/git/components/GitContextProvider/index.tsx`.

Applied to files:

  • app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx
📚 Learning: 2024-12-11T08:33:24.352Z
Learnt from: brayn003Repo: appsmithorg/appsmith PR: 38088File: app/client/src/git/components/GitQuickActions/BranchButton/index.tsx:72-74Timestamp: 2024-12-11T08:33:24.352ZLearning: In the 'BranchButton' component in 'app/client/src/git/components/GitQuickActions/BranchButton/index.tsx' (TypeScript, React), the `useEffect` hook that checks for label ellipsis does not need to include `currentBranch` in its dependency array.

Applied to files:

  • app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx
📚 Learning: 2024-10-08T15:32:34.115Z
Learnt from: ankitakingerRepo: appsmithorg/appsmith PR: 29965File: app/client/src/utils/storage.ts:129-129Timestamp: 2024-10-08T15:32:34.115ZLearning: The `migrateAppIdToEditorId` function in `app/client/src/utils/storage.ts` is intended to be called only when `appId` is present and `editorId` is not in the payload. This context should be considered in future reviews related to this function.

Applied to files:

  • app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx
📚 Learning: 2025-10-30T07:15:20.287Z
Learnt from: ashit-rathRepo: appsmithorg/appsmith PR: 41312File: app/client/src/utils/helpers.tsx:1124-1136Timestamp: 2025-10-30T07:15:20.287ZLearning: In app/client/src/utils/helpers.tsx, within the getUpdateRouteForSlugPath function, the pageSlug parameter extracted from the route includes the trailing hyphen (e.g., "home-page-" not "home-page"). Additionally, when the static slug conversion branch is executed, params.basePageId is guaranteed to be defined because the code path requires successful page data fetch from the server as a precondition.

Applied to files:

  • app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx
🧬 Code graph analysis (1)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (4)
app/client/src/ce/actions/workspaceIDEActions.ts (1)
  • initWorkspaceIDE (7-10)
app/client/src/pages/workspace/WorkspaceDataSidePane.tsx (1)
  • WorkspaceDataSidePane (50-193)
app/client/src/components/SentryRoute.tsx (1)
  • SentryRoute (3-3)
app/client/src/constants/routes/baseRoutes.ts (2)
  • WORKSPACE_DATASOURCES_PAGE_URL (31-31)
  • WORKSPACE_DATASOURCE_EDITOR_PAGE_URL (32-32)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: client-prettier / prettier-check
  • GitHub Check: client-lint / client-lint
  • GitHub Check: client-unit-tests / client-unit-tests
  • GitHub Check: client-build / client-build
  • GitHub Check: client-check-cyclic-deps / check-cyclic-dependencies
🔇 Additional comments (1)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1)

85-103:No changes needed—code already handles undefined workspace gracefully.

WorkspaceDataSidePane has its ownisFetchingCurrentWorkspace guard (line 123) that displays a loading state while the workspace fetch completes. All workspace property accesses use safe optional chaining (currentWorkspace?.userPermissions), so rendering with undefined workspace is handled defensively. The parent'sisWorkspaceEditorInitialized gate and the child'sisFetchingCurrentWorkspace gate serve different purposes and work in tandem.

…spaceEditor Engine to a folder outside of ee or ce, and made it adjacent to AppEditorEngine. Using isWorkspaceContext function across APIOrSaaS and DBOrMostPopular plugins.
Copy link
Contributor

@coderabbitaicoderabbitaibot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/client/src/pages/Editor/IntegrationEditor/APIOrSaasPlugins.tsx (1)

372-385:Add workspace context check to authApiPlugin visibility.

The authenticated REST API (authApiPlugin, lines 208-216) lacks the!isWorkspaceDatasourcesPage check that's applied to bothrestAPIVisible andgraphQLAPIVisible. DBOrMostPopularPlugins.tsx also filters out REST API in workspace context (line 332), establishing a consistent pattern. Apply the same check to authApiPlugin at line 208 for consistency.

🧹 Nitpick comments (1)
app/client/src/entities/Engine/WorkspaceEditorEngine.ts (1)

58-102:LGTM with minor suggestion.

The plugin and datasource loading logic is correct, with proper airgap handling and error flows. ThefailFastApiCalls pattern is used appropriately.

Consider includingworkspaceId in error messages for easier debugging:

   if (!initActionCalls)-    throw new PluginsNotFoundError("Unable to fetch plugins");+    throw new PluginsNotFoundError(`Unable to fetch plugins for workspace ${workspaceId}`);   // ... later ...   if (!pluginFormCall)     throw new PluginFormConfigsNotFoundError(-      "Unable to fetch plugin form configs",+      `Unable to fetch plugin form configs for workspace ${workspaceId}`,     );

Based on learnings, workspace IDs are obfuscated and safe to log.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and betweenca19f3f andaacb669.

📒 Files selected for processing (5)
  • app/client/src/ce/sagas/workspaceIDESagas.ts (1 hunks)
  • app/client/src/ee/sagas/workspaceIDESagas.ts (1 hunks)
  • app/client/src/entities/Engine/WorkspaceEditorEngine.ts (1 hunks)
  • app/client/src/pages/Editor/IntegrationEditor/APIOrSaasPlugins.tsx (2 hunks)
  • app/client/src/pages/Editor/IntegrationEditor/DBOrMostPopularPlugins.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/client/src/ce/sagas/workspaceIDESagas.ts
  • app/client/src/pages/Editor/IntegrationEditor/DBOrMostPopularPlugins.tsx
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Aishwarya-U-RRepo: appsmithorg/appsmith PR: 29405File: app/client/cypress/e2e/Regression/ClientSide/Binding/TableV2_Widget_API_Pagination_spec.js:37-41Timestamp: 2024-10-08T15:32:39.374ZLearning: The pull request titled "test: Cypress | Replace static with Dynamic waits - Part 1" is part of a phased approach where only certain test specifications are targeted for static wait removal in the initial phase. Future phases will address additional specs.
Learnt from: Aishwarya-U-RRepo: appsmithorg/appsmith PR: 29405File: app/client/cypress/e2e/Regression/ClientSide/Binding/TableV2_Widget_API_Pagination_spec.js:37-41Timestamp: 2024-07-26T21:12:57.228ZLearning: The pull request titled "test: Cypress | Replace static with Dynamic waits - Part 1" is part of a phased approach where only certain test specifications are targeted for static wait removal in the initial phase. Future phases will address additional specs.
📚 Learning: 2024-10-11T09:28:32.636Z
Learnt from: brayn003Repo: appsmithorg/appsmith PR: 36622File: app/client/src/entities/Engine/AppEditorEngine.ts:0-0Timestamp: 2024-10-11T09:28:32.636ZLearning: In the file `app/client/src/entities/Engine/AppEditorEngine.ts`, the IDs (`currentApplication.baseId`) and branches (`currentBranch`) are obfuscated, so it's acceptable to log them for debugging purposes.

Applied to files:

  • app/client/src/entities/Engine/WorkspaceEditorEngine.ts
🧬 Code graph analysis (3)
app/client/src/entities/Engine/WorkspaceEditorEngine.ts (5)
app/client/src/ce/actions/environmentAction.ts (1)
  • fetchingEnvironmentConfigs (13-26)
app/client/src/actions/ReduxActionTypes.ts (1)
  • ReduxAction (9-12)
app/client/src/sagas/InitSagas.ts (1)
  • failFastApiCalls (147-167)
app/client/src/entities/Engine/index.ts (2)
  • PluginsNotFoundError (61-61)
  • PluginFormConfigsNotFoundError (62-62)
app/client/src/actions/pluginActions.ts (1)
  • fetchPluginFormConfigs (22-29)
app/client/src/pages/Editor/IntegrationEditor/APIOrSaasPlugins.tsx (2)
app/client/src/pages/Editor/IntegrationEditor/util.ts (1)
  • filterSearch (11-20)
app/client/src/ce/constants/messages.ts (1)
  • CREATE_NEW_DATASOURCE_REST_API (402-402)
app/client/src/ee/sagas/workspaceIDESagas.ts (2)
app/client/src/ce/constants/ReduxActionConstants.tsx (1)
  • ReduxActionTypes (1302-1346)
app/client/src/ce/sagas/workspaceIDESagas.ts (1)
  • startWorkspaceIDE (9-34)
🔇 Additional comments (7)
app/client/src/ee/sagas/workspaceIDESagas.ts (3)

1-1:LGTM! Standard EE/CE re-export pattern.

The re-export statement correctly exposes CE layer functionality through the EE layer, following the established architecture pattern in the codebase.


3-5:LGTM! Import statements are correct.

All imports follow the proper EE/CE conventions and reference the correct modules. The CE implementation ofstartWorkspaceIDE includes appropriate error handling with try-catch blocks.


7-11:LGTM! Saga wiring is correct.

The saga properly usestakeLatest to listen for workspace IDE initialization, which cancels stale initializations on rapid dispatches. The action typeINITIALIZE_WORKSPACE_IDE is defined in ReduxActionConstants, and the structure follows established saga patterns with proper delegation to the CE implementation.

app/client/src/pages/Editor/IntegrationEditor/APIOrSaasPlugins.tsx (1)

369-370:No issues found. The implementation is correct and consistent.

TheurlBuilder.isWorkspaceContext() method correctly identifies workspace context by checking if the URL pathname starts with "/workspace". This detection pattern is consistently applied across bothAPIOrSaasPlugins.tsx andDBOrMostPopularPlugins.tsx, confirming the feature is intentionally designed to hide API creation options in workspace context.

app/client/src/entities/Engine/WorkspaceEditorEngine.ts (3)

53-56:LGTM!

Standard engine setup pattern: starts evaluation and resets autocomplete service.


104-108:LGTM!

Clean completion signal dispatching success action.


23-28:Binding generator methods is valid and correctly preserves context.

The search confirms these methods are called directly viayield call() in workspaceIDESagas.ts and InitSagas.ts, and tests validate this pattern works correctly. Binding generator functions is a legitimate defensive pattern ensuringthis context is always preserved, even when method references are stored or passed around. No issues found.

Comment on lines +30 to +51
*loadWorkspace(workspaceId:string){
// Set the current workspace context
yieldput({
type:ReduxActionTypes.SET_CURRENT_WORKSPACE_ID,
payload:{
workspaceId,
editorId:workspaceId,// Use workspaceId as editorId for workspace context
},
});

// Fetch environment configs for the workspace
yieldput(
fetchingEnvironmentConfigs({
workspaceId,
editorId:workspaceId,
fetchDatasourceMeta:true,
}),
);

// Wait for environments to be fetched
yieldcall(waitForFetchEnvironments);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

⚠️ Potential issue |🟠 Major

Add error handling and timeout for environment fetching.

ThewaitForFetchEnvironments call at line 50 has no error handling or timeout. If environment fetching fails or hangs, the workspace IDE initialization will block indefinitely with no user feedback or recovery path.

Consider wrapping the call in a try-catch block or using a race condition with a timeout, similar to the error handling pattern inloadPluginsAndDatasources.

   // Wait for environments to be fetched-  yield call(waitForFetchEnvironments);+  try {+    yield call(waitForFetchEnvironments);+  } catch (error) {+    throw new Error(`Failed to fetch workspace environments: ${error.message}`);+  }
📝 Committable suggestion

‼️IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
*loadWorkspace(workspaceId: string){
// Set the current workspace context
yieldput({
type:ReduxActionTypes.SET_CURRENT_WORKSPACE_ID,
payload:{
workspaceId,
editorId:workspaceId,// Use workspaceId as editorId for workspace context
},
});
// Fetch environment configs for the workspace
yieldput(
fetchingEnvironmentConfigs({
workspaceId,
editorId:workspaceId,
fetchDatasourceMeta:true,
}),
);
// Wait for environments to be fetched
yieldcall(waitForFetchEnvironments);
}
*loadWorkspace(workspaceId: string){
// Set the current workspace context
yieldput({
type:ReduxActionTypes.SET_CURRENT_WORKSPACE_ID,
payload:{
workspaceId,
editorId:workspaceId,// Use workspaceId as editorId for workspace context
},
});
// Fetch environment configs for the workspace
yieldput(
fetchingEnvironmentConfigs({
workspaceId,
editorId:workspaceId,
fetchDatasourceMeta:true,
}),
);
// Wait for environments to be fetched
try{
yieldcall(waitForFetchEnvironments);
}catch(error){
thrownewError(`Failed to fetch workspace environments:${error.message}`);
}
}
🤖 Prompt for AI Agents
In app/client/src/entities/Engine/WorkspaceEditorEngine.ts around lines 30 to51, the call to waitForFetchEnvironments is unguarded and can hang indefinitely;wrap the environment fetch wait in a guarded flow (use a try/catch or aredux-saga race between call(waitForFetchEnvironments) and a timeout delay,e.g., const { environments, timeout } = yield race({ environments:call(waitForFetchEnvironments), timeout: delay(ENV_FETCH_TIMEOUT_MS) }) ),handle the timeout or thrown error by dispatching a clear failure action ornotification (and logging the error), and ensure you return or abort workspaceinitialization on failure so the IDE doesn't block (also include a configurabletimeout constant and any necessary cleanup/cancel effects).

@tomjose92
Copy link
ContributorAuthor

/build-deploy-preview skip-tests=true

github-actions[bot] reacted with rocket emojigithub-actions[bot] reacted with eyes emoji

@github-actions
Copy link

Deploying Your Preview:https://github.com/appsmithorg/appsmith/actions/runs/19262099578.
Workflow:On demand build Docker image and deploy preview.
skip-tests:true.
env: ``.
PR: 41324.
recreate: .

@github-actions
Copy link

Deploy-Preview-URL:https://ce-41324.dp.appsmith.com

hetunandu
hetunandu previously approved these changesNov 17, 2025
@github-actionsgithub-actionsbot added DatasourcesIssues related to configuring datasource on appsmith Integrations ProductIssues related to a specific integration Query & JS PodIssues related to the query & JS Pod Query Widgets & IDE PodAll issues related to Query, JS, Eval, Widgets & IDE labelsNov 19, 2025
@tomjose92tomjose92 self-assigned thisNov 19, 2025
@tomjose92tomjose92 added the ok-to-testRequired label for CI labelNov 19, 2025
…ge instead of component, hence preventing unmount/mount of it on every navigation. Added cypress test case for WorkspaceDatasourceSettings. And minor css change.
@pedro-santos-rodrigues
Copy link
Contributor

@tomjose92 I've had the opportunity to take a look at it and left some feedback about the experience here:https://jam.dev/c/b7f9aafe-c703-4895-a2ac-9cf60d80a169

@tomjose92
Copy link
ContributorAuthor

Thanks@pedro-santos-rodrigues, regarding the comments

  1. Makes sense, I will show the No Datasources to display as thats something we already do from the App or Package editor
  2. Will remove the + icon when datasources are already being shown on the right side

… Also deciding when to show + icon. Also added test cases.
Copy link
Contributor

@coderabbitaicoderabbitaibot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Actionable comments posted: 6

♻️ Duplicate comments (3)
app/client/src/pages/workspace/WorkspaceDataSidePane.tsx (1)

94-95:Fix route case: "NEW" → "new".

Routes are case-sensitive. The route inWorkspaceDatasourcesPage.tsx uses lowercase/NEW at line 127. Standardize to consistent casing.

Also applies to: 158-160

app/client/src/ce/entities/URLRedirect/URLAssembly.ts (1)

314-324:Validate workspaceId; don't fall back to empty string.

Returning"" yields/workspace//… URLs. Already flagged previously - ensure this is addressed.

app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1)

125-129:Route path case must match callers.

Route uses/NEW (uppercase). Callers inWorkspaceDataSidePane.tsx also push/NEW. Standardize to lowercase/new for URL consistency.

🧹 Nitpick comments (7)
app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts (1)

92-92:Reconsider excessive use of{ force: true } when enabling tests.

The commented tests use{ force: true } extensively in click operations. While not explicitly prohibited, forcing clicks can mask real actionability issues like elements being covered or not properly visible. Consider removing force flags and ensuring elements are properly interactable before clicking.

Example improvement:

-        cy.get(".t--add-datasource-button").first().click({ force: true });+        cy.get(".t--add-datasource-button").first().should("be.visible").should("be.enabled").click();

Also applies to: 97-97, 141-141, 145-145, 147-147, 175-175, 180-180

app/client/src/pages/workspace/index.tsx (2)

15-22:Avoid inline arrow functions incomponent prop.

Usingcomponent={() => <Component />} creates a new component instance on every render, causing unnecessary unmounting/remounting. Userender prop instead for inline JSX.

-      <SentryRoute-        component={() => (-          <PageWrapper displayName="Workspace Settings">-            <Settings />-          </PageWrapper>-        )}-        path={`${path}/:workspaceId/settings`}-      />+      <SentryRoute+        path={`${path}/:workspaceId/settings`}+        render={() => (+          <PageWrapper displayName="Workspace Settings">+            <Settings />+          </PageWrapper>+        )}+      />

Apply the same fix to the default route (lines 35-41).

Also applies to: 35-41


23-34:Consider consolidating duplicate routes.

Both/datasources and/datasource routes render identical components. If intentional for backward compatibility, add a comment. Otherwise, consolidate.

-      <SentryRoute-        path={`${path}/:workspaceId/datasources`}-        render={({ match }: { match: { params: { workspaceId: string } } }) => (-          <WorkspaceDatasourcesPage workspaceId={match.params.workspaceId} />-        )}-      />-      <SentryRoute-        path={`${path}/:workspaceId/datasource`}-        render={({ match }: { match: { params: { workspaceId: string } } }) => (-          <WorkspaceDatasourcesPage workspaceId={match.params.workspaceId} />-        )}-      />+      {/* /datasources for list view, /datasource/:id for editor - both use same page */}+      <SentryRoute+        path={[`${path}/:workspaceId/datasources`, `${path}/:workspaceId/datasource`]}+        render={({ match }: { match: { params: { workspaceId: string } } }) => (+          <WorkspaceDatasourcesPage workspaceId={match.params.workspaceId} />+        )}+      />
app/client/src/pages/workspace/WorkspaceDataSidePane.tsx (2)

122-135:Consider using Spinner for consistent loading UX.

WorkspaceDatasourcesPage uses<Spinner size="lg" /> during loading. This component shows plain text. Consider aligning for consistent UX.


169-201:Short-circuit EntityGroupsList when no datasources.

EntityGroupsList renders even whendatasources.length === 0, producing empty group containers. Short-circuit to avoid rendering empty structure.

       {datasources.length === 0 ? (          <EmptyState            button={blankStateButtonProps}            description={createMessage(DATASOURCE_LIST_BLANK_DESCRIPTION)}            icon={"datasource-v3"}          />-        ) : null}-        <EntityGroupsList+        ) : (+          <EntityGroupsList

And close the ternary properly with) after theEntityGroupsList block.

app/client/src/ce/entities/URLRedirect/URLAssembly.ts (2)

256-260:isWorkspaceContext() is called multiple times per build.

Consider caching the result withinbuild() to avoid repeatedwindow.location.pathname reads and regex matching.

 build(builderParams: URLBuilderParams, mode: APP_MODE = APP_MODE.EDIT) {+    const isWorkspace = this.isWorkspaceContext();     // ... use isWorkspace instead of this.isWorkspaceContext() throughout

262-264:Misleading parameter name ingenerateBasePathForWorkspace.

Parameter is namedworkspaceId but the caller passesentityId. While functionally correct in workspace context, consider renaming for clarity.

-  generateBasePathForWorkspace(workspaceId: string) {-    return `/workspace/${workspaceId}/datasources`;+  generateBasePathForWorkspace(entityId: string) {+    // In workspace context, entityId is the workspaceId+    return `/workspace/${entityId}/datasources`;   }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between547f3f7 and385b5e0.

📒 Files selected for processing (5)
  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts (1 hunks)
  • app/client/src/ce/entities/URLRedirect/URLAssembly.ts (6 hunks)
  • app/client/src/pages/workspace/WorkspaceDataSidePane.tsx (1 hunks)
  • app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1 hunks)
  • app/client/src/pages/workspace/index.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
app/client/cypress/**/**.*

⚙️ CodeRabbit configuration file

app/client/cypress/**/**.*: Review the following e2e test code written using the Cypress test library. Ensure that:

  • Follow best practices for Cypress code and e2e automation.
  • Avoid using cy.wait in code.
  • Avoid using cy.pause in code.
  • Avoid using agHelper.sleep().
  • Use locator variables for locators and do not use plain strings.
  • Use data-* attributes for selectors.
  • Avoid Xpaths, Attributes and CSS path.
  • Avoid selectors like .btn.submit or button[type=submit].
  • Perform logins via API with LoginFromAPI.
  • Perform logout via API with LogOutviaAPI.
  • Perform signup via API with SignupFromAPI.
  • Avoid using it.only.
  • Avoid using after and aftereach in test cases.
  • Use multiple assertions for expect statements.
  • Avoid using strings for assertions.
  • Do not use duplicate filenames even with different paths.
  • Avoid using agHelper.Sleep, this.Sleep in any file in code.

Files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
🧠 Learnings (16)
📚 Learning: 2024-12-16T19:43:14.764Z
Learnt from: brayn003Repo: appsmithorg/appsmith PR: 38171File: app/client/src/git/components/GitContextProvider/index.tsx:60-70Timestamp: 2024-12-16T19:43:14.764ZLearning: Prefer not to throw errors when dispatching actions in the `setImportWorkspaceId` function in `app/client/src/git/components/GitContextProvider/index.tsx`.

Applied to files:

  • app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx
  • app/client/src/ce/entities/URLRedirect/URLAssembly.ts
📚 Learning: 2024-12-11T08:33:24.352Z
Learnt from: brayn003Repo: appsmithorg/appsmith PR: 38088File: app/client/src/git/components/GitQuickActions/BranchButton/index.tsx:72-74Timestamp: 2024-12-11T08:33:24.352ZLearning: In the 'BranchButton' component in 'app/client/src/git/components/GitQuickActions/BranchButton/index.tsx' (TypeScript, React), the `useEffect` hook that checks for label ellipsis does not need to include `currentBranch` in its dependency array.

Applied to files:

  • app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx
📚 Learning: 2024-07-26T21:12:57.228Z
Learnt from: ankitakingerRepo: appsmithorg/appsmith PR: 29965File: app/client/src/utils/storage.ts:129-129Timestamp: 2024-07-26T21:12:57.228ZLearning: The `migrateAppIdToEditorId` function in `app/client/src/utils/storage.ts` is intended to be called only when `appId` is present and `editorId` is not in the payload. This context should be considered in future reviews related to this function.

Applied to files:

  • app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx
📚 Learning: 2025-10-30T07:15:20.287Z
Learnt from: ashit-rathRepo: appsmithorg/appsmith PR: 41312File: app/client/src/utils/helpers.tsx:1124-1136Timestamp: 2025-10-30T07:15:20.287ZLearning: In app/client/src/utils/helpers.tsx, within the getUpdateRouteForSlugPath function, the pageSlug parameter extracted from the route includes the trailing hyphen (e.g., "home-page-" not "home-page"). Additionally, when the static slug conversion branch is executed, params.basePageId is guaranteed to be defined because the code path requires successful page data fetch from the server as a precondition.

Applied to files:

  • app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx
  • app/client/src/ce/entities/URLRedirect/URLAssembly.ts
📚 Learning: 2024-10-08T15:32:34.115Z
Learnt from: alex-golovanovRepo: appsmithorg/appsmith PR: 36665File: app/client/src/IDE/Components/FileTab/styles.tsx:19-19Timestamp: 2024-10-08T15:32:34.115ZLearning: Do not suggest replacing hardcoded `padding-top: 6px;` with design variables in `app/client/src/IDE/Components/FileTab/styles.tsx`.

Applied to files:

  • app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx
📚 Learning: 2025-11-05T12:56:49.249Z
Learnt from: vsvamsi1Repo: appsmithorg/appsmith PR: 41363File: app/client/cypress/e2e/Regression/ClientSide/StaticUrl/PagePersistance_Spec.ts:0-0Timestamp: 2025-11-05T12:56:49.249ZLearning: In the file `app/client/cypress/e2e/Regression/ClientSide/StaticUrl/PagePersistance_Spec.ts`, the test suite intentionally uses sequential tests where Tests 4-6 depend on state (`page1Slug`, `page2Slug`) set in Tests 2-3. The author (vsvamsi1) prioritizes readability by breaking the flow into different segments over strict test isolation.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-10-08T15:32:34.115Z
Learnt from: sagar-qa007Repo: appsmithorg/appsmith PR: 34955File: app/client/cypress/e2e/Regression/ClientSide/ActionExecution/General_settings_Spec.ts:14-56Timestamp: 2024-10-08T15:32:34.115ZLearning: Learnt from: sagar-qa007PR: appsmithorg/appsmith#34955File: app/client/cypress/e2e/Regression/ClientSide/ActionExecution/General_settings_Spec.ts:14-56Timestamp: 2024-07-16T06:44:55.118ZLearning: Avoid using sleep functions like `agHelper.Sleep`, `this.Sleep`, and other related sleep functions in Cypress tests within the `app/client/cypress` directory to prevent non-deterministic behaviors and ensure tests are more reliable and maintainable.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2025-11-05T12:58:32.486Z
Learnt from: vsvamsi1Repo: appsmithorg/appsmith PR: 41363File: app/client/cypress/e2e/Regression/ClientSide/StaticUrl/SlugPersistance_Spec.ts:32-225Timestamp: 2025-11-05T12:58:32.486ZLearning: In the file `app/client/cypress/e2e/Regression/ClientSide/StaticUrl/SlugPersistance_Spec.ts`, the test suite intentionally uses sequential tests where Tests 2-5 depend on state from previous tests (e.g., slug values modified in earlier tests). The author (vsvamsi1) prioritizes readability by breaking the flow into different segments over strict test isolation.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-07-24T08:29:41.208Z
Learnt from: abhishek-bandameediRepo: appsmithorg/appsmith PR: 35133File: app/client/cypress/e2e/Regression/ClientSide/Widgets/Checkbox/CheckBox2_spec.js:0-0Timestamp: 2024-07-24T08:29:41.208ZLearning: In Cypress tests for the Appsmith project, ensure the use of locator variables for selectors and include multiple assertions for comprehensive testing.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-11-13T09:07:54.931Z
Learnt from: vhemeryRepo: appsmithorg/appsmith PR: 37371File: app/client/cypress/e2e/Regression/ClientSide/Widgets/Image/Image_spec.js:44-47Timestamp: 2024-11-13T09:07:54.931ZLearning: When reviewing code in `app/client/cypress/**` paths, ensure that suggestions are appropriate for test code and not for `src` code. Avoid applying source code checks to test code unless relevant.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-10-08T15:32:39.374Z
Learnt from: Aishwarya-U-RRepo: appsmithorg/appsmith PR: 29405File: app/client/cypress/e2e/Regression/ClientSide/Binding/TableV2_Widget_API_Pagination_spec.js:37-41Timestamp: 2024-10-08T15:32:39.374ZLearning: The pull request titled "test: Cypress | Replace static with Dynamic waits - Part 1" is part of a phased approach where only certain test specifications are targeted for static wait removal in the initial phase. Future phases will address additional specs.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-11-13T09:11:36.959Z
Learnt from: vhemeryRepo: appsmithorg/appsmith PR: 37371File: app/client/cypress/e2e/Regression/ClientSide/Widgets/Image/Image_base64_spec.js:35-37Timestamp: 2024-11-13T09:11:36.959ZLearning: In the file `app/client/cypress/e2e/Regression/ClientSide/Widgets/Image/Image_base64_spec.js`, when writing Cypress end-to-end tests for the Image Widget in JavaScript, use `viewWidgetsPage.imageinner` as the selector when asserting 'src' and 'alt' attributes to maintain consistency.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-10-08T15:32:34.114Z
Learnt from: sagar-qa007Repo: appsmithorg/appsmith PR: 34955File: app/client/cypress/e2e/Regression/ClientSide/ActionExecution/General_settingsTe_Spec.ts:33-33Timestamp: 2024-10-08T15:32:34.114ZLearning: Follow best practices for Cypress code and e2e automation:- Avoid using cy.wait in code.- Avoid using cy.pause in code.- Avoid using agHelper.sleep().- Use locator variables for locators and do not use plain strings.- Use data-* attributes for selectors.- Avoid Xpaths, Attributes, and CSS path.- Avoid selectors like .btn.submit or button[type=submit].- Perform logins via API with LoginFromAPI.- Perform logout via API with LogOutviaAPI.- Perform signup via API with SignupFromAPI.- Avoid using it.only.- Avoid using after and aftereach in test cases.- Use multiple assertions for expect statements.- Avoid using strings for assertions.- Do not use duplicate filenames even with different paths.- Avoid using agHelper.Sleep, this.Sleep in any file in code.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-12-05T10:56:13.739Z
Learnt from: brayn003Repo: appsmithorg/appsmith PR: 37984File: app/client/src/git/requests/fetchSSHKeyRequest.ts:5-9Timestamp: 2024-12-05T10:56:13.739ZLearning: In `app/client/src/git/requests/fetchSSHKeyRequest.ts`, the `fetchSSHKeyRequest` function does not require explicit error handling for `baseApplicationId`; the function should throw an error naturally if `baseApplicationId` is missing or invalid.

Applied to files:

  • app/client/src/ce/entities/URLRedirect/URLAssembly.ts
📚 Learning: 2025-01-15T20:46:05.401Z
Learnt from: brayn003Repo: appsmithorg/appsmith PR: 38681File: app/client/src/git/requests/helpers/urlArtifactType.ts:3-12Timestamp: 2025-01-15T20:46:05.401ZLearning: In URL helper functions like `urlArtifactType`, error handling in switch statements is not required as TypeScript's compile-time checks are sufficient.

Applied to files:

  • app/client/src/ce/entities/URLRedirect/URLAssembly.ts
📚 Learning: 2025-10-28T03:30:58.299Z
Learnt from: ashit-rathRepo: appsmithorg/appsmith PR: 41312File: app/client/src/sagas/InitSagas.ts:260-271Timestamp: 2025-10-28T03:30:58.299ZLearning: In app/client/src/sagas/InitSagas.ts, when constructing consolidatedApiParams for static page URLs, the code intentionally reuses applicationId and defaultPageId fields to pass staticApplicationSlug and staticPageSlug values respectively. This is by design, even though ConsolidatedApiParams type has dedicated staticApplicationSlug and staticPageSlug fields.

Applied to files:

  • app/client/src/ce/entities/URLRedirect/URLAssembly.ts
🧬 Code graph analysis (4)
app/client/src/pages/workspace/index.tsx (3)
app/client/src/components/SentryRoute.tsx (1)
  • SentryRoute (3-3)
app/client/src/pages/common/PageWrapper.tsx (1)
  • PageWrapper (63-89)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1)
  • WorkspaceDatasourcesPage (72-146)
app/client/src/pages/workspace/WorkspaceDataSidePane.tsx (4)
app/client/src/ce/selectors/entitiesSelector.ts (4)
  • getDatasources (86-88)
  • getDatasourcesGroupedByPluginCategory (114-144)
  • getPluginImages (605-623)
  • getPlugins (90-91)
app/client/src/ce/entities/FeatureFlag.ts (1)
  • FEATURE_FLAG (2-67)
app/client/src/ce/RouteBuilder.ts (1)
  • workspaceDatasourceEditorURL (203-206)
app/client/src/entities/Datasource/index.ts (1)
  • Datasource (154-162)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (4)
app/client/src/ce/selectors/entitiesSelector.ts (1)
  • getDatasources (86-88)
app/client/src/ce/actions/workspaceIDEActions.ts (1)
  • initWorkspaceIDE (7-10)
app/client/src/pages/workspace/WorkspaceDataSidePane.tsx (1)
  • WorkspaceDataSidePane (50-205)
app/client/src/constants/routes/baseRoutes.ts (2)
  • WORKSPACE_DATASOURCES_PAGE_URL (31-31)
  • WORKSPACE_DATASOURCE_EDITOR_PAGE_URL (32-32)
app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts (1)
app/client/cypress/support/commands.js (2)
  • _ (1071-1071)
  • workspaceId (396-396)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: perform-test / rts-build / build
  • GitHub Check: perform-test / client-build / client-build
  • GitHub Check: perform-test / server-build / server-unit-tests
  • GitHub Check: client-lint / client-lint
  • GitHub Check: client-build / client-build
  • GitHub Check: client-check-cyclic-deps / check-cyclic-dependencies
  • GitHub Check: client-prettier / prettier-check
  • GitHub Check: client-unit-tests / client-unit-tests
🔇 Additional comments (2)
app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx (1)

35-41:LGTM - Height conflict addressed.

IDEContainer now usesflex: 1 without conflictingheight: 100vh. Layout should work correctly within the parent's flex context.

app/client/src/ce/entities/URLRedirect/URLAssembly.ts (1)

347-351: I'll help you verify the edge case concern in the URLAssembly.ts file. Let me search the codebase to understand how this code is called and what suffix values are actually passed.
<function_calls>


#!/bin/bash

Find the URLAssembly file and understand its context

find . -type f -name "URLAssembly.ts" 2>/dev/null | head -5


</function_calls>

Now let me examine the file around the lines in question:
<function_calls>


#!/bin/bash

Read the URLAssembly.ts file to see the function context

wc -l app/client/src/ce/entities/URLRedirect/URLAssembly.ts


</function_calls>

Let me get the broader context of the function containing these lines:
<function_calls>


#!/bin/bash

Get lines around 347-351 to understand the function

sed -n '330,365p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts


</function_calls>

Now let me search for callers of this function and test cases:
<function_calls>


#!/bin/bash

Search for calls to the function that contains this logic

First, let's find what function this is in

sed -n '300,355p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts | grep -n "^[[:space:]][a-zA-Z].(" | head -3


</function_calls>

Let me get more context to identify the function name:
<function_calls>


#!/bin/bash

Get broader context to find function definition

sed -n '320,355p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts


</function_calls>

Now search for callers and test cases:
<function_calls>


#!/bin/bash

Search for places where suffix with "datasource" is used

rg -n "datasource/" app/client/src/ce/entities/URLRedirect/ -C2 --type=ts


</function_calls>

Let me search for test files related to URLAssembly:
<function_calls>


#!/bin/bash

Search for test files

find . -type f -name "URLAssembly" | grep -i test
find . -type f -path "/test/" -name "URL" | head -10
find . -type f -name "*.spec.ts" | xargs grep -l "URLAssembly" 2>/dev/null | head -5


</function_calls>

Let me search for how suffix is used more broadly:
<function_calls>


#!/bin/bash

Search for suffix construction and usage patterns

rg -n "suffix.*datasource" --type=ts -C3


</function_calls>

Let me search for any unit tests and understand the function better:
<function_calls>


#!/bin/bash

Get the entire function to understand its purpose and logic

sed -n '335,360p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts


</function_calls>

Let me try a different approach to find tests:
<function_calls>


#!/bin/bash

Search for test files in the entire repo

find . -type f ( -name ".spec.ts" -o -name ".test.ts" ) | xargs grep -l "URLAssembly|URLRedirect" 2>/dev/null | head -10


</function_calls>

Let me check what paths are actually being generated with different suffix values:
<function_calls>


#!/bin/bash

Look at the full context to understand the method and its return value

sed -n '310,370p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts


</function_calls>

Let me search for any validation or handling of empty suffix paths:
<function_calls>


#!/bin/bash

Search for any validation of suffixPath or basePath

rg -n "suffixPath" app/client/src/ce/entities/URLRedirect/URLAssembly.ts -B2 -A2


</function_calls>

Let me check the complete method more systematically:
<function_calls>


#!/bin/bash

Get the exact lines and some context

cat -n app/client/src/ce/entities/URLRedirect/URLAssembly.ts | sed -n '340,360p'


</function_calls>

Let me look for where this method is called from:
<function_calls>


#!/bin/bash

Search for callers of this method across the codebase

rg -n "isWorkspaceContext" app/client/src/ce/entities/URLRedirect/URLAssembly.ts -B5 | head -20


</function_calls>

Let me search for how datasource URLs are constructed in the codebase:
<function_calls>


#!/bin/bash

Search for datasource URL patterns

rg -n "datasource" app/client/src/ce/entities/URLRedirect/ --type=ts -B2 -A2 | head -50


</function_calls>

Let me search for any tests in the repo that might test this functionality:
<function_calls>


#!/bin/bash

Search for test files

find . -type f -name ".test.ts" -o -name ".spec.ts" | xargs grep -l "datasource" 2>/dev/null | head -5


</function_calls>

Let me check if there's any validation after the suffixPath is set:
<function_calls>


#!/bin/bash

Look at what happens after line 351

sed -n '351,375p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts


</function_calls>

Let me search for the complete function definition more broadly:
<function_calls>


#!/bin/bash

Get lines 1-365 and search for function definition around line 347

sed -n '300,365p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts | cat -n


</function_calls>

Let me check the actual file to better understand the structure:
<function_calls>


#!/bin/bash

Check file size first

wc -l app/client/src/ce/entities/URLRedirect/URLAssembly.ts

Then get the problematic section with more context

sed -n '325,365p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts | nl -v 325


</function_calls>

Now let me search for how suffix values are passed to understand if "datasource/" alone is a realistic input:
<function_calls>


#!/bin/bash

Search for where suffix parameter comes from

rg -n "suffix\s*=" app/client/src/ce/entities/URLRedirect/URLAssembly.ts -B3 -A1


</function_calls>

Let me search across the codebase for how this function is called:
<function_calls>


#!/bin/bash

Search for imports and calls to URLAssembly

rg -n "from.*URLAssembly|import.*URLAssembly" --type=ts | head -10


</function_calls>

Let me search for callers of the specific function:
<function_calls>


#!/bin/bash

First, let me understand what method this is by looking at the class structure

sed -n '1,30p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts


</function_calls>

Let me look at the method more carefully to determine its name:
<function_calls>


#!/bin/bash

Get a wider context around line 347

sed -n '280,365p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts | nl -v 280


</function_calls>

Let me search for the actual method definition:
<function_calls>


#!/bin/bash

Use ast-grep to find methods containing this pattern

ast-grep --pattern 'getWorkspaceUrl($$$) { $$$ }'


</function_calls>

Let me try a more direct approach to understand the method:
<function_calls>


#!/bin/bash

Search for method declarations around this area

sed -n '250,365p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts | grep -n "^\s*[a-zA-Z].*(" | tail -5


</function_calls>

Let me get the raw file and analyze it properly:
<function_calls>


#!/bin/bash

Get the complete context with better structure

python3 << 'EOF'
with open('app/client/src/ce/entities/URLRedirect/URLAssembly.ts', 'r') as f:
lines = f.readlines()

Print lines 340-365 with context

for i in range(339, min(365, len(lines))):
print(f"{i+1:4d}: {lines[i]}", end='')

Also find the method name by looking backwards

print("\n\n--- Finding method name ---")
for i in range(346, 200, -1):
if 'function ' in lines[i] or '(' in lines[i] and ')' in lines[i]:
print(f"{i+1:4d}: {lines[i]}", end='')
if 'function ' in lines[i] or (i > 0 and ')' in lines[i]):
break
EOF


</function_calls>

Now let me search for test cases and how this is used:
<function_calls>


#!/bin/bash

Search for any test files related to URLAssembly

find . -type f ( -name ".test.ts" -o -name ".spec.ts" ) -exec grep -l "URLAssembly|datasource/" {} ; 2>/dev/null | head -5


</function_calls>

Let me search for actual usage of the problematic suffix pattern:
<function_calls>


#!/bin/bash

Search for all references to getRedirectUrl or similar methods

rg -n "getRedirectUrl|getWorkspaceUrl" --type=ts | head -20


</function_calls>

Let me check what happens with the constructed paths:
<function_calls>


#!/bin/bash

Search for where basePath + suffixPath is used

rg -n "basePath.*suffixPath|suffixPath.*basePath|${.*suffixPath" --type=ts -C2 | head -40


</function_calls>

Let me look at the complete function implementation:
<function_calls>


#!/bin/bash

Get context to understand the return statement

sed -n '330,390p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts


</function_calls>

Now let me verify if there are any tests that exercise this code path:
<function_calls>


#!/bin/bash

Search recursively for test files that might test this

find app -type f ( -name ".spec.ts" -o -name ".test.ts" ) -exec grep -l "datasource|URLAssembly" {} ; 2>/dev/null


</function_calls>

Let me check if there's a tests directory:
<function_calls>


#!/bin/bash

Search for test files

find . -type d -name "tests" -o -type d -name "tests" -o -type d -name "test" 2>/dev/null | head -10


</function_calls>

Let me look for any documentation or comments about this behavior:
<function_calls>


#!/bin/bash

Get the full method with comments

sed -n '300,390p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts


</function_calls>

Let me use a more focused Python approach to analyze the code:
<function_calls>


#!/bin/bash
python3 << 'EOF'
import re

with open('app/client/src/ce/entities/URLRedirect/URLAssembly.ts', 'r') as f:
content = f.read()
lines = content.split('\n')

Find the section around line 347

print("=" * 70)
print("SECTION AROUND LINES 347-351:")
print("=" * 70)
for i in range(300, min(400, len(lines))):
marker = " >>> " if 347 <= i+1 <= 351 else " "
print(f"{marker}{i+1:4d}: {lines[i]}")

Find the method this belongs to

print("\n" + "=" * 70)
print("SEARCHING FOR METHOD DEFINITION:")
print("=" * 70)
for i in range(346, 200, -1):
if re.search(r'\b(public|private|protected|async)?\s+\w+\s*(', lines[i]):
# Print a few lines around the method declaration
for j in range(max(0, i-2), min(len(lines), i+3)):
print(f"{j+1:4d}: {lines[j]}")
break

EOF


</function_calls>

Now let me search for where this might be called from and test cases:
<function_calls>


#!/bin/bash

Search for references to this function

rg -n "getRedirectUrl" app/client/src/ce/entities/URLRedirect/ --type=ts
rg -n "URLAssembly" app/client/src --type=ts | head -20


</function_calls>

Let me check if there's validation or handling of empty paths:
<function_calls>


#!/bin/bash

Look for any URL validation or joining logic

sed -n '340,400p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts | cat -n


</function_calls>

Let me check what the full return statement looks like:
<function_calls>


#!/bin/bash

Get lines 340-395 to see the complete logic flow

python3 << 'EOF'
with open('app/client/src/ce/entities/URLRedirect/URLAssembly.ts') as f:
lines = f.readlines()

Get lines 340-395

for i in range(339, min(395, len(lines))):
print(f"{i+1:4d}: {lines[i]}", end='')
EOF


</function_calls>

Let me search across the entire codebase to understand how suffix values are formed:
<function_calls>


#!/bin/bash

Search for patterns that construct "datasource/" strings

rg -n "datasource.*/" --type=ts | grep -v node_modules | head -30


</function_calls>

Let me look for the actual usage pattern and what suffix contains:
<function_calls>


#!/bin/bash

Search for how the function is called - passing suffix parameter

rg -n "getRedirectUrl.*datasource" --type=ts -B2 -A2


</function_calls>

Let me check what the actual return looks like:
<function_calls>


#!/bin/bash

Look for the return statement in the method

sed -n '340,410p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts | grep -n "return|basePath.*suffixPath"


</function_calls>

Let me get the complete method implementation more carefully:
<function_calls>


#!/bin/bash

Get full context

cat -n app/client/src/ce/entities/URLRedirect/URLAssembly.ts | sed -n '325,380p'


</function_calls>

Now let me verify the actual concern by checking if an empty string after replace would cause issues:
<function_calls>


#!/bin/bash

Simulate what happens with "datasource/" input

python3 << 'EOF'

Simulate the logic from lines 347-351

suffix = "datasource/"

if suffix and suffix.startswith("datasource/"):
# This is what the code does
result = suffix.replace("datasource/", "")
print(f"Input suffix: '{suffix}'")
print(f"After replace: '{result}'")
print(f"suffixPath would be: '/{result}'")
print(f"Result length: {len(result)}")
print(f"Is empty: {result == ''}")

# This would produce a path like:print(f"\nFinal path would be: /workspace/xxx/datasource/{result}")print(f"Which is: /workspace/xxx/datasource/")

print("\n---Other examples---")
suffix2 = "datasource/columns"
result2 = suffix2.replace("datasource/", "")
print(f"If suffix = '{suffix2}', result = '{result2}', path = /workspace/xxx/datasource/{result2}")

EOF


</function_calls>

Let me read the actual URL assembly to understand the final result:
<function_calls>


#!/bin/bash

Get lines right after 351 to see how URL is assembled

sed -n '347,365p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts | cat -n -v


</function_calls>

Let me search for all test files in the repository:
<function_calls>


#!/bin/bash

Find all test files

find . -type f ( -name ".test.ts" -o -name ".spec.ts" ) 2>/dev/null | wc -l

Find tests related to URL or datasource

find . -type f ( -name ".test.ts" -o -name ".spec.ts" ) -exec grep -l "URLAssembly|getRedirectUrl" {} ; 2>/dev/null


</function_calls>

Let me check if there's any special handling or middleware that processes URLs:
<function_calls>


#!/bin/bash

Search for URL validation or sanitization

rg -n "URL|path.*validate|trailing.*slash|normaliz" app/client/src/ce/entities/URLRedirect/ --type=ts | head -20


</function_calls>

Let me check the exact lines and what comes after:
<function_calls>


#!/bin/bash

Get exact lines from file

python3 << 'EOF'
with open('app/client/src/ce/entities/URLRedirect/URLAssembly.ts') as f:
lines = f.readlines()

Lines 345-375

for i in range(344, min(375, len(lines))):
print(f"{i+1:3d}: {lines[i]}", end='')
EOF


</function_calls>

Now let me search for how these URLs are actually used downstream:
<function_calls>


#!/bin/bash

Search for any URL normalization or cleaning

rg -n "replace.*/|normalize|trailing" --type=ts app/client/src/ce/entities/URLRedirect/ -C2 | head -40


</function_calls>

Let me check the actual file structure more carefully:
<function_calls>


#!/bin/bash

Use grep to find the exact method and surrounding context

grep -n "isWorkspaceContext" app/client/src/ce/entities/URLRedirect/URLAssembly.ts -B10 -A15


</function_calls>

Perfect! Now let me understand what getRedirectUrl does and how this is actually used:
<function_calls>


#!/bin/bash

Get the complete function definition

grep -n "getRedirectUrl|getWorkspaceUrl" app/client/src/ce/entities/URLRedirect/URLAssembly.ts -B2 -A25 | head -60


</function_calls>

Now let me look for where this is actually called with datasource suffix:
<function_calls>


#!/bin/bash

Search for calls to the method

rg -n "getRedirectUrl|URLAssembly" app/client/src --type=ts | grep -v "node_modules|URLAssembly.ts:" | head -20


</function_calls>

Let me search for datasource-related URL patterns:
<function_calls>


#!/bin/bash

Search for how datasource paths are constructed

rg -n "datasource/|workspace.*datasource" app/client/src --type=ts | head -30


</function_calls>

Let me check if there are any tests by searching more broadly:
<function_calls>


#!/bin/bash

Search for test files and mock data

find . -type f -name "*.mock.ts" -o -name "fixture" -o -name "mock" 2>/dev/null | grep -i url | head -10


</function_calls>

Let me look at the actual implementation to understand what basePath + suffixPath produces:
<function_calls>


#!/bin/bash

Get lines 347-370 to see the complete URL construction

sed -n '345,375p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts


</function_calls>

Now let me verify if the behavior mentioned in the review is correct by searching for the complete function:
<function_calls>


#!/bin/bash

Get more lines to understand the complete method

sed -n '300,400p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts | head -100


</function_calls>

Let me take a different approach and look for imports and usage of this function:
<function_calls>


#!/bin/bash

Check what's exported from this file

grep -n "export|import" app/client/src/ce/entities/URLRedirect/URLAssembly.ts | head -20


</function_calls>

Now let me check for any callers of the functions in this file:
<function_calls>


#!/bin/bash

Search for who calls URLAssembly

rg -n "new URLAssembly|URLAssembly(|from.*URLAssembly" app/client/src --type=ts | head -15


</function_calls>

Let me check if the suffix can actually be just "datasource/":
<function_calls>


#!/bin/bash

Search for where suffix parameter is set or passed

rg -n "suffix\s*[=:]|suffix)" app/client/src/ce/entities/URLRedirect/URLAssembly.ts -B2 -A1 | head -40


</function_calls>

Let me look at the complete method definition one more time with better context:
<function_calls>


#!/bin/bash
python3 << 'EOF'
with open('app/client/src/ce/entities/URLRedirect/URLAssembly.ts') as f:
content = f.read()
lines = content.split('\n')

Find the complete getRedirectUrl or similar method

in_method = False
method_start = 0
for i, line in enumerate(lines):
if 'isWorkspaceContext' in line and '&&' in line:
# Found the line in question, now trace back to find the method start
for j in range(i, -1, -1):
if re.search(r'\bpublic|private|protected\s+\w+\s*([^)])\s[:{]', lines[j]) or (j > 0 and ')' in lines[j] and not '{' in lines[j]):
method_start = j
break
# Now print from method start to find the end
print(f"METHOD STARTING AT LINE {method_start + 1}:")
for k in range(method_start, min(i+25, len(lines))):
marker = ">>>" if i == k else " "
print(f"{marker} {k+1:4d}: {lines[k]}")
break

import re
EOF


</function_calls>

Let me just directly read the section and analyze it:
<function_calls>


#!/bin/bash

Get the exact section that concerns us

python3 << 'EOF'
with open('app/client/src/ce/entities/URLRedirect/URLAssembly.ts') as f:
lines = f.readlines()

Show lines 325-375

print("COMPLETE CONTEXT (lines 325-375):")
print("=" * 80)
for i in range(324, min(375, len(lines))):
marker = ">>>" if 346 <= i < 351 else " "
print(f"{marker} {i+1:4d}: {lines[i]}", end='')
EOF


</function_calls>

Now let me search for what happens after the suffixPath is set to understand the final URL:
<function_calls>


#!/bin/bash

Check what the method returns

sed -n '347,385p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts


</function_calls>

Perfect! Now I have the context. Let me verify if this is actually an issue by checking if suffix can be "datasource/":
<function_calls>


#!/bin/bash

Search for all calls and suffix construction patterns

rg -n "datasource/" --type=ts app/client/src | head -40


</function_calls>

Now let me search for whether there's any guard condition or validation that prevents empty suffixes:
<function_calls>


#!/bin/bash

Check if there are any guards for empty suffix

grep -n "suffix|basePath.*suffixPath|return.*basePath" app/client/src/ce/entities/URLRedirect/URLAssembly.ts | grep -A2 -B2 "347:|348:|349:|350:|351:|352:"


</function_calls>

Let me get the return statement and understand the final URL:
<function_calls>


#!/bin/bash

Get the complete function to see what's returned

sed -n '347,380p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts | cat -n


</function_calls>

Let me look for tests in the codebase:
<function_calls>


#!/bin/bash

Find test files related to URL

find . -path "/node_modules" -prune -o -type f ( -name ".test.ts" -o -name "*.spec.ts" ) -print | xargs grep -l "getRedirectUrl|URLAssembly" 2>/dev/null


</function_calls>

Let me check the exact return statement more carefully:
<function_calls>


#!/bin/bash

Get what's returned from the method

python3 << 'EOF'
with open('app/client/src/ce/entities/URLRedirect/URLAssembly.ts') as f:
lines = f.readlines()

Find the return statement after line 351

for i in range(350, min(375, len(lines))):
line = lines[i]
if 'return' in line or 'basePath' in line and 'suffixPath' in line:
# Print context
for j in range(max(0, i-2), min(len(lines), i+3)):
marker = ">>>" if i == j else " "
print(f"{marker} {j+1:4d}: {lines[j]}", end='')
print()
EOF


</function_calls>

Now let me verify the complete logic by understanding what URL is constructed:
<function_calls>


#!/bin/bash

Get lines 360-375 to see the return

sed -n '360,375p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts


</function_calls>

Let me check the method name and see if there are any tests:
<function_calls>


#!/bin/bash

Find the method name by looking at the function definition

sed -n '320,350p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts | grep -n "getRedirectUrl|getWorkspaceUrl|function|^\s*[a-z].*("


</function_calls>

Based on my investigation, let me now gather information on whether this is actually problematic:
<function_calls>


#!/bin/bash

Search for test cases that specifically test the datasource path

rg -n "datasource.*suffix|suffix.*datasource" --type=ts | head -20


</function_calls>

Let me verify if the edge case is realistic by checking how suffix is constructed in the callers:
<function_calls>


#!/bin/bash

Look for URLAssembly instantiation and method calls

rg -n ".getRedirectUrl|new URLAssembly" app/client/src --type=ts -A3 -B1 | head -50


</function_calls>

Now let me check if there's documentation on what valid suffix values are:
<function_calls>


#!/bin/bash

Look for JSDoc or comments explaining the parameters

sed -n '310,350p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts | grep -E "^\s*//|^\s*/*|*/\s*$|@param|@returns"


</function_calls>

Let me check the complete structure of the file:
<function_calls>


#!/bin/bash

Get a complete picture of the method

sed -n '320,375p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts


</function_calls>

Based on all my searches, let me now verify the actual concern by checking if there's any validation. Let me look for tests one more time:
<function_calls>


#!/bin/bash

Search for test files that might test URLAssembly

find . -path "/node_modules" -prune -o -type f -name ".test.ts" -o -name "*.spec.ts" | head -20 | xargs grep -l "URLAssembly|getRedirectUrl" 2>/dev/null | head -3


</function_calls>

Let me understand whether the concern is valid by analyzing the code logic once more:
<function_calls>


#!/bin/bash
python3 << 'EOF'

Let's trace through the logic as described in the review

The code (lines 347-351):

if (this.isWorkspaceContext() && suffix?.startsWith("datasource/")) {

basePath =/workspace/${entityId}/datasource;

suffixPath =/${suffix.replace("datasource/", "")};

}

Scenario 1: suffix = "datasource/"

suffix1 = "datasource/"
if suffix1.startswith("datasource/"):
base = "/workspace/123/datasource"
suffix_result = suffix1.replace("datasource/", "")
suffix_path = f"/{suffix_result}"
print(f"Scenario 1: suffix = '{suffix1}'")
print(f" basePath = '{base}'")
print(f" suffixPath = '{suffix_path}'")
print(f" Result = '{base}{suffix_path}'")
print()

Scenario 2: suffix = "datasource/columns"

suffix2 = "datasource/columns"
if suffix2.startswith("datasource/"):
base = "/workspace/123/datasource"
suffix_result = suffix2.replace("datasource/", "")
suffix_path = f"/{suffix_result}"
print(f"Scenario 2: suffix = '{suffix2}'")
print(f" basePath = '{base}'")
print(f" suffixPath = '{suffix_path}'")
print(f" Result = '{base}{suffix_path}'")
print()

The concern is that scenario 1 produces a trailing slash with nothing after it

print("CONCERN ANALYSIS:")
print("If suffix = 'datasource/', then suffixPath = '/' (empty content between slashes)")
print("This creates a URL with redundant trailing slash")

EOF


</function_calls>

Let me find the actual callers of this method to understand what suffix values are passed:
<function_calls>


#!/bin/bash

Search for all usages of getRedirectUrl method

rg -n "getRedirectUrl" app/client/src --type=ts -B3 -A3 | grep -v "node_modules"


</function_calls>

Now let me check if there's any URL normalization logic:
<function_calls>


#!/bin/bash

Search for URL normalization or trailing slash handling

rg -n "replace.*/$|trailing|normalize.*url|//" app/client/src/ce/entities/URLRedirect/ --type=ts | head -20


</function_calls>

Let me now verify this is actually part of a real method by checking the context one final time:
<function_calls>


#!/bin/bash

Get complete method with all details

sed -n '310,380p' app/client/src/ce/entities/URLRedirect/URLAssembly.ts | nl -v 310


</function_calls>

Now let me search for where the getRedirectUrl is actually called with what parameters:
<function_calls>


#!/bin/bash

Search for all calls to this method in the codebase

find app -name ".ts" -type f ! -path "/node_modules/*" | xargs grep -n "getRedirectUrl|URLAssembly()" 2>/dev/null | head -15


</function_calls>

Based on all my research, let me now provide the final verification. The concern appears to be about a potential edge case. Let me verify if this is even a realistic scenario by checking the code flow one more time and looking for any guards:
<function_calls>


#!/bin/bash

Final check: Get the complete method and analyze edge cases

python3 << 'EOF'
with open('app/client/src/ce/entities/URLRedirect/URLAssembly.ts') as f:
lines = f.readlines()

print("COMPLETE METHOD CONTEXT (lines 310-385):")
print("=" * 80)
for i in range(309, min(385, len(lines))):
marker = ">>>" if 346 <= i < 351 else " "
print(f"{marker} {i+1:4d}: {lines[i]}", end='')

Analyze the logic

print("\n" + "=" * 80)
print("EDGE CASE ANALYSIS:")
print("=" * 80)
print("If suffix = 'datasource/':")
print(" - Line 348: basePath =/workspace/${entityId}/datasource")
print(" - Line 349: suffixPath =/${suffix.replace('datasource/', '')}")
print(" - suffix.replace('datasource/', '') = '' (empty string)")
print(" - suffixPath = '/' (slash + empty = just slash)")
print(" - This produces a path with trailing slash only")
EOF


</function_calls>

Based on my thorough investigation of the codebase, I have gathered sufficient evidence to conclude my verification. The review comment identifies a valid edge case in the code. Let me provide the final rewritten review comment:


Edge case: If suffix is exactly "datasource/", the replace produces an empty suffixPath, resulting in a path like/workspace/xxx/datasource/ with a trailing slash and no content after it.

Consider adding a guard to ensuresuffix contains additional content beyond the "datasource/" prefix, or document whether this edge case is intentionally acceptable.

    if (this.isWorkspaceContext() && suffix?.startsWith("datasource/")) {      // For workspace datasource URLs, use singular /datasource path      basePath = `/workspace/${entityId}/datasource`;      suffixPath = `/${suffix.replace("datasource/", "")}`;    }


// Open the workspace menu (triple dot) and click the Datasources option
_.homePage.OpenWorkspaceOptions(workspaceId);
agHelper.GetNClickByContains(".workspace-menu-item","Datasources");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

⚠️ Potential issue |🟡 Minor

Replace class selector with data-testid attribute.

The.workspace-menu-item class selector violates the guideline to use data-* attributes for selectors. Consider using a data-testid attribute instead.

Based on coding guidelines: "Use data-* attributes for selectors" and "Avoid CSS path."

Apply this diff:

-        agHelper.GetNClickByContains(".workspace-menu-item", "Datasources");+        agHelper.GetNClickByContains("[data-testid='workspace-menu-item']", "Datasources");
📝 Committable suggestion

‼️IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
agHelper.GetNClickByContains(".workspace-menu-item","Datasources");
agHelper.GetNClickByContains("[data-testid='workspace-menu-item']","Datasources");
🤖 Prompt for AI Agents
Inapp/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.tsaround line 22, replace the CSS class selector usage with a data-testidattribute selector; update the call so it targets the element by data-testid(e.g. '[data-testid="workspace-menu-item"]') instead of ".workspace-menu-item"while keeping the same visible text "Datasources" so theagHelper.GetNClickByContains invocation continues to click the correct item.

_.homePage.CreateNewWorkspace(workspaceId);

_.homePage.OpenWorkspaceOptions(workspaceId);
agHelper.GetNClickByContains(".workspace-menu-item","Datasources");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

⚠️ Potential issue |🟡 Minor

Replace class selector with data-testid attribute.

The.workspace-menu-item class selector violates the guideline to use data-* attributes for selectors.

Based on coding guidelines: "Use data-* attributes for selectors."

Apply this diff:

-        agHelper.GetNClickByContains(".workspace-menu-item", "Datasources");+        agHelper.GetNClickByContains("[data-testid='workspace-menu-item']", "Datasources");
📝 Committable suggestion

‼️IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
agHelper.GetNClickByContains(".workspace-menu-item","Datasources");
agHelper.GetNClickByContains("[data-testid='workspace-menu-item']","Datasources");
🤖 Prompt for AI Agents
Inapp/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.tsaround line 49, replace the class-based selector ".workspace-menu-item" with adata-testid attribute selector (e.g. data-testid="workspace-menu-item") whencalling agHelper.GetNClickByContains so the test uses data-* attributes forelement targeting; update the selector string accordingly and ensure the targetelement in the app has the matching data-testid attribute.

cy.contains("Configurations").should("be.visible");
cy.contains("button", "Edit").should("be.visible");
cy.wait(100);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

⚠️ Potential issue |🔴 Critical

Remove arbitrary waits before enabling these tests.

The commented-out tests containcy.wait(100) calls, which explicitly violate the guideline: "Avoid using cy.wait in code." These arbitrary waits introduce non-deterministic behavior and should be replaced with proper waits for elements, network requests, or application state.

Based on coding guidelines and learnings: "Avoid using cy.wait in code" and "Avoid using agHelper.Sleep, this.Sleep in any file in code."

Before enabling these tests, replace the arbitrary waits with appropriate assertions or aliased route waits:

-        cy.wait(100);-        cy.get(".t--add-datasource-button").first().click({ force: true });+        cy.get(".t--add-datasource-button").first().should("be.visible").click({ force: true });

Also applies to: 174-174

Comment on lines +55 to +56
constdatasources=useSelector(getDatasources);
constgroupedDatasources=useSelector(getDatasourcesGroupedByPluginCategory);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

⚠️ Potential issue |🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash# First, find the getDatasources selector definitionrg -n"export.*getDatasources|function getDatasources|const getDatasources" --type=ts --type=tsx -A 5

Repository: appsmithorg/appsmith

Length of output: 91


🏁 Script executed:

#!/bin/bash# Also check the WorkspaceDataSidePane component to understand its contextfd -t f"WorkspaceDataSidePane.tsx" --exec head -100 {}

Repository: appsmithorg/appsmith

Length of output: 3614


🏁 Script executed:

#!/bin/bash# Search for workspace-filtered datasource selectorsrg -n"workspace.*datasources|getDatasources.*workspace" --type=ts --type=tsx -C 2

Repository: appsmithorg/appsmith

Length of output: 91


🏁 Script executed:

#!/bin/bash# Search for getDatasources selector definition - broader searchrg -n"export.*getDatasources|const getDatasources" -A 5| head -50

Repository: appsmithorg/appsmith

Length of output: 2839


🏁 Script executed:

#!/bin/bash# Find the selectors filefd -t f"entitiesSelector"| head -10

Repository: appsmithorg/appsmith

Length of output: 159


🏁 Script executed:

#!/bin/bash# Search for workspace-filtered datasource patternsrg -n"workspaceId.*datasource|datasource.*workspaceId" -C 2| head -60

Repository: appsmithorg/appsmith

Length of output: 5033


🏁 Script executed:

#!/bin/bash# Check the EE version of entitiesSelector for workspace-filtered selectorscat app/client/src/ee/selectors/entitiesSelector.ts| head -150

Repository: appsmithorg/appsmith

Length of output: 110


🏁 Script executed:

#!/bin/bash# Look for workspace-filtered datasource selectors in the full codebaserg -n"workspace.*getDatasources|workspaceId.*filter.*datasource" -C 3| head -80

Repository: appsmithorg/appsmith

Length of output: 46


🏁 Script executed:

#!/bin/bash# Check the full WorkspaceDataSidePane to see how datasources are renderedsed -n'50,150p' app/client/src/pages/workspace/WorkspaceDataSidePane.tsx

Repository: appsmithorg/appsmith

Length of output: 3239


🏁 Script executed:

#!/bin/bash# Get the rest of the WorkspaceDataSidePane rendering to see how datasources are filteredsed -n'130,200p' app/client/src/pages/workspace/WorkspaceDataSidePane.tsx

Repository: appsmithorg/appsmith

Length of output: 2347


🏁 Script executed:

#!/bin/bash# Check if there's any filtering of datasources in render logicrg -n"datasources.*filter|groupedDatasources.*filter" app/client/src/pages/workspace/WorkspaceDataSidePane.tsx -C 2

Repository: appsmithorg/appsmith

Length of output: 46


🏁 Script executed:

#!/bin/bash# Check if workspaceId is used anywhere to filter data in this filerg -n"workspaceId" app/client/src/pages/workspace/WorkspaceDataSidePane.tsx -C 1

Repository: appsmithorg/appsmith

Length of output: 761


🏁 Script executed:

#!/bin/bash# Find datasource reducer/actions to understand how data is loadedfd -t f"datasource.*reducer\|datasource.*slice\|datasource.*action" --type f| grep -E"(reducer|slice|action)"| head -10

Repository: appsmithorg/appsmith

Length of output: 46


🏁 Script executed:

#!/bin/bash# Search for where getDatasources is used to understand expected behaviorrg -n"getDatasources\(" -B 2 -A 2| head -100

Repository: appsmithorg/appsmith

Length of output: 5236


🏁 Script executed:

#!/bin/bash# Check if workspace filtering happens at API/data-loading levelrg -n"workspaceId.*datasource|fetchDatasources.*workspace" -C 2| head -80

Repository: appsmithorg/appsmith

Length of output: 11998


Based on my verification, the original review comment's concern iscorrect. Here's what I found:

  1. getDatasources selector (line 86-88 ofapp/client/src/ce/selectors/entitiesSelector.ts) returnsstate.entities.datasources.list - ALL datasources in Redux state without any workspace filtering.

  2. WorkspaceDataSidePane component receivesworkspaceId as a prop but uses it only for navigation URLs, not for filtering datasources.

  3. No filtering in component render logic - The component displaysgroupedDatasources directly, which derives from the unfilteredgetDatasources selector.

  4. Datasource model includes workspaceId - Server-side code shows datasources have aworkspaceId field and the backend supportsgetAllByWorkspaceIdWithStorages() for workspace-scoped queries.

  5. Unfiltered display - All datasources in Redux state are displayed, regardless of which workspace page is active.

This is a legitimate data scoping issue where the component displays all datasources instead of filtering to only those belonging to the current workspace.


Datasources are not filtered by workspace in this component.

getDatasources returns all datasources in Redux state without workspace filtering. Since the component has access toworkspaceId, it should filter to workspace-scoped datasources before display.

Consider filtering byworkspaceId:

-  const datasources = useSelector(getDatasources);+  const datasources = useSelector(getDatasources).filter(+    (ds) => ds.workspaceId === workspaceId+  );

Or create a workspace-specific selector in the selectors file.

📝 Committable suggestion

‼️IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
constdatasources=useSelector(getDatasources);
constgroupedDatasources=useSelector(getDatasourcesGroupedByPluginCategory);
constdatasources=useSelector(getDatasources).filter(
(ds)=>ds.workspaceId===workspaceId
);
constgroupedDatasources=useSelector(getDatasourcesGroupedByPluginCategory);
🤖 Prompt for AI Agents
In app/client/src/pages/workspace/WorkspaceDataSidePane.tsx around lines 55-56,the component uses getDatasources and getDatasourcesGroupedByPluginCategorywhich return all datasources from Redux (not workspace-scoped), so the UI showsdatasources from all workspaces; update the component to scope datasources tothe passed workspaceId by either (a) creating new selectors (e.g.,getDatasourcesByWorkspaceId andgetDatasourcesGroupedByPluginCategoryByWorkspace) that filterstate.entities.datasources.list by datasource.workspaceId, then use thoseselectors here, or (b) select the full list and apply a local filter byworkspaceId before grouping and rendering; ensure all downstream grouping/propsuse the filtered list so only datasources for the current workspace are shown.

Comment on lines +62 to +70
constWorkspaceDatasourceDefaultView=()=>{
constdatasources=useSelector(getDatasources);

if(!datasources||datasources.length===0){
return<DatasourceBlankState/>;
}

return<CreateNewDatasourceTab/>;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

⚠️ Potential issue |🟠 Major

Same workspace-scoping issue applies here.

WorkspaceDatasourceDefaultView usesgetDatasources which returns all datasources, not workspace-filtered. Should align with workspace context filtering.

Consider passingworkspaceId to filter or use a workspace-scoped selector.

🤖 Prompt for AI Agents
In app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx around lines 62to 70, the component uses the global getDatasources selector which returns alldatasources instead of only those for the current workspace; change it to use aworkspace-scoped datasource list (either call a selector that acceptsworkspaceId or filter the results by the current workspaceId). Retrieve thecurrent workspaceId from existing workspace context/selector (e.g., useParams orgetCurrentWorkspaceId) and then either switch to a selector likegetDatasourcesForWorkspace(workspaceId) or apply a filter on getDatasources() bycomparing datasource.workspaceId === workspaceId, and update the conditionalrendering to rely on that filtered list.

Comment on lines +97 to +101
useEffect(()=>{
if(!currentWorkspace){
dispatch(fetchAllWorkspaces({ workspaceId,fetchEntities:true}));
}
},[currentWorkspace,dispatch,workspaceId]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

⚠️ Potential issue |🟡 Minor

Potential infinite fetch loop if workspace fetch fails.

IffetchAllWorkspaces fails,currentWorkspace remains undefined, triggering repeated fetches. Add a guard or loading state check.

+  const isFetchingWorkspaces = useSelector(+    (state: DefaultRootState) => state.ui.workspaces.isFetchingAllWorkspaces+  );+   useEffect(() => {-    if (!currentWorkspace) {+    if (!currentWorkspace && !isFetchingWorkspaces) {       dispatch(fetchAllWorkspaces({ workspaceId, fetchEntities: true }));     }-  }, [currentWorkspace, dispatch, workspaceId]);+  }, [currentWorkspace, dispatch, workspaceId, isFetchingWorkspaces]);
🤖 Prompt for AI Agents
In app/client/src/pages/workspace/WorkspaceDatasourcesPage.tsx around lines 97to 101, the useEffect will repeatedly dispatch fetchAllWorkspaces whencurrentWorkspace is undefined (e.g., after a failed fetch), causing a potentialinfinite fetch loop; modify the logic to also check a loading/fetching or errorflag (or a local ref that marks that a fetch attempt is in progress/completed)before dispatching so the effect only triggers when no fetch is active and noprior failed attempt exists, and set/update that flag on fetchstart/finish/error to prevent repeated retries unless a user action triggers aretry.

Copy link
Contributor

@coderabbitaicoderabbitaibot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (5)
app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts (5)

76-76:Replace class selector with data-testid attribute.

The.workspace-menu-item class selector violates the guideline to use data-* attributes for selectors.

Based on coding guidelines: "Use data-* attributes for selectors."

Apply this diff:

-        agHelper.GetNClickByContains(".workspace-menu-item", "Datasources");+        agHelper.GetNClickByContains("[data-testid='workspace-menu-item']", "Datasources");

125-125:Replace class selector with data-testid attribute.

The.workspace-menu-item class selector violates the guideline to use data-* attributes for selectors.

Based on coding guidelines: "Use data-* attributes for selectors."

Apply this diff:

-        agHelper.GetNClickByContains(".workspace-menu-item", "Datasources");+        agHelper.GetNClickByContains("[data-testid='workspace-menu-item']", "Datasources");

165-165:Replace class selector with data-testid attribute.

The.workspace-menu-item class selector violates the guideline to use data-* attributes for selectors.

Based on coding guidelines: "Use data-* attributes for selectors."

Apply this diff:

-        agHelper.GetNClickByContains(".workspace-menu-item", "Datasources");+        agHelper.GetNClickByContains("[data-testid='workspace-menu-item']", "Datasources");

174-176:Remove arbitrary wait and replace ID selector with data-testid.

Thecy.wait(100) arbitrary wait combined withforce: true suggests a synchronization issue. Additionally, the ID selector#new-integrations-wrapper should be replaced with a data-testid attribute.

Based on coding guidelines: "Avoid using cy.wait in code" and "Use data-* attributes for selectors."

Apply this diff to wait for the element properly and use data-testid:

-        cy.wait(100);-        cy.get(".t--add-datasource-button").first().click({ force: true });-        cy.get("#new-integrations-wrapper").should("be.visible");+        cy.get(".t--add-datasource-button").first().should("be.visible").click();+        cy.get("[data-testid='new-integrations-wrapper']").should("be.visible");

91-93:Remove arbitrary wait and replace ID selector with data-testid.

Thecy.wait(100) arbitrary wait combined withforce: true suggests a synchronization issue. Additionally, the ID selector#new-integrations-wrapper should be replaced with a data-testid attribute.

Based on coding guidelines: "Avoid using cy.wait in code" and "Use data-* attributes for selectors."

Apply this diff to wait for the element properly and use data-testid:

-        cy.wait(100);-        cy.get(".t--add-datasource-button").first().click({ force: true });-        cy.get("#new-integrations-wrapper").should("be.visible");+        cy.get(".t--add-datasource-button").first().should("be.visible").click();+        cy.get("[data-testid='new-integrations-wrapper']").should("be.visible");
🧹 Nitpick comments (1)
app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts (1)

193-200:Consider using data-testid attributes for header input fields.

The complex attribute selectors.t--headers-array input[name$='.key'] and.t--headers-array input[name$='.value'] could be more robust and maintainable with data-testid attributes.

Based on coding guidelines: "Use data-* attributes for selectors."

Consider updating the header input components to include data-testid attributes:

-        cy.get(".t--headers-array input[name$='.key']")+        cy.get("[data-testid='header-key-input']")           .first()           .clear({ force: true })           .type("Content-Type", { delay: 0 });-        cy.get(".t--headers-array input[name$='.value']")+        cy.get("[data-testid='header-value-input']")           .first()           .clear({ force: true })           .type("application/json", { delay: 0 });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between385b5e0 andaf290de.

📒 Files selected for processing (1)
  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
app/client/cypress/**/**.*

⚙️ CodeRabbit configuration file

app/client/cypress/**/**.*: Review the following e2e test code written using the Cypress test library. Ensure that:

  • Follow best practices for Cypress code and e2e automation.
  • Avoid using cy.wait in code.
  • Avoid using cy.pause in code.
  • Avoid using agHelper.sleep().
  • Use locator variables for locators and do not use plain strings.
  • Use data-* attributes for selectors.
  • Avoid Xpaths, Attributes and CSS path.
  • Avoid selectors like .btn.submit or button[type=submit].
  • Perform logins via API with LoginFromAPI.
  • Perform logout via API with LogOutviaAPI.
  • Perform signup via API with SignupFromAPI.
  • Avoid using it.only.
  • Avoid using after and aftereach in test cases.
  • Use multiple assertions for expect statements.
  • Avoid using strings for assertions.
  • Do not use duplicate filenames even with different paths.
  • Avoid using agHelper.Sleep, this.Sleep in any file in code.

Files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
🧠 Learnings (12)
📚 Learning: 2025-11-05T12:56:49.249Z
Learnt from: vsvamsi1Repo: appsmithorg/appsmith PR: 41363File: app/client/cypress/e2e/Regression/ClientSide/StaticUrl/PagePersistance_Spec.ts:0-0Timestamp: 2025-11-05T12:56:49.249ZLearning: In the file `app/client/cypress/e2e/Regression/ClientSide/StaticUrl/PagePersistance_Spec.ts`, the test suite intentionally uses sequential tests where Tests 4-6 depend on state (`page1Slug`, `page2Slug`) set in Tests 2-3. The author (vsvamsi1) prioritizes readability by breaking the flow into different segments over strict test isolation.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-10-08T15:32:34.115Z
Learnt from: sagar-qa007Repo: appsmithorg/appsmith PR: 34955File: app/client/cypress/e2e/Regression/ClientSide/ActionExecution/General_settings_Spec.ts:14-56Timestamp: 2024-10-08T15:32:34.115ZLearning: Learnt from: sagar-qa007PR: appsmithorg/appsmith#34955File: app/client/cypress/e2e/Regression/ClientSide/ActionExecution/General_settings_Spec.ts:14-56Timestamp: 2024-07-16T06:44:55.118ZLearning: Avoid using sleep functions like `agHelper.Sleep`, `this.Sleep`, and other related sleep functions in Cypress tests within the `app/client/cypress` directory to prevent non-deterministic behaviors and ensure tests are more reliable and maintainable.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2025-11-05T12:58:32.486Z
Learnt from: vsvamsi1Repo: appsmithorg/appsmith PR: 41363File: app/client/cypress/e2e/Regression/ClientSide/StaticUrl/SlugPersistance_Spec.ts:32-225Timestamp: 2025-11-05T12:58:32.486ZLearning: In the file `app/client/cypress/e2e/Regression/ClientSide/StaticUrl/SlugPersistance_Spec.ts`, the test suite intentionally uses sequential tests where Tests 2-5 depend on state from previous tests (e.g., slug values modified in earlier tests). The author (vsvamsi1) prioritizes readability by breaking the flow into different segments over strict test isolation.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-07-24T08:29:41.208Z
Learnt from: abhishek-bandameediRepo: appsmithorg/appsmith PR: 35133File: app/client/cypress/e2e/Regression/ClientSide/Widgets/Checkbox/CheckBox2_spec.js:0-0Timestamp: 2024-07-24T08:29:41.208ZLearning: In Cypress tests for the Appsmith project, ensure the use of locator variables for selectors and include multiple assertions for comprehensive testing.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-11-13T09:07:54.931Z
Learnt from: vhemeryRepo: appsmithorg/appsmith PR: 37371File: app/client/cypress/e2e/Regression/ClientSide/Widgets/Image/Image_spec.js:44-47Timestamp: 2024-11-13T09:07:54.931ZLearning: When reviewing code in `app/client/cypress/**` paths, ensure that suggestions are appropriate for test code and not for `src` code. Avoid applying source code checks to test code unless relevant.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-11-13T09:11:36.959Z
Learnt from: vhemeryRepo: appsmithorg/appsmith PR: 37371File: app/client/cypress/e2e/Regression/ClientSide/Widgets/Image/Image_base64_spec.js:35-37Timestamp: 2024-11-13T09:11:36.959ZLearning: In the file `app/client/cypress/e2e/Regression/ClientSide/Widgets/Image/Image_base64_spec.js`, when writing Cypress end-to-end tests for the Image Widget in JavaScript, use `viewWidgetsPage.imageinner` as the selector when asserting 'src' and 'alt' attributes to maintain consistency.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-10-08T15:32:39.374Z
Learnt from: Aishwarya-U-RRepo: appsmithorg/appsmith PR: 29405File: app/client/cypress/e2e/Regression/ClientSide/Binding/TableV2_Widget_API_Pagination_spec.js:37-41Timestamp: 2024-10-08T15:32:39.374ZLearning: The pull request titled "test: Cypress | Replace static with Dynamic waits - Part 1" is part of a phased approach where only certain test specifications are targeted for static wait removal in the initial phase. Future phases will address additional specs.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-10-08T15:32:34.114Z
Learnt from: sagar-qa007Repo: appsmithorg/appsmith PR: 34955File: app/client/cypress/e2e/Regression/ClientSide/ActionExecution/General_settingsTe_Spec.ts:33-33Timestamp: 2024-10-08T15:32:34.114ZLearning: Follow best practices for Cypress code and e2e automation:- Avoid using cy.wait in code.- Avoid using cy.pause in code.- Avoid using agHelper.sleep().- Use locator variables for locators and do not use plain strings.- Use data-* attributes for selectors.- Avoid Xpaths, Attributes, and CSS path.- Avoid selectors like .btn.submit or button[type=submit].- Perform logins via API with LoginFromAPI.- Perform logout via API with LogOutviaAPI.- Perform signup via API with SignupFromAPI.- Avoid using it.only.- Avoid using after and aftereach in test cases.- Use multiple assertions for expect statements.- Avoid using strings for assertions.- Do not use duplicate filenames even with different paths.- Avoid using agHelper.Sleep, this.Sleep in any file in code.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-10-08T15:32:39.374Z
Learnt from: sagar-qa007Repo: appsmithorg/appsmith PR: 35412File: app/client/cypress/e2e/Regression/ClientSide/OneClickBinding/TableWidget/mysql_spec.ts:99-99Timestamp: 2024-10-08T15:32:39.374ZLearning: In Cypress tests within the `app/client/cypress` directory, avoid using `agHelper.Sleep`, `this.Sleep`, and other related sleep functions to prevent non-deterministic behaviors and ensure tests are more reliable and maintainable. Instead, use Cypress methods like `cy.get()`, `cy.contains()`, and `cy.intercept()` to wait for specific conditions.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-08-06T05:39:47.929Z
Learnt from: ApekshaBhosaleRepo: appsmithorg/appsmith PR: 35412File: app/client/cypress/e2e/Regression/ClientSide/OneClickBinding/TableWidget/mysql_spec.ts:99-99Timestamp: 2024-08-06T05:39:47.929ZLearning: In Cypress tests, avoid using `agHelper.Sleep` as it can lead to flaky tests and unnecessary delays. Instead, use Cypress methods like `cy.get()`, `cy.contains()`, and `cy.intercept()` to wait for specific conditions.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-07-16T08:25:23.799Z
Learnt from: sagar-qa007Repo: appsmithorg/appsmith PR: 34955File: app/client/cypress/e2e/Regression/ClientSide/ActionExecution/General_settingsTe_Spec.ts:33-33Timestamp: 2024-07-16T08:25:23.799ZLearning: Avoid using sleep functions like `agHelper.Sleep` and `this.Sleep` in Cypress tests within the `app/client/cypress` directory to prevent non-deterministic behaviors and ensure tests are more reliable and maintainable.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-10-08T15:32:34.115Z
Learnt from: sagar-qa007Repo: appsmithorg/appsmith PR: 34955File: app/client/cypress/e2e/Regression/ClientSide/ActionExecution/General_settings_Spec.ts:14-56Timestamp: 2024-10-08T15:32:34.115ZLearning: Avoid using sleep functions like `agHelper.Sleep`, `this.Sleep` in Cypress tests within the `app/client/cypress` directory to prevent non-deterministic behaviors and ensure tests are more reliable and maintainable.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
🧬 Code graph analysis (1)
app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts (1)
app/client/cypress/support/commands.js (2)
  • _ (1071-1071)
  • workspaceId (396-396)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: perform-test / rts-build / build
  • GitHub Check: perform-test / client-build / client-build
  • GitHub Check: perform-test / server-build / server-unit-tests
  • GitHub Check: client-lint / client-lint
  • GitHub Check: client-check-cyclic-deps / check-cyclic-dependencies
  • GitHub Check: client-unit-tests / client-unit-tests
  • GitHub Check: client-prettier / prettier-check
  • GitHub Check: client-build / client-build
🔇 Additional comments (1)
app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts (1)

1-11:LGTM!

The imports and setup follow best practices. UsingbeforeEach to initialize datasource routes ensures consistent test state.

@tomjose92tomjose92 removed the ok-to-testRequired label for CI labelNov 29, 2025
Copy link
Contributor

@coderabbitaicoderabbitaibot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts (2)

22-22:Replace.workspace-menu-item class selector with a data-testid selector.

Using the.workspace-menu-item class as a locator violates the project guideline to use data-* attributes for selectors in Cypress tests. Prefer a stabledata-testid on the menu item and target that instead, while still filtering by the “Datasources” label.

-        agHelper.GetNClickByContains(".workspace-menu-item", "Datasources");+        agHelper.GetNClickByContains("[data-testid='workspace-menu-item']", "Datasources");

Apply the same change at both usages (Lines 22 and 49), and ensure the UI element has the correspondingdata-testid="workspace-menu-item" attribute.

Also applies to: 49-49


66-115:Replace staticcy.wait(100) calls with element- or network-based waits.

The hard-codedcy.wait(100) calls introduce flakiness and violate the “Avoid using cy.wait in code” guideline; they should be replaced with waits that assert on UI or network conditions before proceeding.

A concrete replacement that keeps intent but uses deterministic waits:

@@-        cy.wait(100);-        cy.get(".t--add-datasource-button").first().click({ force: true });+        cy.get(".t--add-datasource-button")+          .first()+          .should("be.visible")+          .click({ force: true });@@-        cy.wait(100);-        cy.get(".t--add-datasource-button").first().click({ force: true });+        cy.get(".t--add-datasource-button")+          .first()+          .should("be.visible")+          .click({ force: true });

If there’s a specific network request that must complete before the button appears, you can also alias that request andcy.wait on the alias instead of a fixed timeout.

Also applies to: 159-218

🧹 Nitpick comments (3)
app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts (3)

1-12:Reduce duplicate imports fromObjectsCore for consistency.

You’re importing fromObjectsCore both as a namespace (_) and via named imports (agHelper,dataSources), which is slightly redundant and can confuse future edits. Consider either using only the namespace (_.agHelper,_.dataSources) or only named imports for a cleaner pattern.


13-38:Align test description with assertions or add coverage for “available plugins.”

The test name mentions “available plugins,” but the assertions only cover the empty list and blank state (including the CTA text). Either add an assertion that verifies the expected plugins or plugin tiles are rendered, or adjust the description so it reflects exactly what’s being checked.


196-217:Strengthen assertions to verify headers actually persist after saving from the discard dialog.

The test edits header key/value, triggers the discard modal, then chooses “save” and only checks that the datasources (“Users”, “Mock API”) are visible. To fully validate “Should keep edits,” consider re-opening the editor and asserting that the header fields containContent-Type andapplication/json.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and betweenaf290de and9caf3ed.

📒 Files selected for processing (1)
  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
app/client/cypress/**/**.*

⚙️ CodeRabbit configuration file

app/client/cypress/**/**.*: Review the following e2e test code written using the Cypress test library. Ensure that:

  • Follow best practices for Cypress code and e2e automation.
  • Avoid using cy.wait in code.
  • Avoid using cy.pause in code.
  • Avoid using agHelper.sleep().
  • Use locator variables for locators and do not use plain strings.
  • Use data-* attributes for selectors.
  • Avoid Xpaths, Attributes and CSS path.
  • Avoid selectors like .btn.submit or button[type=submit].
  • Perform logins via API with LoginFromAPI.
  • Perform logout via API with LogOutviaAPI.
  • Perform signup via API with SignupFromAPI.
  • Avoid using it.only.
  • Avoid using after and aftereach in test cases.
  • Use multiple assertions for expect statements.
  • Avoid using strings for assertions.
  • Do not use duplicate filenames even with different paths.
  • Avoid using agHelper.Sleep, this.Sleep in any file in code.

Files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
🧠 Learnings (12)
📚 Learning: 2024-10-08T15:32:34.115Z
Learnt from: sagar-qa007Repo: appsmithorg/appsmith PR: 34955File: app/client/cypress/e2e/Regression/ClientSide/ActionExecution/General_settings_Spec.ts:14-56Timestamp: 2024-10-08T15:32:34.115ZLearning: Learnt from: sagar-qa007PR: appsmithorg/appsmith#34955File: app/client/cypress/e2e/Regression/ClientSide/ActionExecution/General_settings_Spec.ts:14-56Timestamp: 2024-07-16T06:44:55.118ZLearning: Avoid using sleep functions like `agHelper.Sleep`, `this.Sleep`, and other related sleep functions in Cypress tests within the `app/client/cypress` directory to prevent non-deterministic behaviors and ensure tests are more reliable and maintainable.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2025-11-05T12:56:49.249Z
Learnt from: vsvamsi1Repo: appsmithorg/appsmith PR: 41363File: app/client/cypress/e2e/Regression/ClientSide/StaticUrl/PagePersistance_Spec.ts:0-0Timestamp: 2025-11-05T12:56:49.249ZLearning: In the file `app/client/cypress/e2e/Regression/ClientSide/StaticUrl/PagePersistance_Spec.ts`, the test suite intentionally uses sequential tests where Tests 4-6 depend on state (`page1Slug`, `page2Slug`) set in Tests 2-3. The author (vsvamsi1) prioritizes readability by breaking the flow into different segments over strict test isolation.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2025-11-05T12:58:32.486Z
Learnt from: vsvamsi1Repo: appsmithorg/appsmith PR: 41363File: app/client/cypress/e2e/Regression/ClientSide/StaticUrl/SlugPersistance_Spec.ts:32-225Timestamp: 2025-11-05T12:58:32.486ZLearning: In the file `app/client/cypress/e2e/Regression/ClientSide/StaticUrl/SlugPersistance_Spec.ts`, the test suite intentionally uses sequential tests where Tests 2-5 depend on state from previous tests (e.g., slug values modified in earlier tests). The author (vsvamsi1) prioritizes readability by breaking the flow into different segments over strict test isolation.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-07-24T08:29:41.208Z
Learnt from: abhishek-bandameediRepo: appsmithorg/appsmith PR: 35133File: app/client/cypress/e2e/Regression/ClientSide/Widgets/Checkbox/CheckBox2_spec.js:0-0Timestamp: 2024-07-24T08:29:41.208ZLearning: In Cypress tests for the Appsmith project, ensure the use of locator variables for selectors and include multiple assertions for comprehensive testing.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-11-13T09:07:54.931Z
Learnt from: vhemeryRepo: appsmithorg/appsmith PR: 37371File: app/client/cypress/e2e/Regression/ClientSide/Widgets/Image/Image_spec.js:44-47Timestamp: 2024-11-13T09:07:54.931ZLearning: When reviewing code in `app/client/cypress/**` paths, ensure that suggestions are appropriate for test code and not for `src` code. Avoid applying source code checks to test code unless relevant.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-11-13T09:11:36.959Z
Learnt from: vhemeryRepo: appsmithorg/appsmith PR: 37371File: app/client/cypress/e2e/Regression/ClientSide/Widgets/Image/Image_base64_spec.js:35-37Timestamp: 2024-11-13T09:11:36.959ZLearning: In the file `app/client/cypress/e2e/Regression/ClientSide/Widgets/Image/Image_base64_spec.js`, when writing Cypress end-to-end tests for the Image Widget in JavaScript, use `viewWidgetsPage.imageinner` as the selector when asserting 'src' and 'alt' attributes to maintain consistency.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-10-08T15:32:39.374Z
Learnt from: Aishwarya-U-RRepo: appsmithorg/appsmith PR: 29405File: app/client/cypress/e2e/Regression/ClientSide/Binding/TableV2_Widget_API_Pagination_spec.js:37-41Timestamp: 2024-10-08T15:32:39.374ZLearning: The pull request titled "test: Cypress | Replace static with Dynamic waits - Part 1" is part of a phased approach where only certain test specifications are targeted for static wait removal in the initial phase. Future phases will address additional specs.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-10-08T15:32:34.114Z
Learnt from: sagar-qa007Repo: appsmithorg/appsmith PR: 34955File: app/client/cypress/e2e/Regression/ClientSide/ActionExecution/General_settingsTe_Spec.ts:33-33Timestamp: 2024-10-08T15:32:34.114ZLearning: Follow best practices for Cypress code and e2e automation:- Avoid using cy.wait in code.- Avoid using cy.pause in code.- Avoid using agHelper.sleep().- Use locator variables for locators and do not use plain strings.- Use data-* attributes for selectors.- Avoid Xpaths, Attributes, and CSS path.- Avoid selectors like .btn.submit or button[type=submit].- Perform logins via API with LoginFromAPI.- Perform logout via API with LogOutviaAPI.- Perform signup via API with SignupFromAPI.- Avoid using it.only.- Avoid using after and aftereach in test cases.- Use multiple assertions for expect statements.- Avoid using strings for assertions.- Do not use duplicate filenames even with different paths.- Avoid using agHelper.Sleep, this.Sleep in any file in code.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-10-08T15:32:39.374Z
Learnt from: sagar-qa007Repo: appsmithorg/appsmith PR: 35412File: app/client/cypress/e2e/Regression/ClientSide/OneClickBinding/TableWidget/mysql_spec.ts:99-99Timestamp: 2024-10-08T15:32:39.374ZLearning: In Cypress tests within the `app/client/cypress` directory, avoid using `agHelper.Sleep`, `this.Sleep`, and other related sleep functions to prevent non-deterministic behaviors and ensure tests are more reliable and maintainable. Instead, use Cypress methods like `cy.get()`, `cy.contains()`, and `cy.intercept()` to wait for specific conditions.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-08-06T05:39:47.929Z
Learnt from: ApekshaBhosaleRepo: appsmithorg/appsmith PR: 35412File: app/client/cypress/e2e/Regression/ClientSide/OneClickBinding/TableWidget/mysql_spec.ts:99-99Timestamp: 2024-08-06T05:39:47.929ZLearning: In Cypress tests, avoid using `agHelper.Sleep` as it can lead to flaky tests and unnecessary delays. Instead, use Cypress methods like `cy.get()`, `cy.contains()`, and `cy.intercept()` to wait for specific conditions.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-07-16T08:25:23.799Z
Learnt from: sagar-qa007Repo: appsmithorg/appsmith PR: 34955File: app/client/cypress/e2e/Regression/ClientSide/ActionExecution/General_settingsTe_Spec.ts:33-33Timestamp: 2024-07-16T08:25:23.799ZLearning: Avoid using sleep functions like `agHelper.Sleep` and `this.Sleep` in Cypress tests within the `app/client/cypress` directory to prevent non-deterministic behaviors and ensure tests are more reliable and maintainable.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
📚 Learning: 2024-10-08T15:32:34.115Z
Learnt from: sagar-qa007Repo: appsmithorg/appsmith PR: 34955File: app/client/cypress/e2e/Regression/ClientSide/ActionExecution/General_settings_Spec.ts:14-56Timestamp: 2024-10-08T15:32:34.115ZLearning: Avoid using sleep functions like `agHelper.Sleep`, `this.Sleep` in Cypress tests within the `app/client/cypress` directory to prevent non-deterministic behaviors and ensure tests are more reliable and maintainable.

Applied to files:

  • app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts
🧬 Code graph analysis (1)
app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts (1)
app/client/cypress/support/commands.js (2)
  • _ (1071-1071)
  • workspaceId (396-396)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: client-build / client-build
  • GitHub Check: client-check-cyclic-deps / check-cyclic-dependencies
  • GitHub Check: client-unit-tests / client-unit-tests
  • GitHub Check: client-lint / client-lint
  • GitHub Check: client-prettier / prettier-check
🔇 Additional comments (1)
app/client/cypress/e2e/Regression/ClientSide/Workspace/WorkspaceDatasourceSettings_spec.ts (1)

117-157:Delete flow coverage looks solid for workspace datasource removal.

This test exercises add → open editor → context menu delete → confirm → verify blank state with the CTA visible, and relies only on aliased waits, which should be stable. No issues from a Cypress best-practices perspective.

@tomjose92
Copy link
ContributorAuthor

/build-deploy-preview skip-tests=true

github-actions[bot] reacted with rocket emojigithub-actions[bot] reacted with eyes emoji

@github-actions
Copy link

Deploying Your Preview:https://github.com/appsmithorg/appsmith/actions/runs/19780602226.
Workflow:On demand build Docker image and deploy preview.
skip-tests:true.
env: ``.
PR: 41324.
recreate: .

@github-actions
Copy link

Deploy-Preview-URL:https://ce-41324.dp.appsmith.com

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@coderabbitaicoderabbitai[bot]coderabbitai[bot] left review comments

@hetunanduhetunanduhetunandu left review comments

@ashit-rathashit-rathAwaiting requested review from ashit-rath

At least 1 approving review is required to merge this pull request.

Assignees

@tomjose92tomjose92

Labels

DatasourcesIssues related to configuring datasource on appsmithEnhancementNew feature or requestIntegrations ProductIssues related to a specific integrationQuery & JS PodIssues related to the query & JS PodQuery Widgets & IDE PodAll issues related to Query, JS, Eval, Widgets & IDE

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

[Feature]: Enable datasource configuration from workspace homepage

3 participants

@tomjose92@pedro-santos-rodrigues@hetunandu

[8]ページ先頭

©2009-2025 Movatter.jp