UI : Added add placeholder for settings tables no data (#7237)

* Added add placeholder for settings tables no data

* added dataset id in errorplaceholder

* minor fixes

* cypress fixes

* cypress fix

* fix cypress issue

* fix teams and user cypress issue

* unit test changes
This commit is contained in:
Ashish Gupta 2022-09-07 18:50:29 +05:30 committed by GitHub
parent 58c439e900
commit c6f03dcfc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 511 additions and 255 deletions

View File

@ -564,6 +564,8 @@ export const addCustomPropertiesForEntity = (entityType, customType, value) => {
cy.get('[data-testid="create-custom-field"]').scrollIntoView().click();
//Check if the property got added
cy.intercept('/api/v1/metadata/types/name/*?fields=customProperties').as("customProperties");
cy.wait("@customProperties");
cy.get('[data-testid="data-row"]').should('contain', propertyName);
//Navigating to home page
@ -683,5 +685,37 @@ export const deleteCreatedProperty = (propertyName) => {
cy.get('[data-testid="save-button"]').should('be.visible').click();
//Checking if property got deleted successfully
cy.get('[data-testid="table-body"]').should('not.contain', propertyName);
cy.get('[data-testid="add-field-button"]').should('be.visible');
};
export const updateOwner = () => {
cy.get('[data-testid="avatar"]').should('be.visible').click();
cy.get('[data-testid="user-name"]')
.should('exist')
.invoke('text')
.then((text) => {
cy.get('[data-testid="hiden-layer"]').should('exist').click();
//Clicking on edit owner button
cy.get('[data-testid="edit-Owner-icon"]').should('be.visible').click();
cy.wait(1000);
//Clicking on users tab
cy.get('button[data-testid="dropdown-tab"]')
.should('exist')
.should('be.visible')
.contains('Users')
.click();
cy.get('[data-testid="list-item"]').first()
.should('contain', text.trim())
.click();
//Asserting the added name
cy.get('[data-testid="owner-link"]').should(
'contain',
text.trim()
);
});
}

View File

@ -259,15 +259,25 @@ describe('Roles page should work properly', () => {
});
it('Check if last policy is not removed', () => {
cy.intercept({ method: 'GET', url: `/api/v1/roles/name/${roleName}*` }).as(
'getSelectedRole'
);
cy.get('[data-testid="role-name"]')
.contains(roleName)
.should('be.visible')
.click();
//Asserting navigation
cy.get('[data-testid="inactive-link"]')
.should('contain', roleName)
.should('be.visible');
cy.wait('@getSelectedRole').its('response.statusCode').should('eq', 200);
cy.intercept({ method: 'PATCH', url: '/api/v1/roles/*' }).as(
'checkDeletedRole'
);
//Removing second policy from the role
removePolicyFromRole(policies.dataStewardPolicy);
@ -277,6 +287,8 @@ describe('Roles page should work properly', () => {
policies.dataStewardPolicy
);
cy.wait('@checkDeletedRole').its('response.statusCode').should('eq', 200);
//Removing the last policy and validating the error message
removePolicyFromRole(policies.dataConsumerPolicy);

View File

@ -11,7 +11,7 @@
* limitations under the License.
*/
import { toastNotification, uuid } from '../../common/common';
import { toastNotification, updateOwner, uuid } from '../../common/common';
const orgName = 'Organization';
const updateddescription = 'This is updated description';
@ -85,31 +85,10 @@ describe('Teams flow should work properly', () => {
it('Add owner to created team', () => {
//Clicking on created team
cy.get('table').find('.ant-table-row').contains(TEAM_DETAILS.name).click();
//Clicking on edit owner button
cy.get('[data-testid="edit-Owner-icon"]').should('be.visible').click();
cy.wait(1000);
//Clicking on users tab
cy.get('button[data-testid="dropdown-tab"]')
.should('exist')
.should('be.visible')
.contains('Users')
.click();
cy.get('[data-testid="list-item"]')
.should('contain', TEAM_DETAILS.ownername)
.click();
//Asserting the added name
cy.get('[data-testid="owner-link"]').should(
'contain',
TEAM_DETAILS.ownername
);
updateOwner()
});
it('Add user to created team', () => {
it('Add user to created team', () => {
//Click on created team
cy.get('table').find('.ant-table-row').contains(TEAM_DETAILS.name).click();
@ -119,14 +98,15 @@ describe('Teams flow should work properly', () => {
.should('be.visible')
.click();
cy.get('[data-testid="add-new-user"]')
cy.get('[data-testid="add-user"]')
.scrollIntoView()
.should('exist')
.should('be.visible')
.click();
cy.wait(2000);
cy.get('[data-testid="searchbar"]').eq(1).type(TEAM_DETAILS.ownername);
cy.get('[data-testid="searchbar"]').type(TEAM_DETAILS.ownername);
cy.wait(500);
@ -163,15 +143,13 @@ describe('Teams flow should work properly', () => {
// TODO: Remove cy.wait and wait for API to be completed before querying for new element
cy.wait(2000);
//
//Verify if user is removed
cy.get('[data-testid="searchbar"]')
cy.get('[data-testid="Users"]')
.should('exist')
.should('be.visible')
.type(TEAM_DETAILS.ownername);
.click();
cy.get('.ant-table-cell')
.should('be.visible')
.should('not.contain', TEAM_DETAILS.ownername);
cy.get('[data-testid="add-user"]').should('not.contain', TEAM_DETAILS.ownername);
});
it('Join team should work properly', () => {
@ -215,7 +193,7 @@ describe('Teams flow should work properly', () => {
.should('contain', TEAM_DETAILS.updatedname);
//Click on edit description button
cy.get('[data-testid="edit-description"]').should('be.visible').click();
cy.get('[data-testid="edit-description"] > [data-testid="image"]').should('be.visible').click();
//Entering updated description
cy.get('.toastui-editor-md-container > .toastui-editor > .ProseMirror')

View File

@ -11,7 +11,7 @@
* limitations under the License.
*/
import { Col, Empty, Row } from 'antd';
import { Col, Row } from 'antd';
import classNames from 'classnames';
import { isEmpty, isEqual, isNil, isUndefined } from 'lodash';
import { ColumnJoins, EntityTags, ExtraInfo } from 'Models';
@ -56,6 +56,7 @@ import { CustomPropertyTable } from '../common/CustomPropertyTable/CustomPropert
import { CustomPropertyProps } from '../common/CustomPropertyTable/CustomPropertyTable.interface';
import Description from '../common/description/Description';
import EntityPageInfo from '../common/entityPageInfo/EntityPageInfo';
import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder';
import TabsPane from '../common/TabsPane/TabsPane';
import PageContainer from '../containers/PageContainer';
import EntityLineageComponent from '../EntityLineage/EntityLineage.component';
@ -730,10 +731,10 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
</Col>
) : (
<Col
className="tw-flex tw-justify-center tw-font-medium tw-items-center tw-border tw-border-main tw-rounded-md tw-p-8 tw-col-span-3"
className="tw-flex tw-justify-center tw-font-medium tw-items-center tw-p-8 tw-col-span-3"
span={24}>
<div data-testid="no-queries">
<Empty description={<p>No queries data available</p>} />
<ErrorPlaceHolder heading="queries" />
</div>
</Col>
)}

View File

@ -61,6 +61,10 @@ jest.mock('../common/rich-text-editor/RichTextEditorPreviewer', () => {
return jest.fn().mockReturnValue(<p>RichTextEditorPreviewer</p>);
});
jest.mock('../common/error-with-placeholder/ErrorPlaceHolder', () => {
return jest.fn().mockReturnValue(<p data-testid="error">ErrorPlaceHolder</p>);
});
const mockUserTeam = [
{
description: 'description',

View File

@ -98,6 +98,17 @@ interface AddAttribute {
selectedData: EntityReference[];
}
interface PlaceholderProps {
title?: string;
disabled?: boolean;
label?: string;
onClick?: () => void;
heading?: string;
description?: React.ReactNode;
button?: React.ReactNode;
datatestid?: string;
}
const TeamDetailsV1 = ({
hasAccess,
currentTeam,
@ -196,6 +207,45 @@ const TeamDetailsV1 = ({
setDeletingUser({ user, state: true, leave });
};
const fetchErrorPlaceHolder = useMemo(
() =>
({
title,
disabled,
label,
onClick,
heading,
description,
button,
datatestid,
}: PlaceholderProps) => {
return (
<ErrorPlaceHolder
buttons={
button ? (
button
) : (
<ButtonAntd
ghost
data-testid={datatestid}
disabled={disabled}
size="small"
title={title}
type="primary"
onClick={onClick}>
{label}
</ButtonAntd>
)
}
description={description}
heading={heading}
type="ADD_DATA"
/>
);
},
[]
);
const columns: ColumnsType<User> = useMemo(() => {
return [
...commonUserDetailColumns,
@ -555,45 +605,12 @@ const TeamDetailsV1 = ({
return (
<div>
<div className="tw-flex tw-justify-between tw-items-center tw-mb-3">
<div className="tw-w-4/12">
<Searchbar
removeMargin
placeholder="Search for user..."
searchValue={teamUsersSearchText}
typingInterval={500}
onSearch={handleTeamUsersSearchAction}
/>
</div>
{currentTeamUsers.length > 0 && isActionAllowed() && (
<div>
<Button
className="tw-h-8 tw-px-2"
data-testid="add-user"
disabled={!entityPermissions.EditAll}
size="small"
theme="primary"
title={
entityPermissions.EditAll
? 'Add User'
: NO_PERMISSION_FOR_ACTION
}
variant="contained"
onClick={() => {
handleAddUser(true);
}}>
Add User
</Button>
</div>
)}
</div>
{isTeamMemberLoading ? (
<Loader />
) : (
<div>
{currentTeamUsers.length <= 0 ? (
<div className="tw-flex tw-flex-col tw-items-center tw-place-content-center tw-mt-40 tw-gap-1">
{isEmpty(currentTeamUsers) &&
!teamUsersSearchText &&
!isTeamMemberLoading ? (
fetchErrorPlaceHolder({
description: (
<div className="tw-mb-2">
<p>
There are no users{' '}
{teamUsersSearchText
@ -601,44 +618,79 @@ const TeamDetailsV1 = ({
: `added yet.`}
</p>
<p>Would like to start adding some?</p>
<Button
className="tw-h-8 tw-rounded tw-my-2"
data-testid="add-new-user"
disabled={!entityPermissions.EditAll}
size="small"
theme="primary"
title={
entityPermissions.EditAll
? 'Add New User'
: NO_PERMISSION_FOR_ACTION
}
variant="contained"
onClick={() => handleAddUser(true)}>
Add new user
</Button>
</div>
) : (
<Fragment>
<Table
className="teams-list-table"
columns={columns}
dataSource={sortedUser}
pagination={false}
size="small"
),
disabled: !entityPermissions.EditAll,
title: entityPermissions.EditAll
? 'Add New User'
: NO_PERMISSION_FOR_ACTION,
onClick: () => handleAddUser(true),
label: 'Add new user',
datatestid: 'add-user',
})
) : (
<>
<div className="tw-flex tw-justify-between tw-items-center tw-mb-3">
<div className="tw-w-4/12">
<Searchbar
removeMargin
placeholder="Search for user..."
searchValue={teamUsersSearchText}
typingInterval={500}
onSearch={handleTeamUsersSearchAction}
/>
{teamUserPagin.total > PAGE_SIZE_MEDIUM && (
<NextPrevious
currentPage={currentTeamUserPage}
isNumberBased={Boolean(teamUsersSearchText)}
pageSize={PAGE_SIZE_MEDIUM}
paging={teamUserPagin}
pagingHandler={teamUserPaginHandler}
totalCount={teamUserPagin.total}
</div>
{currentTeamUsers.length > 0 && isActionAllowed() && (
<div>
<Button
className="tw-h-8 tw-px-2"
data-testid="add-user"
disabled={!entityPermissions.EditAll}
size="small"
theme="primary"
title={
entityPermissions.EditAll
? 'Add User'
: NO_PERMISSION_FOR_ACTION
}
variant="contained"
onClick={() => {
handleAddUser(true);
}}>
Add User
</Button>
</div>
)}
</div>
{isTeamMemberLoading ? (
<Loader />
) : (
<div>
<Fragment>
<Table
className="teams-list-table"
columns={columns}
dataSource={sortedUser}
pagination={false}
size="small"
/>
)}
</Fragment>
{teamUserPagin.total > PAGE_SIZE_MEDIUM && (
<NextPrevious
currentPage={currentTeamUserPage}
isNumberBased={Boolean(teamUsersSearchText)}
pageSize={PAGE_SIZE_MEDIUM}
paging={teamUserPagin}
pagingHandler={teamUserPaginHandler}
totalCount={teamUserPagin.total}
/>
)}
</Fragment>
</div>
)}
</div>
</>
)}
</div>
);
@ -652,21 +704,21 @@ const TeamDetailsV1 = ({
const ownData = filterEntityAssets(currentTeam?.owns || []);
if (ownData.length <= 0) {
return (
<div className="tw-flex tw-flex-col tw-items-center tw-place-content-center tw-mt-40 tw-gap-1">
<p>Your team does not have any assets</p>
<p>Would like to start adding some?</p>
return fetchErrorPlaceHolder({
description: (
<div className="tw-mb-4">
<p>Your team does not have any assets</p>
<p>Would like to start adding some?</p>
</div>
),
button: (
<Link to="/explore">
<Button
className="tw-h-8 tw-rounded tw-mb-2 tw-text-white"
size="small"
theme="primary"
variant="contained">
<ButtonAntd ghost size="small" type="primary">
Explore
</Button>
</ButtonAntd>
</Link>
</div>
);
),
});
}
return (
@ -884,109 +936,153 @@ const TeamDetailsV1 = ({
/>
<div className="tw-flex-grow tw-flex tw-flex-col tw-pt-4">
{currentTab === 1 && (
<Row className="team-list-container" gutter={[16, 16]}>
<Col span={8}>
<Searchbar
removeMargin
placeholder="Search for team..."
searchValue={searchTerm}
typingInterval={500}
onSearch={handleTeamSearch}
/>
</Col>
<Col span={16}>
<Space
align="end"
className="tw-w-full"
direction="vertical">
<ButtonAntd
disabled={!createTeamPermission}
title={
createTeamPermission
? 'Add Team'
: NO_PERMISSION_FOR_ACTION
}
type="primary"
onClick={() => handleAddTeam(true)}>
Add Team
</ButtonAntd>
</Space>
</Col>
<Col span={24}>
<TeamHierarchy
data={table as Team[]}
onTeamExpand={onTeamExpand}
/>
</Col>
</Row>
)}
{currentTab === 1 &&
(isEmpty(table) && !searchTerm ? (
fetchErrorPlaceHolder({
title: createTeamPermission
? 'Add Team'
: NO_PERMISSION_FOR_ACTION,
label: 'Add Team',
onClick: () => handleAddTeam(true),
disabled: !createTeamPermission,
heading: 'Team',
})
) : (
<Row className="team-list-container" gutter={[16, 16]}>
<Col span={8}>
<Searchbar
removeMargin
placeholder="Search for team..."
searchValue={searchTerm}
typingInterval={500}
onSearch={handleTeamSearch}
/>
</Col>
<Col span={16}>
<Space
align="end"
className="tw-w-full"
direction="vertical">
<ButtonAntd
disabled={!createTeamPermission}
title={
createTeamPermission
? 'Add Team'
: NO_PERMISSION_FOR_ACTION
}
type="primary"
onClick={() => handleAddTeam(true)}>
Add Team
</ButtonAntd>
</Space>
</Col>
<Col span={24}>
<TeamHierarchy
data={table as Team[]}
onTeamExpand={onTeamExpand}
/>
</Col>
</Row>
))}
{currentTab === 2 && getUserCards()}
{currentTab === 3 && getDatasetCards()}
{currentTab === 4 && (
<Space
className="tw-w-full roles-and-policy"
direction="vertical">
<ButtonAntd
data-testid="add-role"
disabled={!entityPermissions.EditAll}
title={
entityPermissions.EditAll
? 'Add Role'
: NO_PERMISSION_FOR_ACTION
}
type="primary"
onClick={() =>
{currentTab === 4 &&
(isEmpty(currentTeam.defaultRoles || []) ? (
fetchErrorPlaceHolder({
title: entityPermissions.EditAll
? 'Add Role'
: NO_PERMISSION_FOR_ACTION,
label: 'Add Role',
onClick: () =>
setAddAttribute({
type: EntityType.ROLE,
selectedData: currentTeam.defaultRoles || [],
})
}>
Add Role
</ButtonAntd>
<ListEntities
hasAccess={entityPermissions.EditAll}
list={currentTeam.defaultRoles || []}
type={EntityType.ROLE}
onDelete={(record) =>
setEntity({ record, attribute: 'defaultRoles' })
}
/>
</Space>
)}
{currentTab === 5 && (
<Space
className="tw-w-full roles-and-policy"
direction="vertical">
<ButtonAntd
data-testid="add-policy"
disabled={!entityPermissions.EditAll}
title={
entityPermissions.EditAll
? 'Add Policy'
: NO_PERMISSION_FOR_ACTION
}
type="primary"
onClick={() =>
}),
disabled: !entityPermissions.EditAll,
heading: 'Role',
datatestid: 'add-role',
})
) : (
<Space
className="tw-w-full roles-and-policy"
direction="vertical">
<ButtonAntd
data-testid="add-role"
disabled={!entityPermissions.EditAll}
title={
entityPermissions.EditAll
? 'Add Role'
: NO_PERMISSION_FOR_ACTION
}
type="primary"
onClick={() =>
setAddAttribute({
type: EntityType.ROLE,
selectedData: currentTeam.defaultRoles || [],
})
}>
Add Role
</ButtonAntd>
<ListEntities
hasAccess={entityPermissions.EditAll}
list={currentTeam.defaultRoles || []}
type={EntityType.ROLE}
onDelete={(record) =>
setEntity({ record, attribute: 'defaultRoles' })
}
/>
</Space>
))}
{currentTab === 5 &&
(isEmpty(currentTeam.policies) ? (
fetchErrorPlaceHolder({
title: entityPermissions.EditAll
? 'Add Policy'
: NO_PERMISSION_FOR_ACTION,
label: 'Add Policy',
datatestid: 'add-policy',
onClick: () =>
setAddAttribute({
type: EntityType.POLICY,
selectedData: currentTeam.policies || [],
})
}>
Add Policy
</ButtonAntd>
<ListEntities
hasAccess={entityPermissions.EditAll}
list={currentTeam.policies || []}
type={EntityType.POLICY}
onDelete={(record) =>
setEntity({ record, attribute: 'policies' })
}
/>
</Space>
)}
}),
disabled: !entityPermissions.EditAll,
heading: 'Policies',
})
) : (
<Space
className="tw-w-full roles-and-policy"
direction="vertical">
<ButtonAntd
data-testid="add-policy"
disabled={!entityPermissions.EditAll}
title={
entityPermissions.EditAll
? 'Add Policy'
: NO_PERMISSION_FOR_ACTION
}
type="primary"
onClick={() =>
setAddAttribute({
type: EntityType.POLICY,
selectedData: currentTeam.policies || [],
})
}>
Add Policy
</ButtonAntd>
<ListEntities
hasAccess={entityPermissions.EditAll}
list={currentTeam.policies || []}
type={EntityType.POLICY}
onDelete={(record) =>
setEntity({ record, attribute: 'policies' })
}
/>
</Space>
))}
</div>
</div>
</Fragment>

View File

@ -14,7 +14,7 @@
import { Button, Col, Modal, Row, Space, Switch, Table, Tooltip } from 'antd';
import { ColumnsType } from 'antd/lib/table';
import { AxiosError } from 'axios';
import { isUndefined } from 'lodash';
import { isEmpty, isUndefined } from 'lodash';
import React, { FC, useMemo, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { updateUser } from '../../axiosAPIs/userAPI';
@ -33,6 +33,7 @@ import { checkPermission } from '../../utils/PermissionsUtils';
import SVGIcons, { Icons } from '../../utils/SvgUtils';
import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
import DeleteWidgetModal from '../common/DeleteWidget/DeleteWidgetModal';
import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder';
import NextPrevious from '../common/next-previous/NextPrevious';
import Searchbar from '../common/searchbar/Searchbar';
import Loader from '../Loader/Loader';
@ -178,6 +179,46 @@ const UserListV1: FC<UserListV1Props> = ({
];
}, [showRestore]);
const fetchErrorPlaceHolder = useMemo(
() => (type: string) => {
return (
<Row>
<Col className="w-full tw-flex tw-justify-end">
<span>
<Switch
checked={showDeletedUser}
size="small"
onClick={onShowDeletedUserChange}
/>
<span className="tw-ml-2">Deleted Users</span>
</span>
</Col>
<Col span={24}>
<ErrorPlaceHolder
buttons={
<Button
ghost
// data-testid="add-user"
disabled={!createPermission}
type="primary"
onClick={handleAddNewUser}>
Add User
</Button>
}
heading="User"
type={type}
/>
</Col>
</Row>
);
},
[]
);
if (isEmpty(data) && !showDeletedUser && !isDataLoading && !searchTerm) {
return fetchErrorPlaceHolder('ADD_DATA');
}
return (
<Row className="user-listing" gutter={[16, 16]}>
<Col span={8}>

View File

@ -180,7 +180,9 @@ const Appbar: React.FC = (): JSX.Element => {
return (
<div className="tw-max-w-xs" data-testid="greeting-text">
<Link to={getUserPath(currentUser?.name as string)}>
<Link
data-testid="user-name"
to={getUserPath(currentUser?.name as string)}>
{' '}
<Ellipses
tooltip

View File

@ -25,9 +25,17 @@ type Props = {
doc?: string;
buttons?: React.ReactNode;
buttonId?: string;
description?: React.ReactNode;
};
const ErrorPlaceHolder = ({ doc, type, children, heading, buttons }: Props) => {
const ErrorPlaceHolder = ({
doc,
type,
children,
heading,
buttons,
description,
}: Props) => {
const { Paragraph, Link } = Typography;
return type === 'ADD_DATA' ? (
@ -36,19 +44,25 @@ const ErrorPlaceHolder = ({ doc, type, children, heading, buttons }: Props) => {
{' '}
<img data-testid="no-data-image" src={AddPlaceHolder} width="100" />
</div>
<div className="tw-flex tw-flex-col tw-items-center tw-mt-9 tw-text-base tw-font-medium">
<Paragraph style={{ marginBottom: '4px' }}>
{' '}
Adding a new {heading} is easy, just give it a spin!
</Paragraph>
<Paragraph>
{' '}
Still need help? Refer to our{' '}
<Link href={doc} target="_blank">
docs
</Link>{' '}
for more information.
</Paragraph>
<div className="tw-flex tw-flex-col tw-items-center tw-mt-10 tw-text-base tw-font-medium">
{description ? (
description
) : (
<>
<Paragraph style={{ marginBottom: '4px' }}>
{' '}
Adding a new {heading} is easy, just give it a spin!
</Paragraph>
<Paragraph>
{' '}
Still need help? Refer to our{' '}
<Link href={doc} target="_blank">
docs
</Link>{' '}
for more information.
</Paragraph>
</>
)}
<div className="tw-text-lg tw-text-center">{buttons}</div>
</div>

View File

@ -27,6 +27,7 @@ const AnchorDropDownList = ({ dropDownList, setIsOpen }: DropDownListProp) => {
<>
<button
className="tw-z-10 tw-fixed tw-inset-0 tw-h-full tw-w-full tw-bg-black tw-opacity-0"
data-testid="hiden-layer"
onClick={() => setIsOpen && setIsOpen(false)}
/>
<div

View File

@ -11,10 +11,10 @@
* limitations under the License.
*/
import { Col, Empty, Row, Tooltip } from 'antd';
import { Button as ButtonAntd, Col, Empty, Row, Tooltip } from 'antd';
import { AxiosError } from 'axios';
import { compare } from 'fast-json-patch';
import { isUndefined } from 'lodash';
import { isEmpty, isUndefined } from 'lodash';
import React, { useEffect, useMemo, useState } from 'react';
import { useHistory, useParams } from 'react-router-dom';
import { getTypeByFQN, updateType } from '../../axiosAPIs/metadataTypeAPI';
@ -185,29 +185,52 @@ const CustomEntityDetailV1 = () => {
/>
</div>
)}
{activeTab === 1 && (
<div data-testid="entity-custom-fields">
<div className="tw-flex tw-justify-end">
<Tooltip
title={editPermission ? 'Add' : NO_PERMISSION_FOR_ACTION}>
<Button
className="tw-mb-4 tw-py-1 tw-px-2 tw-rounded"
data-testid="add-field-button"
disabled={!editPermission}
size="custom"
theme="primary"
onClick={() => handleAddProperty()}>
Add Property
</Button>
</Tooltip>
{activeTab === 1 &&
(isEmpty(selectedEntityTypeDetail.customProperties) ? (
<div data-testid="entity-custom-fields">
<ErrorPlaceHolder
buttons={
<Tooltip
title={editPermission ? 'Add' : NO_PERMISSION_FOR_ACTION}>
<ButtonAntd
ghost
data-testid="add-field-button"
disabled={!editPermission}
type="primary"
onClick={() => handleAddProperty()}>
Add Property
</ButtonAntd>
</Tooltip>
}
heading="Property"
type="ADD_DATA"
/>
</div>
<CustomPropertyTable
customProperties={selectedEntityTypeDetail.customProperties || []}
hasAccess={editPermission}
updateEntityType={updateEntityType}
/>
</div>
)}
) : (
<div data-testid="entity-custom-fields">
<div className="tw-flex tw-justify-end">
<Tooltip
title={editPermission ? 'Add' : NO_PERMISSION_FOR_ACTION}>
<Button
className="tw-mb-4 tw-py-1 tw-px-2 tw-rounded"
data-testid="add-field-button"
disabled={!editPermission}
size="custom"
theme="primary"
onClick={() => handleAddProperty()}>
Add Property
</Button>
</Tooltip>
</div>
<CustomPropertyTable
customProperties={
selectedEntityTypeDetail.customProperties || []
}
hasAccess={editPermission}
updateEntityType={updateEntityType}
/>
</div>
))}
</Col>
</Row>
) : (

View File

@ -17,6 +17,7 @@ import { isEmpty } from 'lodash';
import React, { useEffect, useMemo, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { getPolicies } from '../../../axiosAPIs/rolesAPIV1';
import ErrorPlaceHolder from '../../../components/common/error-with-placeholder/ErrorPlaceHolder';
import NextPrevious from '../../../components/common/next-previous/NextPrevious';
import Loader from '../../../components/Loader/Loader';
import { usePermissionProvider } from '../../../components/PermissionProvider/PermissionProvider';
@ -82,8 +83,32 @@ const PoliciesListPage = () => {
fetchPolicies();
}, []);
const fetchErrorPlaceHolder = useMemo(
() => () => {
return (
<ErrorPlaceHolder
buttons={
<Button
ghost
data-testid="add-policy"
disabled={!addPolicyPermission}
type="primary"
onClick={handleAddPolicy}>
Add Policy
</Button>
}
heading="Policy"
type="ADD_DATA"
/>
);
},
[]
);
return isLoading ? (
<Loader />
) : isEmpty(policies) ? (
fetchErrorPlaceHolder()
) : (
<Row className="policies-list-container" gutter={[16, 16]}>
<Col span={24}>

View File

@ -17,6 +17,7 @@ import { isEmpty } from 'lodash';
import React, { useEffect, useMemo, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { getRoles } from '../../../axiosAPIs/rolesAPIV1';
import ErrorPlaceHolder from '../../../components/common/error-with-placeholder/ErrorPlaceHolder';
import NextPrevious from '../../../components/common/next-previous/NextPrevious';
import Loader from '../../../components/Loader/Loader';
import { usePermissionProvider } from '../../../components/PermissionProvider/PermissionProvider';
@ -85,8 +86,32 @@ const RolesListPage = () => {
fetchRoles();
}, []);
const fetchErrorPlaceHolder = useMemo(
() => () => {
return (
<ErrorPlaceHolder
buttons={
<Button
ghost
data-testid="add-role"
disabled={!addRolePermission}
type="primary"
onClick={handleAddRole}>
Add Role
</Button>
}
heading="Role"
type="ADD_DATA"
/>
);
},
[]
);
return isLoading ? (
<Loader />
) : isEmpty(roles) ? (
fetchErrorPlaceHolder()
) : (
<Row
className="roles-list-container"