Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Inspect State CTA for discovery #39100

Merged
merged 16 commits into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,10 @@ const SalesforceIcon = importSvg(
async () => import("../__assets__/icons/ads/salesforce.svg"),
);

const StateInspectorIcon = importSvg(
async () => import("../__assets__/icons/ads/state-inspector.svg"),
);

const MdFileIcon = importSvg(
async () => import("../__assets__/icons/ads/md-file.svg"),
);
Expand Down Expand Up @@ -1560,6 +1564,7 @@ const ICON_LOOKUP = {
zendesk: ZendeskIcon,
"google-drive": GoogleDriveIcon,
salesforce: SalesforceIcon,
"state-inspector": StateInspectorIcon,
};

export const IconCollection = Object.keys(ICON_LOOKUP);
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 0 additions & 7 deletions app/client/src/actions/debuggerActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,3 @@ export const showDebuggerLogs = () => {
type: ReduxActionTypes.SHOW_DEBUGGER_LOGS,
};
};

export const setDebuggerStateInspectorSelectedItem = (payload: string) => {
return {
type: ReduxActionTypes.SET_DEBUGGER_STATE_INSPECTOR_SELECTED_ITEM,
payload,
};
};
8 changes: 8 additions & 0 deletions app/client/src/actions/debuggerStateInspector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";

export const setDebuggerStateInspectorSelectedItem = (payload: string) => {
return {
type: ReduxActionTypes.SET_DEBUGGER_STATE_INSPECTOR_SELECTED_ITEM,
payload,
};
};
1 change: 1 addition & 0 deletions app/client/src/ce/constants/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1775,6 +1775,7 @@ export const CONTEXT_SETTINGS = () => "Settings";
export const CONTEXT_PARTIAL_EXPORT = () => "Export";
export const CONTEXT_PARTIAL_IMPORT = () => "Import";
export const CONTEXT_SET_AS_HOME_PAGE = () => "Set as home page";
export const CONTEXT_INSPECT_STATE = () => "Inspect state";
export const PAGE = () => "Page";
export const PAGES = () => "Pages";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import * as Styled from "./styles";
import { CONTAINER_MAX_HEIGHT_PX, PEEK_OVERLAY_DELAY } from "./constants";
import { getDataTypeHeader, getPropertyData } from "./utils";
import { JSONViewer, Size } from "../../JSONViewer";
import { InspectStateHeaderButton } from "components/editorComponents/Debugger/StateInspector/CTAs";
import { getEntityPayloadInfo } from "ee/utils/getEntityPayloadInfo";

export interface PeekOverlayStateProps {
objectName: string;
Expand Down Expand Up @@ -54,6 +56,10 @@ export function PeekOverlayPopUpContent(
configTree,
);

const { id } = getEntityPayloadInfo[dataTree[objectName].ENTITY_TYPE](
configTree[objectName],
);

const [jsData, dataType] = useMemo(
// Because getPropertyData can return a function
// And we don't want to execute it.
Expand Down Expand Up @@ -98,9 +104,15 @@ export function PeekOverlayPopUpContent(
onWheel={onWheel}
{...getPositionValues()}
>
<Styled.DataType className="first-letter:uppercase">
{dataType}
</Styled.DataType>
<Styled.Header>
<Styled.DataType className="first-letter:uppercase">
{dataType}
</Styled.DataType>
{propertyPath.length === 0 && (
<InspectStateHeaderButton entityId={id} />
)}
</Styled.Header>

<Styled.BlockDivider />
<Styled.PeekOverlayData id="t--peek-overlay-data" ref={dataWrapperRef}>
{(dataType === "object" || dataType === "array") && jsData !== null && (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import styled from "styled-components";
import { Divider } from "@appsmith/ads";
import { Divider, Flex } from "@appsmith/ads";

export const PeekOverlayContainer = styled.div<{
$left: string;
Expand All @@ -17,12 +17,18 @@ export const PeekOverlayContainer = styled.div<{
bottom: ${({ $bottom }) => $bottom};
`;

export const Header = styled(Flex)`
padding: var(--ads-v2-spaces-2) var(--ads-v2-spaces-2) var(--ads-v2-spaces-2)
var(--ads-v2-spaces-4);
justify-content: space-between;
align-items: center;
gap: var(--ads-v2-spaces-3);
height: 32px;
`;

export const DataType = styled.div`
height: 24px;
color: var(--appsmith-color-black-700);
padding: var(--ads-v2-spaces-2) 0 var(--ads-v2-spaces-2)
var(--ads-v2-spaces-4);
font-size: 10px;
font-size: 12px;
`;

export const BlockDivider = styled(Divider)`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { useCallback } from "react";
import { Button } from "@appsmith/ads";
import { setDebuggerStateInspectorSelectedItem } from "actions/debuggerStateInspector";
import { useDispatch } from "react-redux";
import { DEBUGGER_TAB_KEYS } from "../../constants";
import { useDebuggerConfig } from "../../hooks/useDebuggerConfig";
import { CONTEXT_INSPECT_STATE, createMessage } from "ee/constants/messages";

interface Props {
entityId: string;
disabled?: boolean;
}

export function InspectStateHeaderButton({ disabled, entityId }: Props) {
const dispatch = useDispatch();
const config = useDebuggerConfig();

const handleSelect = useCallback(() => {
dispatch(setDebuggerStateInspectorSelectedItem(entityId));
dispatch(
config.set({ open: true, selectedTab: DEBUGGER_TAB_KEYS.STATE_TAB }),
);
}, [config, dispatch, entityId]);

return (
<Button
disabled={disabled}
kind="tertiary"
onClick={handleSelect}
size="sm"
startIcon="state-inspector"
>
{createMessage(CONTEXT_INSPECT_STATE)}
</Button>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { useCallback } from "react";
import { MenuItem } from "@appsmith/ads";
import { CONTEXT_INSPECT_STATE, createMessage } from "ee/constants/messages";
import { setDebuggerStateInspectorSelectedItem } from "actions/debuggerStateInspector";
import { useDispatch } from "react-redux";
import { DEBUGGER_TAB_KEYS } from "../../constants";
import { useDebuggerConfig } from "../../hooks/useDebuggerConfig";

interface Props {
entityId: string;
disabled?: boolean;
}

export function InspectStateMenuItem({ disabled, entityId }: Props) {
const dispatch = useDispatch();
const config = useDebuggerConfig();

const handleSelect = useCallback(() => {
dispatch(setDebuggerStateInspectorSelectedItem(entityId));
dispatch(
config.set({ open: true, selectedTab: DEBUGGER_TAB_KEYS.STATE_TAB }),
);
}, [config, dispatch, entityId]);

return (
<MenuItem
disabled={disabled}
onSelect={handleSelect}
startIcon="state-inspector"
>
{createMessage(CONTEXT_INSPECT_STATE)}
</MenuItem>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { useCallback } from "react";
import { Button, Tooltip } from "@appsmith/ads";
import { setDebuggerStateInspectorSelectedItem } from "actions/debuggerStateInspector";
import { useDispatch } from "react-redux";
import { DEBUGGER_TAB_KEYS } from "../../constants";
import { useDebuggerConfig } from "../../hooks/useDebuggerConfig";
import { CONTEXT_INSPECT_STATE, createMessage } from "ee/constants/messages";

interface Props {
entityId: string;
disabled?: boolean;
}

export function InspectStateToolbarButton({ disabled, entityId }: Props) {
const dispatch = useDispatch();
const config = useDebuggerConfig();

const handleSelect = useCallback(() => {
dispatch(setDebuggerStateInspectorSelectedItem(entityId));
dispatch(
config.set({ open: true, selectedTab: DEBUGGER_TAB_KEYS.STATE_TAB }),
);
}, [config, dispatch, entityId]);

return (
<Tooltip content={createMessage(CONTEXT_INSPECT_STATE)}>
<Button
disabled={disabled}
isIconButton
kind="tertiary"
onClick={handleSelect}
startIcon="state-inspector"
/>
</Tooltip>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { InspectStateHeaderButton } from "./InspectStateHeaderButton";
export { InspectStateToolbarButton } from "./InspectStateToolbarButton";
export { InspectStateMenuItem } from "./InspectStateMenuItem";
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function useGetDisplayData(selectedItemName: string) {
const jsActions = useSelector(getJSCollections);

return useMemo(() => {
if (selectedItemName in dataTree && selectedItemName in configTree) {
if (selectedItemName in dataTree) {
return filterInternalProperties(
selectedItemName,
dataTree[selectedItemName],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useDispatch, useSelector } from "react-redux";
import { setDebuggerStateInspectorSelectedItem } from "actions/debuggerActions";
import { getDebuggerStateInspectorSelectedItem } from "selectors/debuggerSelectors";
import { setDebuggerStateInspectorSelectedItem } from "actions/debuggerStateInspector";
import { getDebuggerStateInspectorSelectedItem } from "selectors/debuggerStateInspector";

export const useStateInspectorState: () => [
string | undefined,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useMemo } from "react";
import { useLocation } from "react-router";
import { identifyEntityFromPath } from "navigation/FocusEntity";
import { useSelector } from "react-redux";
import { getIDEViewMode } from "selectors/ideSelectors";
import { getDebuggerPaneConfig } from "../utils/getDebuggerPaneConfig";

export const useDebuggerConfig = () => {
const location = useLocation();
const currentFocus = identifyEntityFromPath(location.pathname);
const ideState = useSelector(getIDEViewMode);

return useMemo(
() => getDebuggerPaneConfig(currentFocus, ideState),
[currentFocus, ideState],
);
};
Original file line number Diff line number Diff line change
@@ -1,68 +1,11 @@
import { useLocation } from "react-router";
import { useDispatch, useSelector } from "react-redux";
import { DEBUGGER_TAB_KEYS } from "../constants";
import { setCanvasDebuggerState } from "actions/debuggerActions";
import AnalyticsUtil from "ee/utils/AnalyticsUtil";
import type { FocusEntityInfo } from "navigation/FocusEntity";
import { FocusEntity, identifyEntityFromPath } from "navigation/FocusEntity";
import { setJsPaneDebuggerState } from "actions/jsPaneActions";
import { getJsPaneDebuggerState } from "selectors/jsPaneSelectors";
import {
getPluginActionDebuggerState,
setPluginActionEditorDebuggerState,
} from "PluginActionEditor/store";
import { getCanvasDebuggerState } from "selectors/debuggerSelectors";
import { getIDEViewMode } from "selectors/ideSelectors";
import { useDispatch, useSelector } from "react-redux";
import { EditorViewMode } from "IDE/Interfaces/EditorTypes";
import type { ReduxAction } from "actions/ReduxActionTypes";
import type { CanvasDebuggerState } from "reducers/uiReducers/debuggerReducer";
import type { AppState } from "ee/reducers";

interface Config {
set: (
payload: Partial<CanvasDebuggerState>,
) => ReduxAction<Partial<CanvasDebuggerState>>;
get: (state: AppState) => CanvasDebuggerState;
}

const canvasDebuggerConfig: Config = {
set: setCanvasDebuggerState,
get: getCanvasDebuggerState,
};

const pluginActionEditorDebuggerConfig: Config = {
set: setPluginActionEditorDebuggerState,
get: getPluginActionDebuggerState,
};

export const getDebuggerPaneConfig = (
focusInfo: FocusEntityInfo,
ideViewMode: EditorViewMode,
): Config => {
if (ideViewMode === EditorViewMode.SplitScreen) {
return canvasDebuggerConfig;
}

switch (focusInfo.entity) {
case FocusEntity.QUERY:
return pluginActionEditorDebuggerConfig;
case FocusEntity.JS_OBJECT:
return {
set: setJsPaneDebuggerState,
get: getJsPaneDebuggerState,
};
default:
return canvasDebuggerConfig;
}
};
import { useDebuggerConfig } from "./useDebuggerConfig";

const useDebuggerTriggerClick = () => {
const location = useLocation();
const currentFocus = identifyEntityFromPath(location.pathname);
const ideState = useSelector(getIDEViewMode);
const dispatch = useDispatch();

const config = getDebuggerPaneConfig(currentFocus, ideState);
const config = useDebuggerConfig();

const state = useSelector(config.get);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {
getPluginActionDebuggerState,
setPluginActionEditorDebuggerState,
} from "PluginActionEditor/store";
import { FocusEntity, type FocusEntityInfo } from "navigation/FocusEntity";
import { EditorViewMode } from "IDE/Interfaces/EditorTypes";
import { setJsPaneDebuggerState } from "actions/jsPaneActions";
import { getJsPaneDebuggerState } from "selectors/jsPaneSelectors";
import type { CanvasDebuggerState } from "reducers/uiReducers/debuggerReducer";
import type { ReduxAction } from "actions/ReduxActionTypes";
import type { AppState } from "ee/reducers";
import { setCanvasDebuggerState } from "actions/debuggerActions";
import { getCanvasDebuggerState } from "selectors/debuggerSelectors";

interface Config {
set: (
payload: Partial<CanvasDebuggerState>,
) => ReduxAction<Partial<CanvasDebuggerState>>;
get: (state: AppState) => CanvasDebuggerState;
}

const canvasDebuggerConfig: Config = {
set: setCanvasDebuggerState,
get: getCanvasDebuggerState,
};
const pluginActionEditorDebuggerConfig: Config = {
set: setPluginActionEditorDebuggerState,
get: getPluginActionDebuggerState,
};

export const getDebuggerPaneConfig = (
focusInfo: FocusEntityInfo,
ideViewMode: EditorViewMode,
): Config => {
if (ideViewMode === EditorViewMode.SplitScreen) {
return canvasDebuggerConfig;
}

switch (focusInfo.entity) {
case FocusEntity.QUERY:
return pluginActionEditorDebuggerConfig;
case FocusEntity.JS_OBJECT:
return {
set: setJsPaneDebuggerState,
get: getJsPaneDebuggerState,
};
default:
return canvasDebuggerConfig;
}
};
Loading
Loading