Skip to content

Commit

Permalink
Task additional information (#202)
Browse files Browse the repository at this point in the history
* feat: add workflow versions table

Signed-off-by: csirius <[email protected]>

* feat: add running status reasons

Signed-off-by: csirius <[email protected]>

* feat: add event handlers and code view for errors

Signed-off-by: csirius <[email protected]>

* fix: remove comments

Signed-off-by: csirius <[email protected]>
  • Loading branch information
govalt authored Sep 23, 2021
1 parent ef89c38 commit 6c8c39e
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,36 @@ import Tabs from '@material-ui/core/Tabs';
import Close from '@material-ui/icons/Close';
import * as classnames from 'classnames';
import { useCommonStyles } from 'components/common/styles';
import { InfoIcon } from 'components/common/Icons/InfoIcon';
import { ExecutionStatusBadge } from 'components/Executions/ExecutionStatusBadge';
import { LocationState } from 'components/hooks/useLocationState';
import { useTabState } from 'components/hooks/useTabState';
import { LocationDescriptor } from 'history';
import { NodeExecution, NodeExecutionIdentifier } from 'models/Execution/types';
import { PaginatedEntityResponse } from 'models/AdminEntity/types';
import {
NodeExecution,
NodeExecutionIdentifier,
TaskExecution
} from 'models/Execution/types';
import { TaskTemplate } from 'models/Task/types';
import * as React from 'react';
import Skeleton from 'react-loading-skeleton';
import { useQuery } from 'react-query';
import { Link as RouterLink } from 'react-router-dom';
import { Routes } from 'routes/routes';
import { NodeExecutionCacheStatus } from '../NodeExecutionCacheStatus';
import { makeNodeExecutionQuery } from '../nodeExecutionQueries';
import {
makeListTaskExecutionsQuery,
makeNodeExecutionQuery
} from '../nodeExecutionQueries';
import { TaskExecutionsList } from '../TaskExecutionsList/TaskExecutionsList';
import { NodeExecutionDetails } from '../types';
import { useNodeExecutionDetails } from '../useNodeExecutionDetails';
import { NodeExecutionInputs } from './NodeExecutionInputs';
import { NodeExecutionOutputs } from './NodeExecutionOutputs';
import { NodeExecutionTaskDetails } from './NodeExecutionTaskDetails';
import { getTaskExecutionDetailReasons } from './utils';
import { ExpandableMonospaceText } from '../../common/ExpandableMonospaceText';

const useStyles = makeStyles((theme: Theme) => {
const paddingVertical = `${theme.spacing(2)}px`;
Expand Down Expand Up @@ -74,6 +85,21 @@ const useStyles = makeStyles((theme: Theme) => {
alignItems: 'flex-start',
display: 'flex',
justifyContent: 'space-between'
},
statusContainer: {
display: 'flex',
flexDirection: 'column'
},
statusHeaderContainer: {
display: 'flex',
alignItems: 'center'
},
reasonsIcon: {
marginLeft: theme.spacing(1),
cursor: 'pointer'
},
statusBody: {
marginTop: theme.spacing(2)
}
};
});
Expand Down Expand Up @@ -198,15 +224,30 @@ export const NodeExecutionDetailsPanelContent: React.FC<NodeExecutionDetailsProp
nodeExecutionId,
onClose
}) => {
const [isReasonsVisible, setReasonsVisible] = React.useState(false);
const nodeExecutionQuery = useQuery<NodeExecution, Error>({
...makeNodeExecutionQuery(nodeExecutionId),
// The selected NodeExecution has been fetched at this point, we don't want to
// issue an additional fetch.
staleTime: Infinity
});

React.useEffect(() => {
setReasonsVisible(false);
}, [nodeExecutionId]);

const nodeExecution = nodeExecutionQuery.data;

const listTaskExecutionsQuery = useQuery<
PaginatedEntityResponse<TaskExecution>,
Error
>({
...makeListTaskExecutionsQuery(nodeExecutionId),
staleTime: Infinity
});

const reasons = getTaskExecutionDetailReasons(listTaskExecutionsQuery.data);

const commonStyles = useCommonStyles();
const styles = useStyles();
const detailsQuery = useNodeExecutionDetails(nodeExecution);
Expand All @@ -219,8 +260,40 @@ export const NodeExecutionDetailsPanelContent: React.FC<NodeExecutionDetailsProp
? detailsQuery.data.taskTemplate
: null;

const isRunningPhase = React.useMemo(() => {
return (
nodeExecution?.closure.phase === 1 ||
nodeExecution?.closure.phase === 2
);
}, [nodeExecution]);

const handleReasonsVisibility = React.useCallback(() => {
setReasonsVisible(prevVisibility => !prevVisibility);
}, []);

const statusContent = nodeExecution ? (
<ExecutionStatusBadge phase={nodeExecution.closure.phase} type="node" />
<div className={styles.statusContainer}>
<div className={styles.statusHeaderContainer}>
<ExecutionStatusBadge
phase={nodeExecution.closure.phase}
type="node"
/>
{isRunningPhase && (
<InfoIcon
className={styles.reasonsIcon}
onClick={handleReasonsVisibility}
/>
)}
</div>
{isRunningPhase && isReasonsVisible && (
<div className={styles.statusBody}>
<ExpandableMonospaceText
initialExpansionState={false}
text={reasons.join('\n')}
/>
</div>
)}
</div>
) : null;

const detailsContent = nodeExecution ? (
Expand Down
13 changes: 12 additions & 1 deletion src/components/Executions/ExecutionDetails/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Identifier, ResourceType } from 'models/Common/types';
import { Execution } from 'models/Execution/types';
import { Execution, TaskExecution } from 'models/Execution/types';
import { Routes } from 'routes/routes';
import { PaginatedEntityResponse } from 'models/AdminEntity/types';

export function isSingleTaskExecution(execution: Execution) {
return execution.spec.launchPlan.resourceType === ResourceType.TASK;
Expand All @@ -18,3 +19,13 @@ export function getExecutionBackLink(execution: Execution): string {
? Routes.TaskDetails.makeUrl(project, domain, name)
: Routes.WorkflowDetails.makeUrl(project, domain, name);
}

export function getTaskExecutionDetailReasons(
taskExecutionDetails?: PaginatedEntityResponse<TaskExecution>
): (string | null | undefined)[] {
return (
taskExecutionDetails?.entities.map(
taskExecution => taskExecution.closure.reason
) || []
);
}
18 changes: 16 additions & 2 deletions src/components/Executions/nodeExecutionQueries.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import { QueryInput, QueryType } from 'components/data/types';
import { useConditionalQuery } from 'components/hooks/useConditionalQuery';
import { isEqual } from 'lodash';
import { RequestConfig } from 'models/AdminEntity/types';
import {
PaginatedEntityResponse,
RequestConfig
} from 'models/AdminEntity/types';
import {
getNodeExecution,
listNodeExecutions,
listTaskExecutionChildren
listTaskExecutionChildren,
listTaskExecutions
} from 'models/Execution/api';
import { nodeExecutionQueryParams } from 'models/Execution/constants';
import {
NodeExecution,
NodeExecutionIdentifier,
TaskExecution,
TaskExecutionIdentifier,
WorkflowExecutionIdentifier
} from 'models/Execution/types';
Expand Down Expand Up @@ -45,6 +50,15 @@ export function makeNodeExecutionQuery(
};
}

export function makeListTaskExecutionsQuery(
id: NodeExecutionIdentifier
): QueryInput<PaginatedEntityResponse<TaskExecution>> {
return {
queryKey: [QueryType.TaskExecutionList, id],
queryFn: () => listTaskExecutions(id)
};
}

/** Composable fetch function which wraps `makeNodeExecutionQuery` */
export function fetchNodeExecution(
queryClient: QueryClient,
Expand Down
43 changes: 43 additions & 0 deletions src/components/common/Icons/InfoIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as React from 'react';
import { IconProps } from './interface';

export const InfoIcon: React.FC<IconProps> = ({
size = 14,
className,
onClick
}) => {
return (
<svg
className={className}
width={size}
height={size}
viewBox="0 0 14 14"
fill="none"
onClick={onClick}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M7 1.00024C10.3139 1.00024 13 3.68695 13 7.00024C13 10.3135 10.3139 13.0002 7 13.0002C3.6867 13.0002 1 10.3135 1 7.00024C1 3.68695 3.6867 1.00024 7 1.00024Z"
stroke="#2F49C6"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M6.99856 4.04517V7.48482"
stroke="#2F49C6"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M6.99858 9.95486H7.00636"
stroke="#2F49C6"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
};
5 changes: 5 additions & 0 deletions src/components/common/Icons/interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface IconProps {
size?: number;
className?: string;
onClick?: () => void;
}

0 comments on commit 6c8c39e

Please sign in to comment.