Skip to content

Commit

Permalink
feat(ui): sortable domain list (datahub-project#6736)
Browse files Browse the repository at this point in the history
  • Loading branch information
looppi authored and cccs-Dustin committed Feb 1, 2023
1 parent 1e36ef1 commit e914740
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 158 deletions.
65 changes: 65 additions & 0 deletions datahub-web-react/src/app/domain/DomainItemMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from 'react';
import { DeleteOutlined } from '@ant-design/icons';
import { Dropdown, Menu, message, Modal } from 'antd';
import { EntityType } from '../../types.generated';
import { useEntityRegistry } from '../useEntityRegistry';
import { useDeleteDomainMutation } from '../../graphql/domain.generated';
import { MenuIcon } from '../entity/shared/EntityDropdown/EntityDropdown';

type Props = {
urn: string;
name: string;
onDelete?: () => void;
};

export default function DomainItemMenu({ name, urn, onDelete }: Props) {
const entityRegistry = useEntityRegistry();
const [deleteDomainMutation] = useDeleteDomainMutation();

const deleteDomain = () => {
deleteDomainMutation({
variables: {
urn,
},
})
.then(({ errors }) => {
if (!errors) {
message.success('Deleted Domain!');
onDelete?.();
}
})
.catch(() => {
message.destroy();
message.error({ content: `Failed to delete Domain!: An unknown error occurred.`, duration: 3 });
});
};

const onConfirmDelete = () => {
Modal.confirm({
title: `Delete Domain '${name}'`,
content: `Are you sure you want to remove this ${entityRegistry.getEntityName(EntityType.Domain)}?`,
onOk() {
deleteDomain();
},
onCancel() {},
okText: 'Yes',
maskClosable: true,
closable: true,
});
};

return (
<Dropdown
trigger={['click']}
overlay={
<Menu>
<Menu.Item onClick={onConfirmDelete} key="delete">
<DeleteOutlined /> &nbsp;Delete
</Menu.Item>
</Menu>
}
>
<MenuIcon fontSize={20} />
</Dropdown>
);
}
65 changes: 65 additions & 0 deletions datahub-web-react/src/app/domain/DomainListColumns.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from 'react';
import { Tag, Tooltip, Typography } from 'antd';
import { Link } from 'react-router-dom';
import styled from 'styled-components';
import { Maybe, Ownership } from '../../types.generated';
import { useEntityRegistry } from '../useEntityRegistry';
import AvatarsGroup from '../shared/avatar/AvatarsGroup';
import DomainItemMenu from './DomainItemMenu';

interface DomainEntry {
name: string;
entities: string;
urn: string;
ownership?: Maybe<Ownership>;
url: string;
}

const AvatarGroupWrapper = styled.div`
margin-right: 10px;
display: inline-block;
`;

const DomainNameContainer = styled.div`
margin-left: 16px;
margin-right: 16px;
display: inline;
`;

export function DomainListMenuColumn(handleDelete: (urn: string) => void) {
return (record: DomainEntry) => (
<DomainItemMenu name={record.name} urn={record.urn} onDelete={() => handleDelete(record.urn)} />
);
}

export function DomainNameColumn(logoIcon: JSX.Element) {
return (record: DomainEntry) => (
<Link to={record.url}>
{logoIcon}
<DomainNameContainer>
<Typography.Text>{record.name}</Typography.Text>
</DomainNameContainer>
<Tooltip title={`There are ${record.entities} entities in this domain.`}>
<Tag>{record.entities} entities</Tag>
</Tooltip>
</Link>
);
}

export function DomainOwnersColumn(ownership: Maybe<Ownership>) {
const entityRegistry = useEntityRegistry();

if (!ownership) {
return null;
}

const { owners } = ownership;
if (!owners || owners.length === 0) {
return null;
}
return (
<AvatarGroupWrapper>
<AvatarsGroup size={24} owners={owners} entityRegistry={entityRegistry} maxCount={4} />
</AvatarGroupWrapper>
);
}
135 changes: 0 additions & 135 deletions datahub-web-react/src/app/domain/DomainListItem.tsx

This file was deleted.

78 changes: 55 additions & 23 deletions datahub-web-react/src/app/domain/DomainsList.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,28 @@
import React, { useEffect, useState } from 'react';
import { Button, Empty, List, Pagination, Typography } from 'antd';
import { Button, Empty, Pagination, Typography } from 'antd';
import { useLocation } from 'react-router';
import styled from 'styled-components';
import * as QueryString from 'query-string';
import { PlusOutlined } from '@ant-design/icons';
import { Domain } from '../../types.generated';
import { AlignType } from 'rc-table/lib/interface';
import { EntityType } from '../../types.generated';
import { useListDomainsQuery } from '../../graphql/domain.generated';
import CreateDomainModal from './CreateDomainModal';
import { Message } from '../shared/Message';
import TabToolbar from '../entity/shared/components/styled/TabToolbar';
import DomainListItem from './DomainListItem';
import { SearchBar } from '../search/SearchBar';
import { useEntityRegistry } from '../useEntityRegistry';
import { scrollToTop } from '../shared/searchUtils';
import { addToListDomainsCache, removeFromListDomainsCache } from './utils';
import { OnboardingTour } from '../onboarding/OnboardingTour';
import { DOMAINS_INTRO_ID, DOMAINS_CREATE_DOMAIN_ID } from '../onboarding/config/DomainsOnboardingConfig';
import { getElasticCappedTotalValueText } from '../entity/shared/constants';
import { StyledTable } from '../entity/shared/components/styled/StyledTable';
import { IconStyleType } from '../entity/Entity';
import { DomainOwnersColumn, DomainListMenuColumn, DomainNameColumn } from './DomainListColumns';

const DomainsContainer = styled.div``;

const DomainsStyledList = styled(List)`
&&& {
width: 100%;
border-color: ${(props) => props.theme.styles['border-color-base']};
}
`;

const DomainsPaginationContainer = styled.div`
display: flex;
justify-content: center;
Expand Down Expand Up @@ -85,6 +82,48 @@ export const DomainsList = () => {
}, 2000);
};

const logoIcon = entityRegistry.getIcon(EntityType.Domain, 12, IconStyleType.ACCENT);
const allColumns = [
{
title: 'Name',
dataIndex: '',
key: 'name',
sorter: (sourceA, sourceB) => {
return sourceA.name.localeCompare(sourceB.name);
},
render: DomainNameColumn(logoIcon),
},
{
title: 'Owners',
dataIndex: 'ownership',
width: '10%',
key: 'ownership',
render: DomainOwnersColumn,
},
{
title: '',
dataIndex: '',
width: '5%',
align: 'right' as AlignType,
key: 'menu',
render: DomainListMenuColumn(handleDelete),
},
];

const tableData = domains.map((domain) => {
const displayName = entityRegistry.getDisplayName(EntityType.Domain, domain);
const totalEntitiesText = getElasticCappedTotalValueText(domain.entities?.total || 0);
const url = entityRegistry.getEntityUrl(EntityType.Domain, domain.urn);

return {
name: displayName,
entities: totalEntitiesText,
urn: domain.urn,
ownership: domain.ownership,
url,
};
});

return (
<>
{!data && loading && <Message type="loading" content="Loading domains..." />}
Expand Down Expand Up @@ -113,19 +152,12 @@ export const DomainsList = () => {
hideRecommendations
/>
</TabToolbar>
<DomainsStyledList
bordered
locale={{
emptyText: <Empty description="No Domains!" image={Empty.PRESENTED_IMAGE_SIMPLE} />,
}}
dataSource={domains}
renderItem={(item: any) => (
<DomainListItem
key={item.urn}
domain={item as Domain}
onDelete={() => handleDelete(item.urn)}
/>
)}
<StyledTable
columns={allColumns}
dataSource={tableData}
rowKey="urn"
pagination={false}
locale={{ emptyText: <Empty description="No Domains!" image={Empty.PRESENTED_IMAGE_SIMPLE} /> }}
/>
<DomainsPaginationContainer>
<PaginationInfo>
Expand Down

0 comments on commit e914740

Please sign in to comment.