mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-01 13:13:10 +00:00
fix(ui): assets virtual scroll (#10820)
* fix(ui): assets virtual scroll fetch tags before make patch api call * fix append issue
This commit is contained in:
parent
c6538a38bf
commit
4241457cfb
@ -18,7 +18,7 @@ import Loader from 'components/Loader/Loader';
|
|||||||
import { PAGE_SIZE_MEDIUM } from 'constants/constants';
|
import { PAGE_SIZE_MEDIUM } from 'constants/constants';
|
||||||
import { EntityType } from 'enums/entity.enum';
|
import { EntityType } from 'enums/entity.enum';
|
||||||
import { SearchIndex } from 'enums/search.enum';
|
import { SearchIndex } from 'enums/search.enum';
|
||||||
import { compare, Operation } from 'fast-json-patch';
|
import { compare } from 'fast-json-patch';
|
||||||
import { cloneDeep, groupBy, map, startCase } from 'lodash';
|
import { cloneDeep, groupBy, map, startCase } from 'lodash';
|
||||||
import { EntityDetailUnion } from 'Models';
|
import { EntityDetailUnion } from 'Models';
|
||||||
import VirtualList from 'rc-virtual-list';
|
import VirtualList from 'rc-virtual-list';
|
||||||
@ -30,37 +30,48 @@ import {
|
|||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { patchDashboardDetails } from 'rest/dashboardAPI';
|
|
||||||
import { patchMlModelDetails } from 'rest/mlModelAPI';
|
|
||||||
import { patchContainerDetails } from 'rest/objectStoreAPI';
|
|
||||||
import { patchPipelineDetails } from 'rest/pipelineAPI';
|
|
||||||
import { searchQuery } from 'rest/searchAPI';
|
import { searchQuery } from 'rest/searchAPI';
|
||||||
import { patchTableDetails } from 'rest/tableAPI';
|
import {
|
||||||
import { patchTopicDetails } from 'rest/topicsAPI';
|
getAPIfromSource,
|
||||||
|
getEntityAPIfromSource,
|
||||||
|
} from 'utils/Assets/AssetsUtils';
|
||||||
import { getCountBadge } from 'utils/CommonUtils';
|
import { getCountBadge } from 'utils/CommonUtils';
|
||||||
import { getQueryFilterToExcludeTerm } from 'utils/GlossaryUtils';
|
import { getQueryFilterToExcludeTerm } from 'utils/GlossaryUtils';
|
||||||
import {
|
import {
|
||||||
AssetFilterKeys,
|
AssetFilterKeys,
|
||||||
AssetSelectionModalProps,
|
AssetSelectionModalProps,
|
||||||
AssetsUnion,
|
|
||||||
MapPatchAPIResponse,
|
|
||||||
} from './AssetSelectionModal.interface';
|
} from './AssetSelectionModal.interface';
|
||||||
|
|
||||||
export const AssetSelectionModal = ({
|
export const AssetSelectionModal = ({
|
||||||
glossaryFQN,
|
glossaryFQN,
|
||||||
onCancel,
|
onCancel,
|
||||||
|
onSave,
|
||||||
open,
|
open,
|
||||||
}: AssetSelectionModalProps) => {
|
}: AssetSelectionModalProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
const [items, setItems] = useState<EntityDetailUnion[]>([]);
|
const [items, setItems] = useState<EntityDetailUnion[]>([]);
|
||||||
const [itemCount, setItemCount] = useState<Record<AssetFilterKeys, number>>();
|
const [itemCount, setItemCount] = useState<Record<AssetFilterKeys, number>>({
|
||||||
|
all: 0,
|
||||||
|
table: 0,
|
||||||
|
pipeline: 0,
|
||||||
|
mlmodel: 0,
|
||||||
|
container: 0,
|
||||||
|
topic: 0,
|
||||||
|
dashboard: 0,
|
||||||
|
});
|
||||||
const [selectedItems, setSelectedItems] =
|
const [selectedItems, setSelectedItems] =
|
||||||
useState<Map<string, EntityDetailUnion>>();
|
useState<Map<string, EntityDetailUnion>>();
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [activeFilter, setActiveFilter] = useState<AssetFilterKeys>('all');
|
const [activeFilter, setActiveFilter] = useState<AssetFilterKeys>('all');
|
||||||
const [pageNumber, setPageNumber] = useState(1);
|
const [pageNumber, setPageNumber] = useState(1);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (open) {
|
||||||
|
fetchEntities();
|
||||||
|
}
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
const fetchEntities = async (searchText = '', page = 1) => {
|
const fetchEntities = async (searchText = '', page = 1) => {
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
@ -80,18 +91,41 @@ export const AssetSelectionModal = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const groupedArray = groupBy(res.hits.hits, '_source.entityType');
|
const groupedArray = groupBy(res.hits.hits, '_source.entityType');
|
||||||
|
const isAppend = page !== 1;
|
||||||
|
const tableCount = groupedArray[EntityType.TABLE]?.length ?? 0;
|
||||||
|
const containerCount = groupedArray[EntityType.CONTAINER]?.length ?? 0;
|
||||||
|
const pipelineCount = groupedArray[EntityType.PIPELINE]?.length ?? 0;
|
||||||
|
const dashboardCount = groupedArray[EntityType.DASHBOARD]?.length ?? 0;
|
||||||
|
const topicCount = groupedArray[EntityType.TOPIC]?.length ?? 0;
|
||||||
|
const mlmodelCount = groupedArray[EntityType.MLMODEL]?.length ?? 0;
|
||||||
|
|
||||||
setItemCount({
|
setItemCount((prevCount) => ({
|
||||||
|
...prevCount,
|
||||||
all: res.hits.total.value,
|
all: res.hits.total.value,
|
||||||
[EntityType.TABLE]: groupedArray[EntityType.TABLE]?.length ?? 0,
|
...(isAppend
|
||||||
[EntityType.PIPELINE]: groupedArray[EntityType.PIPELINE]?.length ?? 0,
|
? {
|
||||||
[EntityType.MLMODEL]: groupedArray[EntityType.MLMODEL]?.length ?? 0,
|
table: prevCount.table + tableCount,
|
||||||
[EntityType.TOPIC]: groupedArray[EntityType.TOPIC]?.length ?? 0,
|
pipeline: prevCount.pipeline + pipelineCount,
|
||||||
[EntityType.DASHBOARD]: groupedArray[EntityType.DASHBOARD]?.length ?? 0,
|
mlmodel: prevCount.mlmodel + mlmodelCount,
|
||||||
[EntityType.CONTAINER]: groupedArray[EntityType.CONTAINER]?.length ?? 0,
|
container: prevCount.container + containerCount,
|
||||||
});
|
topic: prevCount.topic + topicCount,
|
||||||
|
dashboard: prevCount.dashboard + dashboardCount,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
table: tableCount,
|
||||||
|
pipeline: pipelineCount,
|
||||||
|
mlmodel: mlmodelCount,
|
||||||
|
container: containerCount,
|
||||||
|
topic: topicCount,
|
||||||
|
dashboard: dashboardCount,
|
||||||
|
}),
|
||||||
|
}));
|
||||||
setActiveFilter('all');
|
setActiveFilter('all');
|
||||||
setItems(res.hits.hits);
|
setItems(
|
||||||
|
page === 1
|
||||||
|
? res.hits.hits
|
||||||
|
: (prevItems) => [...prevItems, ...res.hits.hits]
|
||||||
|
);
|
||||||
setPageNumber(page);
|
setPageNumber(page);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -131,37 +165,36 @@ export const AssetSelectionModal = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAPIfromSource = (
|
|
||||||
source: AssetsUnion
|
|
||||||
): ((
|
|
||||||
id: string,
|
|
||||||
jsonPatch: Operation[]
|
|
||||||
) => Promise<MapPatchAPIResponse[typeof source]>) => {
|
|
||||||
switch (source) {
|
|
||||||
case EntityType.TABLE:
|
|
||||||
return patchTableDetails;
|
|
||||||
case EntityType.DASHBOARD:
|
|
||||||
return patchDashboardDetails;
|
|
||||||
case EntityType.MLMODEL:
|
|
||||||
return patchMlModelDetails;
|
|
||||||
case EntityType.PIPELINE:
|
|
||||||
return patchPipelineDetails;
|
|
||||||
case EntityType.TOPIC:
|
|
||||||
return patchTopicDetails;
|
|
||||||
case EntityType.CONTAINER:
|
|
||||||
return patchContainerDetails;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const promises = [...(selectedItems?.values() ?? [])].map((item) => {
|
const entityDetails = [...(selectedItems?.values() ?? [])].map((item) =>
|
||||||
|
getEntityAPIfromSource(item.entityType)(item.fullyQualifiedName, 'tags')
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const entityDetailsResponse = await Promise.allSettled(entityDetails);
|
||||||
|
const map = new Map();
|
||||||
|
|
||||||
|
entityDetailsResponse.forEach((response) => {
|
||||||
|
if (response.status === 'fulfilled') {
|
||||||
|
const entity = response.value;
|
||||||
|
|
||||||
|
entity && map.set(entity.fullyQualifiedName, entity.tags);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const patchAPIPromises = [...(selectedItems?.values() ?? [])]
|
||||||
|
.map((item) => {
|
||||||
|
if (map.has(item.fullyQualifiedName)) {
|
||||||
const jsonPatch = compare(
|
const jsonPatch = compare(
|
||||||
{ tags: item.tags },
|
{ tags: map.get(item.fullyQualifiedName) },
|
||||||
{
|
{
|
||||||
tags: [
|
tags: [
|
||||||
...item.tags,
|
...(item.tags ?? []),
|
||||||
{ tagFQN: glossaryFQN, source: 'Glossary', labelType: 'Manual' },
|
{
|
||||||
|
tagFQN: glossaryFQN,
|
||||||
|
source: 'Glossary',
|
||||||
|
labelType: 'Manual',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -169,10 +202,14 @@ export const AssetSelectionModal = ({
|
|||||||
const api = getAPIfromSource(item.entityType);
|
const api = getAPIfromSource(item.entityType);
|
||||||
|
|
||||||
return api(item.id, jsonPatch);
|
return api(item.id, jsonPatch);
|
||||||
});
|
}
|
||||||
|
|
||||||
try {
|
return;
|
||||||
await Promise.all(promises);
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
await Promise.all(patchAPIPromises);
|
||||||
|
onSave && onSave();
|
||||||
onCancel();
|
onCancel();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -181,13 +218,9 @@ export const AssetSelectionModal = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
fetchEntities();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onScroll: UIEventHandler<HTMLElement> = (e) => {
|
const onScroll: UIEventHandler<HTMLElement> = (e) => {
|
||||||
if (e.currentTarget.scrollHeight - e.currentTarget.scrollTop === 500) {
|
if (e.currentTarget.scrollHeight - e.currentTarget.scrollTop === 500) {
|
||||||
fetchEntities(search, pageNumber + 1);
|
!isLoading && fetchEntities(search, pageNumber + 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ export interface GlossaryHeaderProps {
|
|||||||
isGlossary: boolean;
|
isGlossary: boolean;
|
||||||
onUpdate: (data: GlossaryTerm | Glossary) => void;
|
onUpdate: (data: GlossaryTerm | Glossary) => void;
|
||||||
onDelete: (id: string) => void;
|
onDelete: (id: string) => void;
|
||||||
|
onAssetsUpdate?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GlossaryHeader = ({
|
const GlossaryHeader = ({
|
||||||
@ -48,6 +49,7 @@ const GlossaryHeader = ({
|
|||||||
onUpdate,
|
onUpdate,
|
||||||
onDelete,
|
onDelete,
|
||||||
isGlossary,
|
isGlossary,
|
||||||
|
onAssetsUpdate,
|
||||||
}: GlossaryHeaderProps) => {
|
}: GlossaryHeaderProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@ -219,6 +221,7 @@ const GlossaryHeader = ({
|
|||||||
isGlossary={isGlossary}
|
isGlossary={isGlossary}
|
||||||
permission={permissions}
|
permission={permissions}
|
||||||
selectedData={selectedData}
|
selectedData={selectedData}
|
||||||
|
onAssetsUpdate={onAssetsUpdate}
|
||||||
onEntityDelete={onDelete}
|
onEntityDelete={onDelete}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,7 +27,7 @@ import { GlossaryTerm } from 'generated/entity/data/glossaryTerm';
|
|||||||
import { EntityHistory } from 'generated/type/entityHistory';
|
import { EntityHistory } from 'generated/type/entityHistory';
|
||||||
import { toString } from 'lodash';
|
import { toString } from 'lodash';
|
||||||
import { LoadingState } from 'Models';
|
import { LoadingState } from 'Models';
|
||||||
import React, { useMemo, useState } from 'react';
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useHistory, useParams } from 'react-router-dom';
|
import { useHistory, useParams } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
@ -51,6 +51,7 @@ interface GlossaryHeaderButtonsProps {
|
|||||||
selectedData: Glossary | GlossaryTerm;
|
selectedData: Glossary | GlossaryTerm;
|
||||||
permission: OperationPermission;
|
permission: OperationPermission;
|
||||||
onEntityDelete: (id: string) => void;
|
onEntityDelete: (id: string) => void;
|
||||||
|
onAssetsUpdate?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GlossaryHeaderButtons = ({
|
const GlossaryHeaderButtons = ({
|
||||||
@ -59,6 +60,7 @@ const GlossaryHeaderButtons = ({
|
|||||||
selectedData,
|
selectedData,
|
||||||
permission,
|
permission,
|
||||||
onEntityDelete,
|
onEntityDelete,
|
||||||
|
onAssetsUpdate,
|
||||||
}: GlossaryHeaderButtonsProps) => {
|
}: GlossaryHeaderButtonsProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { action, glossaryName: glossaryFqn } =
|
const { action, glossaryName: glossaryFqn } =
|
||||||
@ -74,12 +76,12 @@ const GlossaryHeaderButtons = ({
|
|||||||
[action]
|
[action]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleAddGlossaryTermClick = (glossaryFQN: string) => {
|
const handleAddGlossaryTermClick = useCallback(() => {
|
||||||
if (glossaryFQN) {
|
if (glossaryFqn) {
|
||||||
const activeTerm = glossaryFQN.split(FQN_SEPARATOR_CHAR);
|
const activeTerm = glossaryFqn.split(FQN_SEPARATOR_CHAR);
|
||||||
const glossary = activeTerm[0];
|
const glossary = activeTerm[0];
|
||||||
if (activeTerm.length > 1) {
|
if (activeTerm.length > 1) {
|
||||||
history.push(getAddGlossaryTermsPath(glossary, glossaryFQN));
|
history.push(getAddGlossaryTermsPath(glossary, glossaryFqn));
|
||||||
} else {
|
} else {
|
||||||
history.push(getAddGlossaryTermsPath(glossary));
|
history.push(getAddGlossaryTermsPath(glossary));
|
||||||
}
|
}
|
||||||
@ -88,7 +90,7 @@ const GlossaryHeaderButtons = ({
|
|||||||
getAddGlossaryTermsPath(selectedData.fullyQualifiedName ?? '')
|
getAddGlossaryTermsPath(selectedData.fullyQualifiedName ?? '')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
}, [glossaryFqn]);
|
||||||
|
|
||||||
const handleGlossaryExport = () =>
|
const handleGlossaryExport = () =>
|
||||||
history.push(
|
history.push(
|
||||||
@ -129,7 +131,7 @@ const GlossaryHeaderButtons = ({
|
|||||||
{
|
{
|
||||||
label: t('label.glossary-term'),
|
label: t('label.glossary-term'),
|
||||||
key: '1',
|
key: '1',
|
||||||
onClick: () => handleAddGlossaryTermClick(glossaryFqn),
|
onClick: handleAddGlossaryTermClick,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('label.asset-plural'),
|
label: t('label.asset-plural'),
|
||||||
@ -248,7 +250,7 @@ const GlossaryHeaderButtons = ({
|
|||||||
data-testid="add-new-tag-button-header"
|
data-testid="add-new-tag-button-header"
|
||||||
size="middle"
|
size="middle"
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={() => handleAddGlossaryTermClick(glossaryFqn)}>
|
onClick={handleAddGlossaryTermClick}>
|
||||||
{t('label.add-entity', { entity: t('label.term-lowercase') })}
|
{t('label.add-entity', { entity: t('label.term-lowercase') })}
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
@ -333,6 +335,7 @@ const GlossaryHeaderButtons = ({
|
|||||||
glossaryFQN={selectedData.fullyQualifiedName}
|
glossaryFQN={selectedData.fullyQualifiedName}
|
||||||
open={showAddAssets}
|
open={showAddAssets}
|
||||||
onCancel={() => setShowAddAssets(false)}
|
onCancel={() => setShowAddAssets(false)}
|
||||||
|
onSave={onAssetsUpdate}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -124,6 +124,10 @@ const GlossaryTermsV1 = ({
|
|||||||
isGlossary={false}
|
isGlossary={false}
|
||||||
permissions={permissions}
|
permissions={permissions}
|
||||||
selectedData={glossaryTerm}
|
selectedData={glossaryTerm}
|
||||||
|
onAssetsUpdate={() =>
|
||||||
|
glossaryTerm.fullyQualifiedName &&
|
||||||
|
fetchGlossaryTermAssets(glossaryTerm.fullyQualifiedName)
|
||||||
|
}
|
||||||
onDelete={handleGlossaryTermDelete}
|
onDelete={handleGlossaryTermDelete}
|
||||||
onUpdate={(data) => handleGlossaryTermUpdate(data as GlossaryTerm)}
|
onUpdate={(data) => handleGlossaryTermUpdate(data as GlossaryTerm)}
|
||||||
/>
|
/>
|
||||||
|
@ -37,7 +37,7 @@ import {
|
|||||||
|
|
||||||
type SuggestionProp = {
|
type SuggestionProp = {
|
||||||
searchText: string;
|
searchText: string;
|
||||||
searchCriteria: SearchIndex | null;
|
searchCriteria?: SearchIndex;
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
setIsOpen: (value: boolean) => void;
|
setIsOpen: (value: boolean) => void;
|
||||||
};
|
};
|
||||||
@ -138,7 +138,7 @@ const Suggestions = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isMounting.current && searchText) {
|
if (!isMounting.current && searchText) {
|
||||||
getSuggestions(searchText, searchCriteria ?? undefined)
|
getSuggestions(searchText, searchCriteria)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
setOptions(
|
setOptions(
|
||||||
|
@ -39,7 +39,6 @@ import { refreshPage } from 'utils/CommonUtils';
|
|||||||
import { isCommandKeyPress, Keys } from 'utils/KeyboardUtil';
|
import { isCommandKeyPress, Keys } from 'utils/KeyboardUtil';
|
||||||
import AppState from '../../AppState';
|
import AppState from '../../AppState';
|
||||||
import Logo from '../../assets/svg/logo-monogram.svg';
|
import Logo from '../../assets/svg/logo-monogram.svg';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
NOTIFICATION_READ_TIMER,
|
NOTIFICATION_READ_TIMER,
|
||||||
ROUTES,
|
ROUTES,
|
||||||
@ -113,12 +112,10 @@ const NavBar = ({
|
|||||||
useState<boolean>(false);
|
useState<boolean>(false);
|
||||||
const [activeTab, setActiveTab] = useState<string>('Task');
|
const [activeTab, setActiveTab] = useState<string>('Task');
|
||||||
const [isImgUrlValid, setIsImgUrlValid] = useState<boolean>(true);
|
const [isImgUrlValid, setIsImgUrlValid] = useState<boolean>(true);
|
||||||
const [searchCriteria, setSearchCriteria] = useState<SearchIndex | null>(
|
const [searchCriteria, setSearchCriteria] = useState<SearchIndex | ''>('');
|
||||||
null
|
|
||||||
);
|
|
||||||
const globalSearchOptions = useMemo(
|
const globalSearchOptions = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{ value: null, label: t('label.all') },
|
{ value: '', label: t('label.all') },
|
||||||
{ value: SearchIndex.TABLE, label: t('label.table') },
|
{ value: SearchIndex.TABLE, label: t('label.table') },
|
||||||
{ value: SearchIndex.TOPIC, label: t('label.topic') },
|
{ value: SearchIndex.TOPIC, label: t('label.topic') },
|
||||||
{ value: SearchIndex.DASHBOARD, label: t('label.dashboard') },
|
{ value: SearchIndex.DASHBOARD, label: t('label.dashboard') },
|
||||||
@ -131,7 +128,7 @@ const NavBar = ({
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const updateSearchCriteria = (criteria: SearchIndex | null) => {
|
const updateSearchCriteria = (criteria: SearchIndex | '') => {
|
||||||
setSearchCriteria(criteria);
|
setSearchCriteria(criteria);
|
||||||
handleSearchChange(searchValue);
|
handleSearchChange(searchValue);
|
||||||
};
|
};
|
||||||
@ -507,7 +504,9 @@ const NavBar = ({
|
|||||||
) : (
|
) : (
|
||||||
<Suggestions
|
<Suggestions
|
||||||
isOpen={isSearchBoxOpen}
|
isOpen={isSearchBoxOpen}
|
||||||
searchCriteria={searchCriteria}
|
searchCriteria={
|
||||||
|
searchCriteria === '' ? undefined : searchCriteria
|
||||||
|
}
|
||||||
searchText={suggestionSearch}
|
searchText={suggestionSearch}
|
||||||
setIsOpen={handleSearchBoxOpen}
|
setIsOpen={handleSearchBoxOpen}
|
||||||
/>
|
/>
|
||||||
|
@ -41,7 +41,7 @@ import {
|
|||||||
patchGlossaryTerm,
|
patchGlossaryTerm,
|
||||||
} from 'rest/glossaryAPI';
|
} from 'rest/glossaryAPI';
|
||||||
import { checkPermission } from 'utils/PermissionsUtils';
|
import { checkPermission } from 'utils/PermissionsUtils';
|
||||||
import { getGlossaryPath } from 'utils/RouterUtils';
|
import { getGlossaryPath, getGlossaryTermsPath } from 'utils/RouterUtils';
|
||||||
import { showErrorToast, showSuccessToast } from 'utils/ToastUtils';
|
import { showErrorToast, showSuccessToast } from 'utils/ToastUtils';
|
||||||
import GlossaryLeftPanel from '../GlossaryLeftPanel/GlossaryLeftPanel.component';
|
import GlossaryLeftPanel from '../GlossaryLeftPanel/GlossaryLeftPanel.component';
|
||||||
import GlossaryRightPanel from '../GlossaryRightPanel/GlossaryRightPanel.component';
|
import GlossaryRightPanel from '../GlossaryRightPanel/GlossaryRightPanel.component';
|
||||||
@ -124,6 +124,11 @@ const GlossaryPage = () => {
|
|||||||
glossaries.find((glossary) => glossary.name === glossaryFqn) ||
|
glossaries.find((glossary) => glossary.name === glossaryFqn) ||
|
||||||
glossaries[0]
|
glossaries[0]
|
||||||
);
|
);
|
||||||
|
!glossaryFqn &&
|
||||||
|
glossaries[0].fullyQualifiedName &&
|
||||||
|
history.replace(
|
||||||
|
getGlossaryTermsPath(glossaries[0].fullyQualifiedName)
|
||||||
|
);
|
||||||
setIsRightPanelLoading(false);
|
setIsRightPanelLoading(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,10 @@ export const getContainers = async (args: {
|
|||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getContainerByName = async (name: string, fields: string) => {
|
export const getContainerByName = async (
|
||||||
|
name: string,
|
||||||
|
fields: string | string[]
|
||||||
|
) => {
|
||||||
const response = await APIClient.get<Container>(
|
const response = await APIClient.get<Container>(
|
||||||
`containers/name/${name}?fields=${fields}`
|
`containers/name/${name}?fields=${fields}`
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 Collate.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
AssetsUnion,
|
||||||
|
MapPatchAPIResponse,
|
||||||
|
} from 'components/Assets/AssetsSelectionModal/AssetSelectionModal.interface';
|
||||||
|
import { EntityType } from 'enums/entity.enum';
|
||||||
|
import { Operation } from 'fast-json-patch';
|
||||||
|
import { getDashboardByFqn, patchDashboardDetails } from 'rest/dashboardAPI';
|
||||||
|
import { getMlModelByFQN, patchMlModelDetails } from 'rest/mlModelAPI';
|
||||||
|
import { getContainerByName, patchContainerDetails } from 'rest/objectStoreAPI';
|
||||||
|
import { getPipelineByFqn, patchPipelineDetails } from 'rest/pipelineAPI';
|
||||||
|
import { getTableDetailsByFQN, patchTableDetails } from 'rest/tableAPI';
|
||||||
|
import { getTopicByFqn, patchTopicDetails } from 'rest/topicsAPI';
|
||||||
|
|
||||||
|
export const getAPIfromSource = (
|
||||||
|
source: AssetsUnion
|
||||||
|
): ((
|
||||||
|
id: string,
|
||||||
|
jsonPatch: Operation[]
|
||||||
|
) => Promise<MapPatchAPIResponse[typeof source]>) => {
|
||||||
|
switch (source) {
|
||||||
|
case EntityType.TABLE:
|
||||||
|
return patchTableDetails;
|
||||||
|
case EntityType.DASHBOARD:
|
||||||
|
return patchDashboardDetails;
|
||||||
|
case EntityType.MLMODEL:
|
||||||
|
return patchMlModelDetails;
|
||||||
|
case EntityType.PIPELINE:
|
||||||
|
return patchPipelineDetails;
|
||||||
|
case EntityType.TOPIC:
|
||||||
|
return patchTopicDetails;
|
||||||
|
case EntityType.CONTAINER:
|
||||||
|
return patchContainerDetails;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getEntityAPIfromSource = (
|
||||||
|
source: AssetsUnion
|
||||||
|
): ((
|
||||||
|
id: string,
|
||||||
|
queryFields: string | string[]
|
||||||
|
) => Promise<MapPatchAPIResponse[typeof source]>) => {
|
||||||
|
switch (source) {
|
||||||
|
case EntityType.TABLE:
|
||||||
|
return getTableDetailsByFQN;
|
||||||
|
case EntityType.DASHBOARD:
|
||||||
|
return getDashboardByFqn;
|
||||||
|
case EntityType.MLMODEL:
|
||||||
|
return getMlModelByFQN;
|
||||||
|
case EntityType.PIPELINE:
|
||||||
|
return getPipelineByFqn;
|
||||||
|
case EntityType.TOPIC:
|
||||||
|
return getTopicByFqn;
|
||||||
|
case EntityType.CONTAINER:
|
||||||
|
return getContainerByName;
|
||||||
|
}
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user