mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2026-01-05 20:17:07 +00:00
Fix issue-600: UI: doesn't allow table level tags to be added (#3547)
This commit is contained in:
parent
5bd7fae70d
commit
a66ef4800c
@ -94,6 +94,7 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
|
||||
isNodeLoading,
|
||||
dataModel,
|
||||
deleted,
|
||||
tagUpdateHandler,
|
||||
addLineageHandler,
|
||||
removeLineageHandler,
|
||||
entityLineageHandler,
|
||||
@ -423,6 +424,18 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Formulates updated tags and updates table entity data for API call
|
||||
* @param selectedTags
|
||||
*/
|
||||
const onTagUpdate = (selectedTags?: Array<EntityTags>) => {
|
||||
if (selectedTags) {
|
||||
const updatedTags = [...(tier ? [tier] : []), ...selectedTags];
|
||||
const updatedTable = { ...tableDetails, tags: updatedTags };
|
||||
tagUpdateHandler(updatedTable);
|
||||
}
|
||||
};
|
||||
|
||||
const followTable = () => {
|
||||
if (isFollowing) {
|
||||
setFollowersCount((preValu) => preValu - 1);
|
||||
@ -487,18 +500,28 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
|
||||
<PageContainer>
|
||||
<div className="tw-px-6 tw-w-full tw-h-full tw-flex tw-flex-col">
|
||||
<EntityPageInfo
|
||||
isTagEditable
|
||||
deleted={deleted}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
'tags',
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={datasetFQN}
|
||||
entityName={entityName}
|
||||
entityType={EntityType.DATASET}
|
||||
extraInfo={extraInfo}
|
||||
followHandler={followTable}
|
||||
followers={followersCount}
|
||||
followersList={followers}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
isFollowing={isFollowing}
|
||||
tags={tableTags}
|
||||
tagsHandler={onTagUpdate}
|
||||
tier={tier}
|
||||
titleLinks={slashedTableName}
|
||||
version={version}
|
||||
versionHandler={versionHandler}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
|
||||
<div className="tw-mt-4 tw-flex tw-flex-col tw-flex-grow">
|
||||
|
||||
@ -96,6 +96,7 @@ export interface DatasetDetailsProps {
|
||||
settingsUpdateHandler: (updatedTable: Table) => Promise<void>;
|
||||
columnsUpdateHandler: (updatedTable: Table) => void;
|
||||
descriptionUpdateHandler: (updatedTable: Table) => void;
|
||||
tagUpdateHandler: (updatedTable: Table) => void;
|
||||
versionHandler: () => void;
|
||||
handleSelectedColumn: (value: string | undefined) => void;
|
||||
loadNodeHandler: (node: EntityReference, pos: LineagePos) => void;
|
||||
|
||||
@ -112,6 +112,7 @@ const DatasetDetailsProps = {
|
||||
handleTestModeChange: jest.fn(),
|
||||
qualityTestFormHandler: jest.fn(),
|
||||
deletePostHandler: jest.fn(),
|
||||
tagUpdateHandler: jest.fn(),
|
||||
};
|
||||
jest.mock('../ManageTab/ManageTab.component', () => {
|
||||
return jest.fn().mockReturnValue(<p>ManageTab</p>);
|
||||
|
||||
@ -30,7 +30,6 @@ import {
|
||||
getTagsDiff,
|
||||
} from '../../utils/EntityVersionUtils';
|
||||
import { getOwnerFromId } from '../../utils/TableUtils';
|
||||
import { getTableTags } from '../../utils/TagsUtils';
|
||||
import Description from '../common/description/Description';
|
||||
import EntityPageInfo from '../common/entityPageInfo/EntityPageInfo';
|
||||
import TabsPane from '../common/TabsPane/TabsPane';
|
||||
@ -310,6 +309,47 @@ const DatasetVersion: React.FC<DatasetVersionProp> = ({
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates tags for selected version.
|
||||
* @returns current version's tag.
|
||||
*/
|
||||
const getTags = () => {
|
||||
const tagsDiff = getDiffByFieldName('tags', changeDescription, true);
|
||||
const oldTags: Array<TagLabel> = JSON.parse(
|
||||
tagsDiff?.added?.oldValue ??
|
||||
tagsDiff?.deleted?.oldValue ??
|
||||
tagsDiff?.updated?.oldValue ??
|
||||
'[]'
|
||||
);
|
||||
const newTags: Array<TagLabel> = JSON.parse(
|
||||
tagsDiff?.added?.newValue ??
|
||||
tagsDiff?.deleted?.newValue ??
|
||||
tagsDiff?.updated?.newValue ??
|
||||
'[]'
|
||||
);
|
||||
const flag: { [x: string]: boolean } = {};
|
||||
const uniqueTags: Array<TagLabel & { added: boolean; removed: boolean }> =
|
||||
[];
|
||||
|
||||
[
|
||||
...(getTagsDiff(oldTags, newTags) ?? []),
|
||||
...(currentVersionData.tags ?? []),
|
||||
].forEach((elem: TagLabel & { added: boolean; removed: boolean }) => {
|
||||
if (!flag[elem.tagFQN as string]) {
|
||||
flag[elem.tagFQN as string] = true;
|
||||
uniqueTags.push(elem);
|
||||
}
|
||||
});
|
||||
|
||||
return [
|
||||
...uniqueTags.map((t) =>
|
||||
t.tagFQN.startsWith('Tier')
|
||||
? { ...t, tagFQN: t.tagFQN.split('.')[1] }
|
||||
: t
|
||||
),
|
||||
];
|
||||
};
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
name: 'Schema',
|
||||
@ -346,7 +386,7 @@ const DatasetVersion: React.FC<DatasetVersionProp> = ({
|
||||
entityName={currentVersionData.name ?? ''}
|
||||
extraInfo={getExtraInfo()}
|
||||
followersList={[]}
|
||||
tags={getTableTags(currentVersionData.columns || [])}
|
||||
tags={getTags()}
|
||||
tier={tier}
|
||||
titleLinks={slashedTableName}
|
||||
version={version}
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { faExclamationCircle, faStar } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import classNames from 'classnames';
|
||||
import { isEmpty, isUndefined } from 'lodash';
|
||||
import {
|
||||
@ -27,6 +29,10 @@ import { User } from '../../../generated/entity/teams/user';
|
||||
import { LabelType, State, TagLabel } from '../../../generated/type/tagLabel';
|
||||
import { getHtmlForNonAdminAction } from '../../../utils/CommonUtils';
|
||||
import { getEntityFeedLink, getInfoElements } from '../../../utils/EntityUtils';
|
||||
import {
|
||||
fetchGlossaryTerms,
|
||||
getGlossaryTermlist,
|
||||
} from '../../../utils/GlossaryUtils';
|
||||
import SVGIcons, { Icons } from '../../../utils/SvgUtils';
|
||||
import { getFollowerDetail } from '../../../utils/TableUtils';
|
||||
import { getTagCategories, getTaglist } from '../../../utils/TagsUtils';
|
||||
@ -38,12 +44,6 @@ import PopOver from '../popover/PopOver';
|
||||
import TitleBreadcrumb from '../title-breadcrumb/title-breadcrumb.component';
|
||||
import { TitleBreadcrumbProps } from '../title-breadcrumb/title-breadcrumb.interface';
|
||||
import FollowersModal from './FollowersModal';
|
||||
import {
|
||||
fetchGlossaryTerms,
|
||||
getGlossaryTermlist,
|
||||
} from '../../../utils/GlossaryUtils';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faExclamationCircle, faStar } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
type Props = {
|
||||
titleLinks: TitleBreadcrumbProps['titleLinks'];
|
||||
@ -435,6 +435,7 @@ const EntityPageInfo = ({
|
||||
setIsEditable(true);
|
||||
}}>
|
||||
<TagsContainer
|
||||
dropDownHorzPosRight={false}
|
||||
editable={isEditable}
|
||||
isLoading={isTagLoading}
|
||||
selectedTags={getSelectedTags()}
|
||||
|
||||
@ -21,13 +21,21 @@ const jsonData = {
|
||||
'delete-team-error': 'Error while deleting team!',
|
||||
'elastic-search-error': 'Error while fetch data from Elasticsearch!',
|
||||
'fetch-data-error': 'Error while fetching data!',
|
||||
'fetch-entity-feed-error': 'Error while fetching entity feeds!',
|
||||
'fetch-entity-feed-count-error': 'Error while fetching entity feed count!',
|
||||
'fetch-feed-error': 'Error while fetching messages',
|
||||
'fetch-glossary-error': 'Error while fetching glossary!',
|
||||
'fetch-glossary-list-error': 'Error while fetching glossaries!',
|
||||
'fetch-glossary-term-error': 'Error while fetching glossary term!',
|
||||
'fetch-lineage-error': 'Error while fetching lineage data!',
|
||||
'fetch-sample-data-error': 'Error while fetching sample data!',
|
||||
'fetch-table-details-error': 'Error while fetching table details!',
|
||||
'fetch-table-queries-error': 'Error while fetching table queries!',
|
||||
'fetch-tags-error': 'Error while fetching tags!',
|
||||
'update-glossary-term-error': 'Error while updating glossary term!',
|
||||
'update-description-error': 'Error while updating description!',
|
||||
'update-entity-error': 'Error while updating entity!',
|
||||
'update-tags-error': 'Error while updating tags!',
|
||||
},
|
||||
'form-error-messages': {
|
||||
'empty-email': 'Email is required.',
|
||||
|
||||
@ -89,6 +89,7 @@ import {
|
||||
DatasetTestModeType,
|
||||
ModifiedTableColumn,
|
||||
} from '../../interface/dataQuality.interface';
|
||||
import jsonData from '../../jsons/en';
|
||||
import {
|
||||
addToRecentViewed,
|
||||
getCurrentUserId,
|
||||
@ -104,8 +105,7 @@ import {
|
||||
import { getEntityFeedLink, getEntityLineage } from '../../utils/EntityUtils';
|
||||
import { deletePost, getUpdatedThread } from '../../utils/FeedUtils';
|
||||
import { serviceTypeLogo } from '../../utils/ServiceUtils';
|
||||
import { getTierTags } from '../../utils/TableUtils';
|
||||
import { getTableTags } from '../../utils/TagsUtils';
|
||||
import { getTagsWithoutTier, getTierTags } from '../../utils/TableUtils';
|
||||
|
||||
const DatasetDetailsPage: FunctionComponent = () => {
|
||||
const history = useHistory();
|
||||
@ -178,6 +178,13 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
||||
const [tableTestCase, setTableTestCase] = useState<TableTest[]>([]);
|
||||
const [selectedColumn, setSelectedColumn] = useState<string>();
|
||||
|
||||
const handleShowErrorToast = (errMessage: string) => {
|
||||
showToast({
|
||||
variant: 'error',
|
||||
body: errMessage,
|
||||
});
|
||||
};
|
||||
|
||||
const handleTestModeChange = (mode: DatasetTestModeType) => {
|
||||
setTestMode(mode);
|
||||
};
|
||||
@ -226,10 +233,10 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
||||
setEntityLineage(res.data);
|
||||
})
|
||||
.catch((err: AxiosError) => {
|
||||
showToast({
|
||||
variant: 'error',
|
||||
body: err.message ?? 'Error while fetching lineage data.',
|
||||
});
|
||||
const msg =
|
||||
err.response?.data?.message ||
|
||||
jsonData['api-error-messages']['fetch-lineage-error'];
|
||||
handleShowErrorToast(msg);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLineageLoading(false);
|
||||
@ -243,11 +250,11 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
||||
const { data } = res.data;
|
||||
setEntityThread(data);
|
||||
})
|
||||
.catch(() => {
|
||||
showToast({
|
||||
variant: 'error',
|
||||
body: 'Error while fetching entity feeds',
|
||||
});
|
||||
.catch((err: AxiosError) => {
|
||||
const errMsg =
|
||||
err.response?.data?.message ||
|
||||
jsonData['api-error-messages']['fetch-entity-feed-error'];
|
||||
handleShowErrorToast(errMsg);
|
||||
})
|
||||
.finally(() => setIsentityThreadLoading(false));
|
||||
};
|
||||
@ -325,7 +332,7 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
||||
setColumns(columns || []);
|
||||
setSampleData(sampleData);
|
||||
setTableProfile(tableProfile || []);
|
||||
setTableTags(getTableTags(columns || []));
|
||||
setTableTags(getTagsWithoutTier(tags));
|
||||
setUsageSummary(usageSummary);
|
||||
setJoins(joins);
|
||||
})
|
||||
@ -333,11 +340,10 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
||||
if (err.response?.status === 404) {
|
||||
setIsError(true);
|
||||
} else {
|
||||
const errMsg = err.message || 'Error while fetching table details.';
|
||||
showToast({
|
||||
variant: 'error',
|
||||
body: errMsg,
|
||||
});
|
||||
const errMsg =
|
||||
err.response?.data?.message ||
|
||||
jsonData['api-error-messages']['fetch-table-details-error'];
|
||||
handleShowErrorToast(errMsg);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
@ -357,12 +363,12 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
||||
const { sampleData } = res.data;
|
||||
setSampleData(sampleData);
|
||||
})
|
||||
.catch(() =>
|
||||
showToast({
|
||||
variant: 'error',
|
||||
body: 'Error while getting sample data.',
|
||||
})
|
||||
)
|
||||
.catch((err: AxiosError) => {
|
||||
const errMsg =
|
||||
err.response?.data?.message ||
|
||||
jsonData['api-error-messages']['fetch-sample-data-error'];
|
||||
handleShowErrorToast(errMsg);
|
||||
})
|
||||
.finally(() => setIsSampleDataLoading(false));
|
||||
|
||||
break;
|
||||
@ -391,12 +397,12 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
||||
const { tableQueries } = res.data;
|
||||
setTableQueries(tableQueries);
|
||||
})
|
||||
.catch(() =>
|
||||
showToast({
|
||||
variant: 'error',
|
||||
body: 'Error while getting table queries',
|
||||
})
|
||||
)
|
||||
.catch((err: AxiosError) => {
|
||||
const errMsg =
|
||||
err.response?.data?.message ||
|
||||
jsonData['api-error-messages']['fetch-table-queries-error'];
|
||||
handleShowErrorToast(errMsg);
|
||||
})
|
||||
.finally(() => setIsTableQueriesLoading(false));
|
||||
|
||||
break;
|
||||
@ -429,11 +435,11 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
||||
setFeedCount(res.data.totalCount);
|
||||
setEntityFieldThreadCount(res.data.counts);
|
||||
})
|
||||
.catch(() => {
|
||||
showToast({
|
||||
variant: 'error',
|
||||
body: 'Error while fetching entity feed count',
|
||||
});
|
||||
.catch((err: AxiosError) => {
|
||||
const errMsg =
|
||||
err.response?.data?.message ||
|
||||
jsonData['api-error-messages']['fetch-entity-feed-count-error'];
|
||||
handleShowErrorToast(errMsg);
|
||||
});
|
||||
};
|
||||
|
||||
@ -457,12 +463,9 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
||||
})
|
||||
.catch((err: AxiosError) => {
|
||||
const msg =
|
||||
err.response?.data.message ||
|
||||
`Error while updating entity description.`;
|
||||
showToast({
|
||||
variant: 'error',
|
||||
body: msg,
|
||||
});
|
||||
err.response?.data?.message ||
|
||||
jsonData['api-error-messages']['update-description-error'];
|
||||
handleShowErrorToast(msg);
|
||||
});
|
||||
};
|
||||
|
||||
@ -473,16 +476,35 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
||||
setCurrentVersion(version);
|
||||
setTableDetails(res.data);
|
||||
setColumns(columns);
|
||||
setTableTags(getTableTags(columns || []));
|
||||
getEntityFeedCount();
|
||||
})
|
||||
.catch((err: AxiosError) => {
|
||||
const msg =
|
||||
err.response?.data.message || `Error while updating entity.`;
|
||||
showToast({
|
||||
variant: 'error',
|
||||
body: msg,
|
||||
});
|
||||
err.response?.data?.message ||
|
||||
jsonData['api-error-messages']['update-entity-error'];
|
||||
handleShowErrorToast(msg);
|
||||
});
|
||||
};
|
||||
|
||||
const onTagUpdate = (updatedTable: Table) => {
|
||||
saveUpdatedTableData(updatedTable)
|
||||
.then((res: AxiosResponse) => {
|
||||
if (res.data) {
|
||||
setTier(getTierTags(res.data.tags));
|
||||
setCurrentVersion(res.data.version);
|
||||
setTableTags(getTagsWithoutTier(res.data.tags));
|
||||
getEntityFeedCount();
|
||||
} else {
|
||||
handleShowErrorToast(
|
||||
jsonData['api-error-messages']['update-tags-error']
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch((err: AxiosError) => {
|
||||
const errMsg =
|
||||
err.response?.data?.message ||
|
||||
jsonData['api-error-messages']['update-tags-error'];
|
||||
handleShowErrorToast(errMsg);
|
||||
});
|
||||
};
|
||||
|
||||
@ -500,16 +522,16 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
||||
})
|
||||
.catch((err: AxiosError) => {
|
||||
const msg =
|
||||
err.response?.data.message || `Error while updating entity.`;
|
||||
err.response?.data?.message ||
|
||||
jsonData['api-error-messages']['update-entity-error'];
|
||||
handleShowErrorToast(msg);
|
||||
reject();
|
||||
showToast({
|
||||
variant: 'error',
|
||||
body: msg,
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: move all the error from below code to en.ts and use handleShowErrorToast to show error.
|
||||
|
||||
const followTable = () => {
|
||||
addFollower(tableId, USERId).then((res: AxiosResponse) => {
|
||||
const { newValue } = res.data.changeDescription.fieldsAdded[0];
|
||||
@ -895,6 +917,7 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
||||
tableTags={tableTags}
|
||||
tableTestCase={tableTestCase}
|
||||
tableType={tableType}
|
||||
tagUpdateHandler={onTagUpdate}
|
||||
testMode={testMode}
|
||||
tier={tier as TagLabel}
|
||||
unfollowTableHandler={unfollowTable}
|
||||
|
||||
@ -88,7 +88,6 @@ import {
|
||||
} from '../../utils/FeedUtils';
|
||||
import { serviceTypeLogo } from '../../utils/ServiceUtils';
|
||||
import { getOwnerFromId, getUsagePercentile } from '../../utils/TableUtils';
|
||||
import { getTableTags } from '../../utils/TagsUtils';
|
||||
|
||||
const DatabaseDetails: FunctionComponent = () => {
|
||||
// User Id for getting followers
|
||||
@ -673,16 +672,6 @@ const DatabaseDetails: FunctionComponent = () => {
|
||||
type="label"
|
||||
/>
|
||||
))}
|
||||
{getTableTags(table.columns).map(
|
||||
(tag, tagIdx) => (
|
||||
<Tags
|
||||
key={tagIdx}
|
||||
startWith="#"
|
||||
tag={tag}
|
||||
type="label"
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
|
||||
@ -224,6 +224,7 @@ const TourPage = () => {
|
||||
tableTags={mockDatasetData.tableTags}
|
||||
tableTestCase={[]}
|
||||
tableType={mockDatasetData.tableType as TableType}
|
||||
tagUpdateHandler={handleCountChange}
|
||||
testMode="table"
|
||||
tier={'' as unknown as TagLabel}
|
||||
unfollowTableHandler={handleCountChange}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user