From dfc99a7756a0373b7680a9e0af5f8ce8ee6ac7cf Mon Sep 17 00:00:00 2001 From: Prashant Shahi Date: Wed, 27 Mar 2024 23:15:40 +0545 Subject: [PATCH] Revert "Revert "Explorer Toolbar maximised and minimised (#4656)" (#4705)" This reverts commit c04d0e9419fb8aa6d08fa2dfcc0a0826a9f2ad74. --- frontend/src/constants/localStorage.ts | 1 + .../ExplorerOptions/ExplorerOptionWrapper.tsx | 56 +++++ .../ExplorerOptions.styles.scss | 4 +- .../ExplorerOptions/ExplorerOptions.tsx | 218 +++++++++++------- .../ExplorerOptionsDroppableArea.styles.scss | 55 +++++ .../ExplorerOptionsDroppableArea.tsx | 83 +++++++ .../src/container/ExplorerOptions/utils.ts | 52 +++++ .../src/container/LogsExplorerViews/index.tsx | 4 +- frontend/src/pages/TracesExplorer/index.tsx | 6 +- 9 files changed, 392 insertions(+), 87 deletions(-) create mode 100644 frontend/src/container/ExplorerOptions/ExplorerOptionWrapper.tsx create mode 100644 frontend/src/container/ExplorerOptions/ExplorerOptionsDroppableArea.styles.scss create mode 100644 frontend/src/container/ExplorerOptions/ExplorerOptionsDroppableArea.tsx diff --git a/frontend/src/constants/localStorage.ts b/frontend/src/constants/localStorage.ts index 296735b286..0ba6cac302 100644 --- a/frontend/src/constants/localStorage.ts +++ b/frontend/src/constants/localStorage.ts @@ -16,4 +16,5 @@ export enum LOCALSTORAGE { CHAT_SUPPORT = 'CHAT_SUPPORT', IS_IDENTIFIED_USER = 'IS_IDENTIFIED_USER', DASHBOARD_VARIABLES = 'DASHBOARD_VARIABLES', + SHOW_EXPLORER_TOOLBAR = 'SHOW_EXPLORER_TOOLBAR', } diff --git a/frontend/src/container/ExplorerOptions/ExplorerOptionWrapper.tsx b/frontend/src/container/ExplorerOptions/ExplorerOptionWrapper.tsx new file mode 100644 index 0000000000..bdb300c404 --- /dev/null +++ b/frontend/src/container/ExplorerOptions/ExplorerOptionWrapper.tsx @@ -0,0 +1,56 @@ +import { DndContext, DragEndEvent } from '@dnd-kit/core'; +import { useEffect, useState } from 'react'; + +import ExplorerOptions, { ExplorerOptionsProps } from './ExplorerOptions'; +import { + getExplorerToolBarVisibility, + setExplorerToolBarVisibility, +} from './utils'; + +type ExplorerOptionsWrapperProps = Omit< + ExplorerOptionsProps, + 'isExplorerOptionDrop' +>; + +function ExplorerOptionWrapper({ + disabled, + query, + isLoading, + onExport, + sourcepage, +}: ExplorerOptionsWrapperProps): JSX.Element { + const [isExplorerOptionHidden, setIsExplorerOptionHidden] = useState(false); + + useEffect(() => { + const toolbarVisibility = getExplorerToolBarVisibility(sourcepage); + setIsExplorerOptionHidden(!toolbarVisibility); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const handleDragEnd = (event: DragEndEvent): void => { + const { active, over } = event; + if ( + over !== null && + active.id === 'explorer-options-draggable' && + over.id === 'explorer-options-droppable' + ) { + setIsExplorerOptionHidden(true); + setExplorerToolBarVisibility(false, sourcepage); + } + }; + return ( + + + + ); +} + +export default ExplorerOptionWrapper; diff --git a/frontend/src/container/ExplorerOptions/ExplorerOptions.styles.scss b/frontend/src/container/ExplorerOptions/ExplorerOptions.styles.scss index d76d18bb4f..9f4441904d 100644 --- a/frontend/src/container/ExplorerOptions/ExplorerOptions.styles.scss +++ b/frontend/src/container/ExplorerOptions/ExplorerOptions.styles.scss @@ -3,7 +3,7 @@ } .explorer-update { position: fixed; - bottom: 16px; + bottom: 24px; left: calc(50% - 225px); display: flex; align-items: center; @@ -47,7 +47,7 @@ box-shadow: 4px 4px 16px 4px rgba(0, 0, 0, 0.25); backdrop-filter: blur(20px); position: fixed; - bottom: 16px; + bottom: 24px; left: calc(50% + 240px); transform: translate(calc(-50% - 120px), 0); transition: left 0.2s linear; diff --git a/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx b/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx index 8322c694d6..ab26e03abc 100644 --- a/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx +++ b/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx @@ -1,5 +1,7 @@ +/* eslint-disable react/jsx-props-no-spreading */ import './ExplorerOptions.styles.scss'; +import { useDraggable } from '@dnd-kit/core'; import { Color } from '@signozhq/design-tokens'; import { Button, @@ -31,7 +33,15 @@ import { useHandleExplorerTabChange } from 'hooks/useHandleExplorerTabChange'; import { useNotifications } from 'hooks/useNotifications'; import { mapCompositeQueryFromQuery } from 'lib/newQueryBuilder/queryBuilderMappers/mapCompositeQueryFromQuery'; import { Check, ConciergeBell, Disc3, Plus, X, XCircle } from 'lucide-react'; -import { CSSProperties, useCallback, useMemo, useRef, useState } from 'react'; +import { + CSSProperties, + Dispatch, + SetStateAction, + useCallback, + useMemo, + useRef, + useState, +} from 'react'; import { useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; import { AppState } from 'store/reducers'; @@ -41,6 +51,7 @@ import { DataSource } from 'types/common/queryBuilder'; import AppReducer from 'types/reducer/app'; import { USER_ROLES } from 'types/roles'; +import ExplorerOptionsDroppableArea from './ExplorerOptionsDroppableArea'; import { DATASOURCE_VS_ROUTES, generateRGBAFromHex, @@ -57,6 +68,8 @@ function ExplorerOptions({ onExport, query, sourcepage, + isExplorerOptionHidden = false, + setIsExplorerOptionHidden, }: ExplorerOptionsProps): JSX.Element { const [isExport, setIsExport] = useState(false); const [isSaveModalOpen, setIsSaveModalOpen] = useState(false); @@ -66,6 +79,7 @@ function ExplorerOptions({ const history = useHistory(); const ref = useRef(null); const isDarkMode = useIsDarkMode(); + const [isDragEnabled, setIsDragEnabled] = useState(false); const onModalToggle = useCallback((value: boolean) => { setIsExport(value); @@ -257,11 +271,31 @@ function ExplorerOptions({ [isDarkMode], ); + const { + attributes, + listeners, + setNodeRef, + transform, + isDragging, + } = useDraggable({ + id: 'explorer-options-draggable', + disabled: isDragEnabled, + }); + const isEditDeleteSupported = allowedRoles.includes(role as string); + const style: React.CSSProperties | undefined = transform + ? { + transform: `translate3d(${transform.x - 338}px, ${transform.y}px, 0)`, + width: `${400 - transform.y * 6}px`, + maxWidth: '440px', // initial width of the explorer options + overflow: 'hidden', + } + : undefined; + return ( <> - {isQueryUpdated && ( + {isQueryUpdated && !isExplorerOptionHidden && !isDragging && (
)} -
-
- - showSearch - placeholder="Select a view" - loading={viewsIsLoading || isRefetching} - value={viewName || undefined} - onSelect={handleSelect} - style={{ - minWidth: 170, - }} - dropdownStyle={dropdownStyle} - className="views-dropdown" - allowClear={{ - clearIcon: , - }} - onClear={handleClearSelect} - ref={ref} - > - {viewsData?.data?.data?.map((view) => { - const extraData = - view.extraData !== '' ? JSON.parse(view.extraData) : ''; - let bgColor = getRandomColor(); - if (extraData !== '') { - bgColor = extraData.color; - } - return ( - -
- {' '} - {view.name} -
-
- ); - })} - - - -
- -
- -
- - - + {viewsData?.data?.data?.map((view) => { + const extraData = + view.extraData !== '' ? JSON.parse(view.extraData) : ''; + let bgColor = getRandomColor(); + if (extraData !== '') { + bgColor = extraData.color; + } + return ( + +
+ {' '} + {view.name} +
+
+ ); + })} + - - - +
+ +
+ +
+ + + + + + + +
- + )} + + >; } -ExplorerOptions.defaultProps = { isLoading: false }; +ExplorerOptions.defaultProps = { + isLoading: false, + isExplorerOptionHidden: false, + setIsExplorerOptionHidden: undefined, +}; export default ExplorerOptions; diff --git a/frontend/src/container/ExplorerOptions/ExplorerOptionsDroppableArea.styles.scss b/frontend/src/container/ExplorerOptions/ExplorerOptionsDroppableArea.styles.scss new file mode 100644 index 0000000000..e092229bb9 --- /dev/null +++ b/frontend/src/container/ExplorerOptions/ExplorerOptionsDroppableArea.styles.scss @@ -0,0 +1,55 @@ +.explorer-option-droppable-container { + position: fixed; + bottom: 0; + width: -webkit-fill-available; + height: 24px; + display: flex; + justify-content: center; + border-radius: 10px 10px 0px 0px; + // box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.25); + // backdrop-filter: blur(20px); + + .explorer-actions-btn { + display: flex; + gap: 8px; + margin-right: 8px; + + .action-btn { + display: flex; + justify-content: center; + align-items: center; + border-radius: 10px 10px 0px 0px; + box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.25); + backdrop-filter: blur(20px); + height: 24px !important; + border: none; + } + } + + .explorer-show-btn { + border-radius: 10px 10px 0px 0px; + border: 1px solid var(--bg-slate-400); + background: rgba(22, 24, 29, 0.40); + box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.25); + backdrop-filter: blur(20px); + align-self: center; + padding: 8px 12px; + height: 24px !important; + + .menu-bar { + border-radius: 50px; + background: var(--bg-slate-200); + height: 4px; + width: 50px; + } + } +} + +.lightMode { + .explorer-option-droppable-container { + + .explorer-show-btn { + background: var(--bg-vanilla-400); + } + } +} \ No newline at end of file diff --git a/frontend/src/container/ExplorerOptions/ExplorerOptionsDroppableArea.tsx b/frontend/src/container/ExplorerOptions/ExplorerOptionsDroppableArea.tsx new file mode 100644 index 0000000000..33bef7c984 --- /dev/null +++ b/frontend/src/container/ExplorerOptions/ExplorerOptionsDroppableArea.tsx @@ -0,0 +1,83 @@ +/* eslint-disable no-nested-ternary */ +import './ExplorerOptionsDroppableArea.styles.scss'; + +import { useDroppable } from '@dnd-kit/core'; +import { Color } from '@signozhq/design-tokens'; +import { Button, Tooltip } from 'antd'; +import { Disc3, X } from 'lucide-react'; +import { Dispatch, SetStateAction } from 'react'; +import { DataSource } from 'types/common/queryBuilder'; + +import { setExplorerToolBarVisibility } from './utils'; + +interface DroppableAreaProps { + isQueryUpdated: boolean; + isExplorerOptionHidden?: boolean; + sourcepage: DataSource; + setIsExplorerOptionHidden?: Dispatch>; + handleClearSelect: () => void; + onUpdateQueryHandler: () => void; +} + +function ExplorerOptionsDroppableArea({ + isQueryUpdated, + isExplorerOptionHidden, + sourcepage, + setIsExplorerOptionHidden, + handleClearSelect, + onUpdateQueryHandler, +}: DroppableAreaProps): JSX.Element { + const { setNodeRef } = useDroppable({ + id: 'explorer-options-droppable', + }); + + const handleShowExplorerOption = (): void => { + if (setIsExplorerOptionHidden) { + setIsExplorerOptionHidden(false); + setExplorerToolBarVisibility(true, sourcepage); + } + }; + + return ( +
+ {isExplorerOptionHidden && ( + <> + {isQueryUpdated && ( +
+ +
+ )} + + + )} +
+ ); +} + +ExplorerOptionsDroppableArea.defaultProps = { + isExplorerOptionHidden: undefined, + setIsExplorerOptionHidden: undefined, +}; + +export default ExplorerOptionsDroppableArea; diff --git a/frontend/src/container/ExplorerOptions/utils.ts b/frontend/src/container/ExplorerOptions/utils.ts index e3ac710609..d94e64161e 100644 --- a/frontend/src/container/ExplorerOptions/utils.ts +++ b/frontend/src/container/ExplorerOptions/utils.ts @@ -1,5 +1,6 @@ import { Color } from '@signozhq/design-tokens'; import { showErrorNotification } from 'components/ExplorerCard/utils'; +import { LOCALSTORAGE } from 'constants/localStorage'; import { QueryParams } from 'constants/query'; import ROUTES from 'constants/routes'; import { mapQueryDataFromApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataFromApi'; @@ -67,3 +68,54 @@ export const generateRGBAFromHex = (hex: string, opacity: number): string => hex.slice(3, 5), 16, )}, ${parseInt(hex.slice(5, 7), 16)}, ${opacity})`; + +export const getExplorerToolBarVisibility = (dataSource: string): boolean => { + try { + const showExplorerToolbar = localStorage.getItem( + LOCALSTORAGE.SHOW_EXPLORER_TOOLBAR, + ); + if (showExplorerToolbar === null) { + const parsedShowExplorerToolbar: { + [DataSource.LOGS]: boolean; + [DataSource.TRACES]: boolean; + [DataSource.METRICS]: boolean; + } = { + [DataSource.METRICS]: true, + [DataSource.TRACES]: true, + [DataSource.LOGS]: true, + }; + localStorage.setItem( + LOCALSTORAGE.SHOW_EXPLORER_TOOLBAR, + JSON.stringify(parsedShowExplorerToolbar), + ); + return true; + } + const parsedShowExplorerToolbar = JSON.parse(showExplorerToolbar || '{}'); + return parsedShowExplorerToolbar[dataSource]; + } catch (error) { + console.error(error); + return false; + } +}; + +export const setExplorerToolBarVisibility = ( + value: boolean, + dataSource: string, +): void => { + try { + const showExplorerToolbar = localStorage.getItem( + LOCALSTORAGE.SHOW_EXPLORER_TOOLBAR, + ); + if (showExplorerToolbar) { + const parsedShowExplorerToolbar = JSON.parse(showExplorerToolbar); + parsedShowExplorerToolbar[dataSource] = value; + localStorage.setItem( + LOCALSTORAGE.SHOW_EXPLORER_TOOLBAR, + JSON.stringify(parsedShowExplorerToolbar), + ); + return; + } + } catch (error) { + console.error(error); + } +}; diff --git a/frontend/src/container/LogsExplorerViews/index.tsx b/frontend/src/container/LogsExplorerViews/index.tsx index a12fd80997..45b33d01af 100644 --- a/frontend/src/container/LogsExplorerViews/index.tsx +++ b/frontend/src/container/LogsExplorerViews/index.tsx @@ -14,7 +14,7 @@ import { PANEL_TYPES, } from 'constants/queryBuilder'; import { DEFAULT_PER_PAGE_VALUE } from 'container/Controls/config'; -import ExplorerOptions from 'container/ExplorerOptions/ExplorerOptions'; +import ExplorerOptionWrapper from 'container/ExplorerOptions/ExplorerOptionWrapper'; import GoToTop from 'container/GoToTop'; import LogsExplorerChart from 'container/LogsExplorerChart'; import LogsExplorerList from 'container/LogsExplorerList'; @@ -634,7 +634,7 @@ function LogsExplorerViews({ - -