mirror of
https://github.com/datahub-project/datahub.git
synced 2025-10-11 08:54:00 +00:00
feat(ui/ingestion): add pagination on ingestion executions (#10269)
This commit is contained in:
parent
f8ede9bcf7
commit
23e9e94f6c
@ -1,10 +1,31 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Empty } from 'antd';
|
import { Empty, Pagination, Typography } from 'antd';
|
||||||
|
import styled from 'styled-components';
|
||||||
import { StyledTable } from '../../../entity/shared/components/styled/StyledTable';
|
import { StyledTable } from '../../../entity/shared/components/styled/StyledTable';
|
||||||
import { ExecutionRequest } from '../../../../types.generated';
|
import { ExecutionRequest } from '../../../../types.generated';
|
||||||
import { ButtonsColumn, SourceColumn, StatusColumn, TimeColumn } from './IngestionExecutionTableColumns';
|
import { ButtonsColumn, SourceColumn, StatusColumn, TimeColumn } from './IngestionExecutionTableColumns';
|
||||||
import { SUCCESS } from '../utils';
|
import { SUCCESS } from '../utils';
|
||||||
import { formatDuration } from '../../../shared/formatDuration';
|
import { formatDuration } from '../../../shared/formatDuration';
|
||||||
|
import { SearchCfg } from '../../../../conf';
|
||||||
|
|
||||||
|
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;
|
||||||
|
`;
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
executionRequests: ExecutionRequest[];
|
executionRequests: ExecutionRequest[];
|
||||||
@ -12,14 +33,26 @@ interface Props {
|
|||||||
handleViewDetails: (urn: string) => void;
|
handleViewDetails: (urn: string) => void;
|
||||||
handleCancelExecution: (urn: string) => void;
|
handleCancelExecution: (urn: string) => void;
|
||||||
handleRollbackExecution: (runId: string) => void;
|
handleRollbackExecution: (runId: string) => void;
|
||||||
|
onChangePage: (number: any) => void;
|
||||||
|
setNumResultsPerPage: (number: any) => void;
|
||||||
|
totalExecution?: number | null;
|
||||||
|
page?: any;
|
||||||
|
pageSize?: any;
|
||||||
|
lastResultIndex?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function IngestionExecutionTable({
|
export default function IngestionExecutionTable({
|
||||||
executionRequests,
|
executionRequests,
|
||||||
|
onChangePage,
|
||||||
setFocusExecutionUrn,
|
setFocusExecutionUrn,
|
||||||
handleViewDetails,
|
handleViewDetails,
|
||||||
handleCancelExecution,
|
handleCancelExecution,
|
||||||
handleRollbackExecution,
|
handleRollbackExecution,
|
||||||
|
setNumResultsPerPage,
|
||||||
|
totalExecution,
|
||||||
|
pageSize,
|
||||||
|
lastResultIndex,
|
||||||
|
page,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const tableColumns = [
|
const tableColumns = [
|
||||||
{
|
{
|
||||||
@ -69,7 +102,8 @@ export default function IngestionExecutionTable({
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const mostRecentSuccessfulExecution = executionRequests.find((execution) => execution.result?.status === SUCCESS);
|
const mostRecentSuccessfulExecution =
|
||||||
|
page === 1 && executionRequests.find((execution) => execution.result?.status === SUCCESS);
|
||||||
|
|
||||||
const tableData = executionRequests.map((execution) => ({
|
const tableData = executionRequests.map((execution) => ({
|
||||||
urn: execution.urn,
|
urn: execution.urn,
|
||||||
@ -79,18 +113,38 @@ export default function IngestionExecutionTable({
|
|||||||
executedAt: execution.result?.startTimeMs,
|
executedAt: execution.result?.startTimeMs,
|
||||||
duration: execution.result?.durationMs,
|
duration: execution.result?.durationMs,
|
||||||
status: execution.result?.status,
|
status: execution.result?.status,
|
||||||
showRollback: execution.urn === mostRecentSuccessfulExecution?.urn,
|
showRollback: mostRecentSuccessfulExecution && execution?.urn === mostRecentSuccessfulExecution?.urn,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledTable
|
<>
|
||||||
columns={tableColumns}
|
<StyledTable
|
||||||
dataSource={tableData}
|
columns={tableColumns}
|
||||||
rowKey="id"
|
dataSource={tableData}
|
||||||
locale={{
|
rowKey="id"
|
||||||
emptyText: <Empty description="No Executions found!" image={Empty.PRESENTED_IMAGE_SIMPLE} />,
|
locale={{
|
||||||
}}
|
emptyText: <Empty description="No Executions found!" image={Empty.PRESENTED_IMAGE_SIMPLE} />,
|
||||||
pagination={false}
|
}}
|
||||||
/>
|
pagination={false}
|
||||||
|
/>
|
||||||
|
<PaginationInfoContainer>
|
||||||
|
<PaginationInfo>
|
||||||
|
<b>
|
||||||
|
{lastResultIndex > 0 ? (page - 1) * pageSize + 1 : 0} - {lastResultIndex}
|
||||||
|
</b>{' '}
|
||||||
|
of <b>{totalExecution}</b>
|
||||||
|
</PaginationInfo>
|
||||||
|
<StyledPagination
|
||||||
|
current={page}
|
||||||
|
pageSize={pageSize}
|
||||||
|
total={totalExecution as any}
|
||||||
|
showLessItems
|
||||||
|
onChange={onChangePage}
|
||||||
|
showSizeChanger={(totalExecution as any) > SearchCfg.RESULTS_PER_PAGE}
|
||||||
|
onShowSizeChange={(_currNum, newNum) => setNumResultsPerPage(newNum)}
|
||||||
|
pageSizeOptions={['10', '20', '50', '100']}
|
||||||
|
/>
|
||||||
|
</PaginationInfoContainer>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import IngestionExecutionTable from './IngestionExecutionTable';
|
|||||||
import { ExecutionRequest } from '../../../../types.generated';
|
import { ExecutionRequest } from '../../../../types.generated';
|
||||||
import { ROLLING_BACK, RUNNING } from '../utils';
|
import { ROLLING_BACK, RUNNING } from '../utils';
|
||||||
import useRefreshIngestionData from './useRefreshIngestionData';
|
import useRefreshIngestionData from './useRefreshIngestionData';
|
||||||
|
import { SearchCfg } from '../../../../conf';
|
||||||
|
|
||||||
const ListContainer = styled.div`
|
const ListContainer = styled.div`
|
||||||
margin-left: 28px;
|
margin-left: 28px;
|
||||||
@ -30,18 +31,23 @@ type Props = {
|
|||||||
|
|
||||||
export const IngestionSourceExecutionList = ({ urn, isExpanded, lastRefresh, onRefresh }: Props) => {
|
export const IngestionSourceExecutionList = ({ urn, isExpanded, lastRefresh, onRefresh }: Props) => {
|
||||||
const [focusExecutionUrn, setFocusExecutionUrn] = useState<undefined | string>(undefined);
|
const [focusExecutionUrn, setFocusExecutionUrn] = useState<undefined | string>(undefined);
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const [numResultsPerPage, setNumResultsPerPage] = useState(SearchCfg.RESULTS_PER_PAGE);
|
||||||
|
|
||||||
const start = 0;
|
const start: number = (page - 1) * numResultsPerPage;
|
||||||
const count = 10; // Load 10 items at a time.
|
|
||||||
|
|
||||||
const { loading, data, error, refetch } = useGetIngestionSourceQuery({
|
const { loading, data, error, refetch } = useGetIngestionSourceQuery({
|
||||||
variables: {
|
variables: {
|
||||||
urn,
|
urn,
|
||||||
runStart: start,
|
runStart: start,
|
||||||
runCount: count,
|
runCount: numResultsPerPage,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const onChangePage = (newPage: number) => {
|
||||||
|
setPage(newPage);
|
||||||
|
};
|
||||||
|
|
||||||
function hasActiveExecution() {
|
function hasActiveExecution() {
|
||||||
return !!data?.ingestionSource?.executions?.executionRequests.find((request) =>
|
return !!data?.ingestionSource?.executions?.executionRequests.find((request) =>
|
||||||
isExecutionRequestActive(request as ExecutionRequest),
|
isExecutionRequestActive(request as ExecutionRequest),
|
||||||
@ -139,6 +145,10 @@ export const IngestionSourceExecutionList = ({ urn, isExpanded, lastRefresh, onR
|
|||||||
}
|
}
|
||||||
|
|
||||||
const executionRequests = (data?.ingestionSource?.executions?.executionRequests as ExecutionRequest[]) || [];
|
const executionRequests = (data?.ingestionSource?.executions?.executionRequests as ExecutionRequest[]) || [];
|
||||||
|
const totalExecution = data?.ingestionSource?.executions?.total || 0;
|
||||||
|
const pageSize = data?.ingestionSource?.executions?.count || 0;
|
||||||
|
const pageStart = data?.ingestionSource?.executions?.start || 0;
|
||||||
|
const lastResultIndex = pageStart + pageSize > totalExecution ? totalExecution : pageStart + pageSize;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListContainer>
|
<ListContainer>
|
||||||
@ -147,11 +157,17 @@ export const IngestionSourceExecutionList = ({ urn, isExpanded, lastRefresh, onR
|
|||||||
<Message type="error" content="Failed to load ingestion executions! An unexpected error occurred." />
|
<Message type="error" content="Failed to load ingestion executions! An unexpected error occurred." />
|
||||||
)}
|
)}
|
||||||
<IngestionExecutionTable
|
<IngestionExecutionTable
|
||||||
|
onChangePage={onChangePage}
|
||||||
executionRequests={executionRequests}
|
executionRequests={executionRequests}
|
||||||
|
totalExecution={totalExecution}
|
||||||
|
page={page}
|
||||||
|
pageSize={numResultsPerPage}
|
||||||
|
lastResultIndex={lastResultIndex}
|
||||||
setFocusExecutionUrn={setFocusExecutionUrn}
|
setFocusExecutionUrn={setFocusExecutionUrn}
|
||||||
handleCancelExecution={handleCancelExecution}
|
handleCancelExecution={handleCancelExecution}
|
||||||
handleViewDetails={handleViewDetails}
|
handleViewDetails={handleViewDetails}
|
||||||
handleRollbackExecution={handleRollbackExecution}
|
handleRollbackExecution={handleRollbackExecution}
|
||||||
|
setNumResultsPerPage={setNumResultsPerPage}
|
||||||
/>
|
/>
|
||||||
{focusExecutionUrn && (
|
{focusExecutionUrn && (
|
||||||
<ExecutionDetailsModal
|
<ExecutionDetailsModal
|
||||||
|
Loading…
x
Reference in New Issue
Block a user