UI : Fix the Classifications Count issue (#9744)

* Fix the Tags Count

* minor changes

* added unit test for left panel count
This commit is contained in:
Ashish Gupta 2023-01-17 14:21:10 +05:30 committed by GitHub
parent 1e731856e8
commit 25ef20fe16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 117 additions and 40 deletions

View File

@ -225,7 +225,7 @@ const SelectTestSuite: React.FC<SelectTestSuiteProps> = ({
<SVGIcons <SVGIcons
alt="plus" alt="plus"
className="w-4 m-r-xss" className="w-4 m-r-xss"
icon={Icons.ICON_PLUS_PRIMERY} icon={Icons.ICON_PLUS_PRIMARY}
/> />
} }
onClick={() => setIsNewTestSuite(true)}> onClick={() => setIsNewTestSuite(true)}>

View File

@ -323,7 +323,7 @@ const GlossaryV1 = ({
data-testid="add-glossary" data-testid="add-glossary"
disabled={!createGlossaryPermission} disabled={!createGlossaryPermission}
onClick={handleAddGlossaryClick}> onClick={handleAddGlossaryClick}>
<SVGIcons alt="plus" icon={Icons.ICON_PLUS_PRIMERY} />{' '} <SVGIcons alt="plus" icon={Icons.ICON_PLUS_PRIMARY} />{' '}
<span>{t('label.add-glossary')}</span> <span>{t('label.add-glossary')}</span>
</button> </button>
</Tooltip> </Tooltip>

View File

@ -54,7 +54,7 @@ const Tags: FunctionComponent<TagProps> = ({
<SVGIcons <SVGIcons
alt="plus" alt="plus"
className="tw-w-3.5 tw-mr-1" className="tw-w-3.5 tw-mr-1"
icon={Icons.ICON_PLUS_PRIMERY} icon={Icons.ICON_PLUS_PRIMARY}
/> />
) : ( ) : (
startWith startWith

View File

@ -0,0 +1,27 @@
/*
* Copyright 2022 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 { LoadingState } from 'Models';
export type DeleteTagDetailsType = {
id: string;
name: string;
categoryName?: string;
isCategory: boolean;
status?: LoadingState;
};
export type DeleteTagsType = {
data: DeleteTagDetailsType | undefined;
state: boolean;
};

View File

@ -0,0 +1,35 @@
/*
* Copyright 2022 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 { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Loader from 'components/Loader/Loader';
import React from 'react';
import SVGIcons from 'utils/SvgUtils';
import { DeleteTagsType } from './TagsPage.interface';
export const getDeleteIcon = (
deleteTags: DeleteTagsType,
id: string | undefined
) => {
if (deleteTags.data?.id === id) {
if (deleteTags.data?.status === 'success') {
return <FontAwesomeIcon icon="check" />;
}
return <Loader size="small" type="default" />;
}
return (
<SVGIcons alt="delete" icon="icon-delete" title="Delete" width="16px" />
);
};

View File

@ -18,6 +18,7 @@ import {
findByTestId, findByTestId,
findByText, findByText,
fireEvent, fireEvent,
getByText,
queryByTitle, queryByTitle,
render, render,
screen, screen,
@ -297,6 +298,27 @@ describe('Test TagsPage page', () => {
expect(sidePanelCategories).toHaveLength(3); expect(sidePanelCategories).toHaveLength(3);
}); });
it('Classification LeftPanel count should render properly', async () => {
await act(async () => {
render(<TagsPage />);
});
const leftPanelContent = await screen.findByTestId('left-panel-content');
const sidePanelCategories = await screen.findAllByTestId(
'side-panel-classification'
);
expect(leftPanelContent).toBeInTheDocument();
expect(sidePanelCategories).toHaveLength(3);
const getAllCounts = await screen.findAllByTestId('filter-count');
expect(getAllCounts).toHaveLength(3);
expect(getByText(getAllCounts[0], '2')).toBeInTheDocument();
expect(getByText(getAllCounts[1], '3')).toBeInTheDocument();
expect(getByText(getAllCounts[2], '5')).toBeInTheDocument();
});
it('OnClick of add new tag, FormModal should display', async () => { it('OnClick of add new tag, FormModal should display', async () => {
await act(async () => { await act(async () => {
render(<TagsPage />); render(<TagsPage />);

View File

@ -44,7 +44,7 @@ import {
import TagsLeftPanelSkeleton from 'components/Skeleton/Tags/TagsLeftPanelSkeleton.component'; import TagsLeftPanelSkeleton from 'components/Skeleton/Tags/TagsLeftPanelSkeleton.component';
import { compare } from 'fast-json-patch'; import { compare } from 'fast-json-patch';
import { isEmpty, isUndefined, toLower, trim } from 'lodash'; import { isEmpty, isUndefined, toLower, trim } from 'lodash';
import { FormErrorData, LoadingState } from 'Models'; import { FormErrorData } from 'Models';
import React, { useCallback, useEffect, useMemo, useState } from 'react'; import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Link, useHistory, useParams } from 'react-router-dom'; import { Link, useHistory, useParams } from 'react-router-dom';
@ -91,19 +91,8 @@ import SVGIcons, { Icons } from '../../utils/SvgUtils';
import { showErrorToast } from '../../utils/ToastUtils'; import { showErrorToast } from '../../utils/ToastUtils';
import Form from './Form'; import Form from './Form';
import './TagPage.style.less'; import './TagPage.style.less';
import { DeleteTagsType } from './TagsPage.interface';
type DeleteTagDetailsType = { import { getDeleteIcon } from './TagsPageUtils';
id: string;
name: string;
categoryName?: string;
isCategory: boolean;
status?: LoadingState;
};
type DeleteTagsType = {
data: DeleteTagDetailsType | undefined;
state: boolean;
};
const TagsPage = () => { const TagsPage = () => {
const { getEntityPermission, permissions } = usePermissionProvider(); const { getEntityPermission, permissions } = usePermissionProvider();
@ -205,7 +194,7 @@ const TagsPage = () => {
setIsLoading(true); setIsLoading(true);
try { try {
const response = await getAllClassifications('', 1000); const response = await getAllClassifications('termCount', 1000);
setClassifications(response.data); setClassifications(response.data);
if (setCurrent && response.data.length) { if (setCurrent && response.data.length) {
setCurrentClassification(response.data[0]); setCurrentClassification(response.data[0]);
@ -229,11 +218,23 @@ const TagsPage = () => {
if (currentClassification?.name !== name || update) { if (currentClassification?.name !== name || update) {
setIsLoading(true); setIsLoading(true);
try { try {
const currentClassification = await getClassificationByName( const currentClassification = await getClassificationByName(name, [
name, 'usageCount',
'usageCount' 'termCount',
); ]);
if (currentClassification) { if (currentClassification) {
setClassifications((prevClassifications) =>
prevClassifications.map((data) => {
if (data.name === name) {
return {
...data,
termCount: currentClassification.termCount,
};
}
return data;
})
);
setCurrentClassification(currentClassification); setCurrentClassification(currentClassification);
setCurrentClassificationName(currentClassification.name); setCurrentClassificationName(currentClassification.name);
setIsLoading(false); setIsLoading(false);
@ -587,6 +588,8 @@ const TagsPage = () => {
} }
}; };
// Use the component in the render method
const fetchLeftPanel = () => { const fetchLeftPanel = () => {
return ( return (
<LeftPanelCard id="tags"> <LeftPanelCard id="tags">
@ -613,7 +616,7 @@ const TagsPage = () => {
setIsAddingClassification((prevState) => !prevState); setIsAddingClassification((prevState) => !prevState);
setErrorDataClassification(undefined); setErrorDataClassification(undefined);
}}> }}>
<SVGIcons alt="plus" icon={Icons.ICON_PLUS_PRIMERY} />{' '} <SVGIcons alt="plus" icon={Icons.ICON_PLUS_PRIMARY} />{' '}
<span> <span>
{t('label.add-entity', { {t('label.add-entity', {
entity: t('label.classification'), entity: t('label.classification'),
@ -641,7 +644,7 @@ const TagsPage = () => {
{getEntityName(category as unknown as EntityReference)} {getEntityName(category as unknown as EntityReference)}
</Typography.Paragraph> </Typography.Paragraph>
{getCountBadge( {getCountBadge(
0, category.termCount,
'tw-self-center', 'tw-self-center',
currentClassification?.name === category.name currentClassification?.name === category.name
)} )}
@ -731,20 +734,7 @@ const TagsPage = () => {
!classificationPermissions.EditAll !classificationPermissions.EditAll
} }
onClick={() => handleActionDeleteTag(record)}> onClick={() => handleActionDeleteTag(record)}>
{deleteTags.data?.id === record.id ? ( {getDeleteIcon(deleteTags, record.id)}
deleteTags.data?.status === 'success' ? (
<FontAwesomeIcon icon="check" />
) : (
<Loader size="small" type="default" />
)
) : (
<SVGIcons
alt="delete"
icon="icon-delete"
title="Delete"
width="16px"
/>
)}
</button> </button>
), ),
}, },

View File

@ -22,6 +22,7 @@ export const MOCK_ALL_CLASSIFICATIONS = {
updatedAt: 1672147362401, updatedAt: 1672147362401,
updatedBy: 'admin', updatedBy: 'admin',
href: 'http://localhost:8585/api/v1/classifications/5e77a82e-4bc8-46eb-af52-a383a505eea6', href: 'http://localhost:8585/api/v1/classifications/5e77a82e-4bc8-46eb-af52-a383a505eea6',
termCount: 2,
changeDescription: { changeDescription: {
fieldsAdded: [], fieldsAdded: [],
fieldsUpdated: [ fieldsUpdated: [
@ -57,6 +58,7 @@ export const MOCK_ALL_CLASSIFICATIONS = {
deleted: false, deleted: false,
provider: 'system', provider: 'system',
mutuallyExclusive: true, mutuallyExclusive: true,
termCount: 3,
}, },
{ {
id: '9005388e-5355-412c-8ba9-fc6dbe192a45', id: '9005388e-5355-412c-8ba9-fc6dbe192a45',
@ -70,6 +72,7 @@ export const MOCK_ALL_CLASSIFICATIONS = {
deleted: false, deleted: false,
provider: 'user', provider: 'user',
mutuallyExclusive: false, mutuallyExclusive: false,
termCount: 5,
}, },
], ],
paging: { paging: {

View File

@ -309,7 +309,7 @@ export const Icons = {
ICON_DEPLOY: 'icon-deploy', ICON_DEPLOY: 'icon-deploy',
TOUR: 'tour', TOUR: 'tour',
ICON_PLUS: 'icon-plus', ICON_PLUS: 'icon-plus',
ICON_PLUS_PRIMERY: 'icon-plus-primary', ICON_PLUS_PRIMARY: 'icon-plus-primary',
ICON_PLUS_PRIMARY_OUTLINED: 'icon-plus-primary-outlined', ICON_PLUS_PRIMARY_OUTLINED: 'icon-plus-primary-outlined',
ICON_MINUS: 'icon-minus', ICON_MINUS: 'icon-minus',
TAG: 'icon-tag', TAG: 'icon-tag',
@ -776,7 +776,7 @@ const SVGIcons: FunctionComponent<Props> = ({ icon, ...props }: Props) => {
IconComponent = IconPlus; IconComponent = IconPlus;
break; break;
case Icons.ICON_PLUS_PRIMERY: case Icons.ICON_PLUS_PRIMARY:
IconComponent = IconPlusPrimery; IconComponent = IconPlusPrimery;
break; break;