From 16d3df620f07c4d41118be9c8f38dc0cf46df76f Mon Sep 17 00:00:00 2001
From: Salman-Apptware <101426513+Salman-Apptware@users.noreply.github.com>
Date: Wed, 20 Dec 2023 16:32:52 +0530
Subject: [PATCH] fix(ui): Tab doesn't represent the page you are on for
non-data asset pages (#9468)
---
datahub-web-react/src/app/AppProviders.tsx | 13 ++++----
.../src/app/entity/group/GroupInfoSideBar.tsx | 17 +++++++++++
.../src/app/entity/user/UserInfoSideBar.tsx | 19 +++++++++++-
.../src/app/search/SearchablePage.tsx | 27 +++++++++++++++++
.../src/app/shared/BrowserTabTitleContext.tsx | 30 +++++++++++++++++++
5 files changed, 100 insertions(+), 6 deletions(-)
create mode 100644 datahub-web-react/src/app/shared/BrowserTabTitleContext.tsx
diff --git a/datahub-web-react/src/app/AppProviders.tsx b/datahub-web-react/src/app/AppProviders.tsx
index 81a8ddbfc9..00597e1cf7 100644
--- a/datahub-web-react/src/app/AppProviders.tsx
+++ b/datahub-web-react/src/app/AppProviders.tsx
@@ -5,6 +5,7 @@ import UserContextProvider from './context/UserContextProvider';
import QuickFiltersProvider from '../providers/QuickFiltersProvider';
import SearchContextProvider from './search/context/SearchContextProvider';
import EntityRegistryProvider from './EntityRegistryProvider';
+import { BrowserTitleProvider } from './shared/BrowserTabTitleContext';
interface Props {
children: React.ReactNode;
@@ -15,11 +16,13 @@ export default function AppProviders({ children }: Props) {
-
-
- {children}
-
-
+
+
+
+ {children}
+
+
+
diff --git a/datahub-web-react/src/app/entity/group/GroupInfoSideBar.tsx b/datahub-web-react/src/app/entity/group/GroupInfoSideBar.tsx
index 07885a4d0f..044b09dc18 100644
--- a/datahub-web-react/src/app/entity/group/GroupInfoSideBar.tsx
+++ b/datahub-web-react/src/app/entity/group/GroupInfoSideBar.tsx
@@ -21,6 +21,7 @@ import {
} from '../shared/SidebarStyledComponents';
import GroupMembersSideBarSection from './GroupMembersSideBarSection';
import { useUserContext } from '../../context/useUserContext';
+import { useBrowserTitle } from '../../shared/BrowserTabTitleContext';
import StripMarkdownText, { removeMarkdown } from '../shared/components/styled/StripMarkdownText';
import { Editor } from '../shared/tabs/Documentation/components/editor/Editor';
import EditGroupDescriptionModal from './EditGroupDescriptionModal';
@@ -157,6 +158,22 @@ export default function GroupInfoSidebar({ sideBarData, refetch }: Props) {
const { url } = useRouteMatch();
const history = useHistory();
+ const { updateTitle } = useBrowserTitle();
+
+ useEffect(()=>{
+ // You can use the title and updateTitle function here
+ // For example, updating the title when the component mounts
+ if(name){
+ updateTitle(`Group | ${name}`);
+ }
+ // // Don't forget to clean up the title when the component unmounts
+ return () => {
+ if(name){ // added to condition for rerendering issue
+ updateTitle('');
+ }
+ };
+ }, [name, updateTitle]);
+
/* eslint-disable @typescript-eslint/no-unused-vars */
const [editGroupModal, showEditGroupModal] = useState(false);
const me = useUserContext();
diff --git a/datahub-web-react/src/app/entity/user/UserInfoSideBar.tsx b/datahub-web-react/src/app/entity/user/UserInfoSideBar.tsx
index c01dd3a635..71bfbfcd49 100644
--- a/datahub-web-react/src/app/entity/user/UserInfoSideBar.tsx
+++ b/datahub-web-react/src/app/entity/user/UserInfoSideBar.tsx
@@ -1,5 +1,5 @@
import { Divider, message, Space, Button, Typography, Tag } from 'antd';
-import React, { useState } from 'react';
+import React, { useEffect, useState } from 'react';
import { EditOutlined, MailOutlined, PhoneOutlined, SlackOutlined } from '@ant-design/icons';
import { useUpdateCorpUserPropertiesMutation } from '../../../graphql/user.generated';
import { EntityRelationship, DataHubRole } from '../../../types.generated';
@@ -21,6 +21,7 @@ import {
import EntityGroups from '../shared/EntityGroups';
import { mapRoleIcon } from '../../identity/user/UserUtils';
import { useUserContext } from '../../context/useUserContext';
+import { useBrowserTitle } from '../../shared/BrowserTabTitleContext';
const { Paragraph } = Typography;
@@ -61,6 +62,22 @@ export default function UserInfoSideBar({ sideBarData, refetch }: Props) {
const me = useUserContext();
const isProfileOwner = me?.user?.urn === urn;
+ const { updateTitle } = useBrowserTitle();
+
+ useEffect(()=>{
+ // You can use the title and updateTitle function here
+ // For example, updating the title when the component mounts
+ if(name){
+ updateTitle(`User | ${name}`);
+ }
+ // // Don't forget to clean up the title when the component unmounts
+ return () => {
+ if(name){ // added to condition for rerendering issue
+ updateTitle('');
+ }
+ };
+ }, [name, updateTitle]);
+
const getEditModalData = {
urn,
name,
diff --git a/datahub-web-react/src/app/search/SearchablePage.tsx b/datahub-web-react/src/app/search/SearchablePage.tsx
index 9d02d85d36..53dfc866b9 100644
--- a/datahub-web-react/src/app/search/SearchablePage.tsx
+++ b/datahub-web-react/src/app/search/SearchablePage.tsx
@@ -3,6 +3,7 @@ import { useHistory, useLocation } from 'react-router';
import { debounce } from 'lodash';
import * as QueryString from 'query-string';
import { useTheme } from 'styled-components';
+import { Helmet } from 'react-helmet-async';
import { SearchHeader } from './SearchHeader';
import { useEntityRegistry } from '../useEntityRegistry';
import { EntityType, FacetFilterInput } from '../../types.generated';
@@ -19,6 +20,7 @@ import { useQuickFiltersContext } from '../../providers/QuickFiltersContext';
import { useUserContext } from '../context/useUserContext';
import { useSelectedSortOption } from './context/SearchContext';
import { HALF_SECOND_IN_MS } from '../entity/shared/tabs/Dataset/Queries/utils/constants';
+import { useBrowserTitle } from '../shared/BrowserTabTitleContext';
const styles = {
children: {
@@ -68,6 +70,28 @@ export const SearchablePage = ({ onSearch, onAutoComplete, children }: Props) =>
const { user } = userContext;
const viewUrn = userContext.localState?.selectedViewUrn;
+ const { title, updateTitle } = useBrowserTitle();
+
+ useEffect(() => {
+ // Update the title only if it's not already set and there is a valid pathname
+ if (!title && location.pathname) {
+ const formattedPath = location.pathname
+ .split('/')
+ .filter(word => word !== '')
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
+ .join(' | ');
+
+ if (formattedPath) {
+ return updateTitle(formattedPath);
+ }
+ }
+
+ // Clean up the title when the component unmounts
+ return () => {
+ updateTitle('');
+ };
+ }, [location.pathname, title, updateTitle]);
+
useEffect(() => {
if (suggestionsData !== undefined) {
setNewSuggestionData(suggestionsData);
@@ -140,6 +164,9 @@ export const SearchablePage = ({ onSearch, onAutoComplete, children }: Props) =>
authenticatedUserPictureLink={user?.editableProperties?.pictureLink}
entityRegistry={entityRegistry}
/>
+
+ {title}
+
{children}
>
);
diff --git a/datahub-web-react/src/app/shared/BrowserTabTitleContext.tsx b/datahub-web-react/src/app/shared/BrowserTabTitleContext.tsx
new file mode 100644
index 0000000000..284e277112
--- /dev/null
+++ b/datahub-web-react/src/app/shared/BrowserTabTitleContext.tsx
@@ -0,0 +1,30 @@
+import React, { createContext, ReactNode, useContext } from 'react';
+
+interface BrowserTitleContextProps {
+ title: string;
+ updateTitle: (newTitle: string) => void;
+}
+
+const BrowserTitleContext = createContext(undefined);
+
+export const BrowserTitleProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
+ const [title, setTitle] = React.useState('');
+
+ const updateTitle = (newTitle: string) => {
+ setTitle(newTitle);
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const useBrowserTitle = () => {
+ const context = useContext(BrowserTitleContext);
+ if (!context) {
+ throw new Error('useBrowserTitle must be used within a BrowserTitleProvider');
+ }
+ return context;
+};