diff --git a/openmetadata-ui/src/main/resources/ui/src/assets/svg/closed-lock.svg b/openmetadata-ui/src/main/resources/ui/src/assets/svg/closed-lock.svg index e5ef99c536c..b5d55bfc551 100644 --- a/openmetadata-ui/src/main/resources/ui/src/assets/svg/closed-lock.svg +++ b/openmetadata-ui/src/main/resources/ui/src/assets/svg/closed-lock.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/Badge/Badge.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/Badge/Badge.component.tsx new file mode 100644 index 00000000000..631bf1f8776 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/Badge/Badge.component.tsx @@ -0,0 +1,61 @@ +/* + * Copyright 2023 Collate. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Typography } from 'antd'; +import classNames from 'classnames'; +import React, { ReactNode } from 'react'; +import './badge.style.less'; + +interface AppBadgeProps { + label: string; + icon?: ReactNode; + color?: string; + className?: string; + bgColor?: string; +} + +/** + * Create Badge like component. + * Accepts `label` as required prop + * @param props + * { + * label - Render text between Badge + * className - To customize look & feel of the badge + * icon - Renders icon before label + * color - Controls color of font or Icon + * bgColor - Controls color of badge itself + * } + * @returns Badge component + */ +const AppBadge = ({ + label, + className, + icon, + color, + bgColor, +}: AppBadgeProps) => { + return ( + + {icon && ( + + {icon} + + )} + {label} + + ); +}; + +export default AppBadge; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/Badge/Badge.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/Badge/Badge.test.tsx new file mode 100644 index 00000000000..8f4dd841553 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/Badge/Badge.test.tsx @@ -0,0 +1,60 @@ +/* + * Copyright 2023 Collate. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { render } from '@testing-library/react'; +import React from 'react'; +import AppBadge from './Badge.component'; + +describe(' component', () => { + it('should render badge with label is label is passed', () => { + const { getByText } = render(); + + expect(getByText('test')).toBeInTheDocument(); + }); + + it('should render badge without icon if icon is not passed', () => { + const { queryByTestId } = render(); + + expect(queryByTestId('badge-icon')).not.toBeInTheDocument(); + }); + + it('should render badge with icon if icon is passed', () => { + const { queryByTestId, getByText } = render( + + ); + + expect(queryByTestId('badge-icon')).toBeInTheDocument(); + expect(getByText('test-icon')).toBeInTheDocument(); + }); + + it('should apply className to container if provided', () => { + const { queryByTestId } = render( + + ); + + expect(queryByTestId('badge-container')).toHaveClass('test-className'); + }); + + it('should apply color property to container element if provided', () => { + const { queryByTestId } = render(); + + expect(queryByTestId('badge-container')).toHaveStyle({ color: '#000' }); + }); + + it('should apply bgColor property to container element if provided', () => { + const { queryByTestId } = render(); + + expect(queryByTestId('badge-container')).toHaveStyle({ + 'background-color': '#000', + }); + }); +}); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/Badge/badge.style.less b/openmetadata-ui/src/main/resources/ui/src/components/common/Badge/badge.style.less new file mode 100644 index 00000000000..767577320f8 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/Badge/badge.style.less @@ -0,0 +1,27 @@ +/* + * Copyright 2023 Collate. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@import url('../../../styles/variables.less'); + +.app-badge { + background-color: #06a4a4; + border-radius: 13px; + padding: 4px 8px; + color: #fff; + + .ant-typography { + color: #fff; + font-weight: 600; + font-size: 10px; + line-height: 12px; + } +} diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/tags/index.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/tags/index.test.tsx index 09f6e5b28cd..d48a4d0d810 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/tags/index.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/tags/index.test.tsx @@ -544,6 +544,30 @@ describe('Test TagsPage page', () => { expect(tagCategoryHeading).toHaveValue('newPII'); }); + it('User tag should be load', async () => { + const { container } = render(); + + const tagsComponent = await screen.findByTestId('tags-container'); + const classification = await screen.findAllByText('PersonalData'); + + act(() => { + fireEvent.click(classification[0]); + }); + + act(async () => { + const tagEditIcon = await findAllByTestId(container, 'tag-edit-icon'); + + expect(tagEditIcon[0]).toBeInTheDocument(); + + fireEvent.click(tagEditIcon[0]); + }); + + const tagName = await screen.findByText('test_tag'); + + expect(tagName).toBeInTheDocument(); + expect(tagsComponent).toBeInTheDocument(); + }); + describe('Render Sad Paths', () => { it('Show error message on failing of deleteClassification API', async () => { (deleteClassification as jest.Mock).mockImplementation(() => diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/tags/index.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/tags/index.tsx index d42eecf42bc..1bdb1d30c82 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/tags/index.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/tags/index.tsx @@ -24,7 +24,9 @@ import { Typography, } from 'antd'; import { ColumnsType } from 'antd/lib/table'; +import { ReactComponent as LockIcon } from 'assets/svg/closed-lock.svg'; import { AxiosError } from 'axios'; +import AppBadge from 'components/common/Badge/Badge.component'; import Description from 'components/common/description/Description'; import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder'; import LeftPanelCard from 'components/common/LeftPanelCard/LeftPanelCard'; @@ -44,7 +46,7 @@ import { import TagsLeftPanelSkeleton from 'components/Skeleton/Tags/TagsLeftPanelSkeleton.component'; import { LOADING_STATE } from 'enums/common.enum'; import { compare } from 'fast-json-patch'; -import { isEmpty, isUndefined, toLower, trim } from 'lodash'; +import { capitalize, isEmpty, isUndefined, toLower, trim } from 'lodash'; import { FormErrorData } from 'Models'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -692,7 +694,7 @@ const TagsPage = () => { {classifications && classifications.map((category: Classification) => (
{ ellipsis={{ rows: 1, tooltip: true }}> {getEntityName(category as unknown as EntityReference)} + {getCountBadge( category.termCount, - 'tw-self-center', + 'self-center m-l-auto', currentClassification?.name === category.name )}
@@ -866,7 +869,7 @@ const TagsPage = () => { data-testid="classification-name"> {getEntityName(currentClassification)} - {currentClassification.provider === ProviderType.User && ( + {currentClassification.provider === ProviderType.User ? ( { /> + ) : ( + } + label={capitalize(currentClassification.provider)} + /> )} )} diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/tags/tags.mock.ts b/openmetadata-ui/src/main/resources/ui/src/pages/tags/tags.mock.ts index 506d5a63524..4d0996ed74c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/tags/tags.mock.ts +++ b/openmetadata-ui/src/main/resources/ui/src/pages/tags/tags.mock.ts @@ -134,6 +134,30 @@ export const MOCK_TAGS = { provider: 'system', mutuallyExclusive: false, }, + { + id: '43f1e354-eefa-4c63-94bc-c618badaf6ee', + name: 'test_tag', + fullyQualifiedName: 'PersonalData.test_tag', + description: 'test_tag', + classification: { + id: '7968b3a3-ee7c-4bf9-9bf1-ff8322c6b53f', + type: 'classification', + name: 'PersonalData', + fullyQualifiedName: 'PersonalData', + description: 'Hello testing', + deleted: false, + href: 'http://localhost:8585/api/v1/classifications/7968b3a3-ee7c-4bf9-9bf1-ff8322c6b53f', + }, + version: 0.1, + updatedAt: 1678959133696, + updatedBy: 'admin', + href: 'http://localhost:8585/api/v1/tags/43f1e354-eefa-4c63-94bc-c618badaf6ee', + usageCount: 0, + deprecated: false, + deleted: false, + provider: 'user', + mutuallyExclusive: false, + }, ], paging: { after: 'UGVyc29uYWxEYXRhLnRlc3R0YWc4OQ==', diff --git a/openmetadata-ui/src/main/resources/ui/src/styles/app.less b/openmetadata-ui/src/main/resources/ui/src/styles/app.less index 8b2ca913015..a682bd6f415 100644 --- a/openmetadata-ui/src/main/resources/ui/src/styles/app.less +++ b/openmetadata-ui/src/main/resources/ui/src/styles/app.less @@ -186,6 +186,7 @@ .activeCategory { border-left: 2px solid @primary; background: @primary-light; + padding-left: 10px; font-weight: 600; } diff --git a/openmetadata-ui/src/main/resources/ui/src/styles/spacing.less b/openmetadata-ui/src/main/resources/ui/src/styles/spacing.less index 03eeca82190..0edb1bee34f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/styles/spacing.less +++ b/openmetadata-ui/src/main/resources/ui/src/styles/spacing.less @@ -129,6 +129,9 @@ .m-l-lg { margin-left: @margin-lg; } +.m-l-auto { + margin-left: auto; +} .m-t-0 { margin-top: 0 !important; } @@ -524,3 +527,11 @@ .col-gap-md { column-gap: 1rem; } +// Box sizing + +.border-box { + box-sizing: border-box; +} +.content-box { + box-sizing: content-box; +} diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/CommonUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/CommonUtils.tsx index 2e13761ea01..0692262d33b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/CommonUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/CommonUtils.tsx @@ -220,7 +220,7 @@ export const getCountBadge = ( return (