mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-28 19:05:53 +00:00
UI : Fix missing header of User and Admin table (#9371)
* Fix missing header of User and Admin table * changes as per comments
This commit is contained in:
parent
4619ade3b5
commit
ef61909e6a
@ -65,7 +65,6 @@ import {
|
|||||||
} from '../../interface/teamsAndUsers.interface';
|
} from '../../interface/teamsAndUsers.interface';
|
||||||
import AddAttributeModal from '../../pages/RolesPage/AddAttributeModal/AddAttributeModal';
|
import AddAttributeModal from '../../pages/RolesPage/AddAttributeModal/AddAttributeModal';
|
||||||
import {
|
import {
|
||||||
commonUserDetailColumns,
|
|
||||||
getEntityName,
|
getEntityName,
|
||||||
getTierFromEntityInfo,
|
getTierFromEntityInfo,
|
||||||
hasEditAccess,
|
hasEditAccess,
|
||||||
@ -100,6 +99,7 @@ import {
|
|||||||
OperationPermission,
|
OperationPermission,
|
||||||
ResourceEntity,
|
ResourceEntity,
|
||||||
} from '../PermissionProvider/PermissionProvider.interface';
|
} from '../PermissionProvider/PermissionProvider.interface';
|
||||||
|
import { commonUserDetailColumns } from '../Users/Users.util';
|
||||||
import ListEntities from './RolesAndPoliciesList';
|
import ListEntities from './RolesAndPoliciesList';
|
||||||
import { getTabs, searchTeam } from './TeamDetailsV1.utils';
|
import { getTabs, searchTeam } from './TeamDetailsV1.utils';
|
||||||
import TeamHierarchy from './TeamHierarchy';
|
import TeamHierarchy from './TeamHierarchy';
|
||||||
@ -263,7 +263,7 @@ const TeamDetailsV1 = ({
|
|||||||
|
|
||||||
const columns: ColumnsType<User> = useMemo(() => {
|
const columns: ColumnsType<User> = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
...commonUserDetailColumns,
|
...commonUserDetailColumns(),
|
||||||
{
|
{
|
||||||
title: t('label.actions'),
|
title: t('label.actions'),
|
||||||
dataIndex: 'actions',
|
dataIndex: 'actions',
|
||||||
|
@ -26,10 +26,7 @@ import { User } from '../../generated/entity/teams/user';
|
|||||||
import { Paging } from '../../generated/type/paging';
|
import { Paging } from '../../generated/type/paging';
|
||||||
import { useAuth } from '../../hooks/authHooks';
|
import { useAuth } from '../../hooks/authHooks';
|
||||||
import jsonData from '../../jsons/en';
|
import jsonData from '../../jsons/en';
|
||||||
import {
|
import { getEntityName } from '../../utils/CommonUtils';
|
||||||
commonUserDetailColumns,
|
|
||||||
getEntityName,
|
|
||||||
} from '../../utils/CommonUtils';
|
|
||||||
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
||||||
import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
|
import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
|
||||||
import DeleteWidgetModal from '../common/DeleteWidget/DeleteWidgetModal';
|
import DeleteWidgetModal from '../common/DeleteWidget/DeleteWidgetModal';
|
||||||
@ -37,6 +34,7 @@ import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder'
|
|||||||
import NextPrevious from '../common/next-previous/NextPrevious';
|
import NextPrevious from '../common/next-previous/NextPrevious';
|
||||||
import Searchbar from '../common/searchbar/Searchbar';
|
import Searchbar from '../common/searchbar/Searchbar';
|
||||||
import Loader from '../Loader/Loader';
|
import Loader from '../Loader/Loader';
|
||||||
|
import { commonUserDetailColumns } from '../Users/Users.util';
|
||||||
import './usersList.less';
|
import './usersList.less';
|
||||||
|
|
||||||
interface UserListV1Props {
|
interface UserListV1Props {
|
||||||
@ -117,7 +115,7 @@ const UserListV1: FC<UserListV1Props> = ({
|
|||||||
|
|
||||||
const columns: ColumnsType<User> = useMemo(() => {
|
const columns: ColumnsType<User> = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
...commonUserDetailColumns,
|
...commonUserDetailColumns(),
|
||||||
{
|
{
|
||||||
title: t('label.actions'),
|
title: t('label.actions'),
|
||||||
dataIndex: 'actions',
|
dataIndex: 'actions',
|
||||||
@ -261,6 +259,7 @@ const UserListV1: FC<UserListV1Props> = ({
|
|||||||
indicator: <Loader size="small" />,
|
indicator: <Loader size="small" />,
|
||||||
}}
|
}}
|
||||||
pagination={false}
|
pagination={false}
|
||||||
|
rowKey="id"
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
|
@ -1,6 +1,18 @@
|
|||||||
|
import { Popover, Space, Tag } from 'antd';
|
||||||
|
import { ColumnsType } from 'antd/lib/table';
|
||||||
|
import { t } from 'i18next';
|
||||||
|
import { isEmpty, isUndefined, uniqueId } from 'lodash';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { getUserPath } from '../../constants/constants';
|
||||||
import { User } from '../../generated/entity/teams/user';
|
import { User } from '../../generated/entity/teams/user';
|
||||||
import { EntityReference } from '../../generated/type/entityReference';
|
import { EntityReference } from '../../generated/type/entityReference';
|
||||||
|
import { getEntityName } from '../../utils/CommonUtils';
|
||||||
|
import { LIST_CAP } from '../../utils/PermissionsUtils';
|
||||||
|
import {
|
||||||
|
getRoleWithFqnPath,
|
||||||
|
getTeamsWithFqnPath,
|
||||||
|
} from '../../utils/RouterUtils';
|
||||||
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
||||||
|
|
||||||
export const userPageFilterList = [
|
export const userPageFilterList = [
|
||||||
@ -67,3 +79,115 @@ export const getUserFromEntityReference = (entity: EntityReference): User => {
|
|||||||
email: '',
|
email: '',
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const commonUserDetailColumns = (): ColumnsType<User> => [
|
||||||
|
{
|
||||||
|
title: t('label.username'),
|
||||||
|
dataIndex: 'username',
|
||||||
|
key: 'username',
|
||||||
|
render: (_, record) => (
|
||||||
|
<Link
|
||||||
|
className="hover:tw-underline tw-cursor-pointer"
|
||||||
|
data-testid={record.name}
|
||||||
|
to={getUserPath(record.fullyQualifiedName || record.name)}>
|
||||||
|
{getEntityName(record)}
|
||||||
|
</Link>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('label.teams'),
|
||||||
|
dataIndex: 'teams',
|
||||||
|
key: 'teams',
|
||||||
|
render: (_, record) => {
|
||||||
|
const listLength = record.teams?.length ?? 0;
|
||||||
|
const hasMore = listLength > LIST_CAP;
|
||||||
|
|
||||||
|
if (isUndefined(record.teams) || isEmpty(record.teams)) {
|
||||||
|
return <>No Team</>;
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Space wrap data-testid="policy-link" size={4}>
|
||||||
|
{record.teams.slice(0, LIST_CAP).map((team) => (
|
||||||
|
<Link
|
||||||
|
className="hover:tw-underline tw-cursor-pointer"
|
||||||
|
key={uniqueId()}
|
||||||
|
to={getTeamsWithFqnPath(team.fullyQualifiedName ?? '')}>
|
||||||
|
{getEntityName(team)}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
{hasMore && (
|
||||||
|
<Popover
|
||||||
|
className="tw-cursor-pointer"
|
||||||
|
content={
|
||||||
|
<Space wrap size={4}>
|
||||||
|
{record.teams.slice(LIST_CAP).map((team) => (
|
||||||
|
<Link
|
||||||
|
className="hover:tw-underline tw-cursor-pointer"
|
||||||
|
key={uniqueId()}
|
||||||
|
to={getTeamsWithFqnPath(team.fullyQualifiedName ?? '')}>
|
||||||
|
{getEntityName(team)}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
overlayClassName="tw-w-40 tw-text-center"
|
||||||
|
trigger="click">
|
||||||
|
<Tag className="tw-ml-1" data-testid="plus-more-count">{`+${
|
||||||
|
listLength - LIST_CAP
|
||||||
|
} more`}</Tag>
|
||||||
|
</Popover>
|
||||||
|
)}
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('label.roles'),
|
||||||
|
dataIndex: 'roles',
|
||||||
|
key: 'roles',
|
||||||
|
render: (_, record) => {
|
||||||
|
const listLength = record.roles?.length ?? 0;
|
||||||
|
const hasMore = listLength > LIST_CAP;
|
||||||
|
|
||||||
|
if (isUndefined(record.roles) || isEmpty(record.roles)) {
|
||||||
|
return <>No Role</>;
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Space wrap data-testid="policy-link" size={4}>
|
||||||
|
{record.roles.slice(0, LIST_CAP).map((role) => (
|
||||||
|
<Link
|
||||||
|
className="hover:tw-underline tw-cursor-pointer"
|
||||||
|
key={uniqueId()}
|
||||||
|
to={getRoleWithFqnPath(role.fullyQualifiedName ?? '')}>
|
||||||
|
{getEntityName(role)}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
{hasMore && (
|
||||||
|
<Popover
|
||||||
|
className="tw-cursor-pointer"
|
||||||
|
content={
|
||||||
|
<Space wrap size={4}>
|
||||||
|
{record.roles.slice(LIST_CAP).map((role) => (
|
||||||
|
<Link
|
||||||
|
className="hover:tw-underline tw-cursor-pointer"
|
||||||
|
key={uniqueId()}
|
||||||
|
to={getRoleWithFqnPath(role.fullyQualifiedName ?? '')}>
|
||||||
|
{getEntityName(role)}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
overlayClassName="tw-w-40 tw-text-center"
|
||||||
|
trigger="click">
|
||||||
|
<Tag className="tw-ml-1" data-testid="plus-more-count">{`+${
|
||||||
|
listLength - LIST_CAP
|
||||||
|
} more`}</Tag>
|
||||||
|
</Popover>
|
||||||
|
)}
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
@ -12,8 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { Popover, Space, Tag, Typography } from 'antd';
|
import { Typography } from 'antd';
|
||||||
import { ColumnsType } from 'antd/lib/table';
|
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
@ -25,7 +24,6 @@ import {
|
|||||||
isString,
|
isString,
|
||||||
isUndefined,
|
isUndefined,
|
||||||
toNumber,
|
toNumber,
|
||||||
uniqueId,
|
|
||||||
} from 'lodash';
|
} from 'lodash';
|
||||||
import {
|
import {
|
||||||
CurrentState,
|
CurrentState,
|
||||||
@ -39,7 +37,6 @@ import {
|
|||||||
} from 'Models';
|
} from 'Models';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Trans } from 'react-i18next';
|
import { Trans } from 'react-i18next';
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { reactLocalStorage } from 'reactjs-localstorage';
|
import { reactLocalStorage } from 'reactjs-localstorage';
|
||||||
import AppState from '../AppState';
|
import AppState from '../AppState';
|
||||||
import { getFeedCount } from '../axiosAPIs/feedsAPI';
|
import { getFeedCount } from '../axiosAPIs/feedsAPI';
|
||||||
@ -87,8 +84,6 @@ import { ServicesType } from '../interface/service.interface';
|
|||||||
import jsonData from '../jsons/en';
|
import jsonData from '../jsons/en';
|
||||||
import { getEntityFeedLink, getTitleCase } from './EntityUtils';
|
import { getEntityFeedLink, getTitleCase } from './EntityUtils';
|
||||||
import Fqn from './Fqn';
|
import Fqn from './Fqn';
|
||||||
import { LIST_CAP } from './PermissionsUtils';
|
|
||||||
import { getRoleWithFqnPath, getTeamsWithFqnPath } from './RouterUtils';
|
|
||||||
import { serviceTypeLogo } from './ServiceUtils';
|
import { serviceTypeLogo } from './ServiceUtils';
|
||||||
import { getTierFromSearchTableTags } from './TableUtils';
|
import { getTierFromSearchTableTags } from './TableUtils';
|
||||||
import { TASK_ENTITIES } from './TasksUtils';
|
import { TASK_ENTITIES } from './TasksUtils';
|
||||||
@ -751,118 +746,6 @@ export const getHostNameFromURL = (url: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const commonUserDetailColumns: ColumnsType<User> = [
|
|
||||||
{
|
|
||||||
title: t('label.username'),
|
|
||||||
dataIndex: 'username',
|
|
||||||
key: 'username',
|
|
||||||
render: (_, record) => (
|
|
||||||
<Link
|
|
||||||
className="hover:tw-underline tw-cursor-pointer"
|
|
||||||
data-testid={record.name}
|
|
||||||
to={getUserPath(record.fullyQualifiedName || record.name)}>
|
|
||||||
{getEntityName(record)}
|
|
||||||
</Link>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('label.teams'),
|
|
||||||
dataIndex: 'teams',
|
|
||||||
key: 'teams',
|
|
||||||
render: (_, record) => {
|
|
||||||
const listLength = record.teams?.length ?? 0;
|
|
||||||
const hasMore = listLength > LIST_CAP;
|
|
||||||
|
|
||||||
if (isUndefined(record.teams) || isEmpty(record.teams)) {
|
|
||||||
return <>No Team</>;
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<Space wrap data-testid="policy-link" size={4}>
|
|
||||||
{record.teams.slice(0, LIST_CAP).map((team) => (
|
|
||||||
<Link
|
|
||||||
className="hover:tw-underline tw-cursor-pointer"
|
|
||||||
key={uniqueId()}
|
|
||||||
to={getTeamsWithFqnPath(team.fullyQualifiedName ?? '')}>
|
|
||||||
{getEntityName(team)}
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
{hasMore && (
|
|
||||||
<Popover
|
|
||||||
className="tw-cursor-pointer"
|
|
||||||
content={
|
|
||||||
<Space wrap size={4}>
|
|
||||||
{record.teams.slice(LIST_CAP).map((team) => (
|
|
||||||
<Link
|
|
||||||
className="hover:tw-underline tw-cursor-pointer"
|
|
||||||
key={uniqueId()}
|
|
||||||
to={getTeamsWithFqnPath(team.fullyQualifiedName ?? '')}>
|
|
||||||
{getEntityName(team)}
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
</Space>
|
|
||||||
}
|
|
||||||
overlayClassName="tw-w-40 tw-text-center"
|
|
||||||
trigger="click">
|
|
||||||
<Tag className="tw-ml-1" data-testid="plus-more-count">{`+${
|
|
||||||
listLength - LIST_CAP
|
|
||||||
} more`}</Tag>
|
|
||||||
</Popover>
|
|
||||||
)}
|
|
||||||
</Space>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('label.roles'),
|
|
||||||
dataIndex: 'roles',
|
|
||||||
key: 'roles',
|
|
||||||
render: (_, record) => {
|
|
||||||
const listLength = record.roles?.length ?? 0;
|
|
||||||
const hasMore = listLength > LIST_CAP;
|
|
||||||
|
|
||||||
if (isUndefined(record.roles) || isEmpty(record.roles)) {
|
|
||||||
return <>No Role</>;
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<Space wrap data-testid="policy-link" size={4}>
|
|
||||||
{record.roles.slice(0, LIST_CAP).map((role) => (
|
|
||||||
<Link
|
|
||||||
className="hover:tw-underline tw-cursor-pointer"
|
|
||||||
key={uniqueId()}
|
|
||||||
to={getRoleWithFqnPath(role.fullyQualifiedName ?? '')}>
|
|
||||||
{getEntityName(role)}
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
{hasMore && (
|
|
||||||
<Popover
|
|
||||||
className="tw-cursor-pointer"
|
|
||||||
content={
|
|
||||||
<Space wrap size={4}>
|
|
||||||
{record.roles.slice(LIST_CAP).map((role) => (
|
|
||||||
<Link
|
|
||||||
className="hover:tw-underline tw-cursor-pointer"
|
|
||||||
key={uniqueId()}
|
|
||||||
to={getRoleWithFqnPath(role.fullyQualifiedName ?? '')}>
|
|
||||||
{getEntityName(role)}
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
</Space>
|
|
||||||
}
|
|
||||||
overlayClassName="tw-w-40 tw-text-center"
|
|
||||||
trigger="click">
|
|
||||||
<Tag className="tw-ml-1" data-testid="plus-more-count">{`+${
|
|
||||||
listLength - LIST_CAP
|
|
||||||
} more`}</Tag>
|
|
||||||
</Popover>
|
|
||||||
)}
|
|
||||||
</Space>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const getOwnerValue = (owner: EntityReference) => {
|
export const getOwnerValue = (owner: EntityReference) => {
|
||||||
switch (owner?.type) {
|
switch (owner?.type) {
|
||||||
case 'team':
|
case 'team':
|
||||||
|
Loading…
x
Reference in New Issue
Block a user