From 9c949eda009a778bcadc47f3db8a4dbdff811517 Mon Sep 17 00:00:00 2001 From: Shaurya Sharma Date: Mon, 19 May 2025 02:17:06 +0530 Subject: [PATCH] Left sidebar changes added --- .../AppBuilder/LeftSidebar/LeftSidebar.jsx | 2 +- .../CustomJSONViewer/Components/ArrayNode.jsx | 3 ++- .../Components/BooleanNode.jsx | 4 +++- .../Components/FunctionNode.jsx | 4 +++- .../Components/NumberNode.jsx | 4 +++- .../Components/ObjectNode.jsx | 4 ++-- .../CustomJSONViewer/Components/Row.jsx | 19 +++++++------------ .../Components/StringNode.jsx | 2 +- .../CustomJSONViewer/styles.scss | 19 ++++++++++++++++--- .../LeftSidebarInspector/HiddenOptions.jsx | 11 +++++++---- .../LeftSidebarInspector/JSONTreeViewerV2.jsx | 18 +++++++++++++----- .../LeftSidebar/LeftSidebarInspector/Node.jsx | 4 ++-- .../_stores/slices/inspectorSlice.js | 12 +++++++++--- .../_stores/slices/leftSideBarSlice.js | 11 +++++++++-- frontend/src/_components/OverflowTooltip.jsx | 16 ++++++++++++++-- frontend/src/_styles/left-sidebar.scss | 18 +++++++++++++++++- 16 files changed, 109 insertions(+), 42 deletions(-) diff --git a/frontend/src/AppBuilder/LeftSidebar/LeftSidebar.jsx b/frontend/src/AppBuilder/LeftSidebar/LeftSidebar.jsx index aaf12714b9..b0e4170da1 100644 --- a/frontend/src/AppBuilder/LeftSidebar/LeftSidebar.jsx +++ b/frontend/src/AppBuilder/LeftSidebar/LeftSidebar.jsx @@ -238,7 +238,7 @@ export const BaseLeftSidebar = ({ toggleLeftSidebar(false); }} open={isSidebarOpen} - popoverContentClassName={`p-0 sidebar-h-100-popover ${selectedSidebarItem}`} + popoverContentClassName={`p-0 left-sidebar-scrollbar sidebar-h-100-popover ${selectedSidebarItem}`} side="right" popoverContent={renderPopoverContent()} popoverContentHeight={popoverContentHeight} diff --git a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/ArrayNode.jsx b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/ArrayNode.jsx index f9a0acf5ef..5c5d673c83 100644 --- a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/ArrayNode.jsx +++ b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/ArrayNode.jsx @@ -1,9 +1,10 @@ import React from 'react'; +import OverflowTooltip from '@/_components/OverflowTooltip'; const ArrayNode = ({ value }) => { return (
- {`[${value.length}]`} + {`[${value.length}]`}
); }; diff --git a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/BooleanNode.jsx b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/BooleanNode.jsx index d692a9c10c..65616c4883 100644 --- a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/BooleanNode.jsx +++ b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/BooleanNode.jsx @@ -4,7 +4,9 @@ import OverflowTooltip from '@/_components/OverflowTooltip'; const BooleanNode = ({ value }) => { return (
- {value.toString()} + + {value.toString()} +
); }; diff --git a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/FunctionNode.jsx b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/FunctionNode.jsx index 456b8238c4..858aaa4d8f 100644 --- a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/FunctionNode.jsx +++ b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/FunctionNode.jsx @@ -4,7 +4,9 @@ import OverflowTooltip from '@/_components/OverflowTooltip'; const FunctionNode = () => { return (
- function + + function +
); }; diff --git a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/NumberNode.jsx b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/NumberNode.jsx index 8eb6e981b9..18643844e6 100644 --- a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/NumberNode.jsx +++ b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/NumberNode.jsx @@ -4,7 +4,9 @@ import OverflowTooltip from '@/_components/OverflowTooltip'; const NumberNode = ({ value }) => { return (
- {value} + + {value} +
); }; diff --git a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/ObjectNode.jsx b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/ObjectNode.jsx index e89082cbd1..9977d6f108 100644 --- a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/ObjectNode.jsx +++ b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/ObjectNode.jsx @@ -1,9 +1,9 @@ import React from 'react'; - +import OverflowTooltip from '@/_components/OverflowTooltip'; const ObjectNode = ({ value }) => { return (
- {`{${Object.keys(value).length}}`} + {`{${Object.keys(value).length}}`}
); }; diff --git a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/Row.jsx b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/Row.jsx index 4cc61fd1a4..f7d74ff5a6 100644 --- a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/Row.jsx +++ b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/Components/Row.jsx @@ -7,6 +7,7 @@ import NullNode from './NullNode'; import ArrayNode from './ArrayNode'; import ObjectNode from './ObjectNode'; import SolidIcon from '@/_ui/Icon/SolidIcons'; +import OverflowTooltip from '@/_components/OverflowTooltip'; import { ToolTip } from '@/_components/ToolTip'; import { DefaultCopyIcon } from '../../DefaultCopyIcon'; import { copyToClipboard } from '../../utils'; @@ -35,8 +36,8 @@ const Row = ({ label, value, level = 1, absolutePath }) => { const isArray = Array.isArray(value); return ( -
-
1 ? '8px' : '0px' }}> +
+
setIsExpanded((prev) => !prev)}>
{(isArray || isObject) && @@ -59,13 +60,13 @@ const Row = ({ label, value, level = 1, absolutePath }) => { ))}
- {label} + {label}
- + { copyToClipboard(absolutePath); @@ -89,20 +90,14 @@ const Row = ({ label, value, level = 1, absolutePath }) => {
{isExpanded && isObject && ( -
+
{Object.entries(value).map(([key, val]) => ( ))}
)} {isExpanded && isArray && ( -
+
{value.map((item, index) => { return ( { return (
- {`"${value}"`} + {`"${value}"`}
); }; diff --git a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/styles.scss b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/styles.scss index 4121cc0e4f..feebea681e 100644 --- a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/styles.scss +++ b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/CustomJSONViewer/styles.scss @@ -4,9 +4,20 @@ font-family: "IBM Plex Sans"; font-size: 12px; color: var(--text-default, #1B1F24); - + overflow-x: auto; + min-width: 0; + + // Hide scrollbar for Chrome, Safari and Opera + &::-webkit-scrollbar { + display: none; + } + + // Hide scrollbar for IE, Edge and Firefox + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ .json-viewer-row-container { + min-width: max-content; &:hover { background-color: var(--interactive-overlays-fill-hover); @@ -22,6 +33,7 @@ height: 20px; align-items: center; overflow: hidden; + cursor: pointer; .json-viewer-expand-icon { width: 12px; @@ -33,9 +45,8 @@ } .json-viewer-label-container { - margin-left: 8px; margin-right: 4px; - flex-shrink: 0; /* don’t shrink */ + flex-shrink: 0; /* don't shrink */ white-space: nowrap; } @@ -54,6 +65,8 @@ width:40px; align-items: center; flex-shrink: 0; + position: absolute; + right:20px; .json-viewer-action-icon { display: flex; diff --git a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/HiddenOptions.jsx b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/HiddenOptions.jsx index 6c5f1daad0..5e407f75a1 100644 --- a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/HiddenOptions.jsx +++ b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/HiddenOptions.jsx @@ -13,7 +13,6 @@ export const HiddenOptions = (props) => { const [showMenu, setShowMenu] = useState(false); const closeMenu = () => { setShowMenu(false); - setActionClicked(false); }; const copyPath = () => { @@ -39,6 +38,11 @@ export const HiddenOptions = (props) => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + // This is to ensure that the actionClicked state is updated when the menu is shown or deleted on the next render to avoid misplacing the Popover + useEffect(() => { + setTimeout(() => setActionClicked(showMenu), 0); + }, [showMenu]); + const renderOptions = () => { return nodeSpecificFilteredActions?.map((actionOption, index) => { const { name, icon, src, iconName, dispatchAction, width = 12, height = 12 } = actionOption; @@ -69,7 +73,7 @@ export const HiddenOptions = (props) => { alignItems: 'center', justifyContent: 'center', }} - className="d-flex position-absolute" + className={cx('d-flex position-absolute', { 'show-menu': showMenu })} > {renderOptions()} { rootClose={false} show={showMenu} overlay={ - + e.stopPropagation()}>
{ onClick={(event) => { event.stopPropagation(); setShowMenu((prev) => !prev); - setActionClicked((prev) => !prev); }} className="node-action-icon" style={{ diff --git a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/JSONTreeViewerV2.jsx b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/JSONTreeViewerV2.jsx index a47d9fa060..b45d0bfc20 100644 --- a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/JSONTreeViewerV2.jsx +++ b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/JSONTreeViewerV2.jsx @@ -4,7 +4,6 @@ import useStore from '@/AppBuilder/_stores/store'; import { shallow } from 'zustand/shallow'; import Fuse from 'fuse.js'; import JSONViewer from './JSONViewer'; -import { SearchBox } from '@/_components'; import { Node } from './Node'; import { v4 as uuidv4 } from 'uuid'; import InputComponent from '@/components/ui/Input/Index'; @@ -16,12 +15,21 @@ const JSONTreeViewerV2 = ({ data = {}, iconsList = [], darkMode, searchablePaths const getComponentDefinition = useStore((state) => state.getComponentDefinition, shallow); const getResolvedValue = useStore((state) => state.getResolvedValue, shallow); const setSearchValue = useStore((state) => state.setInspectorSearchValue, shallow); - const [selectedNodePath, setSelectedNodePath] = React.useState(null); + const selectedNodePath = useStore((state) => state.selectedNodePath, shallow); + const setSelectedNodePath = useStore((state) => state.setSelectedNodePath, shallow); + const selectedNodes = useStore((state) => state.selectedNodes, shallow); function fuzzySearch(query, searchablePaths) { const list = Array.from(searchablePaths); - const fuse = new Fuse(list, { threshold: 0.3 }); + const fuse = new Fuse(list, { + threshold: 0.2, + minMatchCharLength: 2, + includeScore: true, + distance: 1000, + tokenize: true, + matchAllTokens: true, + }); return fuse.search(query).map((result) => result.item); } @@ -106,8 +114,8 @@ const JSONTreeViewerV2 = ({ data = {}, iconsList = [], darkMode, searchablePaths const expandedIdsSet = new Set(expandedIds); const filtered = flattendedData.filter((item) => { const { metadata } = item || {}; - const { path } = metadata || {}; - return expandedIdsSet.has(path); + const { actualPath, path } = metadata || {}; + return expandedIdsSet.has(actualPath || path); }); return filtered diff --git a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/Node.jsx b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/Node.jsx index bd7143ee9d..9f33c0c8d9 100644 --- a/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/Node.jsx +++ b/frontend/src/AppBuilder/LeftSidebar/LeftSidebarInspector/Node.jsx @@ -65,8 +65,8 @@ export const Node = (props) => { const onExpand = (node) => { const { element } = node || {}; const { metadata } = element || {}; - const { path } = metadata || {}; - setSelectedNodes(path); + const { path, actualPath } = metadata || {}; + setSelectedNodes(actualPath || path); }; const onSelect = (node) => { diff --git a/frontend/src/AppBuilder/_stores/slices/inspectorSlice.js b/frontend/src/AppBuilder/_stores/slices/inspectorSlice.js index 521fff3b1b..c20768a257 100644 --- a/frontend/src/AppBuilder/_stores/slices/inspectorSlice.js +++ b/frontend/src/AppBuilder/_stores/slices/inspectorSlice.js @@ -3,6 +3,7 @@ const initialState = { searchedNodes: new Set(), inspectorSearchValue: '', inspectorSearchResults: new Set(), + selectedNodePath: null, }; export const createInspectorSlice = (set, get) => ({ @@ -31,6 +32,9 @@ export const createInspectorSlice = (set, get) => ({ setInspectorSearchResults: (results) => { set({ inspectorSearchResults: results }); }, + setSelectedNodePath: (path) => { + set({ selectedNodePath: path }); + }, getAllComponentChildrenById: (id) => { const { getComponentDefinition, getResolvedComponent } = get(); const component = getComponentDefinition(id); @@ -97,7 +101,8 @@ export const createInspectorSlice = (set, get) => ({ .filter((item) => item.name) .reduce((acc, { key, name, parentType }) => { const currentPath = `components.${name}`; - searchablePaths.add(currentPath); + const actualPath = `${path}.${name}`; + searchablePaths.add(actualPath); const children = getAllComponentChildrenById(key).map((childKey) => { const childComponent = getComponentDefinition(childKey); let parentComponentType = null; @@ -115,13 +120,14 @@ export const createInspectorSlice = (set, get) => ({ return [ ...acc, { - id: currentPath, + id: actualPath, name, - children: reduceData(children, currentPath, level + 1), + children: reduceData(children, actualPath, level + 1), metadata: { type: 'components', path: currentPath, parentType: parentType, + actualPath, }, }, ]; diff --git a/frontend/src/AppBuilder/_stores/slices/leftSideBarSlice.js b/frontend/src/AppBuilder/_stores/slices/leftSideBarSlice.js index 367ca4cf0c..bdb02022dd 100644 --- a/frontend/src/AppBuilder/_stores/slices/leftSideBarSlice.js +++ b/frontend/src/AppBuilder/_stores/slices/leftSideBarSlice.js @@ -30,8 +30,15 @@ export const createLeftSideBarSlice = (set, get) => ({ ), setPathToBeInspected: (pathToBeInspected) => set(() => ({ pathToBeInspected }), false, 'setPathToBeInspected'), setComponentToInspect: (componentToInspect) => { - const { setPathToBeInspected, setSelectedSidebarItem, toggleLeftSidebar, selectedSidebarItem } = get(); - setPathToBeInspected(['components', componentToInspect]); + const { + setPathToBeInspected, + setSelectedSidebarItem, + toggleLeftSidebar, + selectedSidebarItem, + setSelectedNodePath, + } = get(); + // setPathToBeInspected(['components', componentToInspect]); + setSelectedNodePath(`components.${componentToInspect}`); if (selectedSidebarItem !== 'inspect') { setSelectedSidebarItem('inspect'); toggleLeftSidebar(true); diff --git a/frontend/src/_components/OverflowTooltip.jsx b/frontend/src/_components/OverflowTooltip.jsx index 1523ae449a..f5c4dd1cfd 100644 --- a/frontend/src/_components/OverflowTooltip.jsx +++ b/frontend/src/_components/OverflowTooltip.jsx @@ -1,7 +1,14 @@ import React, { useEffect, useRef, useState } from 'react'; import { ToolTip } from '@/_components'; -export default function OverflowTooltip({ children, className, whiteSpace = 'nowrap', placement = 'bottom', ...rest }) { +export default function OverflowTooltip({ + children, + className, + whiteSpace = 'nowrap', + placement = 'bottom', + maxLetters, + ...rest +}) { const [isOverflowed, setIsOverflow] = useState(false); const textElementRef = useRef(); @@ -12,6 +19,11 @@ export default function OverflowTooltip({ children, className, whiteSpace = 'now ); }, [children]); + const displayText = + maxLetters && typeof children === 'string' && children.length > maxLetters + ? `${children.substring(0, maxLetters)}...` + : children; + return (