From d7cd1fcc1cbaf56765b87c1136df1613ac3ffb83 Mon Sep 17 00:00:00 2001 From: gaurav2733 <77378510+gaurav2733@users.noreply.github.com> Date: Fri, 19 Apr 2024 20:01:19 +0530 Subject: [PATCH] feat(ui/tasks): add pagination on tasks listing page (#10293) --- .../app/entity/dataFlow/DataFlowEntity.tsx | 3 + .../shared/tabs/Entity/DataFlowJobsTab.tsx | 53 ++++++++- .../tabs/Entity/components/EntityList.tsx | 108 ++++++++++++++++-- .../src/graphql/dataFlow.graphql | 30 +++-- .../cypress/e2e/schema_blame/schema_blame.js | 2 +- 5 files changed, 168 insertions(+), 28 deletions(-) diff --git a/datahub-web-react/src/app/entity/dataFlow/DataFlowEntity.tsx b/datahub-web-react/src/app/entity/dataFlow/DataFlowEntity.tsx index 25c1af09e7e5c8..fb5ea280087412 100644 --- a/datahub-web-react/src/app/entity/dataFlow/DataFlowEntity.tsx +++ b/datahub-web-react/src/app/entity/dataFlow/DataFlowEntity.tsx @@ -81,6 +81,9 @@ export class DataFlowEntity implements Entity { { name: 'Tasks', component: DataFlowJobsTab, + properties: { + urn, + }, }, { name: 'Incidents', diff --git a/datahub-web-react/src/app/entity/shared/tabs/Entity/DataFlowJobsTab.tsx b/datahub-web-react/src/app/entity/shared/tabs/Entity/DataFlowJobsTab.tsx index fe43ee7dc518a9..36e8c035c0d236 100644 --- a/datahub-web-react/src/app/entity/shared/tabs/Entity/DataFlowJobsTab.tsx +++ b/datahub-web-react/src/app/entity/shared/tabs/Entity/DataFlowJobsTab.tsx @@ -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 ; + return ( + + ); }; diff --git a/datahub-web-react/src/app/entity/shared/tabs/Entity/components/EntityList.tsx b/datahub-web-react/src/app/entity/shared/tabs/Entity/components/EntityList.tsx index 3a9061fd97d6e7..9e07e928be55e4 100644 --- a/datahub-web-react/src/app/entity/shared/tabs/Entity/components/EntityList.tsx +++ b/datahub-web-react/src/app/entity/shared/tabs/Entity/components/EntityList.tsx @@ -1,9 +1,27 @@ 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; + height: 100%; + + &::-webkit-scrollbar { + height: 12px; + width: 5px; + background: #f2f2f2; + } + &::-webkit-scrollbar-thumb { + background: #cccccc; + -webkit-border-radius: 1ex; + -webkit-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.75); + } +`; const StyledList = styled(List)` padding-left: 40px; @@ -28,22 +46,94 @@ 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)` + padding: 12px 12px 12px 12px; + width: 100%; + display: flex; + align-items: center; + justify-content: center; +`; + +const PaginationInfo = styled(Typography.Text)` + padding: 0px; + width: 20%; +`; + type EntityListProps = { type: EntityType; entities: Array; 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 ( - ( - {entityRegistry.renderPreview(type, PreviewType.PREVIEW, item)} + <> + + ( + {entityRegistry.renderPreview(type, PreviewType.PREVIEW, item)} + )} + /> + + {loading && } + {error && } + {showPagination && ( + + + + {lastResultIndex > 0 ? ((page as number) - 1) * pageSize + 1 : 0} - {lastResultIndex} + {' '} + of {totalAssets} + + SearchCfg.RESULTS_PER_PAGE} + onShowSizeChange={(_currNum, newNum) => setNumResultsPerPage?.(newNum)} + pageSizeOptions={['10', '20', '50', '100']} + /> + )} - /> + ); }; diff --git a/datahub-web-react/src/graphql/dataFlow.graphql b/datahub-web-react/src/graphql/dataFlow.graphql index e4284225e55b9a..2441ce600c3c55 100644 --- a/datahub-web-react/src/graphql/dataFlow.graphql +++ b/datahub-web-react/src/graphql/dataFlow.graphql @@ -70,7 +70,24 @@ query getDataFlow($urn: String!) { downstream: lineage(input: { direction: DOWNSTREAM, start: 0, count: 100 }) { ...partialLineageResults } - childJobs: relationships(input: { types: ["IsPartOf"], direction: INCOMING, start: 0, count: 100 }) { + autoRenderAspects: aspects(input: { autoRenderOnly: true }) { + ...autoRenderAspectFields + } + structuredProperties { + properties { + ...structuredPropertiesFields + } + } + forms { + ...formsFields + } + } +} + +query getDataFlowChildJobs($urn: String!, $start: Int, $count: Int) { + dataFlow(urn: $urn) { + ...dataFlowFields + childJobs: relationships(input: { types: ["IsPartOf"], direction: INCOMING, start: $start, count: $count }) { start count total @@ -111,17 +128,6 @@ query getDataFlow($urn: String!) { } } } - autoRenderAspects: aspects(input: { autoRenderOnly: true }) { - ...autoRenderAspectFields - } - structuredProperties { - properties { - ...structuredPropertiesFields - } - } - forms { - ...formsFields - } } } diff --git a/smoke-test/tests/cypress/cypress/e2e/schema_blame/schema_blame.js b/smoke-test/tests/cypress/cypress/e2e/schema_blame/schema_blame.js index 1ce1fbe900172a..2218cbd95cf9dd 100644 --- a/smoke-test/tests/cypress/cypress/e2e/schema_blame/schema_blame.js +++ b/smoke-test/tests/cypress/cypress/e2e/schema_blame/schema_blame.js @@ -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