diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataProducts/DataProductsDetailsPage/DataProductsDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataProducts/DataProductsDetailsPage/DataProductsDetailsPage.component.tsx index 5400684ad5f..004b50ad8ce 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataProducts/DataProductsDetailsPage/DataProductsDetailsPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataProducts/DataProductsDetailsPage/DataProductsDetailsPage.component.tsx @@ -332,7 +332,7 @@ const DataProductsDetailsPage = ({ } }; - const onStyleSave = (data: Style) => { + const onStyleSave = async (data: Style) => { const style: Style = { // if color/iconURL is empty or undefined send undefined color: data.color ? data.color : undefined, @@ -343,7 +343,7 @@ const DataProductsDetailsPage = ({ style, }; - onUpdate(updatedDetails); + await onUpdate(updatedDetails); setIsStyleEditing(false); }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataProducts/DataProductsDetailsPage/DataProductsDetailsPage.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/DataProducts/DataProductsDetailsPage/DataProductsDetailsPage.interface.ts index aa926b487d5..d2ffbca9b7b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataProducts/DataProductsDetailsPage/DataProductsDetailsPage.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataProducts/DataProductsDetailsPage/DataProductsDetailsPage.interface.ts @@ -16,7 +16,7 @@ export interface DataProductsDetailsPageProps { dataProduct: DataProduct; isVersionsView?: boolean; onUpdate: (dataProductDetails: DataProduct) => Promise; - onDelete: () => void; + onDelete: () => Promise; } export enum DataProductTabs { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueryRightPanel/TableQueryRightPanel.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueryRightPanel/TableQueryRightPanel.component.tsx index f844adf31f5..c76db044fd3 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueryRightPanel/TableQueryRightPanel.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueryRightPanel/TableQueryRightPanel.component.tsx @@ -24,6 +24,7 @@ import { TagLabel } from '../../../../generated/type/tagLabel'; import { getEntityName } from '../../../../utils/EntityUtils'; import Description from '../../../common/EntityDescription/Description'; import Loader from '../../../common/Loader/Loader'; +import { OwnerLabel } from '../../../common/OwnerLabel/OwnerLabel.component'; import ProfilePicture from '../../../common/ProfilePicture/ProfilePicture'; import { UserTeamSelectableList } from '../../../common/UserTeamSelectableList/UserTeamSelectableList.component'; import TagsInput from '../../../TagsInput/TagsInput.component'; @@ -102,28 +103,7 @@ const TableQueryRightPanel = ({ )} -
- {query.owner && getEntityName(query.owner) ? ( - - - - {getEntityName(query.owner)} - - - ) : ( - - {t('label.no-entity', { - entity: t('label.owner-lowercase'), - })} - - )} -
+ diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueryRightPanel/TableQueryRightPanel.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueryRightPanel/TableQueryRightPanel.test.tsx index a625d42ac7c..ad74492c0c6 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueryRightPanel/TableQueryRightPanel.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueryRightPanel/TableQueryRightPanel.test.tsx @@ -62,9 +62,6 @@ describe('TableQueryRightPanel component test', () => { }); const owner = await screen.findByTestId('owner-link'); - expect( - await screen.findByTestId('owner-name-container') - ).toBeInTheDocument(); expect(owner).toBeInTheDocument(); expect(owner.textContent).toEqual(MOCK_QUERIES[0].owner?.displayName); expect( diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainDetailsPage/DomainDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainDetailsPage/DomainDetailsPage.component.tsx index c58b5b26549..f6c1911f46c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainDetailsPage/DomainDetailsPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainDetailsPage/DomainDetailsPage.component.tsx @@ -312,7 +312,7 @@ const DomainDetailsPage = ({ setIsNameEditing(false); }; - const onStyleSave = (data: Style) => { + const onStyleSave = async (data: Style) => { const style: Style = { // if color/iconURL is empty or undefined send undefined color: data.color ? data.color : undefined, @@ -323,7 +323,7 @@ const DomainDetailsPage = ({ style, }; - onUpdate(updatedDetails); + await onUpdate(updatedDetails); setIsStyleEditing(false); }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainTabs/DocumentationTab/DocumentationTab.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainTabs/DocumentationTab/DocumentationTab.component.tsx index 6127ee8e0de..2c2670604ca 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainTabs/DocumentationTab/DocumentationTab.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainTabs/DocumentationTab/DocumentationTab.component.tsx @@ -136,7 +136,7 @@ const DocumentationTab = ({ await onUpdate(updatedData as Domain | DataProduct); }; - const handleExpertsUpdate = (data: Array) => { + const handleExpertsUpdate = async (data: Array) => { if (!isEqual(data, domain.experts)) { let updatedDomain = cloneDeep(domain); const oldExperts = data.filter((d) => includes(domain.experts, d)); @@ -152,7 +152,7 @@ const DocumentationTab = ({ ...updatedDomain, experts: [...oldExperts, ...newExperts], }; - onUpdate(updatedDomain); + await onUpdate(updatedDomain); } }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityVersionTimeLine/EntityVersionTimeLine.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityVersionTimeLine/EntityVersionTimeLine.tsx index 519a0bc3009..71f6f852ced 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityVersionTimeLine/EntityVersionTimeLine.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityVersionTimeLine/EntityVersionTimeLine.tsx @@ -123,7 +123,7 @@ const EntityVersionTimeLine: React.FC = ({ const versions = useMemo( () => - versionList.versions.map((v, i) => { + versionList.versions?.map((v, i) => { const currV = JSON.parse(v); const majorVersionChecks = () => { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TopicSummary/TopicSummary.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TopicSummary/TopicSummary.component.tsx index bbc10a2a93e..aa4d1c5431b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TopicSummary/TopicSummary.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TopicSummary/TopicSummary.component.tsx @@ -24,12 +24,10 @@ import { getFormattedEntityData, getSortedTagsWithHighlight, } from '../../../../utils/EntitySummaryPanelUtils'; -import { - DRAWER_NAVIGATION_OPTIONS, - getOwnerNameWithProfilePic, -} from '../../../../utils/EntityUtils'; +import { DRAWER_NAVIGATION_OPTIONS } from '../../../../utils/EntityUtils'; import { bytesToSize } from '../../../../utils/StringsUtils'; import { getConfigObject } from '../../../../utils/TopicDetailsUtils'; +import { OwnerLabel } from '../../../common/OwnerLabel/OwnerLabel.component'; import SummaryPanelSkeleton from '../../../common/Skeleton/SummaryPanelSkeleton/SummaryPanelSkeleton.component'; import SummaryTagsDescription from '../../../common/SummaryTagsDescription/SummaryTagsDescription.component'; import { SearchedDataProps } from '../../../SearchedData/SearchedData.interface'; @@ -75,11 +73,7 @@ function TopicSummary({ const owner = entityDetails.owner; return { - value: - getOwnerNameWithProfilePic(owner) ?? - t('label.no-entity', { - entity: t('label.owner'), - }), + value: , url: getTeamAndUserDetailsPath(owner?.name ?? ''), isLink: !isEmpty(owner?.name), }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.interface.ts index 48cea3166c8..53f007bb849 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.interface.ts @@ -29,7 +29,7 @@ export type GlossaryDetailsProps = { termsLoading: boolean; updateGlossary: (value: Glossary) => Promise; updateVote?: (data: VotingDataProps) => Promise; - handleGlossaryDelete: (id: string) => void; + handleGlossaryDelete: (id: string) => Promise; refreshGlossaryTerms: () => void; onAddGlossaryTerm: (glossaryTerm: GlossaryTerm | undefined) => void; onEditGlossaryTerm: (glossaryTerm: GlossaryTerm) => void; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetailsRightPanel/GlossaryReviewers.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetailsRightPanel/GlossaryReviewers.tsx index c7073b91dbd..a310a4c6278 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetailsRightPanel/GlossaryReviewers.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetailsRightPanel/GlossaryReviewers.tsx @@ -32,6 +32,7 @@ import { getDiffByFieldName, getRemovedDiffElement, } from '../../../utils/EntityVersionUtils'; +import { UserTeam } from '../../common/AssigneeList/AssigneeList.interface'; import ProfilePicture from '../../common/ProfilePicture/ProfilePicture'; interface GlossaryReviewersProps { @@ -70,6 +71,7 @@ function GlossaryReviewers({ { + const handleDelete = async () => { const { id } = selectedData; - onDelete(id); + await onDelete(id); setIsDelete(false); }; @@ -227,7 +227,7 @@ const GlossaryHeader = ({ setIsNameEditing(false); }; - const onStyleSave = (data: Style) => { + const onStyleSave = async (data: Style) => { const style: Style = { // if color/iconURL is empty or undefined send undefined color: data.color ? data.color : undefined, @@ -238,7 +238,7 @@ const GlossaryHeader = ({ style, }; - onUpdate(updatedDetails); + await onUpdate(updatedDetails); setIsStyleEditing(false); }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.interface.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.interface.tsx index d3bcee1e6c2..5681879294b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.interface.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.interface.tsx @@ -21,8 +21,8 @@ export interface GlossaryHeaderProps { permissions: OperationPermission; selectedData: Glossary | GlossaryTerm; isGlossary: boolean; - onUpdate: (data: GlossaryTerm | Glossary) => void | Promise; - onDelete: (id: string) => void; + onUpdate: (data: GlossaryTerm | Glossary) => Promise; + onDelete: (id: string) => Promise; onAssetAdd?: () => void; updateVote?: (data: VotingDataProps) => Promise; onAddGlossaryTerm: (glossaryTerm: GlossaryTerm | undefined) => void; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermReferencesModal.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermReferencesModal.component.tsx index 59c6cbbc773..806d4b2f520 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermReferencesModal.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermReferencesModal.component.tsx @@ -12,7 +12,7 @@ */ import Icon from '@ant-design/icons/lib/components/Icon'; import { Button, Col, Form, Input, Modal, Row } from 'antd'; -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ReactComponent as IconDelete } from '../../../assets/svg/ic-delete.svg'; import { ReactComponent as PlusIcon } from '../../../assets/svg/plus-primary.svg'; @@ -22,7 +22,7 @@ interface GlossaryTermReferencesModalProps { references: TermReference[]; isVisible: boolean; onClose: () => void; - onSave: (values: TermReference[]) => void; + onSave: (values: TermReference[]) => Promise; } const GlossaryTermReferencesModal = ({ @@ -33,13 +33,17 @@ const GlossaryTermReferencesModal = ({ }: GlossaryTermReferencesModalProps) => { const { t } = useTranslation(); const [form] = Form.useForm<{ references: TermReference[] }>(); + const [saving, setSaving] = useState(false); const handleSubmit = async (obj: { references: TermReference[] }) => { try { + setSaving(true); await form.validateFields(); - onSave(obj.references); + await onSave(obj.references); } catch (_) { // Nothing here + } finally { + setSaving(false); } }; @@ -69,8 +73,9 @@ const GlossaryTermReferencesModal = ({ , ]} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.component.tsx index 1443b77cb8f..e3d07990df2 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.component.tsx @@ -26,6 +26,7 @@ import { FEED_COUNT_INITIAL_DATA } from '../../../constants/entity.constants'; import { EntityField } from '../../../constants/Feeds.constants'; import { EntityTabs, EntityType } from '../../../enums/entity.enum'; import { SearchIndex } from '../../../enums/search.enum'; +import { Glossary } from '../../../generated/entity/data/glossary'; import { GlossaryTerm, Status, @@ -153,8 +154,8 @@ const GlossaryTermsV1 = ({ [glossaryTerm, handleGlossaryTermUpdate] ); - const onTermUpdate = async (data: GlossaryTerm) => { - await handleGlossaryTermUpdate(data); + const onTermUpdate = async (data: GlossaryTerm | Glossary) => { + await handleGlossaryTermUpdate(data as GlossaryTerm); getEntityFeedCount(); }; @@ -170,7 +171,7 @@ const GlossaryTermsV1 = ({ permissions={permissions} selectedData={glossaryTerm} onThreadLinkSelect={onThreadLinkSelect} - onUpdate={async (data) => await onTermUpdate(data as GlossaryTerm)} + onUpdate={onTermUpdate} /> ), }, @@ -334,7 +335,7 @@ const GlossaryTermsV1 = ({ onAddGlossaryTerm={onAddGlossaryTerm} onAssetAdd={() => setAssetModelVisible(true)} onDelete={handleGlossaryTermDelete} - onUpdate={(data) => onTermUpdate(data as GlossaryTerm)} + onUpdate={onTermUpdate} /> diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.interface.ts index 5d78694557c..f40291babd1 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/GlossaryTermsV1.interface.ts @@ -21,7 +21,7 @@ export interface GlossaryTermsV1Props { glossaryTerm: GlossaryTerm; childGlossaryTerms: GlossaryTerm[]; handleGlossaryTermUpdate: (data: GlossaryTerm) => Promise; - handleGlossaryTermDelete: (id: string) => void; + handleGlossaryTermDelete: (id: string) => Promise; refreshGlossaryTerms: () => void; onAssetClick?: (asset?: EntityDetailsObjectInterface) => void; isSummaryPanelOpen: boolean; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermReferences.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermReferences.tsx index f9f8918584c..f6ba148cae0 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermReferences.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermReferences.tsx @@ -47,7 +47,7 @@ interface GlossaryTermReferencesProps { isVersionView?: boolean; glossaryTerm: GlossaryTerm; permissions: OperationPermission; - onGlossaryTermUpdate: (glossaryTerm: GlossaryTerm) => void; + onGlossaryTermUpdate: (glossaryTerm: GlossaryTerm) => Promise; } const GlossaryTermReferences = ({ @@ -74,7 +74,7 @@ const GlossaryTermReferences = ({ references: updatedRef, }; - onGlossaryTermUpdate(updatedGlossaryTerm); + await onGlossaryTermUpdate(updatedGlossaryTerm); if (updateState) { setReferences(updatedRef); } @@ -85,10 +85,6 @@ const GlossaryTermReferences = ({ } }; - const onReferenceModalSave = (values: TermReference[]) => { - handleReferencesSave(values); - }; - useEffect(() => { setReferences(glossaryTerm.references ? glossaryTerm.references : []); }, [glossaryTerm.references]); @@ -246,9 +242,7 @@ const GlossaryTermReferences = ({ onClose={() => { setIsViewMode(true); }} - onSave={(values: TermReference[]) => { - onReferenceModalSave(values); - }} + onSave={handleReferencesSave} /> ); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermSynonyms.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermSynonyms.tsx index ffa0be4ce5d..5e5488f03dc 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermSynonyms.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/GlossaryTermSynonyms.tsx @@ -38,7 +38,7 @@ interface GlossaryTermSynonymsProps { isVersionView?: boolean; permissions: OperationPermission; glossaryTerm: GlossaryTerm; - onGlossaryTermUpdate: (glossaryTerm: GlossaryTerm) => void; + onGlossaryTermUpdate: (glossaryTerm: GlossaryTerm) => Promise; } const GlossaryTermSynonyms = ({ @@ -49,6 +49,7 @@ const GlossaryTermSynonyms = ({ }: GlossaryTermSynonymsProps) => { const [isViewMode, setIsViewMode] = useState(true); const [synonyms, setSynonyms] = useState([]); + const [saving, setSaving] = useState(false); const getSynonyms = () => (
@@ -156,15 +157,16 @@ const GlossaryTermSynonyms = ({ setIsViewMode(true); }; - const handleSynonymsSave = (newSynonyms: string[]) => { - if (!isEqual(newSynonyms, glossaryTerm.synonyms)) { + const handleSynonymsSave = async () => { + if (!isEqual(synonyms, glossaryTerm.synonyms)) { let updatedGlossaryTerm = cloneDeep(glossaryTerm); updatedGlossaryTerm = { ...updatedGlossaryTerm, - synonyms: newSynonyms, + synonyms, }; - - onGlossaryTermUpdate(updatedGlossaryTerm); + setSaving(true); + await onGlossaryTermUpdate(updatedGlossaryTerm); + setSaving(false); } setIsViewMode(true); }; @@ -217,9 +219,10 @@ const GlossaryTermSynonyms = ({ className="w-6 p-x-05" data-testid="save-synonym-btn" icon={} + loading={saving} size="small" type="primary" - onClick={() => handleSynonymsSave(synonyms)} + onClick={handleSynonymsSave} /> diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/RelatedTerms.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/RelatedTerms.tsx index 2c9acf7af0c..cded12b46cf 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/RelatedTerms.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/RelatedTerms.tsx @@ -77,6 +77,7 @@ const RelatedTerms = ({ if (!isArray(selectedData)) { return; } + const newOptions = uniqWith( options, (arrVal, othVal) => arrVal.id === othVal.id diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.interfaces.ts b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.interfaces.ts index feaef3ec1a8..821220ede14 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.interfaces.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.interfaces.ts @@ -23,8 +23,8 @@ export type GlossaryV1Props = { isGlossaryActive: boolean; updateGlossary: (value: Glossary) => Promise; onGlossaryTermUpdate: (value: GlossaryTerm) => Promise; - onGlossaryDelete: (id: string) => void | Promise; - onGlossaryTermDelete: (id: string) => void | Promise; + onGlossaryDelete: (id: string) => Promise; + onGlossaryTermDelete: (id: string) => Promise; isVersionsView: boolean; onAssetClick?: (asset?: EntityDetailsObjectInterface) => void; isSummaryPanelOpen: boolean; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryVersion/GlossaryVersion.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryVersion/GlossaryVersion.component.tsx index 49a6e24ca13..99e3efa9a5f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryVersion/GlossaryVersion.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryVersion/GlossaryVersion.component.tsx @@ -11,7 +11,7 @@ * limitations under the License. */ import { AxiosError } from 'axios'; -import { noop, toString } from 'lodash'; +import { toString } from 'lodash'; import React, { useEffect, useState } from 'react'; import { useHistory, useParams } from 'react-router-dom'; import { LOADING_STATE } from '../../../enums/common.enum'; @@ -113,8 +113,8 @@ const GlossaryVersion = ({ isGlossary = false }: GlossaryVersionProps) => { isSummaryPanelOpen={false} selectedData={selectedData as Glossary} updateGlossary={() => Promise.resolve()} - onGlossaryDelete={noop} - onGlossaryTermDelete={noop} + onGlossaryDelete={() => Promise.resolve()} + onGlossaryTermDelete={() => Promise.resolve()} onGlossaryTermUpdate={() => Promise.resolve()} /> )} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Modals/EntityDeleteModal/EntityDeleteModal.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Modals/EntityDeleteModal/EntityDeleteModal.interface.ts index 84d8546b5f4..6d1c94451e1 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Modals/EntityDeleteModal/EntityDeleteModal.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Modals/EntityDeleteModal/EntityDeleteModal.interface.ts @@ -14,7 +14,7 @@ import { HTMLAttributes } from 'react'; export interface EntityDeleteModalProp extends HTMLAttributes { - onConfirm: () => void; + onConfirm: () => Promise; onCancel: () => void; entityName: string; entityType: string; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Modals/EntityDeleteModal/EntityDeleteModal.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Modals/EntityDeleteModal/EntityDeleteModal.tsx index 57e70c10476..aa26656b705 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Modals/EntityDeleteModal/EntityDeleteModal.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Modals/EntityDeleteModal/EntityDeleteModal.tsx @@ -30,6 +30,7 @@ const EntityDeleteModal = ({ bodyText, }: EntityDeleteModalProp) => { const [name, setName] = useState(''); + const [saving, setSaving] = useState(false); const handleOnChange = (e: ChangeEvent) => { setName(e.target.value); @@ -42,6 +43,12 @@ const EntityDeleteModal = ({ [loadingState] ); + const handleSave = async () => { + setSaving(true); + await onConfirm(); + setSaving(false); + }; + // To remove the entered text in the modal input after modal closed useEffect(() => { setName(''); @@ -67,9 +74,9 @@ const EntityDeleteModal = ({
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Modals/StyleModal/StyleModal.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Modals/StyleModal/StyleModal.component.tsx index cb1940f442a..c14525c563c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Modals/StyleModal/StyleModal.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Modals/StyleModal/StyleModal.component.tsx @@ -11,7 +11,6 @@ * limitations under the License. */ import { Form, FormProps, Input, Modal } from 'antd'; - import { isUndefined, omit } from 'lodash'; import React from 'react'; import { useTranslation } from 'react-i18next'; @@ -23,9 +22,17 @@ import { StyleModalProps, StyleWithInput } from './StyleModal.interface'; const StyleModal = ({ open, onCancel, onSubmit, style }: StyleModalProps) => { const { t } = useTranslation(); const [form] = Form.useForm(); + const [saving, setSaving] = React.useState(false); - const handleSubmit: FormProps['onFinish'] = (value) => { - onSubmit(omit(value, 'colorInput')); + const handleSubmit: FormProps['onFinish'] = async (value) => { + try { + setSaving(true); + await onSubmit(omit(value, 'colorInput')); + } catch (err) { + // Error is handled in parent component + } finally { + setSaving(false); + } }; return ( @@ -34,6 +41,7 @@ const StyleModal = ({ open, onCancel, onSubmit, style }: StyleModalProps) => { okButtonProps={{ form: 'style-modal', htmlType: 'submit', + loading: saving, }} okText={t('label.submit')} open={open} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Modals/StyleModal/StyleModal.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Modals/StyleModal/StyleModal.interface.ts index 27bacbf638a..ea5e4650e0e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Modals/StyleModal/StyleModal.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Modals/StyleModal/StyleModal.interface.ts @@ -15,7 +15,7 @@ import { Style } from '../../../generated/type/schema'; export interface StyleModalProps { open: boolean; style?: Style; - onSubmit: (value: Style) => void; + onSubmit: (value: Style) => Promise; onCancel: () => void; } diff --git a/openmetadata-ui/src/main/resources/ui/src/components/MyData/Persona/PersonaSelectableList/PersonaSelectableList.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/MyData/Persona/PersonaSelectableList/PersonaSelectableList.component.tsx index bf62a465613..01e37083163 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/MyData/Persona/PersonaSelectableList/PersonaSelectableList.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/MyData/Persona/PersonaSelectableList/PersonaSelectableList.component.tsx @@ -12,7 +12,6 @@ */ import { Button, Popover, Space, Typography } from 'antd'; import { t } from 'i18next'; -import { noop } from 'lodash'; import React, { useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ReactComponent as EditIcon } from '../../../../assets/svg/edit-new.svg'; @@ -46,7 +45,7 @@ export const PersonaListItemRenderer = (props: EntityReference) => { export const PersonaSelectableList = ({ hasPermission, selectedPersonas = [], - onUpdate = noop, + onUpdate, children, popoverProps, multiSelect = false, @@ -96,11 +95,11 @@ export const PersonaSelectableList = ({ }; const handleUpdate = useCallback( - (users: EntityReference[]) => { + async (users: EntityReference[]) => { if (multiSelect) { - (onUpdate as (users: EntityReference[]) => void)(users); + await (onUpdate as (users: EntityReference[]) => Promise)(users); } else { - (onUpdate as (users: EntityReference) => void)(users[0]); + await (onUpdate as (users: EntityReference) => Promise)(users[0]); } setPopupVisible(false); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Services/Ingestion/Ingestion.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Services/Ingestion/Ingestion.component.tsx index 1f0a2514100..cdef5b6b9a8 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Services/Ingestion/Ingestion.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Services/Ingestion/Ingestion.component.tsx @@ -116,18 +116,18 @@ const Ingestion: React.FC = ({ }); }; - const handleDelete = (id: string, displayName: string) => { + const handleDelete = async (id: string, displayName: string) => { setDeleteSelection({ id, name: displayName, state: 'waiting' }); - deleteIngestion(id, displayName) - .then(() => { - setTimeout(() => { - setDeleteSelection({ id, name: displayName, state: 'success' }); - handleCancelConfirmationModal(); - }, 500); - }) - .catch(() => { + try { + await deleteIngestion(id, displayName); + + setTimeout(() => { + setDeleteSelection({ id, name: displayName, state: 'success' }); handleCancelConfirmationModal(); - }); + }, 500); + } catch (error) { + handleCancelConfirmationModal(); + } }; const getSearchedIngestions = () => { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Team/TeamDetails/TeamDetailsV1.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Team/TeamDetails/TeamDetailsV1.interface.ts index 4ea43c1e186..b90d77fbaee 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Team/TeamDetails/TeamDetailsV1.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Team/TeamDetails/TeamDetailsV1.interface.ts @@ -100,7 +100,7 @@ export interface TeamDetailsProp { descriptionHandler: (value: boolean) => void; onDescriptionUpdate: (value: string) => Promise; updateTeamHandler: (data: Team, fetchTeam?: boolean) => Promise; - handleAddUser: (data: Array) => void; + handleAddUser: (data: Array) => Promise; afterDeleteAction: (isSoftDeleted?: boolean) => void; removeUserFromTeam: (id: string) => Promise; handleJoinTeamClick: (id: string, data: Operation[]) => void; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Team/TeamDetails/UserTab/UserTab.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Team/TeamDetails/UserTab/UserTab.interface.ts index 211fafd46aa..9ef2132074f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Team/TeamDetails/UserTab/UserTab.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Team/TeamDetails/UserTab/UserTab.interface.ts @@ -17,6 +17,6 @@ import { EntityReference } from '../../../../../generated/type/entityReference'; export interface UserTabProps { permission: OperationPermission; currentTeam: Team; - onAddUser: (data: EntityReference[]) => void; + onAddUser: (data: EntityReference[]) => Promise; onRemoveUser: (id: string) => Promise; } diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsSelectForm/TagsSelectForm.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsSelectForm/TagsSelectForm.component.tsx index aa6969faf47..d37faa82801 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsSelectForm/TagsSelectForm.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Tag/TagsSelectForm/TagsSelectForm.component.tsx @@ -13,6 +13,7 @@ import { CheckOutlined, CloseOutlined } from '@ant-design/icons'; import { Button, Col, Form, Row, Space } from 'antd'; import { useForm } from 'antd/lib/form/Form'; +import { DefaultOptionType } from 'antd/lib/select'; import React, { useState } from 'react'; import AsyncSelectList from '../../common/AsyncSelectList/AsyncSelectList'; import './tag-select-fom.style.less'; @@ -30,15 +31,20 @@ const TagSelectForm = ({ const [form] = useForm(); const [isSubmitLoading, setIsSubmitLoading] = useState(false); + const handleSave = async (data: { + tags: DefaultOptionType | DefaultOptionType[]; + }) => { + setIsSubmitLoading(true); + await onSubmit(data.tags); + setIsSubmitLoading(false); + }; + return (
{ - setIsSubmitLoading(true); - onSubmit(data.tags); - }}> + onFinish={handleSave}> diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/EntitySummaryDetails/EntitySummaryDetails.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/EntitySummaryDetails/EntitySummaryDetails.tsx index 1e707e0fbfc..83aefe7ed6f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/EntitySummaryDetails/EntitySummaryDetails.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/EntitySummaryDetails/EntitySummaryDetails.tsx @@ -15,41 +15,26 @@ import Icon from '@ant-design/icons/lib/components/Icon'; import { Button, Space } from 'antd'; import Tooltip, { RenderFunction } from 'antd/lib/tooltip'; import classNames from 'classnames'; -import { - isEmpty, - isString, - isUndefined, - lowerCase, - noop, - toLower, -} from 'lodash'; +import { isEmpty, isString, isUndefined, lowerCase, toLower } from 'lodash'; import { ExtraInfo } from 'Models'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { ReactComponent as EditIcon } from '../../../assets/svg/edit-new.svg'; import { ReactComponent as IconExternalLink } from '../../../assets/svg/external-links.svg'; import { ReactComponent as DomainIcon } from '../../../assets/svg/ic-domain.svg'; import { ReactComponent as IconInfoSecondary } from '../../../assets/svg/icon-info.svg'; import { ReactComponent as IconTeamsGrey } from '../../../assets/svg/teams-grey.svg'; import { DE_ACTIVE_COLOR } from '../../../constants/constants'; -import { Tag } from '../../../generated/entity/classification/tag'; import { Dashboard } from '../../../generated/entity/data/dashboard'; -import { Table } from '../../../generated/entity/data/table'; import { TagLabel } from '../../../generated/type/tagLabel'; import { getTeamsUser } from '../../../utils/CommonUtils'; import { useAuthContext } from '../../Auth/AuthProviders/AuthProvider'; import ProfilePicture from '../ProfilePicture/ProfilePicture'; -import TierCard from '../TierCard/TierCard'; -import { UserSelectableList } from '../UserSelectableList/UserSelectableList.component'; -import { UserTeamSelectableList } from '../UserTeamSelectableList/UserTeamSelectableList.component'; import './entity-summary-details.style.less'; export interface GetInfoElementsProps { data: ExtraInfo; - updateOwner?: (value: Table['owner']) => void; tier?: TagLabel; currentTier?: string; - updateTier?: (value?: Tag) => Promise; currentOwner?: Dashboard['owner']; deleted?: boolean; allowTeamOwner?: boolean; @@ -69,35 +54,12 @@ const InfoIcon = ({ ); -const EntitySummaryDetails = ({ - data, - tier, - updateOwner, - updateTier, - currentOwner, - deleted = false, - allowTeamOwner = true, -}: GetInfoElementsProps) => { +const EntitySummaryDetails = ({ data }: GetInfoElementsProps) => { let retVal = <>; const { t } = useTranslation(); const { currentUser } = useAuthContext(); const displayVal = data.placeholderText || data.value; - const ownerDropdown = allowTeamOwner ? ( - - ) : ( - - ); - const { isEntityDetails, userDetails, isTier, isOwner, isTeamOwner } = useMemo(() => { const userDetails = currentUser ? getTeamsUser(data, currentUser) : {}; @@ -158,7 +120,6 @@ const EntitySummaryDetails = ({ className="d-flex gap-1 items-center" data-testid="owner-link"> {t('label.no-entity', { entity: t('label.owner') })} - {updateOwner && !deleted ? ownerDropdown : null} ); } @@ -169,20 +130,7 @@ const EntitySummaryDetails = ({ { retVal = !displayVal || displayVal === '--' ? ( - <> - {t('label.no-entity', { entity: t('label.tier') })} - {updateTier && !deleted ? ( - - - - - - ) : null} - + <>{t('label.no-entity', { entity: t('label.tier') })} ) : ( <> ); @@ -289,8 +237,6 @@ const EntitySummaryDetails = ({ } /> ) : null} - {/* Edit icon with dropdown */} - {(isOwner || isTier) && (updateOwner ? ownerDropdown : null)} ) : isOwner ? ( <> @@ -307,8 +253,6 @@ const EntitySummaryDetails = ({ {displayVal} - {/* Edit icon with dropdown */} - {updateOwner ? ownerDropdown : null} ) : isTier ? ( {displayVal} - - {updateTier && !deleted ? ( - - - - - - ) : null} ) : ( {displayVal} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/SelectableList/SelectableList.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/SelectableList/SelectableList.component.tsx index 467e34c09b1..d9cbb500f7a 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/SelectableList/SelectableList.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/SelectableList/SelectableList.component.tsx @@ -260,7 +260,10 @@ export const SelectableList = ({ /> } itemLayout="vertical" - loading={{ spinning: fetching || updating, indicator: }} + loading={{ + spinning: fetching || updating, + indicator: , + }} locale={{ emptyText: emptyPlaceholderText ?? t('message.no-data-available'), }} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/SelectableList/SelectableList.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/common/SelectableList/SelectableList.interface.ts index 7084cb3cfe6..cb3971a09cb 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/SelectableList/SelectableList.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/SelectableList/SelectableList.interface.ts @@ -22,7 +22,7 @@ export interface SelectableListProps { multiSelect?: boolean; selectedItems: EntityReference[]; onCancel: () => void; - onUpdate: (updatedItems: EntityReference[]) => void | Promise; + onUpdate: (updatedItems: EntityReference[]) => Promise; searchPlaceholder?: string; customTagRenderer?: (props: EntityReference) => ReactNode; searchBarDataTestId?: string; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/UserSelectableList/UserSelectableList.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/UserSelectableList/UserSelectableList.component.tsx index 87a45eb6036..dc4e027a2d2 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/UserSelectableList/UserSelectableList.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/UserSelectableList/UserSelectableList.component.tsx @@ -11,7 +11,6 @@ * limitations under the License. */ import { Button, Popover, Tooltip } from 'antd'; -import { noop } from 'lodash'; import React, { useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ReactComponent as EditIcon } from '../../../assets/svg/edit-new.svg'; @@ -35,7 +34,7 @@ import { UserSelectableListProps } from './UserSelectableList.interface'; export const UserSelectableList = ({ hasPermission, selectedUsers = [], - onUpdate = noop, + onUpdate, children, popoverProps, multiSelect = true, @@ -100,11 +99,11 @@ export const UserSelectableList = ({ }; const handleUpdate = useCallback( - (users: EntityReference[]) => { + async (users: EntityReference[]) => { if (multiSelect) { - (onUpdate as (users: EntityReference[]) => void)(users); + await (onUpdate as (users: EntityReference[]) => Promise)(users); } else { - (onUpdate as (users: EntityReference) => void)(users[0]); + await (onUpdate as (users: EntityReference) => Promise)(users[0]); } setPopupVisible(false); }, diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/UserSelectableList/UserSelectableList.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/common/UserSelectableList/UserSelectableList.interface.ts index 72cdc9d6330..fe290b2d0be 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/UserSelectableList/UserSelectableList.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/UserSelectableList/UserSelectableList.interface.ts @@ -24,10 +24,10 @@ export type UserSelectableListProps = } & ( | { multiSelect?: true; - onUpdate: (updatedUsers: EntityReference[]) => void; + onUpdate: (updatedUsers: EntityReference[]) => Promise; } | { multiSelect: false; - onUpdate: (updatedUsers: EntityReference) => void; + onUpdate: (updatedUsers: EntityReference) => Promise; } ); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.component.tsx index 91c9f78e61b..772aef1583d 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.component.tsx @@ -293,35 +293,36 @@ const GlossaryPage = () => { [selectedData] ); - const handleGlossaryTermDelete = (id: string) => { - setDeleteStatus(LOADING_STATE.WAITING); - deleteGlossaryTerm(id) - .then(() => { - setDeleteStatus(LOADING_STATE.SUCCESS); - showSuccessToast( - t('server.entity-deleted-successfully', { - entity: t('label.glossary-term'), - }) - ); - let fqn; - if (glossaryFqn) { - const fqnArr = Fqn.split(glossaryFqn); - fqnArr.pop(); - fqn = fqnArr.join(FQN_SEPARATOR_CHAR); - } - setIsLoading(true); - history.push(getGlossaryPath(fqn)); - fetchGlossaryList(); - }) - .catch((err: AxiosError) => { - showErrorToast( - err, - t('server.delete-entity-error', { - entity: t('label.glossary-term'), - }) - ); - }) - .finally(() => setDeleteStatus(LOADING_STATE.INITIAL)); + const handleGlossaryTermDelete = async (id: string) => { + try { + setDeleteStatus(LOADING_STATE.WAITING); + await deleteGlossaryTerm(id); + + setDeleteStatus(LOADING_STATE.SUCCESS); + showSuccessToast( + t('server.entity-deleted-successfully', { + entity: t('label.glossary-term'), + }) + ); + let fqn; + if (glossaryFqn) { + const fqnArr = Fqn.split(glossaryFqn); + fqnArr.pop(); + fqn = fqnArr.join(FQN_SEPARATOR_CHAR); + } + setIsLoading(true); + history.push(getGlossaryPath(fqn)); + fetchGlossaryList(); + } catch (err) { + showErrorToast( + err, + t('server.delete-entity-error', { + entity: t('label.glossary-term'), + }) + ); + } finally { + setDeleteStatus(LOADING_STATE.INITIAL); + } }; const handleAssetClick = useCallback( diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/IncidentManager/IncidentManagerDetailPage/IncidentManagerDetailPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/IncidentManager/IncidentManagerDetailPage/IncidentManagerDetailPage.tsx index aa68e9ba98f..862d533e8a5 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/IncidentManager/IncidentManagerDetailPage/IncidentManagerDetailPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/IncidentManager/IncidentManagerDetailPage/IncidentManagerDetailPage.tsx @@ -201,7 +201,7 @@ const IncidentManagerDetailPage = () => { const jsonPatch = compare(data, updatedTestCase); if (jsonPatch.length && data.id) { - updateTestCase(data.id, jsonPatch); + await updateTestCase(data.id, jsonPatch); } } }; diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/ServiceVersionPage/ServiceVersionMainTabContent.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/ServiceVersionPage/ServiceVersionMainTabContent.test.tsx index 45475b30319..8327955a500 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/ServiceVersionPage/ServiceVersionMainTabContent.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/ServiceVersionPage/ServiceVersionMainTabContent.test.tsx @@ -13,6 +13,7 @@ import { render, screen } from '@testing-library/react'; import React from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { EntityType } from '../../enums/entity.enum'; import { Database, @@ -32,7 +33,7 @@ const mockParams = { }; jest.mock('react-router-dom', () => ({ - Link: jest.fn().mockImplementation(({ children }) =>
{children}
), + ...jest.requireActual('react-router-dom'), useParams: jest.fn().mockImplementation(() => mockParams), })); @@ -147,7 +148,9 @@ const props: ServiceVersionMainTabContentProps = { describe('ServiceVersionMainTabContent tests', () => { it('Component should render properly provided proper data', () => { - render(); + render(, { + wrapper: MemoryRouter, + }); const entityTable = screen.getByTestId('service-children-table'); const entityName = screen.getByText('ecommerce_db'); @@ -168,7 +171,9 @@ describe('ServiceVersionMainTabContent tests', () => { }); it('Loader should be displayed if isServiceLoading is true', async () => { - render(); + render(, { + wrapper: MemoryRouter, + }); const loader = await screen.findByTestId('skeleton-table'); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.test.tsx index 8c844528daf..9b62b0dbc0f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.test.tsx @@ -221,7 +221,7 @@ describe('TestDetailsPageV1 component', () => { }); expect(getTableDetailsByFQN).toHaveBeenCalledWith('fqn', { - fields: `${COMMON_API_FIELDS}`, + fields: `${COMMON_API_FIELDS},usageSummary`, }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx index 69aaba6c7bf..f497fdc0e48 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx @@ -159,7 +159,7 @@ const TableDetailsPageV1 = () => { } finally { setLoading(false); } - }, [tableFqn]); + }, [tableFqn, viewUsagePermission]); const fetchQueryCount = async () => { if (!tableDetails?.id) { diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsForm.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsForm.tsx index 8c51ac9a938..c57f9ef3215 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsForm.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsForm.tsx @@ -12,7 +12,7 @@ */ import { Form, Modal, Typography } from 'antd'; -import React, { useEffect, useMemo } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { VALIDATION_MESSAGES } from '../../constants/constants'; import { @@ -22,7 +22,7 @@ import { import { DEFAULT_FORM_VALUE } from '../../constants/Tags.constant'; import { FieldProp, FieldTypes } from '../../interface/FormUtils.interface'; import { generateFormFields } from '../../utils/formUtils'; -import { RenameFormProps } from './TagsPage.interface'; +import { RenameFormProps, SubmitProps } from './TagsPage.interface'; const TagsForm = ({ visible, @@ -40,6 +40,7 @@ const TagsForm = ({ }: RenameFormProps) => { const { t } = useTranslation(); const [form] = Form.useForm(); + const [saving, setSaving] = useState(false); useEffect(() => { form.setFieldsValue({ @@ -202,6 +203,18 @@ const TagsForm = ({ : []), ]; + const handleSave = async (data: SubmitProps) => { + try { + setSaving(true); + await onSubmit(data); + form.setFieldsValue(DEFAULT_FORM_VALUE); + } catch { + // Parent will handle the error + } finally { + setSaving(false); + } + }; + return ( { - onSubmit(data); - form.setFieldsValue(DEFAULT_FORM_VALUE); - }}> + onFinish={handleSave}> {generateFormFields(formFields)} diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.interface.ts b/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.interface.ts index 6a41c93ebe3..28bfa604e5b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.interface.ts @@ -44,7 +44,7 @@ export interface RenameFormProps { onCancel: () => void; header: string; initialValues?: Tag; - onSubmit: (value: SubmitProps) => void; + onSubmit: (value: SubmitProps) => Promise; showMutuallyExclusive?: boolean; isClassification?: boolean; data?: Classification[]; diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.tsx index 3e4b42f0a71..6dddf8b235d 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.tsx @@ -267,56 +267,55 @@ const TagsPage = () => { * @param categoryName - tag category name * @param tagId - tag id */ - const handleDeleteTag = (tagId: string) => { - deleteTag(tagId) - .then((res) => { - if (res) { - if (currentClassification) { - setDeleteStatus(LOADING_STATE.SUCCESS); - setClassifications((prev) => - prev.map((item) => { - if ( - item.fullyQualifiedName === - currentClassification.fullyQualifiedName - ) { - return { - ...item, - termCount: (item.termCount ?? 0) - 1, - }; - } + const handleDeleteTag = async (tagId: string) => { + try { + const res = await deleteTag(tagId); - return item; - }) - ); - } - classificationDetailsRef.current?.refreshClassificationTags(); - } else { - showErrorToast( - t('server.delete-entity-error', { - entity: t('label.tag-lowercase'), + if (res) { + if (currentClassification) { + setDeleteStatus(LOADING_STATE.SUCCESS); + setClassifications((prev) => + prev.map((item) => { + if ( + item.fullyQualifiedName === + currentClassification.fullyQualifiedName + ) { + return { + ...item, + termCount: (item.termCount ?? 0) - 1, + }; + } + + return item; }) ); } - }) - .catch((err: AxiosError) => { + classificationDetailsRef.current?.refreshClassificationTags(); + } else { showErrorToast( - err, - t('server.delete-entity-error', { entity: t('label.tag-lowercase') }) + t('server.delete-entity-error', { + entity: t('label.tag-lowercase'), + }) ); - }) - .finally(() => { - setDeleteTags({ data: undefined, state: false }); - setDeleteStatus(LOADING_STATE.INITIAL); - }); + } + } catch (err) { + showErrorToast( + err, + t('server.delete-entity-error', { entity: t('label.tag-lowercase') }) + ); + } finally { + setDeleteTags({ data: undefined, state: false }); + setDeleteStatus(LOADING_STATE.INITIAL); + } }; /** * It redirects to respective function call based on tag/Classification */ - const handleConfirmClick = () => { + const handleConfirmClick = async () => { if (deleteTags.data?.id) { setDeleteStatus(LOADING_STATE.WAITING); - handleDeleteTag(deleteTags.data.id); + await handleDeleteTag(deleteTags.data.id); } }; @@ -523,16 +522,16 @@ const TagsPage = () => { history.push(getTagPath(category.fullyQualifiedName)); }; - const handleAddTagSubmit = (data: SubmitProps) => { + const handleAddTagSubmit = async (data: SubmitProps) => { const updatedData = omit(data, 'color', 'iconURL'); const style = { color: data.color, iconURL: data.iconURL, }; if (editTag) { - handleUpdatePrimaryTag({ ...editTag, ...updatedData, style }); + await handleUpdatePrimaryTag({ ...editTag, ...updatedData, style }); } else { - handleCreatePrimaryTag({ ...updatedData, style }); + await handleCreatePrimaryTag({ ...updatedData, style }); } }; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx index ee2d24bfdb4..a3a8d785e74 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx @@ -25,7 +25,6 @@ import { Bucket, EntityDetailUnion } from 'Models'; import React, { Fragment } from 'react'; import { Link } from 'react-router-dom'; import { OwnerLabel } from '../components/common/OwnerLabel/OwnerLabel.component'; -import ProfilePicture from '../components/common/ProfilePicture/ProfilePicture'; import QueryCount from '../components/common/QueryCount/QueryCount.component'; import { DataAssetsWithoutServiceField } from '../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface'; import { QueryVoteType } from '../components/Database/TableQueries/TableQueries.interface'; @@ -174,21 +173,6 @@ export const getEntityTags = ( } }; -export const getOwnerNameWithProfilePic = ( - owner: EntityReference | undefined -) => - owner ? ( -
- {' '} - - {getEntityName(owner)} -
- ) : null; - const getUsageData = (usageSummary: UsageDetails | undefined) => !isNil(usageSummary?.weeklyStats?.percentileRank) ? getUsagePercentile(usageSummary?.weeklyStats?.percentileRank ?? 0) @@ -347,11 +331,7 @@ const getPipelineOverview = (pipelineDetails: Pipeline) => { const overview = [ { name: i18next.t('label.owner'), - value: - getOwnerNameWithProfilePic(owner) ?? - i18next.t('label.no-entity', { - entity: i18next.t('label.owner'), - }), + value: , url: getOwnerValue(owner as EntityReference), isLink: !isEmpty(owner?.name), visible: [DRAWER_NAVIGATION_OPTIONS.lineage], @@ -400,11 +380,7 @@ const getDashboardOverview = (dashboardDetails: Dashboard) => { const overview = [ { name: i18next.t('label.owner'), - value: - getOwnerNameWithProfilePic(owner) ?? - i18next.t('label.no-entity', { - entity: i18next.t('label.owner'), - }), + value: , url: getOwnerValue(owner as EntityReference), isLink: !isEmpty(owner?.name), visible: [DRAWER_NAVIGATION_OPTIONS.lineage], @@ -455,11 +431,7 @@ export const getSearchIndexOverview = ( const overview = [ { name: i18next.t('label.owner'), - value: - getOwnerNameWithProfilePic(owner) ?? - i18next.t('label.no-entity', { - entity: i18next.t('label.owner'), - }), + value: , url: getOwnerValue(owner as EntityReference), isLink: !isEmpty(owner?.name), visible: [DRAWER_NAVIGATION_OPTIONS.lineage], @@ -493,11 +465,7 @@ const getMlModelOverview = (mlModelDetails: Mlmodel) => { const overview = [ { name: i18next.t('label.owner'), - value: - getOwnerNameWithProfilePic(owner) ?? - i18next.t('label.no-entity', { - entity: i18next.t('label.owner'), - }), + value: , url: getOwnerValue(owner as EntityReference), isLink: !isEmpty(owner?.name), visible: [DRAWER_NAVIGATION_OPTIONS.lineage], @@ -598,11 +566,7 @@ const getDataModelOverview = (dataModelDetails: DashboardDataModel) => { const overview = [ { name: i18next.t('label.owner'), - value: - getOwnerNameWithProfilePic(owner) ?? - i18next.t('label.no-entity', { - entity: i18next.t('label.owner'), - }), + value: , url: getOwnerValue(owner as EntityReference), isLink: !isEmpty(owner?.name), visible: [DRAWER_NAVIGATION_OPTIONS.lineage], @@ -675,11 +639,7 @@ const getStoredProcedureOverview = ( const overview = [ { name: i18next.t('label.owner'), - value: - getOwnerNameWithProfilePic(owner) ?? - i18next.t('label.no-entity', { - entity: i18next.t('label.owner'), - }), + value: , url: getOwnerValue(owner as EntityReference), isLink: !isEmpty(owner?.name), visible: [DRAWER_NAVIGATION_OPTIONS.lineage], @@ -757,11 +717,7 @@ const getDatabaseOverview = (databaseDetails: Database) => { const overview = [ { name: i18next.t('label.owner'), - value: - getOwnerNameWithProfilePic(owner) ?? - i18next.t('label.no-entity', { - entity: i18next.t('label.owner'), - }), + value: , url: getOwnerValue(owner as EntityReference), isLink: !isEmpty(owner?.name), visible: [DRAWER_NAVIGATION_OPTIONS.explore], @@ -804,11 +760,7 @@ const getDatabaseSchemaOverview = (databaseSchemaDetails: DatabaseSchema) => { const overview = [ { name: i18next.t('label.owner'), - value: - getOwnerNameWithProfilePic(owner) ?? - i18next.t('label.no-entity', { - entity: i18next.t('label.owner'), - }), + value: , url: getOwnerValue(owner as EntityReference), isLink: !isEmpty(owner?.name), visible: [DRAWER_NAVIGATION_OPTIONS.explore], @@ -856,11 +808,7 @@ const getEntityServiceOverview = (serviceDetails: EntityServiceUnion) => { const overview = [ { name: i18next.t('label.owner'), - value: - getOwnerNameWithProfilePic(owner) ?? - i18next.t('label.no-entity', { - entity: i18next.t('label.owner'), - }), + value: , url: getOwnerValue(owner as EntityReference), isLink: !isEmpty(owner?.name), visible: [DRAWER_NAVIGATION_OPTIONS.explore], diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/EntityVersionUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/EntityVersionUtils.tsx index 70ec0851757..f4d36b8de4d 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/EntityVersionUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/EntityVersionUtils.tsx @@ -11,7 +11,7 @@ * limitations under the License. */ -import { Space, Typography } from 'antd'; +import { Typography } from 'antd'; import { ArrayChange, Change, @@ -31,15 +31,11 @@ import { } from 'lodash'; import React, { Fragment, ReactNode } from 'react'; import ReactDOMServer from 'react-dom/server'; -import { Link } from 'react-router-dom'; -import { ReactComponent as IconTeamsGrey } from '../assets/svg/teams-grey.svg'; import { ExtentionEntities, ExtentionEntitiesKeys, } from '../components/common/CustomPropertyTable/CustomPropertyTable.interface'; -import ProfilePicture from '../components/common/ProfilePicture/ProfilePicture'; import { FQN_SEPARATOR_CHAR } from '../constants/char.constants'; -import { getTeamAndUserDetailsPath, getUserPath } from '../constants/constants'; import { EntityField } from '../constants/Feeds.constants'; import { EntityType } from '../enums/entity.enum'; import { Column as ContainerColumn } from '../generated/entity/data/container'; @@ -522,33 +518,6 @@ export function getEntityTagDiff< return entityList ?? []; } -export const getOwnerInfo = (owner: EntityReference, ownerLabel: ReactNode) => { - const isTeamType = owner.type === 'team'; - - return ( - - {isTeamType ? ( - - ) : ( - - )} - - {ownerLabel} - - - ); -}; - export const getEntityReferenceDiffFromFieldName = ( fieldName: string, changeDescription: ChangeDescription, diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/ServiceMainTabContentUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/ServiceMainTabContentUtils.tsx index ca643dd8d82..83ab2f6484d 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/ServiceMainTabContentUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/ServiceMainTabContentUtils.tsx @@ -11,14 +11,15 @@ * limitations under the License. */ -import { Space, Typography } from 'antd'; +import { Typography } from 'antd'; import { ColumnsType } from 'antd/lib/table'; import { t } from 'i18next'; import { isUndefined } from 'lodash'; import { ServiceTypes } from 'Models'; import React from 'react'; import { Link } from 'react-router-dom'; -import ProfilePicture from '../components/common/ProfilePicture/ProfilePicture'; +import { UserTeam } from '../components/common/AssigneeList/AssigneeList.interface'; +import UserPopOverCard from '../components/common/PopOverCard/UserPopOverCard'; import RichTextEditorPreviewer from '../components/common/RichTextEditor/RichTextEditorPreviewer'; import TagsViewer from '../components/Tag/TagsViewer/TagsViewer'; import { NO_DATA_PLACEHOLDER } from '../constants/constants'; @@ -92,12 +93,14 @@ export const getServiceMainTabColumns = ( key: 'owner', render: (owner: ServicePageData['owner']) => !isUndefined(owner) ? ( - - - - {getEntityName(owner)} - - + ) : ( -- ),