Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui/tasks): add pagination on tasks listing page #10293

Merged
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions datahub-web-react/src/app/entity/dataFlow/DataFlowEntity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ export class DataFlowEntity implements Entity<DataFlow> {
{
name: 'Tasks',
component: DataFlowJobsTab,
properties: {
urn,
},
},
{
name: 'Incidents',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,60 @@
import React from 'react';
import { useBaseEntity } from '../../EntityContext';
import React, { useState } from 'react';
import { EntityType } from '../../../../../types.generated';
import { EntityList } from './components/EntityList';
import { useEntityRegistry } from '../../../../useEntityRegistry';
import { useGetDataFlowChildJobsQuery } from '../../../../../graphql/dataFlow.generated';
import { SearchCfg } from '../../../../../conf';

export const DataFlowJobsTab = () => {
const entity = useBaseEntity() as any;
const dataFlow = entity && entity.dataFlow;
interface Props {
properties?: {
urn: string;
};
}

export const DataFlowJobsTab = ({ properties = { urn: '' } }: Props) => {
const [page, setPage] = useState(1);
const [numResultsPerPage, setNumResultsPerPage] = useState(SearchCfg.RESULTS_PER_PAGE);

const start: number = (page - 1) * numResultsPerPage;

const { data, loading, error } = useGetDataFlowChildJobsQuery({
variables: {
urn: properties.urn,
start,
count: numResultsPerPage,
},
});

const onChangePage = (newPage: number) => {
setPage(newPage);
};

const dataFlow = data && data?.dataFlow;
const dataJobs = dataFlow?.childJobs?.relationships.map((relationship) => relationship.entity);
const entityRegistry = useEntityRegistry();
const totalJobs = dataFlow?.childJobs?.total || 0;
const pageSize = data?.dataFlow?.childJobs?.count || 0;
const pageStart = data?.dataFlow?.childJobs?.start || 0;
const lastResultIndex = pageStart + pageSize > totalJobs ? totalJobs : pageStart + pageSize;
const title = `Contains ${totalJobs} ${
totalJobs === 1
? entityRegistry.getEntityName(EntityType.DataJob)
: entityRegistry.getCollectionName(EntityType.DataJob)
}`;
return <EntityList title={title} type={EntityType.DataJob} entities={dataJobs || []} />;
return (
<EntityList
title={title}
type={EntityType.DataJob}
entities={dataJobs || []}
showPagination
loading={loading}
error={error}
totalAssets={totalJobs}
page={page}
pageSize={numResultsPerPage}
lastResultIndex={lastResultIndex}
onChangePage={onChangePage}
setNumResultsPerPage={setNumResultsPerPage}
/>
);
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import React from 'react';
import { List } from 'antd';
import { List, Pagination, Typography } from 'antd';
import styled from 'styled-components';
import { useEntityRegistry } from '../../../../../useEntityRegistry';
import { PreviewType } from '../../../../Entity';
import { EntityType } from '../../../../../../types.generated';
import { SearchCfg } from '../../../../../../conf';
import { Message } from '../../../../../shared/Message';

const ScrollWrapper = styled.div`
overflow: auto;
max-height: 100%;
`;

const StyledList = styled(List)`
padding-left: 40px;
Expand All @@ -28,22 +35,90 @@ const StyledListItem = styled(List.Item)`
padding-top: 20px;
`;

const PaginationInfoContainer = styled.span`
padding: 8px;
padding-left: 16px;
border-top: 1px solid;
border-color: ${(props) => props.theme.styles['border-color-base']};
display: flex;
justify-content: space-between;
align-items: center;
`;

const StyledPagination = styled(Pagination)`
margin: 0px;
padding: 0px;
`;

const PaginationInfo = styled(Typography.Text)`
padding: 0px;
`;

type EntityListProps = {
type: EntityType;
entities: Array<any>;
title?: string;
totalAssets?: number;
pageSize?: any;
page?: number;
lastResultIndex?: any;
showPagination?: boolean;
loading?: boolean;
error?: any;
onChangePage?: (number: any) => void;
setNumResultsPerPage?: (number: any) => void;
};

export const EntityList = ({ type, entities, title }: EntityListProps) => {
export const EntityList = ({
type,
entities,
title,
totalAssets,
pageSize,
page,
lastResultIndex,
showPagination = false,
loading = false,
error = undefined,
onChangePage,
setNumResultsPerPage,
}: EntityListProps) => {
const entityRegistry = useEntityRegistry();

return (
<StyledList
bordered
dataSource={entities}
header={title || `${entities.length || 0} ${entityRegistry.getCollectionName(type)}`}
renderItem={(item) => (
<StyledListItem>{entityRegistry.renderPreview(type, PreviewType.PREVIEW, item)}</StyledListItem>
<>
<ScrollWrapper>
<StyledList
bordered
dataSource={entities}
header={title || `${entities.length || 0} ${entityRegistry.getCollectionName(type)}`}
renderItem={(item) => (
<StyledListItem>{entityRegistry.renderPreview(type, PreviewType.PREVIEW, item)}</StyledListItem>
)}
/>
</ScrollWrapper>
{loading && <Message type="loading" content="Loading..." style={{ marginTop: '10%' }} />}
{error && <Message type="error" content="Failed to load results! An unexpected error occurred." />}
{showPagination && (
<PaginationInfoContainer>
<PaginationInfo>
<b>
{lastResultIndex > 0 ? ((page as number) - 1) * pageSize + 1 : 0} - {lastResultIndex}
</b>{' '}
of <b>{totalAssets}</b>
</PaginationInfo>
<StyledPagination
current={page}
pageSize={pageSize}
total={totalAssets}
showLessItems
onChange={onChangePage}
showSizeChanger={(totalAssets as any) > SearchCfg.RESULTS_PER_PAGE}
onShowSizeChange={(_currNum, newNum) => setNumResultsPerPage?.(newNum)}
pageSizeOptions={['10', '20', '50', '100']}
/>
</PaginationInfoContainer>
)}
/>
</>
);
};
47 changes: 47 additions & 0 deletions datahub-web-react/src/graphql/dataFlow.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,53 @@ query getDataFlow($urn: String!) {
}
}

query getDataFlowChildJobs($urn: String!, $start: Int, $count: Int) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice! as a followup we can actually remove the childJobs that we're currently getting in the main dataflow query since we're getting it now when you open the tab

dataFlow(urn: $urn) {
...dataFlowFields
childJobs: relationships(input: { types: ["IsPartOf"], direction: INCOMING, start: $start, count: $count }) {
start
count
total
relationships {
entity {
... on DataJob {
urn
type
jobId
dataFlow {
urn
type
orchestrator
platform {
...platformFields
}
}
ownership {
...ownershipFields
}
properties {
name
description
}
editableProperties {
description
}
globalTags {
...globalTagsFields
}
glossaryTerms {
...glossaryTerms
}
deprecation {
...deprecationFields
}
}
}
}
}
}
}

mutation updateDataFlow($urn: String!, $input: DataFlowUpdateInput!) {
updateDataFlow(urn: $urn, input: $input) {
urn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ describe('schema blame', () => {
cy.contains('field_foo');
cy.contains('field_baz');
cy.contains('field_bar').should('not.exist');
cy.clickOptionWithText("field_foo");
cy.contains('Foo field description has changed');
cy.contains('Baz field description');
cy.clickOptionWithText("field_foo");
cy.get('[data-testid="schema-field-field_foo-tags"]').contains('Legacy');

// Make sure the schema blame is accurate
Expand Down
Loading