- Notifications
You must be signed in to change notification settings - Fork4.4k
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
base:release
Are you sure you want to change the base?
Changes from6 commits
228474dad664c8e4c0ba25aa777b1a30e1b3f3d1909698179ca19f3faacb669547f3f77582821385b5e0af290de9caf3edFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -2,6 +2,7 @@ export const IDE_TYPE = { | ||
| None: "None", | ||
| App: "App", | ||
| UIPackage: "UIPackage", | ||
| Workspace: "Workspace", | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. 🧩 Analysis chainLGTM — new IDE type addition is consistent. 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 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 in Currently, 🤖 Prompt for AI Agents | ||
| } as const; | ||
| export type IDEType = keyof typeof IDE_TYPE; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; | ||
| export interface InitWorkspaceIDEPayload { | ||
| workspaceId: string; | ||
| } | ||
| export const initWorkspaceIDE = (payload: InitWorkspaceIDEPayload) => ({ | ||
| type: ReduxActionTypes.INITIALIZE_WORKSPACE_IDE, | ||
| payload, | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| import{call,put}from"redux-saga/effects"; | ||
| importCodemirrorTernServicefrom"utils/autocomplete/CodemirrorTernService"; | ||
| import{ | ||
| ReduxActionErrorTypes, | ||
| ReduxActionTypes, | ||
| }from"ee/constants/ReduxActionConstants"; | ||
| import{isAirgapped}from"ee/utils/airgapHelpers"; | ||
| import{fetchPluginFormConfigs,fetchPlugins}from"actions/pluginActions"; | ||
| import{ | ||
| fetchDatasources, | ||
| fetchMockDatasources, | ||
| }from"actions/datasourceActions"; | ||
| import{failFastApiCalls}from"sagas/InitSagas"; | ||
| import{ | ||
| PluginFormConfigsNotFoundError, | ||
| PluginsNotFoundError, | ||
| }from"entities/Engine"; | ||
| importtype{ReduxAction}from"actions/ReduxActionTypes"; | ||
| import{waitForFetchEnvironments}from"ee/sagas/EnvironmentSagas"; | ||
| import{fetchingEnvironmentConfigs}from"ee/actions/environmentAction"; | ||
| exportdefaultclassWorkspaceEditorEngine{ | ||
| constructor(){ | ||
| this.setupEngine=this.setupEngine.bind(this); | ||
| this.loadWorkspace=this.loadWorkspace.bind(this); | ||
| this.loadPluginsAndDatasources=this.loadPluginsAndDatasources.bind(this); | ||
| this.completeChore=this.completeChore.bind(this); | ||
| } | ||
| *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); | ||
| } | ||
| public*setupEngine(){ | ||
| yieldput({type:ReduxActionTypes.START_EVALUATION}); | ||
| CodemirrorTernService.resetServer(); | ||
| } | ||
| *loadPluginsAndDatasources(workspaceId:string){ | ||
| constisAirgappedInstance=isAirgapped(); | ||
| constinitActions:ReduxAction<unknown>[]=[ | ||
| fetchPlugins({ workspaceId}), | ||
| fetchDatasources({ workspaceId}), | ||
| ]; | ||
| constsuccessActions=[ | ||
| ReduxActionTypes.FETCH_PLUGINS_SUCCESS, | ||
| ReduxActionTypes.FETCH_DATASOURCES_SUCCESS, | ||
| ]; | ||
| consterrorActions=[ | ||
| ReduxActionErrorTypes.FETCH_PLUGINS_ERROR, | ||
| ReduxActionErrorTypes.FETCH_DATASOURCES_ERROR, | ||
| ]; | ||
| if(!isAirgappedInstance){ | ||
| initActions.push(fetchMockDatasources()); | ||
| successActions.push(ReduxActionTypes.FETCH_MOCK_DATASOURCES_SUCCESS); | ||
| errorActions.push(ReduxActionErrorTypes.FETCH_MOCK_DATASOURCES_ERROR); | ||
| } | ||
| constinitActionCalls:boolean=yieldcall( | ||
| failFastApiCalls, | ||
| initActions, | ||
| successActions, | ||
| errorActions, | ||
| ); | ||
| if(!initActionCalls) | ||
| thrownewPluginsNotFoundError("Unable to fetch plugins"); | ||
| constpluginFormCall:boolean=yieldcall( | ||
| failFastApiCalls, | ||
| [fetchPluginFormConfigs()], | ||
| [ReduxActionTypes.FETCH_PLUGIN_FORM_CONFIGS_SUCCESS], | ||
| [ReduxActionErrorTypes.FETCH_PLUGIN_FORM_CONFIGS_ERROR], | ||
| ); | ||
| if(!pluginFormCall) | ||
| thrownewPluginFormConfigsNotFoundError( | ||
| "Unable to fetch plugin form configs", | ||
| ); | ||
| } | ||
| *completeChore(){ | ||
| yieldput({ | ||
| type:ReduxActionTypes.INITIALIZE_WORKSPACE_IDE_SUCCESS, | ||
| }); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -13,6 +13,7 @@ import { APP_MODE } from "entities/App"; | ||
| import { generatePath } from "react-router"; | ||
| import getQueryParamsObject from "utils/getQueryParamsObject"; | ||
| import { isNil } from "lodash"; | ||
| import { objectKeys } from "@appsmith/utils"; | ||
| export interface URLBuilderParams { | ||
| suffix?: string; | ||
| @@ -26,6 +27,7 @@ export interface URLBuilderParams { | ||
| // This is used to pass ID if the sender doesn't know the type of the entity | ||
| // base version of parent entity id, can be basePageId or moduleId | ||
| baseParentEntityId?: string; | ||
| workspaceId?: string; | ||
| generateEditorPath?: boolean; | ||
| } | ||
| @@ -65,7 +67,7 @@ export interface PageURLParams { | ||
| export function getQueryStringfromObject( | ||
| params: Record<string, string> = {}, | ||
| ): string { | ||
| const paramKeys =objectKeys(params); | ||
| const queryParams: string[] = []; | ||
| if (paramKeys) { | ||
| @@ -241,9 +243,24 @@ export class URLBuilder { | ||
| } | ||
| generateBasePath(basePageId: string, mode: APP_MODE) { | ||
| // Check if we're in workspace context | ||
| if (this.isWorkspaceContext()) { | ||
| return this.generateBasePathForWorkspace(basePageId); | ||
| } | ||
| return this.generateBasePathForApp(basePageId, mode); | ||
| } | ||
| isWorkspaceContext(): boolean { | ||
| const currentUrl = window.location.pathname; | ||
| return currentUrl.startsWith("/workspace"); | ||
| } | ||
| generateBasePathForWorkspace(workspaceId: string) { | ||
| return `/workspace/${workspaceId}/datasources`; | ||
| } | ||
| getCustomSlugPathPreview(basePageId: string, customSlug: string) { | ||
| const urlPattern = | ||
| baseURLRegistry[URL_TYPE.CUSTOM_SLUG][APP_MODE.PUBLISHED]; | ||
| @@ -284,9 +301,26 @@ export class URLBuilder { | ||
| } | ||
| resolveEntityId(builderParams: URLBuilderParams): string { | ||
| // Check if we're in workspace context | ||
| if (this.isWorkspaceContext()) { | ||
| return this.resolveEntityIdForWorkspace(builderParams); | ||
| } | ||
| return this.resolveEntityIdForApp(builderParams); | ||
| } | ||
| resolveEntityIdForWorkspace(builderParams: URLBuilderParams): string { | ||
| // Extract workspaceId from current URL if not provided | ||
| if (builderParams?.workspaceId) { | ||
| return builderParams.workspaceId; | ||
| } | ||
| const currentUrl = window.location.pathname; | ||
| const workspaceMatch = currentUrl.match(/^\/workspace\/([^\/]+)/); | ||
| return workspaceMatch ? workspaceMatch[1] : ""; | ||
| } | ||
Comment on lines +314 to +325 Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. 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 | ||
| /** | ||
| * @throws {URIError} | ||
| * @param builderParams | ||
| @@ -304,7 +338,15 @@ export class URLBuilder { | ||
| const entityId = this.resolveEntityId(builderParams); | ||
| // Handle workspace-specific URL generation | ||
| let basePath = this.generateBasePath(entityId, mode); | ||
| let suffixPath = suffix ? `/${suffix}` : ""; | ||
| if (this.isWorkspaceContext() && suffix?.startsWith("datasource/")) { | ||
| // For workspace datasource URLs, use singular /datasource path | ||
| basePath = `/workspace/${entityId}/datasource`; | ||
| suffixPath = `/${suffix.replace("datasource/", "")}`; | ||
| } | ||
| const queryParamsToPersist = fetchQueryParamsToPersist( | ||
| persistExistingParams, | ||
| @@ -320,8 +362,6 @@ export class URLBuilder { | ||
| const queryString = getQueryStringfromObject(modifiedQueryParams); | ||
| const hashPath = hash ? `#${hash}` : ""; | ||
| // hash fragment should be at the end of the href | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -15,6 +15,7 @@ import type { UpdateCanvasPayload } from "actions/pageActions"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const initialState: EditorReduxState = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| widgetConfigBuilt: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| initialized: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isWorkspaceEditorInitialized: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| loadingStates: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| publishing: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| publishingError: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @@ -65,6 +66,14 @@ export const handlers = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ReduxActionTypes.INITIALIZE_EDITOR_SUCCESS]: (state: EditorReduxState) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { ...state, initialized: true }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ReduxActionTypes.INITIALIZE_WORKSPACE_IDE]: (state: EditorReduxState) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { ...state, isWorkspaceEditorInitialized: false }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ReduxActionTypes.INITIALIZE_WORKSPACE_IDE_SUCCESS]: ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| state: EditorReduxState, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { ...state, isWorkspaceEditorInitialized: true }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines +69 to +76 Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. 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
Suggested change
🤖 Prompt for AI Agents | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ReduxActionTypes.UPDATE_PAGE_SUCCESS]: ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| state: EditorReduxState, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| action: ReduxAction<UpdatePageResponse>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @@ -318,6 +327,7 @@ const editorReducer = createReducer(initialState, handlers); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export interface EditorReduxState { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| widgetConfigBuilt: boolean; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| initialized: boolean; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isWorkspaceEditorInitialized: boolean; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pageWidgetId?: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| currentLayoutId?: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| currentPageName?: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.