diff --git a/datahub-web-react/src/app/domain/DomainSearch.tsx b/datahub-web-react/src/app/domain/DomainSearch.tsx
index e82dae9c2c9e6..5036a795ea5e4 100644
--- a/datahub-web-react/src/app/domain/DomainSearch.tsx
+++ b/datahub-web-react/src/app/domain/DomainSearch.tsx
@@ -1,17 +1,12 @@
-import React, { CSSProperties, useRef, useState } from 'react';
-import { Link } from 'react-router-dom';
+import React, { useRef, useState } from 'react';
+import { LoadingOutlined } from '@ant-design/icons';
import styled from 'styled-components/macro';
-import Highlight from 'react-highlighter';
import { useGetSearchResultsForMultipleQuery } from '../../graphql/search.generated';
import { EntityType } from '../../types.generated';
-import { IconStyleType } from '../entity/Entity';
-import { ANTD_GRAY } from '../entity/shared/constants';
import { SearchBar } from '../search/SearchBar';
import ClickOutside from '../shared/ClickOutside';
import { useEntityRegistry } from '../useEntityRegistry';
-import DomainIcon from './DomainIcon';
-import ParentEntities from '../search/filters/ParentEntities';
-import { getParentDomains } from './utils';
+import DomainSearchResultItem from './DomainSearchResultItem';
const DomainSearchWrapper = styled.div`
position: relative;
@@ -33,34 +28,19 @@ const ResultsWrapper = styled.div`
z-index: 1;
`;
-const SearchResult = styled(Link)`
- color: #262626;
+const LoadingWrapper = styled.div`
display: flex;
align-items: center;
- gap: 8px;
- height: 100%;
- padding: 6px 8px;
- width: 100%;
- &:hover {
- background-color: ${ANTD_GRAY[3]};
- color: #262626;
- }
+ justify-content: center;
+ height: 350px;
+ font-size: 30px;
`;
-const IconWrapper = styled.span``;
-
-const highlightMatchStyle: CSSProperties = {
- fontWeight: 'bold',
- background: 'none',
- padding: 0,
-};
-
function DomainSearch() {
const [query, setQuery] = useState('');
const [isSearchBarFocused, setIsSearchBarFocused] = useState(false);
const entityRegistry = useEntityRegistry();
-
- const { data } = useGetSearchResultsForMultipleQuery({
+ const { data, loading } = useGetSearchResultsForMultipleQuery({
variables: {
input: {
types: [EntityType.Domain],
@@ -69,11 +49,11 @@ function DomainSearch() {
count: 50,
},
},
- skip: !query,
});
const searchResults = data?.searchAcrossEntities?.searchResults;
const timerRef = useRef(-1);
+
const handleQueryChange = (q: string) => {
window.clearTimeout(timerRef.current);
timerRef.current = window.setTimeout(() => {
@@ -81,6 +61,26 @@ function DomainSearch() {
}, 250);
};
+ const renderLoadingIndicator = () => (
+
+
+
+ );
+
+ const renderSearchResults = () => (
+
+ {searchResults?.map((result) => (
+ setIsSearchBarFocused(false)}
+ />
+ ))}
+
+ );
+
return (
setIsSearchBarFocused(false)}>
@@ -102,39 +102,8 @@ function DomainSearch() {
entityRegistry={entityRegistry}
onFocus={() => setIsSearchBarFocused(true)}
/>
- {isSearchBarFocused && searchResults && !!searchResults.length && (
-
- {searchResults.map((result) => {
- return (
- setIsSearchBarFocused(false)}
- >
-
- {result.entity.type === EntityType.Domain ? (
-
- ) : (
- entityRegistry.getIcon(result.entity.type, 12, IconStyleType.ACCENT)
- )}
-
-
-
-
- {entityRegistry.getDisplayName(result.entity.type, result.entity)}
-
-
-
- );
- })}
-
- )}
+ {loading && renderLoadingIndicator()}
+ {!loading && isSearchBarFocused && !!searchResults?.length && renderSearchResults()}
);
diff --git a/datahub-web-react/src/app/domain/DomainSearchResultItem.tsx b/datahub-web-react/src/app/domain/DomainSearchResultItem.tsx
new file mode 100644
index 0000000000000..dc33ea173e0ae
--- /dev/null
+++ b/datahub-web-react/src/app/domain/DomainSearchResultItem.tsx
@@ -0,0 +1,68 @@
+// Create a new component called SearchResultItem.js
+import React from 'react';
+import { Link } from 'react-router-dom';
+import Highlight from 'react-highlighter';
+import styled from 'styled-components/macro';
+import { Entity, EntityType } from '../../types.generated';
+import { IconStyleType } from '../entity/Entity';
+import { ANTD_GRAY } from '../entity/shared/constants';
+import DomainIcon from './DomainIcon';
+import ParentEntities from '../search/filters/ParentEntities';
+import { getParentDomains } from './utils';
+import EntityRegistry from '../entity/EntityRegistry';
+
+type Props = {
+ entity: Entity;
+ entityRegistry: EntityRegistry;
+ query: string;
+ onResultClick: () => void;
+};
+
+const SearchResult = styled(Link)`
+ color: #262626;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ height: 100%;
+ padding: 6px 8px;
+ width: 100%;
+ &:hover {
+ background-color: ${ANTD_GRAY[3]};
+ color: #262626;
+ }
+`;
+
+const IconWrapper = styled.span``;
+
+const highlightMatchStyle = {
+ fontWeight: 'bold',
+ background: 'none',
+ padding: 0,
+};
+
+function DomainSearchResultItem({ entity, entityRegistry, query, onResultClick }: Props) {
+ return (
+
+
+ {entity.type === EntityType.Domain ? (
+
+ ) : (
+ entityRegistry.getIcon(entity.type, 12, IconStyleType.ACCENT)
+ )}
+
+
+
+
+ {entityRegistry.getDisplayName(entity.type, entity)}
+
+
+
+ );
+}
+
+export default DomainSearchResultItem;
diff --git a/datahub-web-react/src/app/domain/nestedDomains/domainNavigator/DomainNavigator.tsx b/datahub-web-react/src/app/domain/nestedDomains/domainNavigator/DomainNavigator.tsx
index 0fbcffb9a260c..8decc2840a379 100644
--- a/datahub-web-react/src/app/domain/nestedDomains/domainNavigator/DomainNavigator.tsx
+++ b/datahub-web-react/src/app/domain/nestedDomains/domainNavigator/DomainNavigator.tsx
@@ -1,9 +1,10 @@
-import { Alert } from 'antd';
+import { Alert, Empty } from 'antd';
import React from 'react';
import styled from 'styled-components';
import useListDomains from '../../useListDomains';
import DomainNode from './DomainNode';
import { Domain } from '../../../../types.generated';
+import { ANTD_GRAY } from '../../../entity/shared/constants';
const NavigatorWrapper = styled.div`
font-size: 14px;
@@ -19,19 +20,28 @@ interface Props {
export default function DomainNavigator({ domainUrnToHide, selectDomainOverride }: Props) {
const { sortedDomains, error } = useListDomains({});
+ const noDomainsFound: boolean = !sortedDomains || sortedDomains.length === 0;
return (
{error && }
- {sortedDomains?.map((domain) => (
-
- ))}
+ )}
+ {!noDomainsFound &&
+ sortedDomains?.map((domain) => (
+
+ ))}
);
}
diff --git a/datahub-web-react/src/app/entity/shared/containers/profile/sidebar/Domain/SetDomainModal.tsx b/datahub-web-react/src/app/entity/shared/containers/profile/sidebar/Domain/SetDomainModal.tsx
index 405442e8d7f50..3d9a7d7f08425 100644
--- a/datahub-web-react/src/app/entity/shared/containers/profile/sidebar/Domain/SetDomainModal.tsx
+++ b/datahub-web-react/src/app/entity/shared/containers/profile/sidebar/Domain/SetDomainModal.tsx
@@ -1,6 +1,8 @@
import React, { useRef, useState } from 'react';
-import { Button, Form, message, Modal, Select } from 'antd';
+import { Button, Form, message, Modal, Select, Empty } from 'antd';
+import { LoadingOutlined } from '@ant-design/icons';
+import styled from 'styled-components/macro';
import { useGetSearchResultsLazyQuery } from '../../../../../../../graphql/search.generated';
import { Domain, Entity, EntityType } from '../../../../../../../types.generated';
import { useBatchSetDomainMutation } from '../../../../../../../graphql/mutations.generated';
@@ -12,6 +14,7 @@ import { tagRender } from '../tagRenderer';
import { BrowserWrapper } from '../../../../../../shared/tags/AddTagsTermsModal';
import DomainNavigator from '../../../../../../domain/nestedDomains/domainNavigator/DomainNavigator';
import ClickOutside from '../../../../../../shared/ClickOutside';
+import { ANTD_GRAY } from '../../../../constants';
type Props = {
urns: string[];
@@ -28,6 +31,18 @@ type SelectedDomain = {
urn: string;
};
+const LoadingWrapper = styled.div`
+ padding: 8px;
+ display: flex;
+ justify-content: center;
+
+ svg {
+ height: 15px;
+ width: 15px;
+ color: ${ANTD_GRAY[8]};
+ }
+`;
+
export const SetDomainModal = ({ urns, onCloseModal, refetch, defaultValue, onOkOverride, titleOverride }: Props) => {
const entityRegistry = useEntityRegistry();
const [isFocusedOnInput, setIsFocusedOnInput] = useState(false);
@@ -41,7 +56,7 @@ export const SetDomainModal = ({ urns, onCloseModal, refetch, defaultValue, onOk
}
: undefined,
);
- const [domainSearch, { data: domainSearchData }] = useGetSearchResultsLazyQuery();
+ const [domainSearch, { data: domainSearchData, loading }] = useGetSearchResultsLazyQuery();
const domainSearchResults =
domainSearchData?.search?.searchResults?.map((searchResult) => searchResult.entity) || [];
const [batchSetDomainMutation] = useBatchSetDomainMutation();
@@ -206,8 +221,23 @@ export const SetDomainModal = ({ urns, onCloseModal, refetch, defaultValue, onOk
onBlur={handleBlur}
onFocus={() => setIsFocusedOnInput(true)}
dropdownStyle={isShowingDomainNavigator ? { display: 'none' } : {}}
+ notFoundContent={
+
+ }
>
- {domainSearchOptions}
+ {loading ? (
+
+
+
+
+
+ ) : (
+ domainSearchOptions
+ )}