pawarprasad123 commented on code in PR #688:
URL: https://github.com/apache/atlas/pull/688#discussion_r3977320247
##########
dashboard/src/views/SideBar/SideBarBody.tsx:
##########
@@ -101,61 +93,122 @@ const DrawerHeader = styled("div")(({ theme }) => ({
marginBottom: "1rem",
}));
+
const SideBarBody = (props: {
- loading: boolean;
- handleOpenModal: any;
- handleOpenAboutModal: any;
+ handleOpenModal: () => void;
+ handleOpenAboutModal: () => void;
}) => {
const location = useLocation();
const routes = useRoutes(AppRoutes as RouteObject[]);
const history = useHistory();
const dispatch = useAppDispatch();
- const { loading: loader, handleOpenModal, handleOpenAboutModal } = props;
+ const { handleOpenModal, handleOpenAboutModal } = props;
const navigate = useNavigate();
- const { loading } = useSelector((state: TypeHeaderState) =>
state.typeHeader);
- const { relationshipSearch = {} } = globalSessionData || {};
+ const relationshipSearch = Boolean(globalSessionData?.relationshipSearch);
const [open, setOpen] = useState(true);
const [searchTerm, setSearchTerm] = useState<string>("");
+ const { data: versionData, loading: isVersionLoading, error: versionError }
= useAppSelector((state) => state.session?.versionData || {});
+ const activeModule = useMemo(() => {
+ const searchParams = new URLSearchParams(location.search);
+ if (searchParams.get("isCF") === "true") return "customFilters";
+ if (location.pathname.includes("/glossary") || !!searchParams.get("gtype")
|| !!searchParams.get("term") || !!searchParams.get("category")) return
"glossary";
+ if (location.pathname.includes("/administrator/businessMetadata")) return
"businessMetadata";
+ if (!!searchParams.get("tag") ||
location.pathname.includes("/tag/tagAttribute")) return "classification";
+ if (!!searchParams.get("relationshipName") ||
location.pathname.includes("/relationshipDetailPage")) return "relationships";
+ if (!!searchParams.get("type") ||
location.pathname.includes("/detailPage")) return "entities";
+ return null;
+ }, [location.pathname, location.search]);
+
+ const isCustomFilterActive = activeModule === "customFilters";
+ const isGlossaryActive = activeModule === "glossary";
+ const isBusinessMetadataActive = activeModule === "businessMetadata";
+ const isClassificationActive = activeModule === "classification";
+ const isRelationshipActive = activeModule === "relationships";
+ const isEntitiesActive = activeModule === "entities";
+
+ const modules = useMemo(() => [
+ { id: "entities", title: "Entities", isActive: isEntitiesActive, iconUrl:
"/img/sidebar-icons/icon-entities.svg", Component: EntitiesTree, isVisible:
true },
+ { id: "classification", title: "Classifications", isActive:
isClassificationActive, iconUrl: "/img/sidebar-icons/icon-classifications.svg",
Component: ClassificationTree, isVisible: true },
+ { id: "glossary", title: "Glossary", isActive: isGlossaryActive, iconUrl:
"/img/sidebar-icons/icon-glossary.svg", Component: GlossaryTree, isVisible:
true },
+ { id: "businessMetadata", title: "Business Metadata", isActive:
isBusinessMetadataActive, iconUrl:
"/img/sidebar-icons/icon-business-metadata.svg", Component:
BusinessMetadataTree, isVisible: true },
+ { id: "relationships", title: "Relationships", isActive:
isRelationshipActive, iconUrl: "/img/sidebar-icons/icon-relationships.svg",
Component: RelationshipsTree, isVisible: !!relationshipSearch },
+ { id: "customFilters", title: "Custom Filters", isActive:
isCustomFilterActive, iconUrl: "/img/sidebar-icons/icon-custom-filters.svg",
Component: CustomFiltersTree, isVisible: true }
+ ], [
+ isEntitiesActive,
+ isClassificationActive,
+ isGlossaryActive,
+ isBusinessMetadataActive,
+ isRelationshipActive,
+ isCustomFilterActive,
+ relationshipSearch
+ ]);
+
+ const [popoverAnchor, setPopoverAnchor] = useState<HTMLButtonElement |
null>(null);
+ const [activePopover, setActivePopover] = useState<string | null>(null);
+ const [popoverMaxHeight, setPopoverMaxHeight] = useState<string>("calc(100vh
- 100px)");
+ const [isBottomHalf, setIsBottomHalf] = useState<boolean>(false);
+ const [popoverContainer, setPopoverContainer] = useState<HTMLDivElement |
null>(null);
+ const [sidebarRefs, setSidebarRefs] = useState<Record<string, HTMLDivElement
| null>>({});
+ const refCallbacks = useRef<Record<string, (el: HTMLDivElement | null) =>
void>>({});
+ const setSidebarRef = useCallback((id: string) => {
+ if (!refCallbacks.current[id]) {
+ refCallbacks.current[id] = (el: HTMLDivElement | null) => {
+ setSidebarRefs(prev => prev[id] === el ? prev : { ...prev, [id]: el });
+ };
+ }
+ return refCallbacks.current[id];
+ }, []);
- const handleDrawerOpen = () => {
- setOpen(!open);
- };
- const [position, setPosition] = useState<string |
number>(defaultDrawerWidth);
- const draggerRef = useRef<HTMLDivElement>(null);
- const headerRef = useRef<HTMLDivElement>(null);
- const windowWidth = window.innerWidth;
- const minPosition = 300;
- const maxPosition = windowWidth * 0.6;
+ const handlePopoverOpen = (event: React.MouseEvent<HTMLButtonElement>, id:
string) => {
+ const target = event.currentTarget;
- const handleMouseMove = (e: MouseEvent) => {
- let newPosition = e.clientX;
+ setPopoverAnchor(target);
+ setActivePopover(id);
- if (newPosition < minPosition) {
- newPosition = minPosition;
- } else if (newPosition > maxPosition) {
- newPosition = maxPosition;
- }
+ // Calculate remaining screen height from the anchor to the bottom
+ const rect = target.getBoundingClientRect();
+ const spaceBelow = window.innerHeight - rect.top - 24;
+ const isBottom = spaceBelow < 350;
+ setIsBottomHalf(isBottom);
- setPosition(newPosition);
+ if (isBottom) {
+ const spaceAbove = rect.bottom - 24;
+ setPopoverMaxHeight(`${Math.max(250, spaceAbove)}px`);
+ } else {
+ setPopoverMaxHeight(`${Math.max(250, spaceBelow)}px`);
+ }
};
- const handleMouseUp = () => {
- window.removeEventListener("mousemove", handleMouseMove);
- window.removeEventListener("mouseup", handleMouseUp);
+ const handlePopoverClose = () => {
+ setPopoverAnchor(null);
+ setActivePopover(null);
};
- const handleMouseDown = () => {
- window.addEventListener("mousemove", handleMouseMove);
- window.addEventListener("mouseup", handleMouseUp);
+ const handleDrawerOpen = () => {
+ setOpen(!open);
+ if (!open) {
+ handlePopoverClose();
+ }
};
+
+
+ const renderPopoverSearch = () => (
+ <div className="sidebar-popover-search">
+ <SidebarSearchInput searchTerm={searchTerm} onChange={setSearchTerm} />
+ </div>
+ );
+
+ const headerRef = useRef<HTMLDivElement>(null);
+
useEffect(() => {
Review Comment:
Consider cache guards before dispatching fetchTypeHeaderData,
fetchRootEntity, etc., similar to tree components, to avoid redundant API calls
on layout remount.
##########
dashboard/src/redux/slice/__tests__/sessionSlice.test.ts:
##########
Review Comment:
Add fetchSessionData.rejected while retaining previous stale data test
(mirror the version test at lines 238–257)
##########
dashboard/src/views/DetailPage/EntityDetailPage.tsx:
##########
@@ -350,7 +353,7 @@ const EntityDetailPage: React.FC = () => {
<Stack spacing={2} direction="row" alignItems="center">
{!isEmpty(entity) && (
<DisplayImage
- entity={entity}
+ entity={{ ...entity, serviceType: entityObj?.serviceType }}
Review Comment:
Please add a unit test verifying serviceType from entityObj is merged into
the entity passed to DisplayImage when the detail API omits it.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]