From e6db43d095f011e5c3db3b6ab76f1ca4dc408226 Mon Sep 17 00:00:00 2001 From: devanshu052000 Date: Fri, 9 May 2025 01:09:28 +0530 Subject: [PATCH 1/6] Integrate the popup hook in events manager in settings tab --- .../RightSideBar/Inspector/EventManager.jsx | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/frontend/src/AppBuilder/RightSideBar/Inspector/EventManager.jsx b/frontend/src/AppBuilder/RightSideBar/Inspector/EventManager.jsx index 6c8398724d..018dd28b28 100644 --- a/frontend/src/AppBuilder/RightSideBar/Inspector/EventManager.jsx +++ b/frontend/src/AppBuilder/RightSideBar/Inspector/EventManager.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useContext } from 'react'; +import React, { useState, useEffect, useContext, useRef } from 'react'; import { ActionTypes } from '@/Editor/ActionTypes'; import OverlayTrigger from 'react-bootstrap/OverlayTrigger'; @@ -32,6 +32,7 @@ import useStore from '@/AppBuilder/_stores/store'; import { useEventActions, useEvents } from '@/AppBuilder/_stores/slices/eventsSlice'; import ToggleGroup from '@/ToolJetUI/SwitchGroup/ToggleGroup'; import ToggleGroupItem from '@/ToolJetUI/SwitchGroup/ToggleGroupItem'; +import usePopoverObserver from '@/AppBuilder/_hooks/usePopoverObserver'; export const EventManager = ({ sourceId, @@ -82,6 +83,8 @@ export const EventManager = ({ const [events, setEvents] = useState([]); const [focusedEventIndex, setFocusedEventIndex] = useState(null); + const lastFocusedEventIndex = useRef(null); + const shouldSkipOnToggle = useRef(null); const { t } = useTranslation(); @@ -1006,10 +1009,21 @@ export const EventManager = ({ placement={popoverPlacement || 'left'} rootClose={true} overlay={eventPopover(event.event, index)} - onHide={() => setFocusedEventIndex(null)} onToggle={(showing) => { + // If the toggle action should be skipped (e.g., due to a previous state change), reset the flag and exit early. + if (shouldSkipOnToggle.current) { + shouldSkipOnToggle.current = false; + return; + } + + // If there is already a focused event, set the skip flag to prevent unnecessary state updates. + if (focusedEventIndex !== null) { + shouldSkipOnToggle.current = true; + } + if (showing) { setFocusedEventIndex(index); + lastFocusedEventIndex.current = index; } else { setFocusedEventIndex(null); } @@ -1018,6 +1032,7 @@ export const EventManager = ({ >
(document.getElementById('popover-basic').style.display = 'block'), + () => (document.getElementById('popover-basic').style.display = 'none') + ); + if (events.length === 0) { return ( <> From 3b69bb8a115ec8bdabfa219e5777423dcc8cbac2 Mon Sep 17 00:00:00 2001 From: devanshu052000 Date: Fri, 9 May 2025 01:38:51 +0530 Subject: [PATCH 2/6] Fixed one edge case --- frontend/src/AppBuilder/RightSideBar/Inspector/EventManager.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/AppBuilder/RightSideBar/Inspector/EventManager.jsx b/frontend/src/AppBuilder/RightSideBar/Inspector/EventManager.jsx index 018dd28b28..28bcb70f84 100644 --- a/frontend/src/AppBuilder/RightSideBar/Inspector/EventManager.jsx +++ b/frontend/src/AppBuilder/RightSideBar/Inspector/EventManager.jsx @@ -1017,7 +1017,7 @@ export const EventManager = ({ } // If there is already a focused event, set the skip flag to prevent unnecessary state updates. - if (focusedEventIndex !== null) { + if (focusedEventIndex !== null && showing) { shouldSkipOnToggle.current = true; } From c57971e6fb7226dbad4893102350e793e0e5d06f Mon Sep 17 00:00:00 2001 From: devanshu052000 Date: Fri, 9 May 2025 09:28:19 +0530 Subject: [PATCH 3/6] Added intersectionObserver to rest api's mthod dropdown --- .../QueryEditors/Restapi/index.jsx | 44 +++++++++++++++++++ frontend/src/_ui/Select/SelectComponent.jsx | 3 +- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/frontend/src/AppBuilder/QueryManager/QueryEditors/Restapi/index.jsx b/frontend/src/AppBuilder/QueryManager/QueryEditors/Restapi/index.jsx index 4c89ad849e..cf1be544ab 100644 --- a/frontend/src/AppBuilder/QueryManager/QueryEditors/Restapi/index.jsx +++ b/frontend/src/AppBuilder/QueryManager/QueryEditors/Restapi/index.jsx @@ -31,6 +31,9 @@ class Restapi extends React.Component { codeHinterHeight: 32, // Default height }; this.codeHinterRef = React.createRef(); + this.isMenuOpenRef = React.createRef(); + this.prevIsMenuOpenRef = React.createRef(false); + this.intersectionObserver = null; this.resizeObserver = null; } @@ -47,6 +50,9 @@ class Restapi extends React.Component { if (this.codeHinterRef.current && !this.resizeObserver) { this.setupResizeObserver(); } + if (!this.intersectionObserver) { + this.setupIntersectionObserver(); + } } componentDidMount() { @@ -75,6 +81,7 @@ class Restapi extends React.Component { }, 1000); this.setupResizeObserver(); + this.setupIntersectionObserver(); } catch (error) { console.log(error); } @@ -84,6 +91,9 @@ class Restapi extends React.Component { if (this.resizeObserver) { this.resizeObserver.disconnect(); } + if (this.intersectionObserver) { + this.intersectionObserver.disconnect(); + } } setupResizeObserver() { @@ -132,6 +142,33 @@ class Restapi extends React.Component { this.resizeObserver.observe(element); } + setupIntersectionObserver() { + const container = document.getElementsByClassName('query-details')[0]; + const trigger = document.querySelector('.react-select-restapi-method__control'); + + if (this.intersectionObserver) { + this.intersectionObserver.disconnect(); + } + + this.intersectionObserver = new IntersectionObserver( + ([entry]) => { + const popover = document.querySelector('.react-select-restapi-method__menu'); + if (entry.isIntersecting) { + if (this.prevIsMenuOpenRef.current) { + popover.style.display = 'block'; + this.prevIsMenuOpenRef.current = false; + } + } else if (this.isMenuOpenRef.current) { + popover.style.display = 'none'; + this.prevIsMenuOpenRef.current = true; + } + }, + { root: container, threshold: [0.5] } + ); + + this.intersectionObserver.observe(trigger); + } + initizalizeRetryNetworkErrorsToggle = () => { const isRetryNetworkErrorToggleUnused = this.props.options.retry_network_errors === null; if (isRetryNetworkErrorToggleUnused) { @@ -287,6 +324,13 @@ class Restapi extends React.Component { height={32} styles={this.customSelectStyles(this.props.darkMode, 91)} useCustomStyles={true} + customClassPrefix="-restapi-method" + onMenuOpen={() => { + this.isMenuOpenRef.current = true; + }} + onMenuClose={() => { + this.isMenuOpenRef.current = false; + }} />
); }; From 215a5305604d14efd651ebc5364a09c6e46bd449 Mon Sep 17 00:00:00 2001 From: devanshu052000 Date: Fri, 9 May 2025 12:10:34 +0530 Subject: [PATCH 4/6] Integrate the popup hook in change data source dropdown --- .../Components/ChangeDataSource.jsx | 21 ++++++++++++++++++- .../QueryEditors/Restapi/index.jsx | 6 +++--- frontend/src/_ui/Select/SelectComponent.jsx | 2 +- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/frontend/src/AppBuilder/QueryManager/Components/ChangeDataSource.jsx b/frontend/src/AppBuilder/QueryManager/Components/ChangeDataSource.jsx index 244668cf8a..85958cd97b 100644 --- a/frontend/src/AppBuilder/QueryManager/Components/ChangeDataSource.jsx +++ b/frontend/src/AppBuilder/QueryManager/Components/ChangeDataSource.jsx @@ -1,8 +1,20 @@ -import React from 'react'; +import React, { useState } from 'react'; import Select from '@/_ui/Select'; import { decodeEntities } from '@/_helpers/utils'; +import usePopoverObserver from '@/AppBuilder/_hooks/usePopoverObserver'; export const ChangeDataSource = ({ dataSources, onChange, value, isVersionReleased }) => { + const [isMenuOpen, setIsMenuOpen] = useState(false); + + usePopoverObserver( + document.getElementsByClassName('query-details')[0], + document.querySelector('.change-data-source-select.react-select__control'), + document.querySelector('.change-data-source-select.react-select__menu'), + isMenuOpen, + () => (document.querySelector('.change-data-source-select.react-select__menu').style.display = 'block'), + () => (document.querySelector('.change-data-source-select.react-select__menu').style.display = 'none') + ); + return (