chore: Debugger Split states (#31043)
## Description Creates local states for the debugger for Query Pane, Api Pane and JS Pane and separates it from the main Canvas Debugger state. This is done so that in Split pane, the states of Action Pane debugger can be different from the Canvas Debugger state. To keep handling the Fullscreen Debugger experience, a new hook `useDebuggerTriggerClick` is introduced which opens the correct debugger based on the IDE state. Also removes the Error and Logs from the Query / Api / JS Debuggers when in split screen mode for a cleaner debugging experience ##### This change removes the expectation of having a common debugger state that follows around as the user navigates in the IDE. Instead it create a new debugger state per entity item. The tests have been updated to reflect this #### PR fixes following issue(s) Fixes #30836 Fixes #30342 #### Media #### Type of change - Breaking change (fix or feature that would cause existing functionality to not work as expected) ## Testing #### How Has This Been Tested? - [ ] Manual - [ ] JUnit - [ ] Jest - [ ] Cypress > > #### Test Plan > Add Testsmith test cases links that relate to this PR > > #### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) > > > ## Checklist: #### Dev activity - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered - [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [ ] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed
This commit is contained in:
parent
5c5ae36275
commit
1d4198048c
|
|
@ -31,7 +31,6 @@ describe(
|
|||
debuggerHelper.ClicklogEntityLink();
|
||||
|
||||
agHelper.AssertElementVisibility(apiPage._nextCursorValue);
|
||||
debuggerHelper.CloseBottomBar();
|
||||
entityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: "Api1",
|
||||
entityType: entityItems.Api,
|
||||
|
|
@ -51,11 +50,9 @@ describe(
|
|||
apiPage.SelectPaneTab("Headers");
|
||||
EditorNavigation.ShowCanvas();
|
||||
debuggerHelper.AssertErrorCount(1);
|
||||
debuggerHelper.ClickDebuggerIcon();
|
||||
debuggerHelper.ClicklogEntityLink();
|
||||
|
||||
agHelper.AssertElementVisibility(apiPage._bodyValue(0));
|
||||
debuggerHelper.CloseBottomBar();
|
||||
entityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: "Api2",
|
||||
entityType: entityItems.Api,
|
||||
|
|
@ -69,12 +66,11 @@ describe(
|
|||
|
||||
apiPage.SelectPaneTab("Pagination");
|
||||
EditorNavigation.ShowCanvas();
|
||||
debuggerHelper.ClickDebuggerIcon();
|
||||
// The Debugger should already be open here as it was opened before
|
||||
debuggerHelper.ClickLogsTab();
|
||||
debuggerHelper.ClicklogEntityLink(true);
|
||||
|
||||
agHelper.AssertElementVisibility(dataSources._queryTimeout);
|
||||
debuggerHelper.CloseBottomBar();
|
||||
entityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: "Api3",
|
||||
entityType: entityItems.Api,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import * as _ from "../../../../support/Objects/ObjectsCore";
|
|||
import { PageType } from "../../../../support/Pages/DebuggerHelper";
|
||||
import EditorNavigation from "../../../../support/Pages/EditorNavigation";
|
||||
|
||||
describe("Entity bottom bar", () => {
|
||||
describe("Entity bottom bar", { tags: ["@tag.Debugger"] }, () => {
|
||||
it("1. Debugger should be closable", () => {
|
||||
//Verify if bottom bar is closed.
|
||||
_.debuggerHelper.AssertClosed();
|
||||
|
|
@ -32,17 +32,14 @@ describe("Entity bottom bar", () => {
|
|||
_.debuggerHelper.AssertSelectedTab("Response");
|
||||
//verify if bottom bar is closed on switching to canvas page.
|
||||
EditorNavigation.ShowCanvas();
|
||||
_.debuggerHelper.AssertSelectedTab("Errors");
|
||||
_.debuggerHelper.AssertClosed();
|
||||
});
|
||||
|
||||
it("3. Api bottom pane should be collapsable", () => {
|
||||
_.apiPage.CreateAndFillApi(
|
||||
_.dataManager.dsValues[_.dataManager.defaultEnviorment].mockApiUrl,
|
||||
);
|
||||
//Verify that the errors tab is still open.
|
||||
_.debuggerHelper.AssertSelectedTab("Errors");
|
||||
//Verify if bottom bar is closed on clicking close icon in API page.
|
||||
_.debuggerHelper.CloseBottomBar();
|
||||
//Verify that the errors tab is still closed.
|
||||
_.debuggerHelper.AssertClosed();
|
||||
//Verify if bottom bar opens on clicking debugger icon in api page.
|
||||
_.debuggerHelper.ClickDebuggerIcon();
|
||||
|
|
@ -60,12 +57,11 @@ describe("Entity bottom bar", () => {
|
|||
it("4. Bottom bar in Datasource", () => {
|
||||
//Verify if bottom bar remain open on shifting to create new datasource page.
|
||||
_.dataSources.NavigateToDSCreateNew();
|
||||
//Expecting errors tab to be closed as previous selected tab was response.
|
||||
//And response tab is not part of datasource page.
|
||||
//Expecting errors tab to be closed as this is now a datasource
|
||||
_.debuggerHelper.AssertClosed();
|
||||
//Verify if bottom bar opens on clicking debugger icon in datasource page.
|
||||
_.debuggerHelper.ClickDebuggerIcon();
|
||||
_.debuggerHelper.AssertClosed();
|
||||
_.debuggerHelper.AssertOpen(PageType.DataSources);
|
||||
});
|
||||
|
||||
it(
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ const generateTestLogString = () => {
|
|||
return logString;
|
||||
};
|
||||
|
||||
describe("Debugger logs", function () {
|
||||
describe("Debugger logs", { tags: ["@tag.Debugger"] }, function () {
|
||||
this.beforeEach(() => {
|
||||
logString = generateTestLogString();
|
||||
});
|
||||
|
|
@ -285,7 +285,8 @@ describe("Debugger logs", function () {
|
|||
});
|
||||
|
||||
EditorNavigation.SelectEntityByName("Page1", EntityType.Page);
|
||||
_.agHelper.GetNClick(_.locators._errorTab);
|
||||
_.agHelper.AssertElementVisibility(".t--debugger-count");
|
||||
_.debuggerHelper.ClickDebuggerIcon();
|
||||
|
||||
_.debuggerHelper.ClicklogEntityLink();
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants";
|
|||
import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants";
|
||||
import type { EventLocation } from "@appsmith/utils/analyticsUtilTypes";
|
||||
import type { SlashCommandPayload } from "entities/Action";
|
||||
import type { ApiPaneDebuggerState } from "@appsmith/reducers/uiReducers/apiPaneReducer";
|
||||
|
||||
export const changeApi = (
|
||||
id: string,
|
||||
|
|
@ -14,40 +15,6 @@ export const changeApi = (
|
|||
};
|
||||
};
|
||||
|
||||
export const initApiPane = (urlId?: string): ReduxAction<{ id?: string }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.INIT_API_PANE,
|
||||
payload: { id: urlId },
|
||||
};
|
||||
};
|
||||
|
||||
export const setCurrentCategory = (
|
||||
category: string,
|
||||
): ReduxAction<{ category: string }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_CURRENT_CATEGORY,
|
||||
payload: { category },
|
||||
};
|
||||
};
|
||||
|
||||
export const setLastUsedEditorPage = (
|
||||
path: string,
|
||||
): ReduxAction<{ path: string }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_LAST_USED_EDITOR_PAGE,
|
||||
payload: { path },
|
||||
};
|
||||
};
|
||||
|
||||
export const setLastSelectedPage = (
|
||||
selectedPageId: string,
|
||||
): ReduxAction<{ selectedPageId: string }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_LAST_SELECTED_PAGE_PAGE,
|
||||
payload: { selectedPageId },
|
||||
};
|
||||
};
|
||||
|
||||
export const createNewApiAction = (
|
||||
pageId: string,
|
||||
from: EventLocation,
|
||||
|
|
@ -109,3 +76,10 @@ export const setApiRightPaneSelectedTab: (
|
|||
type: ReduxActionTypes.SET_API_RIGHT_PANE_SELECTED_TAB,
|
||||
payload: { selectedTab: payload },
|
||||
});
|
||||
|
||||
export const setApiPaneDebuggerState = (
|
||||
payload: Partial<ApiPaneDebuggerState>,
|
||||
) => ({
|
||||
type: ReduxActionTypes.SET_API_PANE_DEBUGGER_STATE,
|
||||
payload,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants";
|
||||
import type { Log, Message, SourceEntity } from "entities/AppsmithConsole";
|
||||
import type { ENTITY_TYPE } from "@appsmith/entities/AppsmithConsole/utils";
|
||||
import type { DebuggerContext } from "reducers/uiReducers/debuggerReducer";
|
||||
import type {
|
||||
CanvasDebuggerState,
|
||||
DebuggerContext,
|
||||
} from "reducers/uiReducers/debuggerReducer";
|
||||
import type { EventName } from "@appsmith/utils/analyticsUtilTypes";
|
||||
import type { APP_MODE } from "entities/App";
|
||||
|
||||
|
|
@ -126,3 +129,12 @@ export const setDebuggerContext = (context: DebuggerContext) => {
|
|||
payload: { context },
|
||||
};
|
||||
};
|
||||
|
||||
export const setCanvasDebuggerState = (
|
||||
payload: Partial<CanvasDebuggerState>,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_CANVAS_DEBUGGER_STATE,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@ import type {
|
|||
SetFunctionPropertyPayload,
|
||||
} from "@appsmith/api/JSActionAPI";
|
||||
import type { EventLocation } from "@appsmith/utils/analyticsUtilTypes";
|
||||
import type { JSEditorTab } from "reducers/uiReducers/jsPaneReducer";
|
||||
import type {
|
||||
JSEditorTab,
|
||||
JSPaneDebuggerState,
|
||||
} from "reducers/uiReducers/jsPaneReducer";
|
||||
|
||||
export const createNewJSCollection = (
|
||||
pageId: string,
|
||||
|
|
@ -111,3 +114,10 @@ export const setJsPaneConfigSelectedTab: (
|
|||
type: ReduxActionTypes.SET_JS_PANE_CONFIG_SELECTED_TAB,
|
||||
payload: { selectedTab: payload },
|
||||
});
|
||||
|
||||
export const setJsPaneDebuggerState = (
|
||||
payload: Partial<JSPaneDebuggerState>,
|
||||
) => ({
|
||||
type: ReduxActionTypes.SET_JS_PANE_DEBUGGER_STATE,
|
||||
payload,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants";
|
||||
import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants";
|
||||
import type { Action } from "entities/Action";
|
||||
import type { QueryPaneDebuggerState } from "@appsmith/reducers/uiReducers/queryPaneReducer";
|
||||
|
||||
export interface ChangeQueryPayload {
|
||||
id: string;
|
||||
|
|
@ -26,3 +27,12 @@ export const setQueryPaneConfigSelectedTabIndex: (
|
|||
type: ReduxActionTypes.SET_QUERY_PANE_CONFIG_SELECTED_TAB,
|
||||
payload: { selectedTabIndex: payload },
|
||||
});
|
||||
|
||||
export const setQueryPaneDebuggerState = (
|
||||
payload: Partial<QueryPaneDebuggerState>,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_QUERY_PANE_DEBUGGER_STATE,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -463,7 +463,6 @@ const ActionTypes = {
|
|||
FETCH_ALL_PUBLISHED_PAGES: "FETCH_ALL_PUBLISHED_PAGES",
|
||||
CREATE_NEW_API_ACTION: "CREATE_NEW_API_ACTION",
|
||||
CREATE_NEW_QUERY_ACTION: "CREATE_NEW_QUERY_ACTION",
|
||||
SET_CURRENT_CATEGORY: "SET_CURRENT_CATEGORY",
|
||||
SET_LAST_USED_EDITOR_PAGE: "SET_LAST_USED_EDITOR_PAGE",
|
||||
SET_LAST_SELECTED_PAGE_PAGE: "SET_LAST_SELECTED_PAGE_PAGE",
|
||||
FETCH_PROVIDER_DETAILS_BY_PROVIDER_ID_INIT:
|
||||
|
|
@ -911,6 +910,10 @@ const ActionTypes = {
|
|||
END_CONSOLIDATED_PAGE_LOAD: "END_CONSOLIDATED_PAGE_LOAD",
|
||||
FETCH_ENVIRONMENT_SUCCESS: "FETCH_ENVIRONMENT_SUCCESS",
|
||||
SET_SHOW_CREATE_NEW_MODAL: "SET_SHOW_CREATE_NEW_MODAL",
|
||||
SET_QUERY_PANE_DEBUGGER_STATE: "SET_QUERY_PANE_DEBUGGER_STATE",
|
||||
SET_API_PANE_DEBUGGER_STATE: "SET_API_PANE_DEBUGGER_STATE",
|
||||
SET_JS_PANE_DEBUGGER_STATE: "SET_JS_PANE_DEBUGGER_STATE",
|
||||
SET_CANVAS_DEBUGGER_STATE: "SET_CANVAS_DEBUGGER_STATE",
|
||||
};
|
||||
|
||||
export const ReduxActionTypes = {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import {
|
||||
setApiPaneConfigSelectedTabIndex,
|
||||
setApiPaneDebuggerState,
|
||||
setApiRightPaneSelectedTab,
|
||||
} from "actions/apiPaneActions";
|
||||
import {
|
||||
|
|
@ -13,6 +14,7 @@ import {
|
|||
} from "actions/editorContextActions";
|
||||
import {
|
||||
getApiPaneConfigSelectedTabIndex,
|
||||
getApiPaneDebuggerState,
|
||||
getApiRightPaneSelectedTab,
|
||||
} from "selectors/apiPaneSelectors";
|
||||
import {
|
||||
|
|
@ -33,14 +35,20 @@ import {
|
|||
|
||||
import { setDatasourceViewMode } from "actions/datasourceActions";
|
||||
import { updateExplorerWidthAction } from "actions/explorerActions";
|
||||
import { setJsPaneConfigSelectedTab } from "actions/jsPaneActions";
|
||||
import {
|
||||
setJsPaneConfigSelectedTab,
|
||||
setJsPaneDebuggerState,
|
||||
} from "actions/jsPaneActions";
|
||||
import {
|
||||
setAllPropertySectionState,
|
||||
setFocusablePropertyPaneField,
|
||||
setPropertyPaneWidthAction,
|
||||
setSelectedPropertyPanels,
|
||||
} from "actions/propertyPaneActions";
|
||||
import { setQueryPaneConfigSelectedTabIndex } from "actions/queryPaneActions";
|
||||
import {
|
||||
setQueryPaneConfigSelectedTabIndex,
|
||||
setQueryPaneDebuggerState,
|
||||
} from "actions/queryPaneActions";
|
||||
import { selectWidgetInitAction } from "actions/widgetSelectionActions";
|
||||
import {
|
||||
DEFAULT_ENTITY_EXPLORER_WIDTH,
|
||||
|
|
@ -53,6 +61,7 @@ import { getExplorerWidth } from "selectors/explorerSelector";
|
|||
import {
|
||||
getFirstJSObject,
|
||||
getJSPaneConfigSelectedTab,
|
||||
getJsPaneDebuggerState,
|
||||
} from "selectors/jsPaneSelectors";
|
||||
import {
|
||||
getFocusablePropertyPaneField,
|
||||
|
|
@ -62,6 +71,7 @@ import {
|
|||
import {
|
||||
getFirstQuery,
|
||||
getQueryPaneConfigSelectedTabIndex,
|
||||
getQueryPaneDebuggerState,
|
||||
} from "selectors/queryPaneSelectors";
|
||||
import { getDebuggerContext } from "selectors/debuggerSelectors";
|
||||
import { setDebuggerContext } from "actions/debuggerActions";
|
||||
|
|
@ -83,6 +93,7 @@ import { FocusElement, FocusElementConfigType } from "navigation/FocusElements";
|
|||
import type { FocusElementsConfigList } from "sagas/FocusRetentionSaga";
|
||||
import { getJSTabs, getQueryTabs } from "selectors/ideSelectors";
|
||||
import { setJSTabs, setQueryTabs } from "actions/ideActions";
|
||||
import { ActionExecutionResizerHeight } from "pages/Editor/APIEditor/constants";
|
||||
|
||||
export const AppIDEFocusElements: FocusElementsConfigList = {
|
||||
[FocusEntity.DATASOURCE_LIST]: [
|
||||
|
|
@ -117,6 +128,17 @@ export const AppIDEFocusElements: FocusElementsConfigList = {
|
|||
setter: setJsPaneConfigSelectedTab,
|
||||
defaultValue: JSEditorTab.CODE,
|
||||
},
|
||||
{
|
||||
type: FocusElementConfigType.Redux,
|
||||
name: FocusElement.JSDebugger,
|
||||
selector: getJsPaneDebuggerState,
|
||||
setter: setJsPaneDebuggerState,
|
||||
defaultValue: {
|
||||
open: false,
|
||||
responseTabHeight: ActionExecutionResizerHeight,
|
||||
selectedTab: undefined,
|
||||
},
|
||||
},
|
||||
],
|
||||
[FocusEntity.QUERY]: [
|
||||
{
|
||||
|
|
@ -156,6 +178,28 @@ export const AppIDEFocusElements: FocusElementsConfigList = {
|
|||
selector: getApiRightPaneSelectedTab,
|
||||
setter: setApiRightPaneSelectedTab,
|
||||
},
|
||||
{
|
||||
type: FocusElementConfigType.Redux,
|
||||
name: FocusElement.QueryDebugger,
|
||||
selector: getQueryPaneDebuggerState,
|
||||
setter: setQueryPaneDebuggerState,
|
||||
defaultValue: {
|
||||
open: false,
|
||||
responseTabHeight: ActionExecutionResizerHeight,
|
||||
selectedTab: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: FocusElementConfigType.Redux,
|
||||
name: FocusElement.ApiDebugger,
|
||||
selector: getApiPaneDebuggerState,
|
||||
setter: setApiPaneDebuggerState,
|
||||
defaultValue: {
|
||||
open: false,
|
||||
responseTabHeight: ActionExecutionResizerHeight,
|
||||
selectedTab: undefined,
|
||||
},
|
||||
},
|
||||
],
|
||||
[FocusEntity.PROPERTY_PANE]: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,32 +6,38 @@ import {
|
|||
} from "@appsmith/constants/ReduxActionConstants";
|
||||
import type { Action } from "entities/Action";
|
||||
import type { UpdateActionPropertyActionPayload } from "actions/pluginActionActions";
|
||||
import { ActionExecutionResizerHeight } from "pages/Editor/APIEditor/constants";
|
||||
|
||||
export const initialState: ApiPaneReduxState = {
|
||||
isCreating: false,
|
||||
isFetching: false,
|
||||
isRunning: {},
|
||||
isSaving: {},
|
||||
isDeleting: {},
|
||||
isDirty: {},
|
||||
currentCategory: "",
|
||||
extraformData: {},
|
||||
selectedConfigTabIndex: 0,
|
||||
selectedResponseTab: "",
|
||||
debugger: {
|
||||
open: false,
|
||||
responseTabHeight: ActionExecutionResizerHeight,
|
||||
},
|
||||
};
|
||||
|
||||
export interface ApiPaneDebuggerState {
|
||||
open: boolean;
|
||||
responseTabHeight: number;
|
||||
selectedTab?: string;
|
||||
}
|
||||
|
||||
export interface ApiPaneReduxState {
|
||||
isCreating: boolean; // RR
|
||||
isFetching: boolean; // RR
|
||||
isRunning: Record<string, boolean>;
|
||||
isSaving: Record<string, boolean>; // RN
|
||||
isDeleting: Record<string, boolean>;
|
||||
isDirty: Record<string, boolean>;
|
||||
currentCategory: string;
|
||||
extraformData: Record<string, any>;
|
||||
selectedConfigTabIndex: number;
|
||||
selectedResponseTab: string;
|
||||
selectedRightPaneTab?: string;
|
||||
debugger: ApiPaneDebuggerState;
|
||||
}
|
||||
|
||||
export const handlers = {
|
||||
|
|
@ -74,6 +80,10 @@ export const handlers = {
|
|||
...state.isRunning,
|
||||
[action.payload.id]: true,
|
||||
},
|
||||
debugger: {
|
||||
...state.debugger,
|
||||
open: true,
|
||||
},
|
||||
}),
|
||||
[ReduxActionTypes.RUN_ACTION_SUCCESS]: (
|
||||
state: ApiPaneReduxState,
|
||||
|
|
@ -183,14 +193,6 @@ export const handlers = {
|
|||
},
|
||||
}),
|
||||
|
||||
[ReduxActionTypes.SET_CURRENT_CATEGORY]: (
|
||||
state: ApiPaneReduxState,
|
||||
action: ReduxAction<{ category: string }>,
|
||||
) => ({
|
||||
...state,
|
||||
currentCategory: action.payload.category,
|
||||
}),
|
||||
|
||||
/**
|
||||
* This redux action sets the extraformData field for an action. This is used to select the
|
||||
* appropriate body type tab selection in the Rest API plugin based on the content-type.
|
||||
|
|
@ -233,6 +235,18 @@ export const handlers = {
|
|||
selectedRightPaneTab: selectedTab,
|
||||
};
|
||||
},
|
||||
[ReduxActionTypes.SET_API_PANE_DEBUGGER_STATE]: (
|
||||
state: ApiPaneReduxState,
|
||||
action: ReduxAction<Partial<ApiPaneDebuggerState>>,
|
||||
) => {
|
||||
return {
|
||||
...state,
|
||||
debugger: {
|
||||
...state.debugger,
|
||||
...action.payload,
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
const apiPaneReducer = createReducer(initialState, handlers);
|
||||
|
|
|
|||
|
|
@ -8,29 +8,33 @@ import { omit } from "lodash";
|
|||
import type { Action } from "entities/Action";
|
||||
import type { ActionResponse } from "api/ActionAPI";
|
||||
import { ActionExecutionResizerHeight } from "pages/Editor/APIEditor/constants";
|
||||
import { DEBUGGER_TAB_KEYS } from "../../../components/editorComponents/Debugger/helpers";
|
||||
|
||||
export const initialState: QueryPaneReduxState = {
|
||||
isFetching: false,
|
||||
isCreating: false,
|
||||
isRunning: {},
|
||||
isSaving: {},
|
||||
isDeleting: {},
|
||||
runErrorMessage: {},
|
||||
lastUsed: "", // NR
|
||||
responseTabHeight: ActionExecutionResizerHeight,
|
||||
debugger: {
|
||||
open: false,
|
||||
responseTabHeight: ActionExecutionResizerHeight,
|
||||
},
|
||||
selectedConfigTabIndex: "0",
|
||||
};
|
||||
|
||||
export interface QueryPaneDebuggerState {
|
||||
open: boolean;
|
||||
responseTabHeight: number;
|
||||
selectedTab?: string;
|
||||
}
|
||||
|
||||
export interface QueryPaneReduxState {
|
||||
isFetching: boolean; // RR
|
||||
isRunning: Record<string, boolean>;
|
||||
isSaving: Record<string, boolean>; // RR
|
||||
isDeleting: Record<string, boolean>;
|
||||
runErrorMessage: Record<string, string>;
|
||||
lastUsed: string; // NR
|
||||
isCreating: boolean; // RR
|
||||
selectedConfigTabIndex: string;
|
||||
responseTabHeight: number;
|
||||
debugger: QueryPaneDebuggerState;
|
||||
}
|
||||
|
||||
export const handlers = {
|
||||
|
|
@ -122,13 +126,18 @@ export const handlers = {
|
|||
[ReduxActionTypes.RUN_ACTION_REQUEST]: (
|
||||
state: any,
|
||||
action: ReduxAction<{ id: string }>,
|
||||
) => {
|
||||
): QueryPaneReduxState => {
|
||||
return {
|
||||
...state,
|
||||
isRunning: {
|
||||
...state.isRunning,
|
||||
[action.payload.id]: true,
|
||||
},
|
||||
debugger: {
|
||||
...state.debugger,
|
||||
selectedTab: DEBUGGER_TAB_KEYS.RESPONSE_TAB,
|
||||
open: true,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
|
|
@ -187,6 +196,18 @@ export const handlers = {
|
|||
selectedConfigTabIndex: selectedTabIndex,
|
||||
};
|
||||
},
|
||||
[ReduxActionTypes.SET_QUERY_PANE_DEBUGGER_STATE]: (
|
||||
state: QueryPaneReduxState,
|
||||
action: ReduxAction<Partial<QueryPaneDebuggerState>>,
|
||||
) => {
|
||||
return {
|
||||
...state,
|
||||
debugger: {
|
||||
...state.debugger,
|
||||
...action.payload,
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
const queryPaneReducer = createReducer(initialState, handlers);
|
||||
|
|
|
|||
|
|
@ -13,11 +13,10 @@ import { isArray, isEmpty, isString } from "lodash";
|
|||
import {
|
||||
CHECK_REQUEST_BODY,
|
||||
createMessage,
|
||||
DEBUGGER_ERRORS,
|
||||
DEBUGGER_LOGS,
|
||||
EMPTY_RESPONSE_FIRST_HALF,
|
||||
EMPTY_RESPONSE_LAST_HALF,
|
||||
INSPECT_ENTITY,
|
||||
DEBUGGER_ERRORS,
|
||||
} from "@appsmith/constants/messages";
|
||||
import { Text as BlueprintText } from "@blueprintjs/core";
|
||||
import { EditorTheme } from "./CodeEditor/EditorConfig";
|
||||
|
|
@ -26,26 +25,17 @@ import DebuggerLogs from "./Debugger/DebuggerLogs";
|
|||
import ErrorLogs from "./Debugger/Errors";
|
||||
import Resizer, { ResizerCSS } from "./Debugger/Resizer";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
import EntityDeps from "./Debugger/EntityDependecies";
|
||||
import { Classes, TAB_MIN_HEIGHT, Text, TextType } from "design-system-old";
|
||||
import { Button, Callout, Flex, SegmentedControl } from "design-system";
|
||||
import type { BottomTab } from "./EntityBottomTabs";
|
||||
import EntityBottomTabs from "./EntityBottomTabs";
|
||||
import { DEBUGGER_TAB_KEYS } from "./Debugger/helpers";
|
||||
import Table from "pages/Editor/QueryEditor/Table";
|
||||
import { API_RESPONSE_TYPE_OPTIONS } from "constants/ApiEditorConstants/CommonApiConstants";
|
||||
import { setActionResponseDisplayFormat } from "actions/pluginActionActions";
|
||||
import { isHtml } from "./utils";
|
||||
import {
|
||||
getDebuggerSelectedTab,
|
||||
getErrorCount,
|
||||
getResponsePaneHeight,
|
||||
} from "selectors/debuggerSelectors";
|
||||
import { getErrorCount } from "selectors/debuggerSelectors";
|
||||
import { ActionExecutionResizerHeight } from "pages/Editor/APIEditor/constants";
|
||||
import {
|
||||
setDebuggerSelectedTab,
|
||||
setResponsePaneHeight,
|
||||
showDebugger,
|
||||
} from "actions/debuggerActions";
|
||||
import LogAdditionalInfo from "./Debugger/ErrorLogs/components/LogAdditionalInfo";
|
||||
import {
|
||||
JsonWrapper,
|
||||
|
|
@ -59,6 +49,10 @@ import ActionExecutionInProgressView from "./ActionExecutionInProgressView";
|
|||
import { CloseDebugger } from "./Debugger/DebuggerTabs";
|
||||
import { EMPTY_RESPONSE } from "./emptyResponse";
|
||||
import BindDataButton from "../../pages/Editor/QueryEditor/BindDataButton";
|
||||
import { setApiPaneDebuggerState } from "actions/apiPaneActions";
|
||||
import { getApiPaneDebuggerState } from "selectors/apiPaneSelectors";
|
||||
import { getIDEViewMode } from "selectors/ideSelectors";
|
||||
import { EditorViewMode } from "@appsmith/entities/IDE/constants";
|
||||
|
||||
interface TextStyleProps {
|
||||
accent: "primary" | "secondary" | "error";
|
||||
|
|
@ -312,12 +306,19 @@ function ApiResponseView(props: Props) {
|
|||
const panelRef: RefObject<HTMLDivElement> = useRef(null);
|
||||
const dispatch = useDispatch();
|
||||
const errorCount = useSelector(getErrorCount);
|
||||
const { open, responseTabHeight, selectedTab } = useSelector(
|
||||
getApiPaneDebuggerState,
|
||||
);
|
||||
|
||||
const ideViewMode = useSelector(getIDEViewMode);
|
||||
|
||||
const onDebugClick = useCallback(() => {
|
||||
AnalyticsUtil.logEvent("OPEN_DEBUGGER", {
|
||||
source: "API",
|
||||
});
|
||||
dispatch(setDebuggerSelectedTab(DEBUGGER_TAB_KEYS.ERROR_TAB));
|
||||
dispatch(
|
||||
setApiPaneDebuggerState({ selectedTab: DEBUGGER_TAB_KEYS.ERROR_TAB }),
|
||||
);
|
||||
}, []);
|
||||
|
||||
const onRunClick = () => {
|
||||
|
|
@ -380,7 +381,7 @@ function ApiResponseView(props: Props) {
|
|||
panelComponent: responseTabComponent(
|
||||
dataType.key,
|
||||
actionResponse?.body,
|
||||
responsePaneHeight,
|
||||
responseTabHeight,
|
||||
),
|
||||
};
|
||||
});
|
||||
|
|
@ -401,8 +402,6 @@ function ApiResponseView(props: Props) {
|
|||
(dataType) => dataType.title === responseDisplayFormat?.title,
|
||||
);
|
||||
|
||||
// get the selected tab in the response pane.
|
||||
const selectedResponseTab = useSelector(getDebuggerSelectedTab);
|
||||
// update the selected tab in the response pane.
|
||||
const updateSelectedResponseTab = useCallback((tabKey: string) => {
|
||||
if (tabKey === DEBUGGER_TAB_KEYS.ERROR_TAB) {
|
||||
|
|
@ -410,13 +409,12 @@ function ApiResponseView(props: Props) {
|
|||
source: "API_PANE",
|
||||
});
|
||||
}
|
||||
dispatch(setDebuggerSelectedTab(tabKey));
|
||||
dispatch(setApiPaneDebuggerState({ selectedTab: tabKey }));
|
||||
}, []);
|
||||
// get the height of the response pane.
|
||||
const responsePaneHeight = useSelector(getResponsePaneHeight);
|
||||
|
||||
// update the height of the response pane on resize.
|
||||
const updateResponsePaneHeight = useCallback((height: number) => {
|
||||
dispatch(setResponsePaneHeight(height));
|
||||
dispatch(setApiPaneDebuggerState({ responseTabHeight: height }));
|
||||
}, []);
|
||||
|
||||
// get request timestamp formatted to human readable format.
|
||||
|
|
@ -427,7 +425,7 @@ function ApiResponseView(props: Props) {
|
|||
name: currentActionConfig ? currentActionConfig.name : "API",
|
||||
id: currentActionConfig?.id || "",
|
||||
};
|
||||
const tabs = [
|
||||
const tabs: BottomTab[] = [
|
||||
{
|
||||
key: "response",
|
||||
title: "Response",
|
||||
|
|
@ -526,7 +524,7 @@ function ApiResponseView(props: Props) {
|
|||
{responseTabComponent(
|
||||
selectedControl || segmentedControlOptions[0]?.value,
|
||||
actionResponse?.body,
|
||||
responsePaneHeight,
|
||||
responseTabHeight,
|
||||
)}
|
||||
</SegmentedControlContainer>
|
||||
) : null}
|
||||
|
|
@ -579,32 +577,34 @@ function ApiResponseView(props: Props) {
|
|||
</ResponseTabWrapper>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: DEBUGGER_TAB_KEYS.ERROR_TAB,
|
||||
title: createMessage(DEBUGGER_ERRORS),
|
||||
count: errorCount,
|
||||
panelComponent: <ErrorLogs />,
|
||||
},
|
||||
{
|
||||
key: DEBUGGER_TAB_KEYS.LOGS_TAB,
|
||||
title: createMessage(DEBUGGER_LOGS),
|
||||
panelComponent: <DebuggerLogs searchQuery={props.apiName} />,
|
||||
},
|
||||
{
|
||||
key: DEBUGGER_TAB_KEYS.INSPECT_TAB,
|
||||
title: createMessage(INSPECT_ENTITY),
|
||||
panelComponent: <EntityDeps />,
|
||||
},
|
||||
];
|
||||
|
||||
if (ideViewMode === EditorViewMode.FullScreen) {
|
||||
tabs.push(
|
||||
{
|
||||
key: DEBUGGER_TAB_KEYS.ERROR_TAB,
|
||||
title: createMessage(DEBUGGER_ERRORS),
|
||||
count: errorCount,
|
||||
panelComponent: <ErrorLogs />,
|
||||
},
|
||||
{
|
||||
key: DEBUGGER_TAB_KEYS.LOGS_TAB,
|
||||
title: createMessage(DEBUGGER_LOGS),
|
||||
panelComponent: <DebuggerLogs searchQuery={props.apiName} />,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// close the debugger
|
||||
//TODO: move this to a common place
|
||||
const onClose = () => dispatch(showDebugger(false));
|
||||
const onClose = () => dispatch(setApiPaneDebuggerState({ open: false }));
|
||||
|
||||
if (!open) return null;
|
||||
|
||||
return (
|
||||
<ResponseContainer className="t--api-bottom-pane-container" ref={panelRef}>
|
||||
<Resizer
|
||||
initialHeight={responsePaneHeight}
|
||||
initialHeight={responseTabHeight}
|
||||
onResizeComplete={(height: number) => {
|
||||
updateResponsePaneHeight(height);
|
||||
}}
|
||||
|
|
@ -659,7 +659,7 @@ function ApiResponseView(props: Props) {
|
|||
<EntityBottomTabs
|
||||
expandedHeight={`${ActionExecutionResizerHeight}px`}
|
||||
onSelect={updateSelectedResponseTab}
|
||||
selectedTabKey={selectedResponseTab}
|
||||
selectedTabKey={selectedTab || ""}
|
||||
tabs={tabs}
|
||||
/>
|
||||
<CloseDebugger
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ import {
|
|||
getDatasourceStructureById,
|
||||
getIsFetchingDatasourceStructure,
|
||||
} from "@appsmith/selectors/entitiesSelector";
|
||||
import { getResponsePaneHeight } from "selectors/debuggerSelectors";
|
||||
import DatasourceField from "pages/Editor/DatasourceInfo/DatasourceField";
|
||||
import { find } from "lodash";
|
||||
import type { AppState } from "@appsmith/reducers";
|
||||
import RenderInterimDataState from "pages/Editor/DatasourceInfo/RenderInterimDataState";
|
||||
import { getQueryPaneDebuggerState } from "selectors/queryPaneSelectors";
|
||||
|
||||
interface Props {
|
||||
datasourceId: string;
|
||||
|
|
@ -24,7 +24,7 @@ const Schema = (props: Props) => {
|
|||
const datasourceStructure = useSelector((state) =>
|
||||
getDatasourceStructureById(state, props.datasourceId),
|
||||
);
|
||||
const responsePaneHeight = useSelector(getResponsePaneHeight);
|
||||
const { responseTabHeight } = useSelector(getQueryPaneDebuggerState);
|
||||
const [selectedTable, setSelectedTable] = useState<string>();
|
||||
|
||||
const selectedTableItems = find(datasourceStructure?.tables, [
|
||||
|
|
@ -69,7 +69,7 @@ const Schema = (props: Props) => {
|
|||
<Flex
|
||||
flexDirection="row"
|
||||
gap="spaces-2"
|
||||
height={`${responsePaneHeight - 45}px`}
|
||||
height={`${responseTabHeight - 45}px`}
|
||||
maxWidth="70rem"
|
||||
overflow="hidden"
|
||||
>
|
||||
|
|
@ -94,7 +94,7 @@ const Schema = (props: Props) => {
|
|||
borderLeft="1px solid var(--ads-v2-color-border)"
|
||||
flex="1"
|
||||
flexDirection="column"
|
||||
height={`${responsePaneHeight - 45}px`}
|
||||
height={`${responseTabHeight - 45}px`}
|
||||
justifyContent={
|
||||
isLoading || columns.length === 0 ? "center" : "flex-start"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
import { useLocation } from "react-router";
|
||||
import { DEBUGGER_TAB_KEYS } from "../helpers";
|
||||
import { setCanvasDebuggerState } from "actions/debuggerActions";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
import type { FocusEntityInfo } from "navigation/FocusEntity";
|
||||
import { FocusEntity, identifyEntityFromPath } from "navigation/FocusEntity";
|
||||
import { setJsPaneDebuggerState } from "actions/jsPaneActions";
|
||||
import { setApiPaneDebuggerState } from "actions/apiPaneActions";
|
||||
import { setQueryPaneDebuggerState } from "actions/queryPaneActions";
|
||||
import { getJsPaneDebuggerState } from "selectors/jsPaneSelectors";
|
||||
import { getApiPaneDebuggerState } from "selectors/apiPaneSelectors";
|
||||
import { getQueryPaneDebuggerState } from "selectors/queryPaneSelectors";
|
||||
import { getCanvasDebuggerState } from "selectors/debuggerSelectors";
|
||||
import { getIDEViewMode } from "selectors/ideSelectors";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { EditorViewMode } from "@appsmith/entities/IDE/constants";
|
||||
import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants";
|
||||
import type { CanvasDebuggerState } from "reducers/uiReducers/debuggerReducer";
|
||||
import type { AppState } from "@appsmith/reducers";
|
||||
|
||||
interface Config {
|
||||
set: (
|
||||
payload: Partial<CanvasDebuggerState>,
|
||||
) => ReduxAction<Partial<CanvasDebuggerState>>;
|
||||
get: (state: AppState) => CanvasDebuggerState;
|
||||
}
|
||||
|
||||
const canvasDebuggerConfig: Config = {
|
||||
set: setCanvasDebuggerState,
|
||||
get: getCanvasDebuggerState,
|
||||
};
|
||||
|
||||
const queryDebuggerConfig: Config = {
|
||||
set: setQueryPaneDebuggerState,
|
||||
get: getQueryPaneDebuggerState,
|
||||
};
|
||||
|
||||
const getConfig = (focusInfo: FocusEntityInfo): Config => {
|
||||
switch (focusInfo.entity) {
|
||||
case FocusEntity.QUERY:
|
||||
if (focusInfo.params.apiId) {
|
||||
if (focusInfo.params.pluginPackageName) {
|
||||
return queryDebuggerConfig;
|
||||
}
|
||||
return {
|
||||
set: setApiPaneDebuggerState,
|
||||
get: getApiPaneDebuggerState,
|
||||
};
|
||||
}
|
||||
return queryDebuggerConfig;
|
||||
case FocusEntity.JS_OBJECT:
|
||||
return {
|
||||
set: setJsPaneDebuggerState,
|
||||
get: getJsPaneDebuggerState,
|
||||
};
|
||||
default:
|
||||
return canvasDebuggerConfig;
|
||||
}
|
||||
};
|
||||
|
||||
const useDebuggerTriggerClick = () => {
|
||||
const location = useLocation();
|
||||
const currentFocus = identifyEntityFromPath(location.pathname);
|
||||
const ideState = useSelector(getIDEViewMode);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const config =
|
||||
ideState === EditorViewMode.FullScreen
|
||||
? getConfig(currentFocus)
|
||||
: canvasDebuggerConfig;
|
||||
|
||||
const state = useSelector(config.get);
|
||||
return () => {
|
||||
// If debugger is already open and selected tab is error tab then we will close debugger.
|
||||
if (state.open && state.selectedTab === DEBUGGER_TAB_KEYS.ERROR_TAB) {
|
||||
dispatch(config.set({ open: false }));
|
||||
} else {
|
||||
// If debugger is not open then we will open debugger and show error tab.
|
||||
if (!state.open) {
|
||||
dispatch(
|
||||
config.set({ open: true, selectedTab: DEBUGGER_TAB_KEYS.ERROR_TAB }),
|
||||
);
|
||||
}
|
||||
// Select error tab if debugger is open and selected tab is not error tab.
|
||||
// And also when we are opening debugger.
|
||||
dispatch(config.set({ selectedTab: DEBUGGER_TAB_KEYS.ERROR_TAB }));
|
||||
}
|
||||
if (!state.open) {
|
||||
AnalyticsUtil.logEvent("OPEN_DEBUGGER", {
|
||||
source: "TRIGGER",
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default useDebuggerTriggerClick;
|
||||
|
|
@ -1,20 +1,10 @@
|
|||
import React, { useEffect } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import DebuggerTabs from "./DebuggerTabs";
|
||||
import {
|
||||
setDebuggerSelectedTab,
|
||||
setErrorCount,
|
||||
showDebugger as showDebuggerAction,
|
||||
} from "actions/debuggerActions";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
import { stopEventPropagation } from "utils/AppsmithUtils";
|
||||
import {
|
||||
getDebuggerSelectedTab,
|
||||
getMessageCount,
|
||||
showDebuggerFlag,
|
||||
} from "selectors/debuggerSelectors";
|
||||
import { DEBUGGER_TAB_KEYS } from "./helpers";
|
||||
import { setErrorCount } from "actions/debuggerActions";
|
||||
import { getMessageCount, showDebuggerFlag } from "selectors/debuggerSelectors";
|
||||
import { Button, Tooltip } from "design-system";
|
||||
import useDebuggerTriggerClick from "./hooks/useDebuggerTriggerClick";
|
||||
|
||||
function Debugger() {
|
||||
// Debugger render flag
|
||||
|
|
@ -25,33 +15,13 @@ function Debugger() {
|
|||
|
||||
export function DebuggerTrigger() {
|
||||
const dispatch = useDispatch();
|
||||
const showDebugger = useSelector(showDebuggerFlag);
|
||||
const selectedTab = useSelector(getDebuggerSelectedTab);
|
||||
const messageCounters = useSelector(getMessageCount);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(setErrorCount(messageCounters.errors));
|
||||
});
|
||||
|
||||
const onClick = (e: any) => {
|
||||
// If debugger is already open and selected tab is error tab then we will close debugger.
|
||||
if (showDebugger && selectedTab === DEBUGGER_TAB_KEYS.ERROR_TAB) {
|
||||
dispatch(showDebuggerAction(false));
|
||||
} else {
|
||||
// If debugger is not open then we will open debugger and show error tab.
|
||||
if (!showDebugger) {
|
||||
dispatch(showDebuggerAction(true));
|
||||
}
|
||||
// Select error tab if debugger is open and selected tab is not error tab.
|
||||
// And also when we are opening debugger.
|
||||
dispatch(setDebuggerSelectedTab(DEBUGGER_TAB_KEYS.ERROR_TAB));
|
||||
}
|
||||
if (!showDebugger)
|
||||
AnalyticsUtil.logEvent("OPEN_DEBUGGER", {
|
||||
source: "CANVAS",
|
||||
});
|
||||
stopEventPropagation(e);
|
||||
};
|
||||
const onClick = useDebuggerTriggerClick();
|
||||
|
||||
//tooltip will always show error count as we are opening error tab on click of debugger.
|
||||
const tooltipContent =
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { RefObject } from "react";
|
||||
import React, { useEffect, useRef, useCallback, useState } from "react";
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { connect, useDispatch, useSelector } from "react-redux";
|
||||
import type { RouteComponentProps } from "react-router";
|
||||
import { withRouter } from "react-router";
|
||||
|
|
@ -9,15 +9,14 @@ import type { AppState } from "@appsmith/reducers";
|
|||
import type { JSEditorRouteParams } from "constants/routes";
|
||||
import {
|
||||
createMessage,
|
||||
DEBUGGER_LOGS,
|
||||
DEBUGGER_ERRORS,
|
||||
DEBUGGER_LOGS,
|
||||
EXECUTING_FUNCTION,
|
||||
NO_JS_FUNCTION_RETURN_VALUE,
|
||||
UPDATING_JS_COLLECTION,
|
||||
} from "@appsmith/constants/messages";
|
||||
import type { EditorTheme } from "./CodeEditor/EditorConfig";
|
||||
import DebuggerLogs from "./Debugger/DebuggerLogs";
|
||||
import ErrorLogs from "./Debugger/Errors";
|
||||
import Resizer, { ResizerCSS } from "./Debugger/Resizer";
|
||||
import type { JSAction } from "entities/JSCollection";
|
||||
import ReadOnlyEditor from "components/editorComponents/ReadOnlyEditor";
|
||||
|
|
@ -26,22 +25,14 @@ import LoadingOverlayScreen from "components/editorComponents/LoadingOverlayScre
|
|||
import type { JSCollectionData } from "@appsmith/reducers/entityReducers/jsActionsReducer";
|
||||
import type { EvaluationError } from "utils/DynamicBindingUtils";
|
||||
import { DEBUGGER_TAB_KEYS } from "./Debugger/helpers";
|
||||
import type { BottomTab } from "./EntityBottomTabs";
|
||||
import EntityBottomTabs from "./EntityBottomTabs";
|
||||
import { TAB_MIN_HEIGHT } from "design-system-old";
|
||||
import { CodeEditorWithGutterStyles } from "pages/Editor/JSEditor/constants";
|
||||
import { getIsSavingEntity } from "selectors/editorSelectors";
|
||||
import { getJSResponseViewState } from "./utils";
|
||||
import {
|
||||
getDebuggerSelectedTab,
|
||||
getFilteredErrors,
|
||||
getResponsePaneHeight,
|
||||
} from "selectors/debuggerSelectors";
|
||||
import { getFilteredErrors } from "selectors/debuggerSelectors";
|
||||
import { ActionExecutionResizerHeight } from "pages/Editor/APIEditor/constants";
|
||||
import {
|
||||
setDebuggerSelectedTab,
|
||||
setResponsePaneHeight,
|
||||
showDebugger,
|
||||
} from "actions/debuggerActions";
|
||||
import {
|
||||
NoResponse,
|
||||
ResponseTabErrorContainer,
|
||||
|
|
@ -52,6 +43,11 @@ import LOG_TYPE from "entities/AppsmithConsole/logtype";
|
|||
import type { SourceEntity, Log } from "entities/AppsmithConsole";
|
||||
import { ENTITY_TYPE } from "@appsmith/entities/AppsmithConsole/utils";
|
||||
import { CloseDebugger } from "./Debugger/DebuggerTabs";
|
||||
import { getJsPaneDebuggerState } from "selectors/jsPaneSelectors";
|
||||
import { setJsPaneDebuggerState } from "actions/jsPaneActions";
|
||||
import { getIDEViewMode } from "selectors/ideSelectors";
|
||||
import { EditorViewMode } from "@appsmith/entities/IDE/constants";
|
||||
import ErrorLogs from "./Debugger/Errors";
|
||||
|
||||
const ResponseContainer = styled.div`
|
||||
${ResizerCSS};
|
||||
|
|
@ -210,7 +206,10 @@ function JSResponseView(props: Props) {
|
|||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
const tabs = [
|
||||
|
||||
const ideViewMode = useSelector(getIDEViewMode);
|
||||
|
||||
const tabs: BottomTab[] = [
|
||||
{
|
||||
key: "response",
|
||||
title: "Response",
|
||||
|
|
@ -279,12 +278,6 @@ function JSResponseView(props: Props) {
|
|||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: DEBUGGER_TAB_KEYS.ERROR_TAB,
|
||||
title: createMessage(DEBUGGER_ERRORS),
|
||||
count: errorCount,
|
||||
panelComponent: <ErrorLogs />,
|
||||
},
|
||||
{
|
||||
key: DEBUGGER_TAB_KEYS.LOGS_TAB,
|
||||
title: createMessage(DEBUGGER_LOGS),
|
||||
|
|
@ -292,24 +285,34 @@ function JSResponseView(props: Props) {
|
|||
},
|
||||
];
|
||||
|
||||
if (ideViewMode === EditorViewMode.FullScreen) {
|
||||
tabs.push({
|
||||
key: DEBUGGER_TAB_KEYS.ERROR_TAB,
|
||||
title: createMessage(DEBUGGER_ERRORS),
|
||||
count: errorCount,
|
||||
panelComponent: <ErrorLogs />,
|
||||
});
|
||||
}
|
||||
|
||||
// get the selected tab from the store.
|
||||
const selectedResponseTab = useSelector(getDebuggerSelectedTab);
|
||||
const { open, responseTabHeight, selectedTab } = useSelector(
|
||||
getJsPaneDebuggerState,
|
||||
);
|
||||
|
||||
// set the selected tab in the store.
|
||||
const setSelectedResponseTab = useCallback((selectedTab: string) => {
|
||||
dispatch(setDebuggerSelectedTab(selectedTab));
|
||||
dispatch(setJsPaneDebuggerState({ selectedTab }));
|
||||
}, []);
|
||||
// get the height of the response pane.
|
||||
const responseTabHeight = useSelector(getResponsePaneHeight);
|
||||
// set the height of the response pane on resize.
|
||||
const setResponseHeight = useCallback((height: number) => {
|
||||
dispatch(setResponsePaneHeight(height));
|
||||
dispatch(setJsPaneDebuggerState({ responseTabHeight: height }));
|
||||
}, []);
|
||||
|
||||
// close the debugger
|
||||
const onClose = () => dispatch(showDebugger(false));
|
||||
const onClose = () => dispatch(setJsPaneDebuggerState({ open: false }));
|
||||
|
||||
// Do not render if header tab is selected in the bottom bar.
|
||||
return !(selectedResponseTab === DEBUGGER_TAB_KEYS.HEADER_TAB) ? (
|
||||
return open && selectedTab ? (
|
||||
<ResponseContainer
|
||||
className="t--js-editor-bottom-pane-container"
|
||||
ref={panelRef}
|
||||
|
|
@ -323,7 +326,7 @@ function JSResponseView(props: Props) {
|
|||
<EntityBottomTabs
|
||||
expandedHeight={`${ActionExecutionResizerHeight}px`}
|
||||
onSelect={setSelectedResponseTab}
|
||||
selectedTabKey={selectedResponseTab}
|
||||
selectedTabKey={selectedTab}
|
||||
tabs={tabs}
|
||||
/>
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ export enum FocusElement {
|
|||
SelectedJSObject = "SelectedJSObject",
|
||||
SelectedSegment = "SelectedSegment",
|
||||
IDETabs = "IDETabs",
|
||||
QueryDebugger = "QueryDebugger",
|
||||
ApiDebugger = "ApiDebugger",
|
||||
JSDebugger = "JSDebugger",
|
||||
}
|
||||
|
||||
export enum FocusElementConfigType {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ import { replayHighlightClass } from "globalStyles/portals";
|
|||
import { getPlugin } from "@appsmith/selectors/entitiesSelector";
|
||||
import { setApiPaneConfigSelectedTabIndex } from "actions/apiPaneActions";
|
||||
import type { AutoGeneratedHeader } from "./helpers";
|
||||
import { showDebuggerFlag } from "selectors/debuggerSelectors";
|
||||
import { getApiPaneConfigSelectedTabIndex } from "selectors/apiPaneSelectors";
|
||||
import { noop } from "lodash";
|
||||
import { DEFAULT_DATASOURCE_NAME } from "constants/ApiEditorConstants/ApiEditorConstants";
|
||||
|
|
@ -573,9 +572,6 @@ function CommonEditorForm(props: CommonFormPropsWithExtraParams) {
|
|||
actionDatasourceName === DEFAULT_DATASOURCE_NAME) ||
|
||||
!isExecutePermitted;
|
||||
|
||||
// Debugger render flag
|
||||
const showDebugger = useSelector(showDebuggerFlag);
|
||||
|
||||
const isGraphql = isGraphqlPlugin(plugin);
|
||||
|
||||
const theme = EditorTheme.LIGHT;
|
||||
|
|
@ -732,19 +728,17 @@ function CommonEditorForm(props: CommonFormPropsWithExtraParams) {
|
|||
</StyledTabPanel>
|
||||
</Tabs>
|
||||
</TabbedViewContainer>
|
||||
{showDebugger && (
|
||||
<ApiResponseView
|
||||
actionResponse={actionResponse}
|
||||
apiName={actionName}
|
||||
currentActionConfig={currentActionConfig}
|
||||
disabled={!isExecutePermitted}
|
||||
isRunning={isRunning}
|
||||
onRunClick={onRunClick}
|
||||
responseDataTypes={responseDataTypes}
|
||||
responseDisplayFormat={responseDisplayFormat}
|
||||
theme={theme}
|
||||
/>
|
||||
)}
|
||||
<ApiResponseView
|
||||
actionResponse={actionResponse}
|
||||
apiName={actionName}
|
||||
currentActionConfig={currentActionConfig}
|
||||
disabled={!isExecutePermitted}
|
||||
isRunning={isRunning}
|
||||
onRunClick={onRunClick}
|
||||
responseDataTypes={responseDataTypes}
|
||||
responseDisplayFormat={responseDisplayFormat}
|
||||
theme={theme}
|
||||
/>
|
||||
</SecondaryWrapper>
|
||||
<ActionRightPane
|
||||
actionRightPaneBackLink={actionRightPaneBackLink}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { executeDatasourceQuery } from "actions/datasourceActions";
|
||||
import type { Datasource, QueryTemplate } from "entities/Datasource";
|
||||
import { useState, useCallback } from "react";
|
||||
import { useCallback, useState } from "react";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { memo, useEffect, useMemo, useRef, useState } from "react";
|
||||
import React, { memo, useMemo, useRef, useState } from "react";
|
||||
import Entity, { EntityClassNames } from "../Explorer/Entity";
|
||||
import { datasourceTableIcon } from "../Explorer/ExplorerIcons";
|
||||
import QueryTemplates from "./QueryTemplates";
|
||||
|
|
@ -22,7 +22,6 @@ import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
|||
import { hasCreateDSActionPermissionInApp } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
|
||||
import { useEditorType } from "@appsmith/hooks";
|
||||
import history from "utils/history";
|
||||
import ResizeObserver from "resize-observer-polyfill";
|
||||
|
||||
interface DatasourceStructureItemProps {
|
||||
dbStructure: DatasourceTable;
|
||||
|
|
@ -45,6 +44,7 @@ const StructureWrapper = styled.div`
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
const DatasourceStructureItem = memo((props: DatasourceStructureItemProps) => {
|
||||
|
|
@ -160,33 +160,6 @@ type DatasourceStructureProps = Partial<DatasourceStructureItemProps> & {
|
|||
};
|
||||
|
||||
const DatasourceStructure = (props: DatasourceStructureProps) => {
|
||||
const [containerHeight, setContainerHeight] = useState<number>();
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const updateContainerHeight = () => {
|
||||
if (containerRef.current?.offsetHeight) {
|
||||
setContainerHeight(containerRef.current?.offsetHeight);
|
||||
}
|
||||
};
|
||||
|
||||
const resizeObserver = useRef(
|
||||
new ResizeObserver(() => {
|
||||
updateContainerHeight();
|
||||
}),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
updateContainerHeight();
|
||||
if (containerRef.current) {
|
||||
resizeObserver.current.observe(containerRef.current);
|
||||
}
|
||||
return () => {
|
||||
if (containerRef.current) {
|
||||
resizeObserver.current.unobserve(containerRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
const Row = (index: number) => {
|
||||
const structure = props.tables[index];
|
||||
|
||||
|
|
@ -201,15 +174,12 @@ const DatasourceStructure = (props: DatasourceStructureProps) => {
|
|||
};
|
||||
|
||||
return (
|
||||
<StructureWrapper ref={containerRef}>
|
||||
{containerHeight && (
|
||||
<Virtuoso
|
||||
className="t--schema-virtuoso-container"
|
||||
itemContent={Row}
|
||||
style={{ height: `${containerHeight}px` }}
|
||||
totalCount={props.tables.length}
|
||||
/>
|
||||
)}
|
||||
<StructureWrapper>
|
||||
<Virtuoso
|
||||
className="t--schema-virtuoso-container"
|
||||
itemContent={Row}
|
||||
totalCount={props.tables.length}
|
||||
/>
|
||||
</StructureWrapper>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@ import React, { useEffect, useRef, useState } from "react";
|
|||
import styled from "styled-components";
|
||||
import { ResizerCSS } from "components/editorComponents/Debugger/Resizer";
|
||||
import Resizable from "components/editorComponents/Debugger/Resizer";
|
||||
import { useSelector } from "react-redux";
|
||||
import { getResponsePaneHeight } from "selectors/debuggerSelectors";
|
||||
import { ActionExecutionResizerHeight } from "pages/Editor/APIEditor/constants";
|
||||
import type { BottomTab } from "components/editorComponents/EntityBottomTabs";
|
||||
import EntityBottomTabs from "components/editorComponents/EntityBottomTabs";
|
||||
|
|
@ -23,11 +21,11 @@ interface Props {
|
|||
onResizeComplete: (height: number) => void;
|
||||
isRunning: boolean;
|
||||
tabs: BottomTab[];
|
||||
height?: number;
|
||||
}
|
||||
|
||||
const ActionDrawer = (props: Props) => {
|
||||
const panelRef = useRef<HTMLDivElement>(null);
|
||||
const responsePaneHeight = useSelector(getResponsePaneHeight);
|
||||
const [selectedTab, setSelectedTab] = useState<string>("");
|
||||
useEffect(() => {
|
||||
if (props.tabs.length) {
|
||||
|
|
@ -38,7 +36,7 @@ const ActionDrawer = (props: Props) => {
|
|||
return (
|
||||
<Container ref={panelRef}>
|
||||
<Resizable
|
||||
initialHeight={responsePaneHeight}
|
||||
initialHeight={props.height || ActionExecutionResizerHeight}
|
||||
onResizeComplete={props.onResizeComplete}
|
||||
openResizer={props.isRunning}
|
||||
panelRef={panelRef}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { Flex } from "design-system";
|
|||
import React, { useCallback, useState } from "react";
|
||||
import ActionToolbar from "./ActionToolbar";
|
||||
import ActionDrawer from "./ActionDrawer";
|
||||
import { setResponsePaneHeight } from "actions/debuggerActions";
|
||||
import { useDispatch } from "react-redux";
|
||||
import type { BottomTab } from "components/editorComponents/EntityBottomTabs";
|
||||
|
||||
|
|
@ -14,12 +13,16 @@ interface Props {
|
|||
tabs: BottomTab[];
|
||||
runOptionsSelector?: React.ReactNode;
|
||||
settingsRender: React.ReactNode;
|
||||
height?: number;
|
||||
onSetHeight?: (height: number) => void;
|
||||
}
|
||||
|
||||
const ActionEditor = (props: Props) => {
|
||||
const dispatch = useDispatch();
|
||||
const setDrawerHeight = useCallback((height: number) => {
|
||||
dispatch(setResponsePaneHeight(height));
|
||||
if (props.onSetHeight) {
|
||||
dispatch(props.onSetHeight(height));
|
||||
}
|
||||
}, []);
|
||||
const [settingsOpen, setSettingsOpen] = useState(false);
|
||||
|
||||
|
|
@ -42,6 +45,7 @@ const ActionEditor = (props: Props) => {
|
|||
/>
|
||||
</Flex>
|
||||
<ActionDrawer
|
||||
height={props.height}
|
||||
isRunning={props.isRunning}
|
||||
onResizeComplete={setDrawerHeight}
|
||||
tabs={props.tabs}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import NewApiScreen from "./NewApi";
|
|||
import NewQueryScreen from "./NewQuery";
|
||||
import { isAirgapped } from "@appsmith/utils/airgapHelpers";
|
||||
import history from "utils/history";
|
||||
import { showDebuggerFlag } from "../../../selectors/debuggerSelectors";
|
||||
import { showDebuggerFlag } from "selectors/debuggerSelectors";
|
||||
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
||||
import {
|
||||
createMessage,
|
||||
|
|
@ -40,6 +40,7 @@ import {
|
|||
import { useEditorType } from "@appsmith/hooks";
|
||||
import { useParentEntityInfo } from "@appsmith/hooks/datasourceEditorHooks";
|
||||
import AIDataSources from "./AIDataSources";
|
||||
import Debugger from "../DataSourceEditor/Debugger";
|
||||
|
||||
const NewIntegrationsContainer = styled.div`
|
||||
${thinScrollbar};
|
||||
|
|
@ -280,6 +281,7 @@ class CreateNewDatasourceTab extends React.Component<
|
|||
isEnabledForCreateNew,
|
||||
isOnboardingScreen,
|
||||
pageId,
|
||||
showDebugger,
|
||||
} = this.props;
|
||||
if (!canCreateDatasource) return null;
|
||||
const mockDataSection =
|
||||
|
|
@ -290,68 +292,72 @@ class CreateNewDatasourceTab extends React.Component<
|
|||
/>
|
||||
) : null;
|
||||
return (
|
||||
<NewIntegrationsContainer className="p-4" id="new-integrations-wrapper">
|
||||
{dataSources.length === 0 && <AddDatasourceSecurely />}
|
||||
{dataSources.length === 0 && this.props.mockDatasources.length > 0 && (
|
||||
<>
|
||||
{mockDataSection}
|
||||
<StyledDivider />
|
||||
</>
|
||||
)}
|
||||
{isEnabledForCreateNew && (
|
||||
<>
|
||||
<CreateNewDatasource
|
||||
active={false}
|
||||
history={history}
|
||||
isCreating={isCreating}
|
||||
isOnboardingScreen={!!isOnboardingScreen}
|
||||
location={location}
|
||||
pageId={pageId}
|
||||
showMostPopularPlugins
|
||||
showUnsupportedPluginDialog={this.showUnsupportedPluginDialog}
|
||||
/>
|
||||
<StyledDivider />
|
||||
</>
|
||||
)}
|
||||
<CreateNewAPI
|
||||
active={false}
|
||||
history={history}
|
||||
isCreating={isCreating}
|
||||
isOnboardingScreen={!!isOnboardingScreen}
|
||||
location={location}
|
||||
pageId={pageId}
|
||||
showUnsupportedPluginDialog={this.showUnsupportedPluginDialog}
|
||||
/>
|
||||
<StyledDivider />
|
||||
<CreateNewDatasource
|
||||
active={false}
|
||||
history={history}
|
||||
isCreating={isCreating}
|
||||
location={location}
|
||||
pageId={pageId}
|
||||
showUnsupportedPluginDialog={this.showUnsupportedPluginDialog}
|
||||
/>
|
||||
<CreateNewSaasIntegration
|
||||
active={false}
|
||||
history={history}
|
||||
isCreating={isCreating}
|
||||
location={location}
|
||||
pageId={pageId}
|
||||
showUnsupportedPluginDialog={this.showUnsupportedPluginDialog}
|
||||
/>
|
||||
<CreateNewAIIntegration
|
||||
history={history}
|
||||
isCreating={isCreating}
|
||||
pageId={pageId}
|
||||
showUnsupportedPluginDialog={this.showUnsupportedPluginDialog}
|
||||
/>
|
||||
{dataSources.length > 0 && this.props.mockDatasources.length > 0 && (
|
||||
<>
|
||||
<StyledDivider />
|
||||
{mockDataSection}
|
||||
</>
|
||||
)}
|
||||
</NewIntegrationsContainer>
|
||||
<>
|
||||
<NewIntegrationsContainer className="p-4" id="new-integrations-wrapper">
|
||||
{dataSources.length === 0 && <AddDatasourceSecurely />}
|
||||
{dataSources.length === 0 &&
|
||||
this.props.mockDatasources.length > 0 && (
|
||||
<>
|
||||
{mockDataSection}
|
||||
<StyledDivider />
|
||||
</>
|
||||
)}
|
||||
{isEnabledForCreateNew && (
|
||||
<>
|
||||
<CreateNewDatasource
|
||||
active={false}
|
||||
history={history}
|
||||
isCreating={isCreating}
|
||||
isOnboardingScreen={!!isOnboardingScreen}
|
||||
location={location}
|
||||
pageId={pageId}
|
||||
showMostPopularPlugins
|
||||
showUnsupportedPluginDialog={this.showUnsupportedPluginDialog}
|
||||
/>
|
||||
<StyledDivider />
|
||||
</>
|
||||
)}
|
||||
<CreateNewAPI
|
||||
active={false}
|
||||
history={history}
|
||||
isCreating={isCreating}
|
||||
isOnboardingScreen={!!isOnboardingScreen}
|
||||
location={location}
|
||||
pageId={pageId}
|
||||
showUnsupportedPluginDialog={this.showUnsupportedPluginDialog}
|
||||
/>
|
||||
<StyledDivider />
|
||||
<CreateNewDatasource
|
||||
active={false}
|
||||
history={history}
|
||||
isCreating={isCreating}
|
||||
location={location}
|
||||
pageId={pageId}
|
||||
showUnsupportedPluginDialog={this.showUnsupportedPluginDialog}
|
||||
/>
|
||||
<CreateNewSaasIntegration
|
||||
active={false}
|
||||
history={history}
|
||||
isCreating={isCreating}
|
||||
location={location}
|
||||
pageId={pageId}
|
||||
showUnsupportedPluginDialog={this.showUnsupportedPluginDialog}
|
||||
/>
|
||||
<CreateNewAIIntegration
|
||||
history={history}
|
||||
isCreating={isCreating}
|
||||
pageId={pageId}
|
||||
showUnsupportedPluginDialog={this.showUnsupportedPluginDialog}
|
||||
/>
|
||||
{dataSources.length > 0 && this.props.mockDatasources.length > 0 && (
|
||||
<>
|
||||
<StyledDivider />
|
||||
{mockDataSection}
|
||||
</>
|
||||
)}
|
||||
</NewIntegrationsContainer>
|
||||
{showDebugger && <Debugger />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import JSObjectNameEditor from "./JSObjectNameEditor";
|
|||
import {
|
||||
setActiveJSAction,
|
||||
setJsPaneConfigSelectedTab,
|
||||
setJsPaneDebuggerState,
|
||||
startExecutingJSFunction,
|
||||
updateJSCollectionBody,
|
||||
} from "actions/jsPaneActions";
|
||||
|
|
@ -60,7 +61,6 @@ import history from "utils/history";
|
|||
import { CursorPositionOrigin } from "@appsmith/reducers/uiReducers/editorContextReducer";
|
||||
import LazyCodeEditor from "components/editorComponents/LazyCodeEditor";
|
||||
import styled from "styled-components";
|
||||
import { showDebuggerFlag } from "selectors/debuggerSelectors";
|
||||
import { Tab, TabPanel, Tabs, TabsList } from "design-system";
|
||||
import { JSEditorTab } from "reducers/uiReducers/jsPaneReducer";
|
||||
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
||||
|
|
@ -70,6 +70,7 @@ import {
|
|||
getHasManageActionPermission,
|
||||
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
|
||||
import type { JSCollectionData } from "@appsmith/reducers/entityReducers/jsActionsReducer";
|
||||
import { DEBUGGER_TAB_KEYS } from "../../../components/editorComponents/Debugger/helpers";
|
||||
|
||||
interface JSFormProps {
|
||||
jsCollectionData: JSCollectionData;
|
||||
|
|
@ -202,6 +203,12 @@ function JSEditorForm({
|
|||
|
||||
// Executes JS action
|
||||
const executeJSAction = (jsAction: JSAction, from: EventLocation) => {
|
||||
dispatch(
|
||||
setJsPaneDebuggerState({
|
||||
open: true,
|
||||
selectedTab: DEBUGGER_TAB_KEYS.RESPONSE_TAB,
|
||||
}),
|
||||
);
|
||||
setActiveResponse(jsAction);
|
||||
if (jsAction.id !== selectedJSActionOption.data?.id)
|
||||
setSelectedJSActionOption(convertJSActionToDropdownOption(jsAction));
|
||||
|
|
@ -303,9 +310,6 @@ function JSEditorForm({
|
|||
|
||||
const selectedConfigTab = useSelector(getJSPaneConfigSelectedTab);
|
||||
|
||||
// Debugger render flag
|
||||
const showDebugger = useSelector(showDebuggerFlag);
|
||||
|
||||
const setSelectedConfigTab = useCallback((selectedTab: JSEditorTab) => {
|
||||
dispatch(setJsPaneConfigSelectedTab(selectedTab));
|
||||
}, []);
|
||||
|
|
@ -418,23 +422,21 @@ function JSEditorForm({
|
|||
)}
|
||||
</Tabs>
|
||||
</TabbedViewContainer>
|
||||
{showDebugger ? (
|
||||
<JSResponseView
|
||||
currentFunction={activeResponse}
|
||||
disabled={disableRunFunctionality || !isExecutePermitted}
|
||||
errors={parseErrors}
|
||||
isLoading={isExecutingCurrentJSAction}
|
||||
jsCollectionData={jsCollectionData}
|
||||
onButtonClick={(
|
||||
event:
|
||||
| React.MouseEvent<HTMLElement, MouseEvent>
|
||||
| KeyboardEvent,
|
||||
) => {
|
||||
handleRunAction(event, "JS_OBJECT_RESPONSE_RUN_BUTTON");
|
||||
}}
|
||||
theme={theme}
|
||||
/>
|
||||
) : null}
|
||||
<JSResponseView
|
||||
currentFunction={activeResponse}
|
||||
disabled={disableRunFunctionality || !isExecutePermitted}
|
||||
errors={parseErrors}
|
||||
isLoading={isExecutingCurrentJSAction}
|
||||
jsCollectionData={jsCollectionData}
|
||||
onButtonClick={(
|
||||
event:
|
||||
| React.MouseEvent<HTMLElement, MouseEvent>
|
||||
| KeyboardEvent,
|
||||
) => {
|
||||
handleRunAction(event, "JS_OBJECT_RESPONSE_RUN_BUTTON");
|
||||
}}
|
||||
theme={theme}
|
||||
/>
|
||||
</SecondaryWrapper>
|
||||
</div>
|
||||
</Wrapper>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useContext, useEffect, useState } from "react";
|
||||
import { useContext } from "react";
|
||||
import React, { useCallback } from "react";
|
||||
import type { InjectedFormProps } from "redux-form";
|
||||
import { noop } from "lodash";
|
||||
|
|
@ -15,7 +15,6 @@ import ActionSettings from "pages/Editor/ActionSettings";
|
|||
import { Button, Tab, TabPanel, Tabs, TabsList, Tooltip } from "design-system";
|
||||
import styled from "styled-components";
|
||||
import FormRow from "components/editorComponents/FormRow";
|
||||
import { ResizerCSS } from "components/editorComponents/Debugger/Resizer";
|
||||
import {
|
||||
createMessage,
|
||||
DOCUMENTATION,
|
||||
|
|
@ -30,16 +29,10 @@ import ActionRightPane, {
|
|||
import type { ActionResponse } from "api/ActionAPI";
|
||||
import type { Plugin } from "api/PluginApi";
|
||||
import type { UIComponentTypes } from "api/PluginApi";
|
||||
import { DEBUGGER_TAB_KEYS } from "components/editorComponents/Debugger/helpers";
|
||||
import { EDITOR_TABS } from "constants/QueryEditorConstants";
|
||||
import type { FormEvalOutput } from "reducers/evaluationReducers/formEvaluationReducer";
|
||||
import { getQueryPaneConfigSelectedTabIndex } from "selectors/queryPaneSelectors";
|
||||
import { setQueryPaneConfigSelectedTabIndex } from "actions/queryPaneActions";
|
||||
import { ActionExecutionResizerHeight } from "pages/Editor/APIEditor/constants";
|
||||
import {
|
||||
getDebuggerSelectedTab,
|
||||
showDebuggerFlag,
|
||||
} from "selectors/debuggerSelectors";
|
||||
import type { SourceEntity } from "entities/AppsmithConsole";
|
||||
import { ENTITY_TYPE as SOURCE_ENTITY_TYPE } from "@appsmith/entities/AppsmithConsole/utils";
|
||||
import { DocsLink, openDoc } from "../../../constants/DocumentationLinks";
|
||||
|
|
@ -47,7 +40,6 @@ import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
|||
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
||||
import { QueryEditorContext } from "./QueryEditorContext";
|
||||
import QueryDebuggerTabs from "./QueryDebuggerTabs";
|
||||
import { setDebuggerSelectedTab, showDebugger } from "actions/debuggerActions";
|
||||
import useShowSchema from "components/editorComponents/ActionRightPane/useShowSchema";
|
||||
import { doesPluginRequireDatasource } from "@appsmith/entities/Engine/actionHelpers";
|
||||
import FormRender from "./FormRender";
|
||||
|
|
@ -79,16 +71,6 @@ const QueryFormContainer = styled.form`
|
|||
}
|
||||
`;
|
||||
|
||||
export const TabbedViewContainer = styled.div`
|
||||
${ResizerCSS};
|
||||
height: ${ActionExecutionResizerHeight}px;
|
||||
// Minimum height of bottom tabs as it can be resized
|
||||
min-height: 36px;
|
||||
width: 100%;
|
||||
background-color: var(--ads-v2-color-bg);
|
||||
border-top: 1px solid var(--ads-v2-color-border);
|
||||
`;
|
||||
|
||||
const SettingsWrapper = styled.div`
|
||||
${thinScrollbar};
|
||||
height: 100%;
|
||||
|
|
@ -221,7 +203,6 @@ export function EditorJSONtoForm(props: Props) {
|
|||
onCreateDatasourceClick,
|
||||
onRunClick,
|
||||
plugin,
|
||||
responseDisplayFormat,
|
||||
runErrorMessage,
|
||||
settingConfig,
|
||||
uiComponent,
|
||||
|
|
@ -242,8 +223,6 @@ export function EditorJSONtoForm(props: Props) {
|
|||
const currentActionConfig: Action | undefined = actions.find(
|
||||
(action) => action.id === params.apiId || action.id === params.queryId,
|
||||
);
|
||||
const [showResponseOnFirstLoad, setShowResponseOnFirstLoad] =
|
||||
useState<boolean>(false);
|
||||
|
||||
const pluginRequireDatasource = doesPluginRequireDatasource(plugin);
|
||||
|
||||
|
|
@ -264,38 +243,6 @@ export function EditorJSONtoForm(props: Props) {
|
|||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
// These useEffects are used to open the response tab by default for page load queries
|
||||
// as for page load queries, query response is available and can be shown in response tab
|
||||
useEffect(() => {
|
||||
// actionResponse and responseDisplayFormat is present only when query has response available
|
||||
if (
|
||||
responseDisplayFormat &&
|
||||
!!responseDisplayFormat?.title &&
|
||||
actionResponse &&
|
||||
actionResponse.isExecutionSuccess &&
|
||||
!showResponseOnFirstLoad
|
||||
) {
|
||||
dispatch(showDebugger(true));
|
||||
dispatch(setDebuggerSelectedTab(DEBUGGER_TAB_KEYS.RESPONSE_TAB));
|
||||
setShowResponseOnFirstLoad(true);
|
||||
}
|
||||
}, [responseDisplayFormat, actionResponse, showResponseOnFirstLoad]);
|
||||
|
||||
useEffect(() => {
|
||||
if (showSchema) {
|
||||
dispatch(showDebugger(true));
|
||||
dispatch(setDebuggerSelectedTab(DEBUGGER_TAB_KEYS.SCHEMA_TAB));
|
||||
}
|
||||
}, [showSchema]);
|
||||
|
||||
// When multiple page load queries exist, we want to response tab by default for all of them
|
||||
// Hence this useEffect will reset showResponseOnFirstLoad flag used to track whether to show response tab or not
|
||||
useEffect(() => {
|
||||
if (!!currentActionConfig?.id) {
|
||||
setShowResponseOnFirstLoad(false);
|
||||
}
|
||||
}, [currentActionConfig?.id]);
|
||||
|
||||
const handleDocumentationClick = () => {
|
||||
openDoc(DocsLink.QUERY, plugin?.documentationLink, plugin?.name);
|
||||
};
|
||||
|
|
@ -311,15 +258,10 @@ export function EditorJSONtoForm(props: Props) {
|
|||
|
||||
const selectedConfigTab = useSelector(getQueryPaneConfigSelectedTabIndex);
|
||||
|
||||
// Debugger render flag
|
||||
const renderDebugger = useSelector(showDebuggerFlag);
|
||||
|
||||
const setSelectedConfigTab = useCallback((selectedIndex: string) => {
|
||||
dispatch(setQueryPaneConfigSelectedTabIndex(selectedIndex));
|
||||
}, []);
|
||||
|
||||
const selectedResponseTab = useSelector(getDebuggerSelectedTab);
|
||||
|
||||
// here we check for normal conditions for opening action pane
|
||||
// or if any of the flags are true, We should open the actionpane by default.
|
||||
const shouldOpenActionPaneByDefault =
|
||||
|
|
@ -465,19 +407,16 @@ export function EditorJSONtoForm(props: Props) {
|
|||
</Tooltip>
|
||||
)}
|
||||
</TabContainerView>
|
||||
{renderDebugger &&
|
||||
selectedResponseTab !== DEBUGGER_TAB_KEYS.HEADER_TAB && (
|
||||
<QueryDebuggerTabs
|
||||
actionName={actionName}
|
||||
actionResponse={actionResponse}
|
||||
actionSource={actionSource}
|
||||
currentActionConfig={currentActionConfig}
|
||||
isRunning={isRunning}
|
||||
onRunClick={onRunClick}
|
||||
runErrorMessage={runErrorMessage}
|
||||
showSchema={showSchema}
|
||||
/>
|
||||
)}
|
||||
<QueryDebuggerTabs
|
||||
actionName={actionName}
|
||||
actionResponse={actionResponse}
|
||||
actionSource={actionSource}
|
||||
currentActionConfig={currentActionConfig}
|
||||
isRunning={isRunning}
|
||||
onRunClick={onRunClick}
|
||||
runErrorMessage={runErrorMessage}
|
||||
showSchema={showSchema}
|
||||
/>
|
||||
</SecondaryWrapper>
|
||||
</div>
|
||||
{showRightPane && (
|
||||
|
|
|
|||
|
|
@ -1,20 +1,11 @@
|
|||
import {
|
||||
setDebuggerSelectedTab,
|
||||
setResponsePaneHeight,
|
||||
showDebugger,
|
||||
} from "actions/debuggerActions";
|
||||
import { CloseDebugger } from "components/editorComponents/Debugger/DebuggerTabs";
|
||||
import type { BottomTab } from "components/editorComponents/EntityBottomTabs";
|
||||
import EntityBottomTabs from "components/editorComponents/EntityBottomTabs";
|
||||
import React, { useCallback, useEffect, useRef } from "react";
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import styled from "styled-components";
|
||||
import { ActionExecutionResizerHeight } from "pages/Editor/APIEditor/constants";
|
||||
import {
|
||||
getDebuggerSelectedTab,
|
||||
getErrorCount,
|
||||
getResponsePaneHeight,
|
||||
} from "selectors/debuggerSelectors";
|
||||
import { getErrorCount } from "selectors/debuggerSelectors";
|
||||
import { Text, TextType } from "design-system-old";
|
||||
import Resizable, {
|
||||
ResizerCSS,
|
||||
|
|
@ -23,12 +14,10 @@ import { DEBUGGER_TAB_KEYS } from "components/editorComponents/Debugger/helpers"
|
|||
import {
|
||||
DEBUGGER_ERRORS,
|
||||
DEBUGGER_LOGS,
|
||||
INSPECT_ENTITY,
|
||||
createMessage,
|
||||
} from "@appsmith/constants/messages";
|
||||
import DebuggerLogs from "components/editorComponents/Debugger/DebuggerLogs";
|
||||
import ErrorLogs from "components/editorComponents/Debugger/Errors";
|
||||
import EntityDeps from "components/editorComponents/Debugger/EntityDependecies";
|
||||
import Schema from "components/editorComponents/Debugger/Schema";
|
||||
import type { ActionResponse } from "api/ActionAPI";
|
||||
import { isString } from "lodash";
|
||||
|
|
@ -42,6 +31,11 @@ import {
|
|||
import { DatasourceComponentTypes } from "api/PluginApi";
|
||||
import { fetchDatasourceStructure } from "actions/datasourceActions";
|
||||
import { DatasourceStructureContext } from "entities/Datasource";
|
||||
import { getQueryPaneDebuggerState } from "selectors/queryPaneSelectors";
|
||||
import { setQueryPaneDebuggerState } from "actions/queryPaneActions";
|
||||
import { actionResponseDisplayDataFormats } from "../utils";
|
||||
import { getIDEViewMode } from "selectors/ideSelectors";
|
||||
import { EditorViewMode } from "@appsmith/entities/IDE/constants";
|
||||
|
||||
const ResultsCount = styled.div`
|
||||
position: absolute;
|
||||
|
|
@ -86,8 +80,16 @@ function QueryDebuggerTabs({
|
|||
const panelRef = useRef<HTMLDivElement>(null);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const selectedResponseTab = useSelector(getDebuggerSelectedTab);
|
||||
const responsePaneHeight = useSelector(getResponsePaneHeight);
|
||||
const { open, responseTabHeight, selectedTab } = useSelector(
|
||||
getQueryPaneDebuggerState,
|
||||
);
|
||||
|
||||
const { responseDisplayFormat } =
|
||||
actionResponseDisplayDataFormats(actionResponse);
|
||||
|
||||
const [showResponseOnFirstLoad, setShowResponseOnFirstLoad] =
|
||||
useState<boolean>(false);
|
||||
|
||||
const errorCount = useSelector(getErrorCount);
|
||||
|
||||
const pluginDatasourceForm = useSelector((state) =>
|
||||
|
|
@ -120,6 +122,46 @@ function QueryDebuggerTabs({
|
|||
}
|
||||
}, []);
|
||||
|
||||
// These useEffects are used to open the response tab by default for page load queries
|
||||
// as for page load queries, query response is available and can be shown in response tab
|
||||
useEffect(() => {
|
||||
// actionResponse and responseDisplayFormat is present only when query has response available
|
||||
if (
|
||||
responseDisplayFormat &&
|
||||
!!responseDisplayFormat?.title &&
|
||||
actionResponse &&
|
||||
actionResponse.isExecutionSuccess &&
|
||||
!showResponseOnFirstLoad
|
||||
) {
|
||||
dispatch(
|
||||
setQueryPaneDebuggerState({
|
||||
open: true,
|
||||
selectedTab: DEBUGGER_TAB_KEYS.RESPONSE_TAB,
|
||||
}),
|
||||
);
|
||||
setShowResponseOnFirstLoad(true);
|
||||
}
|
||||
}, [responseDisplayFormat, actionResponse, showResponseOnFirstLoad]);
|
||||
|
||||
useEffect(() => {
|
||||
if (showSchema && !selectedTab) {
|
||||
dispatch(
|
||||
setQueryPaneDebuggerState({
|
||||
open: true,
|
||||
selectedTab: DEBUGGER_TAB_KEYS.SCHEMA_TAB,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}, [showSchema, currentActionConfig?.id, selectedTab]);
|
||||
|
||||
// When multiple page load queries exist, we want to response tab by default for all of them
|
||||
// Hence this useEffect will reset showResponseOnFirstLoad flag used to track whether to show response tab or not
|
||||
useEffect(() => {
|
||||
if (!!currentActionConfig?.id) {
|
||||
setShowResponseOnFirstLoad(false);
|
||||
}
|
||||
}, [currentActionConfig?.id]);
|
||||
|
||||
// Query is executed even once during the session, show the response data.
|
||||
if (actionResponse) {
|
||||
if (isString(actionResponse.body)) {
|
||||
|
|
@ -140,32 +182,36 @@ function QueryDebuggerTabs({
|
|||
}
|
||||
|
||||
const setQueryResponsePaneHeight = useCallback((height: number) => {
|
||||
dispatch(setResponsePaneHeight(height));
|
||||
dispatch(setQueryPaneDebuggerState({ responseTabHeight: height }));
|
||||
}, []);
|
||||
|
||||
const onClose = useCallback(() => {
|
||||
dispatch(setQueryPaneDebuggerState({ open: false }));
|
||||
}, []);
|
||||
|
||||
const onClose = () => dispatch(showDebugger(false));
|
||||
const setSelectedResponseTab = useCallback((tabKey: string) => {
|
||||
dispatch(setDebuggerSelectedTab(tabKey));
|
||||
dispatch(setQueryPaneDebuggerState({ selectedTab: tabKey }));
|
||||
}, []);
|
||||
|
||||
const responseTabs: BottomTab[] = [
|
||||
{
|
||||
key: DEBUGGER_TAB_KEYS.ERROR_TAB,
|
||||
title: createMessage(DEBUGGER_ERRORS),
|
||||
count: errorCount,
|
||||
panelComponent: <ErrorLogs />,
|
||||
},
|
||||
{
|
||||
key: DEBUGGER_TAB_KEYS.LOGS_TAB,
|
||||
title: createMessage(DEBUGGER_LOGS),
|
||||
panelComponent: <DebuggerLogs searchQuery={actionName} />,
|
||||
},
|
||||
{
|
||||
key: DEBUGGER_TAB_KEYS.INSPECT_TAB,
|
||||
title: createMessage(INSPECT_ENTITY),
|
||||
panelComponent: <EntityDeps />,
|
||||
},
|
||||
];
|
||||
const ideViewMode = useSelector(getIDEViewMode);
|
||||
|
||||
const responseTabs: BottomTab[] = [];
|
||||
|
||||
if (ideViewMode === EditorViewMode.FullScreen) {
|
||||
responseTabs.push(
|
||||
{
|
||||
key: DEBUGGER_TAB_KEYS.ERROR_TAB,
|
||||
title: createMessage(DEBUGGER_ERRORS),
|
||||
count: errorCount,
|
||||
panelComponent: <ErrorLogs />,
|
||||
},
|
||||
{
|
||||
key: DEBUGGER_TAB_KEYS.LOGS_TAB,
|
||||
title: createMessage(DEBUGGER_LOGS),
|
||||
panelComponent: <DebuggerLogs searchQuery={actionName} />,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (currentActionConfig) {
|
||||
responseTabs.unshift({
|
||||
|
|
@ -197,13 +243,15 @@ function QueryDebuggerTabs({
|
|||
});
|
||||
}
|
||||
|
||||
if (!open) return null;
|
||||
|
||||
return (
|
||||
<TabbedViewContainer
|
||||
className="t--query-bottom-pane-container"
|
||||
ref={panelRef}
|
||||
>
|
||||
<Resizable
|
||||
initialHeight={responsePaneHeight}
|
||||
initialHeight={responseTabHeight}
|
||||
onResizeComplete={(height: number) =>
|
||||
setQueryResponsePaneHeight(height)
|
||||
}
|
||||
|
|
@ -226,7 +274,7 @@ function QueryDebuggerTabs({
|
|||
<EntityBottomTabs
|
||||
expandedHeight={`${ActionExecutionResizerHeight}px`}
|
||||
onSelect={setSelectedResponseTab}
|
||||
selectedTabKey={selectedResponseTab}
|
||||
selectedTabKey={selectedTab || ""}
|
||||
tabs={responseTabs}
|
||||
/>
|
||||
<CloseDebugger
|
||||
|
|
|
|||
|
|
@ -26,12 +26,12 @@ import { actionResponseDisplayDataFormats } from "../utils";
|
|||
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
||||
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
||||
import { getHasExecuteActionPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
|
||||
import { getResponsePaneHeight } from "selectors/debuggerSelectors";
|
||||
import { getErrorAsString } from "sagas/ActionExecution/errorUtils";
|
||||
import { isString } from "lodash";
|
||||
import ActionExecutionInProgressView from "components/editorComponents/ActionExecutionInProgressView";
|
||||
import { EditorTheme } from "components/editorComponents/CodeEditor/EditorConfig";
|
||||
import BindDataButton from "./BindDataButton";
|
||||
import { getQueryPaneDebuggerState } from "selectors/queryPaneSelectors";
|
||||
|
||||
const HelpSection = styled.div``;
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ const QueryResponseTab = (props: Props) => {
|
|||
const actionResponse = useSelector((state) =>
|
||||
getActionData(state, currentActionConfig.id),
|
||||
);
|
||||
const responsePaneHeight = useSelector(getResponsePaneHeight);
|
||||
const { responseTabHeight } = useSelector(getQueryPaneDebuggerState);
|
||||
|
||||
const { responseDataTypes, responseDisplayFormat } =
|
||||
actionResponseDisplayDataFormats(actionResponse);
|
||||
|
|
@ -99,7 +99,7 @@ const QueryResponseTab = (props: Props) => {
|
|||
panelComponent: responseTabComponent(
|
||||
dataType.key,
|
||||
output,
|
||||
responsePaneHeight,
|
||||
responseTabHeight,
|
||||
),
|
||||
};
|
||||
});
|
||||
|
|
@ -278,7 +278,7 @@ const QueryResponseTab = (props: Props) => {
|
|||
{responseTabComponent(
|
||||
selectedControl || segmentedControlOptions[0]?.value,
|
||||
output,
|
||||
responsePaneHeight,
|
||||
responseTabHeight,
|
||||
)}
|
||||
</ResponseDataContainer>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -160,6 +160,26 @@ const debuggerReducer = createImmerReducer(initialState, {
|
|||
) => {
|
||||
state.context = action.context;
|
||||
},
|
||||
[ReduxActionTypes.SET_CANVAS_DEBUGGER_STATE]: (
|
||||
state: DebuggerReduxState,
|
||||
action: { payload: Partial<CanvasDebuggerState> },
|
||||
): DebuggerReduxState => {
|
||||
return {
|
||||
...state,
|
||||
isOpen: "open" in action.payload ? !!action.payload.open : state.isOpen,
|
||||
context: {
|
||||
...state.context,
|
||||
responseTabHeight:
|
||||
"responseTabHeight" in action.payload
|
||||
? Number(action.payload.responseTabHeight)
|
||||
: state.context.responseTabHeight,
|
||||
selectedDebuggerTab:
|
||||
"selectedTab" in action.payload
|
||||
? String(action.payload.selectedTab)
|
||||
: state.context.selectedDebuggerTab,
|
||||
},
|
||||
};
|
||||
},
|
||||
// Resetting debugger state after env switch
|
||||
[ReduxActionTypes.SWITCH_ENVIRONMENT_SUCCESS]: () => {
|
||||
return klona(initialState);
|
||||
|
|
@ -183,4 +203,10 @@ export interface DebuggerContext {
|
|||
selectedDebuggerFilter: string;
|
||||
}
|
||||
|
||||
export interface CanvasDebuggerState {
|
||||
open: boolean;
|
||||
responseTabHeight: number;
|
||||
selectedTab?: string;
|
||||
}
|
||||
|
||||
export default debuggerReducer;
|
||||
|
|
|
|||
|
|
@ -12,24 +12,31 @@ export enum JSEditorTab {
|
|||
SETTINGS = "SETTINGS",
|
||||
}
|
||||
|
||||
export interface JSPaneDebuggerState {
|
||||
open: boolean;
|
||||
responseTabHeight: number;
|
||||
selectedTab?: string;
|
||||
}
|
||||
|
||||
export interface JsPaneReduxState {
|
||||
isCreating: boolean;
|
||||
isFetching: boolean;
|
||||
isSaving: Record<string, boolean>;
|
||||
isDeleting: Record<string, boolean>;
|
||||
isDirty: Record<string, boolean>;
|
||||
selectedConfigTab: JSEditorTab;
|
||||
responseTabHeight: number;
|
||||
debugger: JSPaneDebuggerState;
|
||||
}
|
||||
|
||||
const initialState: JsPaneReduxState = {
|
||||
isCreating: false,
|
||||
isFetching: false,
|
||||
isSaving: {},
|
||||
isDeleting: {},
|
||||
isDirty: {},
|
||||
responseTabHeight: ActionExecutionResizerHeight,
|
||||
selectedConfigTab: JSEditorTab.CODE,
|
||||
debugger: {
|
||||
open: false,
|
||||
responseTabHeight: ActionExecutionResizerHeight,
|
||||
},
|
||||
};
|
||||
|
||||
const jsPaneReducer = createReducer(initialState, {
|
||||
|
|
@ -184,6 +191,18 @@ const jsPaneReducer = createReducer(initialState, {
|
|||
selectedConfigTab: selectedTab,
|
||||
};
|
||||
},
|
||||
[ReduxActionTypes.SET_JS_PANE_DEBUGGER_STATE]: (
|
||||
state: JsPaneReduxState,
|
||||
action: ReduxAction<Partial<JSPaneDebuggerState>>,
|
||||
) => {
|
||||
return {
|
||||
...state,
|
||||
debugger: {
|
||||
...state.debugger,
|
||||
...action.payload,
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default jsPaneReducer;
|
||||
|
|
|
|||
|
|
@ -18,9 +18,11 @@ import {
|
|||
updateAction,
|
||||
updateActionData,
|
||||
} from "actions/pluginActionActions";
|
||||
import { makeUpdateJSCollection } from "sagas/JSPaneSagas";
|
||||
import {
|
||||
handleExecuteJSFunctionSaga,
|
||||
makeUpdateJSCollection,
|
||||
} from "sagas/JSPaneSagas";
|
||||
|
||||
import { setDebuggerSelectedTab, showDebugger } from "actions/debuggerActions";
|
||||
import type {
|
||||
ApplicationPayload,
|
||||
ReduxAction,
|
||||
|
|
@ -38,12 +40,13 @@ import type {
|
|||
import ActionAPI from "api/ActionAPI";
|
||||
import {
|
||||
getAction,
|
||||
getCurrentActions,
|
||||
getCurrentPageNameByActionId,
|
||||
getDatasource,
|
||||
getJSCollectionFromAllEntities,
|
||||
getPlugin,
|
||||
isActionDirty,
|
||||
isActionSaving,
|
||||
getDatasource,
|
||||
getJSCollectionFromAllEntities,
|
||||
} from "@appsmith/selectors/entitiesSelector";
|
||||
import { getIsGitSyncModalOpen } from "selectors/gitSyncSelectors";
|
||||
import {
|
||||
|
|
@ -51,15 +54,15 @@ import {
|
|||
getCurrentApplication,
|
||||
} from "@appsmith/selectors/applicationSelectors";
|
||||
import {
|
||||
find,
|
||||
flatten,
|
||||
get,
|
||||
isArray,
|
||||
isString,
|
||||
set,
|
||||
find,
|
||||
isNil,
|
||||
flatten,
|
||||
isArrayBuffer,
|
||||
isEmpty,
|
||||
isNil,
|
||||
isString,
|
||||
set,
|
||||
unset,
|
||||
} from "lodash";
|
||||
import AppsmithConsole from "utils/AppsmithConsole";
|
||||
|
|
@ -77,12 +80,12 @@ import type { Action } from "entities/Action";
|
|||
import { PluginType } from "entities/Action";
|
||||
import LOG_TYPE from "entities/AppsmithConsole/logtype";
|
||||
import {
|
||||
ACTION_EXECUTION_CANCELLED,
|
||||
ACTION_EXECUTION_FAILED,
|
||||
createMessage,
|
||||
ERROR_ACTION_EXECUTE_FAIL,
|
||||
ERROR_FAIL_ON_PAGE_LOAD_ACTIONS,
|
||||
ERROR_PLUGIN_ACTION_EXECUTE,
|
||||
ACTION_EXECUTION_CANCELLED,
|
||||
ACTION_EXECUTION_FAILED,
|
||||
SWITCH_ENVIRONMENT_SUCCESS,
|
||||
} from "@appsmith/constants/messages";
|
||||
import type {
|
||||
|
|
@ -107,7 +110,7 @@ import * as log from "loglevel";
|
|||
import { EMPTY_RESPONSE } from "components/editorComponents/emptyResponse";
|
||||
import type { AppState } from "@appsmith/reducers";
|
||||
import { DEFAULT_EXECUTE_ACTION_TIMEOUT_MS } from "@appsmith/constants/ApiConstants";
|
||||
import { evalWorker, evaluateActionBindings } from "sagas/EvaluationsSaga";
|
||||
import { evaluateActionBindings, evalWorker } from "sagas/EvaluationsSaga";
|
||||
import { isBlobUrl, parseBlobUrl } from "utils/AppsmithUtils";
|
||||
import { getType, Types } from "utils/TypeHelpers";
|
||||
import { matchPath } from "react-router";
|
||||
|
|
@ -115,11 +118,11 @@ import {
|
|||
API_EDITOR_BASE_PATH,
|
||||
API_EDITOR_ID_PATH,
|
||||
API_EDITOR_PATH_WITH_SELECTED_PAGE_ID,
|
||||
CURL_IMPORT_PAGE_PATH,
|
||||
INTEGRATION_EDITOR_PATH,
|
||||
matchQueryBuilderPath,
|
||||
QUERIES_EDITOR_BASE_PATH,
|
||||
QUERIES_EDITOR_ID_PATH,
|
||||
CURL_IMPORT_PAGE_PATH,
|
||||
matchQueryBuilderPath,
|
||||
} from "constants/routes";
|
||||
import { SAAS_EDITOR_API_ID_PATH } from "pages/Editor/SaaSEditor/constants";
|
||||
import { APP_MODE } from "entities/App";
|
||||
|
|
@ -141,10 +144,9 @@ import { submitCurlImportForm } from "actions/importActions";
|
|||
import type { curlImportFormValues } from "pages/Editor/APIEditor/helpers";
|
||||
import { matchBasePath } from "@appsmith/pages/Editor/Explorer/helpers";
|
||||
import {
|
||||
isTrueObject,
|
||||
findDatatype,
|
||||
isTrueObject,
|
||||
} from "@appsmith/workers/Evaluation/evaluationUtils";
|
||||
import { handleExecuteJSFunctionSaga } from "sagas/JSPaneSagas";
|
||||
import type { Plugin } from "api/PluginApi";
|
||||
import { setDefaultActionDisplayFormat } from "./PluginActionSagaUtils";
|
||||
import { checkAndLogErrorsIfCyclicDependency } from "sagas/helper";
|
||||
|
|
@ -152,13 +154,15 @@ import { toast } from "design-system";
|
|||
import type { TRunDescription } from "workers/Evaluation/fns/actionFns";
|
||||
import { DEBUGGER_TAB_KEYS } from "components/editorComponents/Debugger/helpers";
|
||||
import { FILE_SIZE_LIMIT_FOR_BLOBS } from "constants/WidgetConstants";
|
||||
import { getCurrentActions } from "@appsmith/selectors/entitiesSelector";
|
||||
import type { ActionData } from "@appsmith/reducers/entityReducers/actionsReducer";
|
||||
import { handleStoreOperations } from "./StoreActionSaga";
|
||||
import { fetchPage } from "actions/pageActions";
|
||||
import type { Datasource } from "entities/Datasource";
|
||||
import { softRefreshDatasourceStructure } from "actions/datasourceActions";
|
||||
import { changeQuery } from "actions/queryPaneActions";
|
||||
import {
|
||||
changeQuery,
|
||||
setQueryPaneDebuggerState,
|
||||
} from "actions/queryPaneActions";
|
||||
import {
|
||||
getCurrentEnvironmentDetails,
|
||||
getCurrentEnvironmentName,
|
||||
|
|
@ -179,6 +183,7 @@ import {
|
|||
} from "@appsmith/utils/actionExecutionUtils";
|
||||
import type { JSAction, JSCollection } from "entities/JSCollection";
|
||||
import { getAllowedActionAnalyticsKeys } from "constants/AppsmithActionConstants/formConfig/ActionAnalyticsConfig";
|
||||
import { setApiPaneDebuggerState } from "../../actions/apiPaneActions";
|
||||
|
||||
enum ActionResponseDataTypes {
|
||||
BINARY = "BINARY",
|
||||
|
|
@ -792,7 +797,7 @@ export function* runActionSaga(
|
|||
const { paginationField } = reduxAction.payload;
|
||||
// open response tab in debugger on exection of action.
|
||||
if (!reduxAction.payload.skipOpeningDebugger) {
|
||||
yield call(openDebugger);
|
||||
yield call(openDebugger, plugin.type);
|
||||
}
|
||||
|
||||
let payload = EMPTY_RESPONSE;
|
||||
|
|
@ -1170,7 +1175,7 @@ function* executePageLoadAction(pageAction: PageAction, span?: OtlpSpan) {
|
|||
// open response tab in debugger on exection of action on page load.
|
||||
// Only if current page is the page on which the action is executed.
|
||||
if (window.location.pathname.includes(pageAction.id))
|
||||
yield call(openDebugger);
|
||||
yield call(openDebugger, plugin.type);
|
||||
|
||||
if (isError) {
|
||||
AppsmithConsole.addErrors([
|
||||
|
|
@ -1563,9 +1568,20 @@ function triggerFileUploadInstrumentation(
|
|||
}
|
||||
|
||||
//Open debugger with response tab selected.
|
||||
function* openDebugger() {
|
||||
yield put(showDebugger(true));
|
||||
yield put(setDebuggerSelectedTab(DEBUGGER_TAB_KEYS.RESPONSE_TAB));
|
||||
function* openDebugger(pluginType: PluginType) {
|
||||
if (pluginType === PluginType.API) {
|
||||
yield put(
|
||||
setApiPaneDebuggerState({
|
||||
open: true,
|
||||
selectedTab: DEBUGGER_TAB_KEYS.RESPONSE_TAB,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
setQueryPaneDebuggerState({
|
||||
open: true,
|
||||
selectedTab: DEBUGGER_TAB_KEYS.RESPONSE_TAB,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Function to clear the action responses for the actions which are not executeOnLoad.
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ import {
|
|||
updateJSCollectionBodySuccess,
|
||||
updateJSFunction,
|
||||
executeJSFunctionInit,
|
||||
setJsPaneDebuggerState,
|
||||
} from "actions/jsPaneActions";
|
||||
import { getCurrentWorkspaceId } from "@appsmith/selectors/selectedWorkspaceSelectors";
|
||||
import { getPluginIdOfPackageName } from "sagas/selectors";
|
||||
|
|
@ -91,14 +92,13 @@ import type { EventLocation } from "@appsmith/utils/analyticsUtilTypes";
|
|||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
import { checkAndLogErrorsIfCyclicDependency } from "./helper";
|
||||
import { toast } from "design-system";
|
||||
import { setDebuggerSelectedTab, showDebugger } from "actions/debuggerActions";
|
||||
import { DEBUGGER_TAB_KEYS } from "components/editorComponents/Debugger/helpers";
|
||||
import { getDebuggerSelectedTab } from "selectors/debuggerSelectors";
|
||||
import { getIsServerDSLMigrationsEnabled } from "selectors/pageSelectors";
|
||||
import {
|
||||
getJSActionNameToDisplay,
|
||||
getJSActionPathNameToDisplay,
|
||||
} from "@appsmith/utils/actionExecutionUtils";
|
||||
import { getJsPaneDebuggerState } from "selectors/jsPaneSelectors";
|
||||
|
||||
export interface GenerateDefaultJSObjectProps {
|
||||
name: string;
|
||||
|
|
@ -434,15 +434,16 @@ export function* handleExecuteJSFunctionSaga(data: {
|
|||
// open response tab in debugger on runnning or page load js action.
|
||||
|
||||
if (doesURLPathContainCollectionId || openDebugger) {
|
||||
yield put(showDebugger(true));
|
||||
yield put(setJsPaneDebuggerState({ open: true }));
|
||||
|
||||
const debuggerSelectedTab: ReturnType<typeof getDebuggerSelectedTab> =
|
||||
yield select(getDebuggerSelectedTab);
|
||||
const { selectedTab: debuggerSelectedTab } = yield select(
|
||||
getJsPaneDebuggerState,
|
||||
);
|
||||
|
||||
yield put(
|
||||
setDebuggerSelectedTab(
|
||||
debuggerSelectedTab || DEBUGGER_TAB_KEYS.RESPONSE_TAB,
|
||||
),
|
||||
setJsPaneDebuggerState({
|
||||
selectedTab: debuggerSelectedTab || DEBUGGER_TAB_KEYS.RESPONSE_TAB,
|
||||
}),
|
||||
);
|
||||
}
|
||||
yield put({
|
||||
|
|
@ -481,8 +482,12 @@ export function* handleExecuteJSFunctionSaga(data: {
|
|||
} catch (error) {
|
||||
// open response tab in debugger on runnning js action.
|
||||
if (doesURLPathContainCollectionId) {
|
||||
yield put(showDebugger(true));
|
||||
yield put(setDebuggerSelectedTab(DEBUGGER_TAB_KEYS.RESPONSE_TAB));
|
||||
yield put(
|
||||
setJsPaneDebuggerState({
|
||||
open: true,
|
||||
selectedTab: DEBUGGER_TAB_KEYS.RESPONSE_TAB,
|
||||
}),
|
||||
);
|
||||
}
|
||||
AppsmithConsole.addErrors([
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import type { AppState } from "@appsmith/reducers";
|
||||
import { createSelector } from "reselect";
|
||||
import { combinedPreviewModeSelector } from "./editorSelectors";
|
||||
|
||||
type GetFormData = (
|
||||
state: AppState,
|
||||
|
|
@ -18,3 +20,12 @@ export const getApiRightPaneSelectedTab = (state: AppState) =>
|
|||
|
||||
export const getIsRunning = (state: AppState, apiId: string) =>
|
||||
state.ui.apiPane.isRunning[apiId];
|
||||
|
||||
export const getApiPaneDebuggerState = (state: AppState) =>
|
||||
state.ui.apiPane.debugger;
|
||||
|
||||
export const showApiPaneDebugger = createSelector(
|
||||
(state) => state.ui.apiPane.debugger.open,
|
||||
combinedPreviewModeSelector,
|
||||
(isOpen, isPreview) => isOpen && !isPreview,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
} from "@appsmith/workers/Evaluation/evaluationUtils";
|
||||
import { getDataTree } from "./dataTreeSelectors";
|
||||
import { combinedPreviewModeSelector } from "./editorSelectors";
|
||||
import type { CanvasDebuggerState } from "reducers/uiReducers/debuggerReducer";
|
||||
|
||||
interface ErrorObejct {
|
||||
[k: string]: Log;
|
||||
|
|
@ -148,8 +149,22 @@ export const getScrollPosition = (state: AppState) =>
|
|||
export const getDebuggerContext = (state: AppState) =>
|
||||
state.ui.debugger.context;
|
||||
|
||||
export const getDebuggerOpen = (state: AppState) => state.ui.debugger.isOpen;
|
||||
|
||||
export const showDebuggerFlag = createSelector(
|
||||
(state) => state.ui.debugger.isOpen,
|
||||
getDebuggerOpen,
|
||||
combinedPreviewModeSelector,
|
||||
(isOpen, isPreview) => isOpen && !isPreview,
|
||||
);
|
||||
|
||||
export const getCanvasDebuggerState = createSelector(
|
||||
showDebuggerFlag,
|
||||
getDebuggerContext,
|
||||
(openState, context): CanvasDebuggerState => {
|
||||
return {
|
||||
open: openState,
|
||||
selectedTab: context.selectedDebuggerTab,
|
||||
responseTabHeight: context.responseTabHeight,
|
||||
};
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -21,3 +21,6 @@ export const getFirstJSObject = (
|
|||
return identifyEntityFromPath(urlWithoutQueryParams);
|
||||
}
|
||||
};
|
||||
|
||||
export const getJsPaneDebuggerState = (state: AppState) =>
|
||||
state.ui.jsPane.debugger;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ export const getFirstQuery = (state: AppState): FocusEntityInfo | undefined => {
|
|||
}
|
||||
};
|
||||
|
||||
export const getQueryPaneDebuggerState = (state: AppState) =>
|
||||
state.ui.queryPane.debugger;
|
||||
|
||||
export const getQueryRunErrorMessage = (state: AppState, id: string) => {
|
||||
const { runErrorMessage } = state.ui.queryPane;
|
||||
return runErrorMessage[id];
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user