mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-21 07:28:44 +00:00
Fixed No data placeholders for reviewers and related terms (#3359)
* Fixed No data placeholders for reviewers and related terms
This commit is contained in:
parent
f03fb1cafa
commit
4d1d25a58b
@ -29,7 +29,6 @@ import { getTagCategories, getTaglist } from '../../utils/TagsUtils';
|
|||||||
import { Button } from '../buttons/Button/Button';
|
import { Button } from '../buttons/Button/Button';
|
||||||
import Avatar from '../common/avatar/Avatar';
|
import Avatar from '../common/avatar/Avatar';
|
||||||
import Description from '../common/description/Description';
|
import Description from '../common/description/Description';
|
||||||
import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder';
|
|
||||||
import NonAdminAction from '../common/non-admin-action/NonAdminAction';
|
import NonAdminAction from '../common/non-admin-action/NonAdminAction';
|
||||||
import PopOver from '../common/popover/PopOver';
|
import PopOver from '../common/popover/PopOver';
|
||||||
import TabsPane from '../common/TabsPane/TabsPane';
|
import TabsPane from '../common/TabsPane/TabsPane';
|
||||||
@ -181,7 +180,7 @@ const GlossaryDetails = ({ isHasAccess, glossary, updateGlossary }: props) => {
|
|||||||
}
|
}
|
||||||
}, [glossary.reviewers]);
|
}, [glossary.reviewers]);
|
||||||
|
|
||||||
const rightPosButton = () => {
|
const AddReviewerButton = () => {
|
||||||
return (
|
return (
|
||||||
<NonAdminAction position="bottom" title={TITLE_FOR_NON_ADMIN_ACTION}>
|
<NonAdminAction position="bottom" title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||||
<Button
|
<Button
|
||||||
@ -217,10 +216,10 @@ const GlossaryDetails = ({ isHasAccess, glossary, updateGlossary }: props) => {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<ErrorPlaceHolder>
|
<div className="tw-py-3 tw-text-center tw-bg-white tw-border tw-border-main">
|
||||||
<p className="tw-text-base tw-text-center">No Reviewers.</p>
|
<p className="tw-mb-3">No reviewers assigned</p>
|
||||||
<p className="tw-text-lg tw-text-center tw-mt-2">{rightPosButton()}</p>
|
<p>{AddReviewerButton()}</p>
|
||||||
</ErrorPlaceHolder>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -353,7 +352,7 @@ const GlossaryDetails = ({ isHasAccess, glossary, updateGlossary }: props) => {
|
|||||||
glossary.reviewers &&
|
glossary.reviewers &&
|
||||||
glossary.reviewers.length > 0 &&
|
glossary.reviewers.length > 0 &&
|
||||||
activeTab === 1
|
activeTab === 1
|
||||||
? rightPosButton()
|
? AddReviewerButton()
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
setActiveTab={setActiveTabHandler}
|
setActiveTab={setActiveTabHandler}
|
||||||
|
@ -13,7 +13,12 @@
|
|||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { cloneDeep, includes, isEqual } from 'lodash';
|
import { cloneDeep, includes, isEqual } from 'lodash';
|
||||||
import { EntityTags, FormatedUsersData, GlossaryTermAssets } from 'Models';
|
import {
|
||||||
|
EntityTags,
|
||||||
|
FormatedGlossaryTermData,
|
||||||
|
FormatedUsersData,
|
||||||
|
GlossaryTermAssets,
|
||||||
|
} from 'Models';
|
||||||
import React, { Fragment, useEffect, useState } from 'react';
|
import React, { Fragment, useEffect, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
LIST_SIZE,
|
LIST_SIZE,
|
||||||
@ -29,11 +34,11 @@ import SVGIcons from '../../utils/SvgUtils';
|
|||||||
import { getTagCategories, getTaglist } from '../../utils/TagsUtils';
|
import { getTagCategories, getTaglist } from '../../utils/TagsUtils';
|
||||||
import { Button } from '../buttons/Button/Button';
|
import { Button } from '../buttons/Button/Button';
|
||||||
import Description from '../common/description/Description';
|
import Description from '../common/description/Description';
|
||||||
import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder';
|
|
||||||
import NonAdminAction from '../common/non-admin-action/NonAdminAction';
|
import NonAdminAction from '../common/non-admin-action/NonAdminAction';
|
||||||
import PopOver from '../common/popover/PopOver';
|
import PopOver from '../common/popover/PopOver';
|
||||||
import TabsPane from '../common/TabsPane/TabsPane';
|
import TabsPane from '../common/TabsPane/TabsPane';
|
||||||
import GlossaryReferenceModal from '../Modals/GlossaryReferenceModal/GlossaryReferenceModal';
|
import GlossaryReferenceModal from '../Modals/GlossaryReferenceModal/GlossaryReferenceModal';
|
||||||
|
import RelatedTermsModal from '../Modals/RelatedTermsModal/RelatedTermsModal';
|
||||||
import ReviewerModal from '../Modals/ReviewerModal/ReviewerModal.component';
|
import ReviewerModal from '../Modals/ReviewerModal/ReviewerModal.component';
|
||||||
import TagsContainer from '../tags-container/tags-container';
|
import TagsContainer from '../tags-container/tags-container';
|
||||||
import Tags from '../tags/tags';
|
import Tags from '../tags/tags';
|
||||||
@ -60,6 +65,7 @@ const GlossaryTermsV1 = ({
|
|||||||
const [isDescriptionEditable, setIsDescriptionEditable] = useState(false);
|
const [isDescriptionEditable, setIsDescriptionEditable] = useState(false);
|
||||||
const [activeTab, setActiveTab] = useState(1);
|
const [activeTab, setActiveTab] = useState(1);
|
||||||
const [showRevieweModal, setShowRevieweModal] = useState(false);
|
const [showRevieweModal, setShowRevieweModal] = useState(false);
|
||||||
|
const [showRelatedTermsModal, setShowRelatedTermsModal] = useState(false);
|
||||||
const [isSynonymsEditing, setIsSynonymsEditing] = useState(false);
|
const [isSynonymsEditing, setIsSynonymsEditing] = useState(false);
|
||||||
const [isReferencesEditing, setIsReferencesEditing] = useState(false);
|
const [isReferencesEditing, setIsReferencesEditing] = useState(false);
|
||||||
const [synonyms, setSynonyms] = useState(
|
const [synonyms, setSynonyms] = useState(
|
||||||
@ -67,12 +73,9 @@ const GlossaryTermsV1 = ({
|
|||||||
);
|
);
|
||||||
const [references, setReferences] = useState(glossaryTerm.references || []);
|
const [references, setReferences] = useState(glossaryTerm.references || []);
|
||||||
const [reviewer, setReviewer] = useState<Array<FormatedUsersData>>([]);
|
const [reviewer, setReviewer] = useState<Array<FormatedUsersData>>([]);
|
||||||
const [relatedTerms, setRelatedTerms] = useState<
|
const [relatedTerms, setRelatedTerms] = useState<FormatedGlossaryTermData[]>(
|
||||||
{
|
[]
|
||||||
relatedTerms: string;
|
);
|
||||||
description: string;
|
|
||||||
}[]
|
|
||||||
>([]);
|
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
@ -92,6 +95,32 @@ const GlossaryTermsV1 = ({
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const onRelatedTermsModalCancel = () => {
|
||||||
|
setShowRelatedTermsModal(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRelatedTermsSave = (terms: Array<FormatedGlossaryTermData>) => {
|
||||||
|
if (!isEqual(terms, relatedTerms)) {
|
||||||
|
let updatedGlossaryTerm = cloneDeep(glossaryTerm);
|
||||||
|
const oldTerms = terms.filter((d) => includes(relatedTerms, d));
|
||||||
|
const newTerms = terms
|
||||||
|
.filter((d) => !includes(relatedTerms, d))
|
||||||
|
.map((d) => ({
|
||||||
|
id: d.id,
|
||||||
|
type: d.type,
|
||||||
|
displayName: d.displayName,
|
||||||
|
name: d.name,
|
||||||
|
}));
|
||||||
|
updatedGlossaryTerm = {
|
||||||
|
...updatedGlossaryTerm,
|
||||||
|
relatedTerms: [...oldTerms, ...newTerms],
|
||||||
|
};
|
||||||
|
setRelatedTerms(terms);
|
||||||
|
handleGlossaryTermUpdate(updatedGlossaryTerm);
|
||||||
|
}
|
||||||
|
onRelatedTermsModalCancel();
|
||||||
|
};
|
||||||
|
|
||||||
const onReviewerModalCancel = () => {
|
const onReviewerModalCancel = () => {
|
||||||
setShowRevieweModal(false);
|
setShowRevieweModal(false);
|
||||||
};
|
};
|
||||||
@ -258,19 +287,12 @@ const GlossaryTermsV1 = ({
|
|||||||
}, [glossaryTerm.reviewers]);
|
}, [glossaryTerm.reviewers]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (glossaryTerm.relatedTerms && glossaryTerm.relatedTerms.length) {
|
if (glossaryTerm.relatedTerms?.length) {
|
||||||
setRelatedTerms(
|
setRelatedTerms(glossaryTerm.relatedTerms as FormatedGlossaryTermData[]);
|
||||||
glossaryTerm.relatedTerms.map((term) => {
|
|
||||||
return {
|
|
||||||
relatedTerms: (term.displayName || term.name) as string,
|
|
||||||
description: term.description ?? '',
|
|
||||||
};
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}, [glossaryTerm]);
|
}, [glossaryTerm.relatedTerms]);
|
||||||
|
|
||||||
const rightPosButton = () => {
|
const AddReviewerButton = () => {
|
||||||
return (
|
return (
|
||||||
<NonAdminAction position="bottom" title={TITLE_FOR_NON_ADMIN_ACTION}>
|
<NonAdminAction position="bottom" title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||||
<Button
|
<Button
|
||||||
@ -288,6 +310,24 @@ const GlossaryTermsV1 = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const AddRelatedTermButton = () => {
|
||||||
|
return (
|
||||||
|
<NonAdminAction position="bottom" title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||||
|
<Button
|
||||||
|
className={classNames('tw-h-8 tw-rounded', {
|
||||||
|
'tw-opacity-40': isHasAccess,
|
||||||
|
})}
|
||||||
|
data-testid="add-new-tag-button"
|
||||||
|
size="small"
|
||||||
|
theme="primary"
|
||||||
|
variant="contained"
|
||||||
|
onClick={() => setShowRelatedTermsModal(true)}>
|
||||||
|
Add Related Term
|
||||||
|
</Button>
|
||||||
|
</NonAdminAction>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const getReviewerTabData = () => {
|
const getReviewerTabData = () => {
|
||||||
return glossaryTerm.reviewers && glossaryTerm.reviewers.length > 0 ? (
|
return glossaryTerm.reviewers && glossaryTerm.reviewers.length > 0 ? (
|
||||||
<div className="tw-grid xxl:tw-grid-cols-4 lg:tw-grid-cols-3 md:tw-grid-cols-2 tw-gap-4">
|
<div className="tw-grid xxl:tw-grid-cols-4 lg:tw-grid-cols-3 md:tw-grid-cols-2 tw-gap-4">
|
||||||
@ -306,13 +346,26 @@ const GlossaryTermsV1 = ({
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<ErrorPlaceHolder>
|
<div className="tw-py-3 tw-text-center tw-bg-white tw-border tw-border-main">
|
||||||
<p className="tw-text-base tw-text-center">No Reviewers.</p>
|
<p className="tw-mb-3">No reviewers assigned</p>
|
||||||
<p className="tw-text-lg tw-text-center tw-mt-2">{rightPosButton()}</p>
|
<p>{AddReviewerButton()}</p>
|
||||||
</ErrorPlaceHolder>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getTabPaneButton = () => {
|
||||||
|
switch (activeTab) {
|
||||||
|
case 1: {
|
||||||
|
return relatedTerms.length ? AddRelatedTermButton() : undefined;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
return glossaryTerm.reviewers?.length ? AddReviewerButton() : undefined;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="tw-w-full tw-h-full tw-flex tw-flex-col">
|
<div className="tw-w-full tw-h-full tw-flex tw-flex-col">
|
||||||
<div className="tw-flex tw-gap-5 tw-mb-2">
|
<div className="tw-flex tw-gap-5 tw-mb-2">
|
||||||
@ -551,19 +604,18 @@ const GlossaryTermsV1 = ({
|
|||||||
<TabsPane
|
<TabsPane
|
||||||
activeTab={activeTab}
|
activeTab={activeTab}
|
||||||
className="tw-flex-initial"
|
className="tw-flex-initial"
|
||||||
rightPosButton={
|
rightPosButton={getTabPaneButton()}
|
||||||
glossaryTerm.reviewers &&
|
|
||||||
glossaryTerm.reviewers.length > 0 &&
|
|
||||||
activeTab === 3
|
|
||||||
? rightPosButton()
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
setActiveTab={activeTabHandler}
|
setActiveTab={activeTabHandler}
|
||||||
tabs={tabs}
|
tabs={tabs}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="tw-flex-grow tw-py-4">
|
<div className="tw-flex-grow tw-py-4">
|
||||||
{activeTab === 1 && <RelationshipTab data={relatedTerms} />}
|
{activeTab === 1 && (
|
||||||
|
<RelationshipTab
|
||||||
|
addButton={<>{AddRelatedTermButton()}</>}
|
||||||
|
data={relatedTerms}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{activeTab === 2 && (
|
{activeTab === 2 && (
|
||||||
<AssetsTabs
|
<AssetsTabs
|
||||||
assetData={assetData}
|
assetData={assetData}
|
||||||
@ -573,6 +625,14 @@ const GlossaryTermsV1 = ({
|
|||||||
{activeTab === 3 && getReviewerTabData()}
|
{activeTab === 3 && getReviewerTabData()}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{showRelatedTermsModal && (
|
||||||
|
<RelatedTermsModal
|
||||||
|
header="Add Related Terms"
|
||||||
|
relatedTerms={relatedTerms}
|
||||||
|
onCancel={onRelatedTermsModalCancel}
|
||||||
|
onSave={handleRelatedTermsSave}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{showRevieweModal && (
|
{showRevieweModal && (
|
||||||
<ReviewerModal
|
<ReviewerModal
|
||||||
header="Add Reviewer"
|
header="Add Reviewer"
|
||||||
|
@ -12,40 +12,35 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import React from 'react';
|
import { FormatedGlossaryTermData } from 'Models';
|
||||||
import ErrorPlaceHolder from '../../common/error-with-placeholder/ErrorPlaceHolder';
|
import React, { ReactNode } from 'react';
|
||||||
import RichTextEditorPreviewer from '../../common/rich-text-editor/RichTextEditorPreviewer';
|
import RichTextEditorPreviewer from '../../common/rich-text-editor/RichTextEditorPreviewer';
|
||||||
/* eslint-disable max-len */
|
|
||||||
// need to remove eslint disable once API data comes
|
|
||||||
|
|
||||||
type RelationshipTableType = {
|
|
||||||
relatedTerms: string;
|
|
||||||
description: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
data?: RelationshipTableType[];
|
data?: FormatedGlossaryTermData[];
|
||||||
|
addButton?: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
const RelationshipTab = ({ data }: Props) => {
|
const RelationshipTab = ({ data, addButton }: Props) => {
|
||||||
return data?.length ? (
|
return (
|
||||||
<div className="tw-table-responsive" id="relationship">
|
<div className="tw-table-responsive" id="relationship">
|
||||||
<table className="tw-w-full tw-bg-white">
|
<table className="tw-w-full tw-bg-white">
|
||||||
<thead>
|
<thead>
|
||||||
<tr className="tableHead-row">
|
<tr className="tableHead-row">
|
||||||
<th className="tableHead-cell">Terms</th>
|
<th className="tableHead-cell tw-w-2/12">Terms</th>
|
||||||
<th className="tableHead-cell">Description</th>
|
<th className="tableHead-cell">Description</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{data.map((row, index) => {
|
{data?.length ? (
|
||||||
|
data.map((row, index) => {
|
||||||
return (
|
return (
|
||||||
<tr className={classNames('tableBody-row')} key={index}>
|
<tr className={classNames('tableBody-row')} key={index}>
|
||||||
<td
|
<td
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'tableBody-cell tw-group tw-relative tw-align-baseline tw-w-2/12'
|
'tableBody-cell tw-group tw-relative tw-align-baseline'
|
||||||
)}>
|
)}>
|
||||||
{row.relatedTerms}
|
{row.displayName || row.name}
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
className={classNames(
|
className={classNames(
|
||||||
@ -54,26 +49,32 @@ const RelationshipTab = ({ data }: Props) => {
|
|||||||
<div
|
<div
|
||||||
className="description-text"
|
className="description-text"
|
||||||
data-testid="description-text">
|
data-testid="description-text">
|
||||||
{row.description.trim() ? (
|
{row.description?.trim() ? (
|
||||||
<RichTextEditorPreviewer
|
<RichTextEditorPreviewer
|
||||||
enableSeeMoreVariant={false}
|
enableSeeMoreVariant={false}
|
||||||
markdown={row.description}
|
markdown={row.description}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<span className="tw-no-description">No description</span>
|
<span className="tw-no-description">
|
||||||
|
No description
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
})}
|
})
|
||||||
|
) : (
|
||||||
|
<tr className="tableBody-row">
|
||||||
|
<td className="tableBody-cell tw-text-center" colSpan={4}>
|
||||||
|
<p className="tw-mb-3">No related terms available.</p>
|
||||||
|
{addButton}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
|
||||||
<ErrorPlaceHolder>
|
|
||||||
<p className="tw-text-base tw-text-center">No related terms.</p>
|
|
||||||
</ErrorPlaceHolder>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ const RelatedTermsModal = ({
|
|||||||
>(relatedTerms ?? []);
|
>(relatedTerms ?? []);
|
||||||
|
|
||||||
const getSearchedTerms = (searchedData: FormatedGlossaryTermData[]) => {
|
const getSearchedTerms = (searchedData: FormatedGlossaryTermData[]) => {
|
||||||
const currOptions = selectedOption.map((item) => item.fqdn);
|
const currOptions = selectedOption.map((item) => item.fqdn || item.name);
|
||||||
const data = searchedData.filter((item: FormatedGlossaryTermData) => {
|
const data = searchedData.filter((item: FormatedGlossaryTermData) => {
|
||||||
return !currOptions.includes(item.fqdn);
|
return !currOptions.includes(item.fqdn);
|
||||||
});
|
});
|
||||||
|
@ -223,6 +223,7 @@ declare module 'Models' {
|
|||||||
fqdn: string;
|
fqdn: string;
|
||||||
type: string;
|
type: string;
|
||||||
id: string;
|
id: string;
|
||||||
|
description?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface FormatedGlossarySuggestion {
|
export interface FormatedGlossarySuggestion {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user