diff --git a/.storybook/preview.js b/.storybook/preview.js index 9d1ce00f98..1b2809c1a1 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -9,6 +9,11 @@ export const parameters = { date: /Date$/, }, }, + options: { + storySort: { + order: ['Primitives', 'Common'], + }, + }, }; export const decorators = [ diff --git a/jest.config.js b/jest.config.js index 77c3a88e65..e2bd7b7fb1 100644 --- a/jest.config.js +++ b/jest.config.js @@ -24,7 +24,7 @@ module.exports = { '/assetsTransformer.js', }, coverageDirectory: '.coverage', - collectCoverageFrom: ['**/*.{ts,tsx}'], + collectCoverageFrom: ['**/*.{ts,tsx}', '!**/*/*.stories.tsx'], coveragePathIgnorePatterns: [ '__stories__', '/.storybook', diff --git a/src/components/Errors/__stories__/DataError.stories.tsx b/src/components/Errors/__stories__/DataError.stories.tsx index d642bedce1..9a40e858a2 100644 --- a/src/components/Errors/__stories__/DataError.stories.tsx +++ b/src/components/Errors/__stories__/DataError.stories.tsx @@ -7,7 +7,7 @@ import { DataError } from '../DataError'; const retryAction = action('retry'); -const stories = storiesOf('Errors/DataError', module); +const stories = storiesOf('Common/DataError', module); stories.add('Title Only', () => ( )); diff --git a/src/components/Executions/ExecutionDetails/ExecutionNodeViews.tsx b/src/components/Executions/ExecutionDetails/ExecutionNodeViews.tsx index e2d0f7b432..2a8afdd494 100644 --- a/src/components/Executions/ExecutionDetails/ExecutionNodeViews.tsx +++ b/src/components/Executions/ExecutionDetails/ExecutionNodeViews.tsx @@ -1,15 +1,11 @@ import * as React from 'react'; import { Tab, Tabs } from '@material-ui/core'; import { makeStyles, Theme } from '@material-ui/core/styles'; -import { noop } from 'lodash'; - -import { FeatureFlag, useFeatureFlag } from 'basics/FeatureFlags'; import { WaitForQuery } from 'components/common/WaitForQuery'; import { DataError } from 'components/Errors/DataError'; import { useTabState } from 'components/hooks/useTabState'; import { secondaryBackgroundColor } from 'components/Theme/constants'; import { Execution, NodeExecution } from 'models/Execution/types'; -import { LocalCacheItem, useLocalCache } from 'basics/LocalCache'; import { NodeExecutionDetailsContextProvider } from '../contextProvider/NodeExecutionDetails'; import { NodeExecutionsRequestConfigContext } from '../contexts'; import { ExecutionFilters } from '../ExecutionFilters'; diff --git a/src/components/Executions/Tables/__stories__/NodeExecutionsTable.stories.tsx b/src/components/Executions/Tables/__stories__/NodeExecutionsTable.stories.tsx index a4b80d30a3..c7a683023f 100644 --- a/src/components/Executions/Tables/__stories__/NodeExecutionsTable.stories.tsx +++ b/src/components/Executions/Tables/__stories__/NodeExecutionsTable.stories.tsx @@ -2,6 +2,7 @@ import { makeStyles, Theme } from '@material-ui/core/styles'; import { storiesOf } from '@storybook/react'; import { NodeExecutionDetailsContext } from 'components/Executions/contextProvider/NodeExecutionDetails'; import { makeNodeExecutionListQuery } from 'components/Executions/nodeExecutionQueries'; +import { NodeExecutionDisplayType } from 'components/Executions/types'; import { basicPythonWorkflow } from 'mocks/data/fixtures/basicPythonWorkflow'; import * as React from 'react'; import { useQuery, useQueryClient } from 'react-query'; @@ -26,7 +27,7 @@ const getNodeExecutionDetails = async () => { return { displayId: 'node0', displayName: 'basic.byton.workflow.unique.task_name', - displayType: 'Python-Task', + displayType: NodeExecutionDisplayType.PythonTask, }; }; diff --git a/src/components/Executions/TaskExecutionsList/TaskExecutionLogs.tsx b/src/components/Executions/TaskExecutionsList/TaskExecutionLogs.tsx index c948477832..f8b298d575 100644 --- a/src/components/Executions/TaskExecutionsList/TaskExecutionLogs.tsx +++ b/src/components/Executions/TaskExecutionsList/TaskExecutionLogs.tsx @@ -1,10 +1,9 @@ +import * as React from 'react'; import { Typography } from '@material-ui/core'; import { makeStyles, Theme } from '@material-ui/core/styles'; import { NewTargetLink } from 'components/common/NewTargetLink'; import { useCommonStyles } from 'components/common/styles'; import { TaskLog } from 'models/Common/types'; -import { TaskExecution } from 'models/Execution/types'; -import * as React from 'react'; import { noLogsFoundString } from '../constants'; const useStyles = makeStyles((theme: Theme) => ({ @@ -33,19 +32,17 @@ const TaskLogList: React.FC<{ logs: TaskLog[] }> = ({ logs }) => { ); }; -/** Renders log links from a `TaskExecution`, if they exist. Otherwise renders - * a message indicating that no logs are available. +/** Renders log links from a `taskLogs`(aka taskExecution.closure.logs), if they exist. + * Otherwise renders a message indicating that no logs are available. */ -export const TaskExecutionLogs: React.FC<{ taskExecution: TaskExecution }> = ({ - taskExecution, -}) => { +export const TaskExecutionLogs: React.FC<{ taskLogs: TaskLog[] }> = ({ taskLogs }) => { const styles = useStyles(); return (
Logs
- +
); }; diff --git a/src/components/Executions/TaskExecutionsList/TaskExecutionsListItem.tsx b/src/components/Executions/TaskExecutionsList/TaskExecutionsListItem.tsx index 26b6e3949b..c6f73c5f71 100644 --- a/src/components/Executions/TaskExecutionsList/TaskExecutionsListItem.tsx +++ b/src/components/Executions/TaskExecutionsList/TaskExecutionsListItem.tsx @@ -63,7 +63,7 @@ export const TaskExecutionsListItem: React.FC = ({ {taskHasStarted && ( <>
- +
diff --git a/src/components/Executions/constants.ts b/src/components/Executions/constants.ts index f11b9960f4..4af6a7c009 100644 --- a/src/components/Executions/constants.ts +++ b/src/components/Executions/constants.ts @@ -182,7 +182,7 @@ export const taskExecutionPhaseConstants: { export const taskTypeToNodeExecutionDisplayType: { [k in TaskType]: NodeExecutionDisplayType; } = { - [TaskType.ARRAY]: NodeExecutionDisplayType.ArrayTask, + [TaskType.ARRAY]: NodeExecutionDisplayType.MapTask, [TaskType.BATCH_HIVE]: NodeExecutionDisplayType.BatchHiveTask, [TaskType.DYNAMIC]: NodeExecutionDisplayType.DynamicTask, [TaskType.HIVE]: NodeExecutionDisplayType.HiveTask, @@ -192,6 +192,8 @@ export const taskTypeToNodeExecutionDisplayType: { [TaskType.UNKNOWN]: NodeExecutionDisplayType.UnknownTask, [TaskType.WAITABLE]: NodeExecutionDisplayType.WaitableTask, [TaskType.MPI]: NodeExecutionDisplayType.MpiTask, + [TaskType.ARRAY_AWS]: NodeExecutionDisplayType.ARRAY_AWS, + [TaskType.ARRAY_K8S]: NodeExecutionDisplayType.ARRAY_K8S, }; export const cacheStatusMessages: { [k in Core.CatalogCacheStatus]: string } = { diff --git a/src/components/Executions/contextProvider/NodeExecutionDetails/createExecutionArray.tsx b/src/components/Executions/contextProvider/NodeExecutionDetails/createExecutionArray.tsx index 5fd7638fe1..ef4a29f40a 100644 --- a/src/components/Executions/contextProvider/NodeExecutionDetails/createExecutionArray.tsx +++ b/src/components/Executions/contextProvider/NodeExecutionDetails/createExecutionArray.tsx @@ -1,4 +1,5 @@ import { transformerWorkflowToDag } from 'components/WorkflowGraph/transformerWorkflowToDag'; +import { getTaskDisplayType } from 'components/Executions/utils'; import { NodeExecutionDetails, NodeExecutionDisplayType } from 'components/Executions/types'; import { Workflow } from 'models/Workflow/types'; import { Identifier } from 'models/Common/types'; @@ -37,11 +38,13 @@ const getNodeDetails = (node: dNode, tasks: CompiledTask[]): NodeExecutionInfo = if (node.value.taskNode) { const templateName = node.value.taskNode.referenceId.name ?? node.name; const task = tasks.find((t) => t.template.id.name === templateName); + const taskType = getTaskDisplayType(task?.template.type); + return { scopedId: node.scopedId, displayId: node.value.id ?? node.id, displayName: templateName, - displayType: task?.template.type ?? NodeExecutionDisplayType.UnknownTask, + displayType: taskType, taskTemplate: task?.template, }; } diff --git a/src/components/Executions/contextProvider/NodeExecutionDetails/getTaskThroughExecution.ts b/src/components/Executions/contextProvider/NodeExecutionDetails/getTaskThroughExecution.ts index f5a40a6d3a..47b16bfc5e 100644 --- a/src/components/Executions/contextProvider/NodeExecutionDetails/getTaskThroughExecution.ts +++ b/src/components/Executions/contextProvider/NodeExecutionDetails/getTaskThroughExecution.ts @@ -1,5 +1,6 @@ +import { getTaskDisplayType } from 'components/Executions/utils'; import { fetchTaskExecutionList } from 'components/Executions/taskExecutionQueries'; -import { NodeExecutionDetails, NodeExecutionDisplayType } from 'components/Executions/types'; +import { NodeExecutionDetails } from 'components/Executions/types'; import { fetchTaskTemplate } from 'components/Task/taskQueries'; import { NodeExecution } from 'models/Execution/types'; import { TaskTemplate } from 'models/Task/types'; @@ -15,6 +16,7 @@ export const getTaskThroughExecution = async ( if (taskExecutions && taskExecutions.length > 0) { taskTemplate = await fetchTaskTemplate(queryClient, taskExecutions[0].id.taskId); if (!taskTemplate) { + // eslint-disable-next-line no-console console.error( `ERROR: Unexpected missing task template while fetching NodeExecution details: ${JSON.stringify( taskExecutions[0].id.taskId, @@ -26,7 +28,7 @@ export const getTaskThroughExecution = async ( const taskDetails: NodeExecutionDetails = { displayId: nodeExecution.id.nodeId, displayName: taskExecutions?.[0]?.id.taskId.name, - displayType: taskTemplate?.type ?? NodeExecutionDisplayType.Unknown, + displayType: getTaskDisplayType(taskTemplate?.type), taskTemplate: taskTemplate, }; diff --git a/src/components/Executions/types.ts b/src/components/Executions/types.ts index f076138c07..35791f7c4c 100644 --- a/src/components/Executions/types.ts +++ b/src/components/Executions/types.ts @@ -13,7 +13,7 @@ export interface ExecutionPhaseConstants { } export enum NodeExecutionDisplayType { - ArrayTask = 'Array Task', + MapTask = 'Map Task', BatchHiveTask = 'Hive Batch Task', BranchNode = 'Branch Node', DynamicTask = 'Dynamic Task', @@ -26,6 +26,9 @@ export enum NodeExecutionDisplayType { UnknownTask = 'Unknown Task', WaitableTask = 'Waitable Task', MpiTask = 'MPI Task', + // plugins + ARRAY_AWS = 'AWS Map Task', + ARRAY_K8S = 'K8S Map Task', } export interface ParentNodeExecution extends NodeExecution { diff --git a/src/components/Executions/utils.ts b/src/components/Executions/utils.ts index 35af7dfb49..31c1fa3408 100644 --- a/src/components/Executions/utils.ts +++ b/src/components/Executions/utils.ts @@ -21,9 +21,10 @@ import { CompiledNode } from 'models/Node/types'; import { nodeExecutionPhaseConstants, taskExecutionPhaseConstants, + taskTypeToNodeExecutionDisplayType, workflowExecutionPhaseConstants, } from './constants'; -import { ExecutionPhaseConstants, ParentNodeExecution } from './types'; +import { ExecutionPhaseConstants, NodeExecutionDisplayType, ParentNodeExecution } from './types'; /** Given an execution phase, returns a set of constants (i.e. color, display * string) used to represent it in various UI components. @@ -55,6 +56,17 @@ export function getTaskExecutionPhaseConstants(phase: TaskExecutionPhase): Execu ); } +/** + * Transforms taskType value to more convinient readable display Type + */ +export function getTaskDisplayType(taskType?: string): string { + if (taskType) { + return taskTypeToNodeExecutionDisplayType[taskType] ?? taskType; + } + + return NodeExecutionDisplayType.Unknown; +} + /** Determines if a workflow execution can be considered finalized and will not * change state again. */ diff --git a/src/components/Notifications/__stories__/SystemStatusBanner.stories.tsx b/src/components/Notifications/__stories__/SystemStatusBanner.stories.tsx index 74a224468a..3072a99291 100644 --- a/src/components/Notifications/__stories__/SystemStatusBanner.stories.tsx +++ b/src/components/Notifications/__stories__/SystemStatusBanner.stories.tsx @@ -32,7 +32,7 @@ const renderBanner = (status: SystemStatus) => ( ); -const stories = storiesOf('Notifications/SystemStatusBanner', module); +const stories = storiesOf('Common/SystemStatusBanner', module); stories.add('Normal Status', () => renderBanner(normalStatus)); stories.add('Degraded Status', () => renderBanner(degradedStatus)); stories.add('Down Status', () => renderBanner(downStatus)); diff --git a/src/components/Theme/constants.ts b/src/components/Theme/constants.ts index aa566cb346..d1970816e7 100644 --- a/src/components/Theme/constants.ts +++ b/src/components/Theme/constants.ts @@ -58,16 +58,19 @@ export const statusColors = { export type TaskColorMap = Record; export const taskColors: TaskColorMap = { + [TaskType.PYTHON]: '#7157D9', + [TaskType.SPARK]: '#00B3A4', + [TaskType.MPI]: '#00B3A4', [TaskType.BATCH_HIVE]: '#E1E8ED', [TaskType.DYNAMIC]: '#E1E8ED', [TaskType.HIVE]: '#E1E8ED', - [TaskType.PYTHON]: '#7157D9', - [TaskType.SPARK]: '#00B3A4', - [TaskType.ARRAY]: '#E1E8ED', [TaskType.SIDECAR]: '#E1E8ED', [TaskType.UNKNOWN]: '#E1E8ED', [TaskType.WAITABLE]: '#E1E8ED', - [TaskType.MPI]: '#00B3A4', + [TaskType.ARRAY]: '#E1E8ED', + // plugins + [TaskType.ARRAY_AWS]: '#E1E8ED', + [TaskType.ARRAY_K8S]: '#E1E8ED', }; export const bodyFontSize = '0.875rem'; diff --git a/src/components/WorkflowGraph/WorkflowGraph.tsx b/src/components/WorkflowGraph/WorkflowGraph.tsx index e3b965c30a..ffd9b1bc35 100644 --- a/src/components/WorkflowGraph/WorkflowGraph.tsx +++ b/src/components/WorkflowGraph/WorkflowGraph.tsx @@ -9,7 +9,7 @@ import { NodeExecutionsContext } from 'components/Executions/contexts'; import { WaitForQuery } from 'components/common/WaitForQuery'; import { useQuery, useQueryClient } from 'react-query'; import { makeNodeExecutionDynamicWorkflowQuery } from 'components/Workflow/workflowQueries'; -import { createDebugLogger } from 'components/flytegraph/utils'; +import { createDebugLogger } from 'common/log'; import { CompiledNode } from 'models/Node/types'; import { transformerWorkflowToDag } from './transformerWorkflowToDag'; diff --git a/src/components/WorkflowGraph/transformerWorkflowToDag.tsx b/src/components/WorkflowGraph/transformerWorkflowToDag.tsx index b5d7080090..81cf411b30 100644 --- a/src/components/WorkflowGraph/transformerWorkflowToDag.tsx +++ b/src/components/WorkflowGraph/transformerWorkflowToDag.tsx @@ -1,5 +1,5 @@ import { DISPLAY_NAME_END, DISPLAY_NAME_START } from 'components/flytegraph/ReactFlow/utils'; -import { createDebugLogger } from 'components/flytegraph/utils'; +import { createDebugLogger } from 'common/log'; import { dTypes, dEdge, dNode } from 'models/Graph/types'; import { startNodeId, endNodeId } from 'models/Node/constants'; import { CompiledNode, ConnectionSet, TaskNode } from 'models/Node/types'; diff --git a/src/components/common/MapTaskExecutionsList/MapTaskStatusInfo.stories.tsx b/src/components/common/MapTaskExecutionsList/MapTaskStatusInfo.stories.tsx new file mode 100644 index 0000000000..4ea05d9975 --- /dev/null +++ b/src/components/common/MapTaskExecutionsList/MapTaskStatusInfo.stories.tsx @@ -0,0 +1,35 @@ +import * as React from 'react'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; +import { NodeExecutionPhase } from 'models/Execution/enums'; +import { MapTaskStatusInfo } from './MapTaskStatusInfo'; +import { PanelViewDecorator } from '../__stories__/Decorators'; + +export default { + title: 'Common/MapTaskExecutionList/MapTaskStatusInfo', + component: MapTaskStatusInfo, + parameters: { actions: { argTypesRegex: 'toggleExpanded' } }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Default = Template.bind({}); +Default.decorators = [(Story) => PanelViewDecorator(Story)]; +Default.args = { + taskLogs: [ + { uri: '#', name: 'Kubernetes Logs #0-0' }, + { uri: '#', name: 'Kubernetes Logs #0-1' }, + { uri: '#', name: 'Kubernetes Logs #0-2' }, + { uri: '#', name: 'Kubernetes Logs #0-3' }, + { uri: '#', name: 'Kubernetes Logs #0-4' }, + ], + status: NodeExecutionPhase.QUEUED, + expanded: true, +}; + +export const AllSpace = Template.bind({}); +AllSpace.args = { + taskLogs: [], + status: NodeExecutionPhase.SUCCEEDED, +}; diff --git a/src/components/common/MapTaskExecutionsList/MapTaskStatusInfo.test.tsx b/src/components/common/MapTaskExecutionsList/MapTaskStatusInfo.test.tsx new file mode 100644 index 0000000000..768535f50a --- /dev/null +++ b/src/components/common/MapTaskExecutionsList/MapTaskStatusInfo.test.tsx @@ -0,0 +1,48 @@ +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { noLogsFoundString } from 'components/Executions/constants'; +import { getNodeExecutionPhaseConstants } from 'components/Executions/utils'; +import { NodeExecutionPhase } from 'models/Execution/enums'; +import * as React from 'react'; + +import { MapTaskStatusInfo } from './MapTaskStatusInfo'; + +const taskLogs = [ + { uri: '#', name: 'Kubernetes Logs #0-0' }, + { uri: '#', name: 'Kubernetes Logs #0-1' }, + { uri: '#', name: 'Kubernetes Logs #0-2' }, +]; + +describe('MapTaskStatusInfo', () => { + it('Phase and amount of links rendered correctly', async () => { + const status = NodeExecutionPhase.RUNNING; + const phaseData = getNodeExecutionPhaseConstants(status); + + const { queryByText, getByTitle } = render( + , + ); + + expect(queryByText(phaseData.text)).toBeInTheDocument(); + expect(queryByText(`x${taskLogs.length}`)).toBeInTheDocument(); + expect(queryByText('Logs')).not.toBeInTheDocument(); + + // Expand item - see logs section + const buttonEl = getByTitle('Expand row'); + fireEvent.click(buttonEl); + await waitFor(() => { + expect(queryByText('Logs')).toBeInTheDocument(); + }); + }); + + it('Phase with no links show proper texts when opened', () => { + const status = NodeExecutionPhase.ABORTED; + const phaseData = getNodeExecutionPhaseConstants(status); + + const { queryByText } = render( + , + ); + + expect(queryByText(phaseData.text)).toBeInTheDocument(); + expect(queryByText(`x0`)).toBeInTheDocument(); + expect(queryByText(noLogsFoundString)).toBeInTheDocument(); + }); +}); diff --git a/src/components/common/MapTaskExecutionsList/MapTaskStatusInfo.tsx b/src/components/common/MapTaskExecutionsList/MapTaskStatusInfo.tsx new file mode 100644 index 0000000000..451fbac296 --- /dev/null +++ b/src/components/common/MapTaskExecutionsList/MapTaskStatusInfo.tsx @@ -0,0 +1,70 @@ +import * as React from 'react'; +import { useState } from 'react'; +import { makeStyles, Theme } from '@material-ui/core/styles'; +import { RowExpander } from 'components/Executions/Tables/RowExpander'; +import { NodeExecutionPhase } from 'models/Execution/enums'; +import { getNodeExecutionPhaseConstants } from 'components/Executions/utils'; +import { Typography } from '@material-ui/core'; +import { TaskExecutionLogs } from 'components/Executions/TaskExecutionsList/TaskExecutionLogs'; +import { TaskLog } from 'models/Common/types'; + +const useStyles = makeStyles((_theme: Theme) => ({ + mainWrapper: { + display: 'flex', + flex: 1, + flexDirection: 'column', + }, + headerWrapper: { + display: 'flex', + flex: 'auto', + alignItems: 'center', + }, + colorBar: { + height: '20px', + borderLeft: 'solid 4px red', + margin: '0 8px 0 4px', + }, + title: { + flex: 'auto', + }, + logs: { + marginLeft: '46px', + }, + semiboldText: { + fontWeight: 600, + }, +})); + +interface MapTaskStatusInfoProps { + taskLogs: TaskLog[]; + status: NodeExecutionPhase; + expanded: boolean; +} + +export const MapTaskStatusInfo = (props: MapTaskStatusInfoProps) => { + const [expanded, setExpanded] = useState(props.expanded); + const styles = useStyles(); + + const toggleExpanded = () => { + setExpanded(!expanded); + }; + + const phaseData = getNodeExecutionPhaseConstants(props.status); + return ( +
+
+ +
+ + {phaseData.text} + + {`x${props.taskLogs.length}`} +
+ {expanded && ( +
+ +
+ )} +
+ ); +}; diff --git a/src/components/common/__stories__/Decorators.tsx b/src/components/common/__stories__/Decorators.tsx new file mode 100644 index 0000000000..362dccd341 --- /dev/null +++ b/src/components/common/__stories__/Decorators.tsx @@ -0,0 +1,17 @@ +import * as React from 'react'; + +const PANEL_VIEW = '320px'; + +export function PanelViewDecorator(Story: any) { + return ( +
+
+ Panel View + {PANEL_VIEW} +
+
+ +
+
+ ); +} diff --git a/src/components/common/__stories__/Typography.stories.tsx b/src/components/common/__stories__/Typography.stories.tsx new file mode 100644 index 0000000000..8601cedca5 --- /dev/null +++ b/src/components/common/__stories__/Typography.stories.tsx @@ -0,0 +1,17 @@ +import * as React from 'react'; +import { storiesOf } from '@storybook/react'; +import Typography from '@material-ui/core/Typography'; + +const stories = storiesOf('Primitives/Material UI', module); +stories.add('Typography', () => ( +
+ H5 - Biggest header, not that we use it yet + H6 - Most used header + + body 1 - for regular text + body 2 - looks like the same as body1? + + Subtitle1 - just some text for visibility + Overline - with some real text +
+)); diff --git a/src/components/flytegraph/ReactFlow/ReactFlowGraphComponent.tsx b/src/components/flytegraph/ReactFlow/ReactFlowGraphComponent.tsx index 4c41ab797d..1d8c2096a4 100644 --- a/src/components/flytegraph/ReactFlow/ReactFlowGraphComponent.tsx +++ b/src/components/flytegraph/ReactFlow/ReactFlowGraphComponent.tsx @@ -1,11 +1,11 @@ import * as React from 'react'; -import { ConvertFlyteDagToReactFlows } from 'components/flytegraph/ReactFlow/transformDAGToReactFlowV2'; import { useState, useEffect } from 'react'; +import { ConvertFlyteDagToReactFlows } from 'components/flytegraph/ReactFlow/transformDAGToReactFlowV2'; +import { createDebugLogger } from 'common/log'; import { RFWrapperProps, RFGraphTypes, ConvertDagProps } from './types'; import { getRFBackground } from './utils'; import { ReactFlowWrapper } from './ReactFlowWrapper'; import { Legend } from './NodeStatusLegend'; -import { createDebugLogger } from '../utils'; const debug = createDebugLogger('@ReactFlowGraphComponent'); diff --git a/src/components/flytegraph/ReactFlow/ReactFlowWrapper.tsx b/src/components/flytegraph/ReactFlow/ReactFlowWrapper.tsx index 262fb82b38..d905e98564 100644 --- a/src/components/flytegraph/ReactFlow/ReactFlowWrapper.tsx +++ b/src/components/flytegraph/ReactFlow/ReactFlowWrapper.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { useState, useEffect, useCallback } from 'react'; import ReactFlow, { Background } from 'react-flow-renderer'; +import { createDebugLogger } from 'common/log'; import { RFWrapperProps } from './types'; import { ReactFlowCustomEndNode, @@ -13,7 +14,6 @@ import { ReactFlowStaticNode, } from './customNodeComponents'; import { getPositionedNodes, ReactFlowIdHash } from './utils'; -import { createDebugLogger } from '../utils'; const debug = createDebugLogger('@ReactFlowWrapper'); diff --git a/src/components/flytegraph/ReactFlow/transformDAGToReactFlowV2.tsx b/src/components/flytegraph/ReactFlow/transformDAGToReactFlowV2.tsx index 0ceb07730e..9da480b515 100644 --- a/src/components/flytegraph/ReactFlow/transformDAGToReactFlowV2.tsx +++ b/src/components/flytegraph/ReactFlow/transformDAGToReactFlowV2.tsx @@ -1,9 +1,9 @@ import { dEdge, dNode, dTypes } from 'models/Graph/types'; import { Edge, Node, Position } from 'react-flow-renderer'; import { NodeExecutionPhase } from 'models/Execution/enums'; +import { createDebugLogger } from 'common/log'; import { ReactFlowGraphConfig } from './utils'; import { ConvertDagProps } from './types'; -import { createDebugLogger } from '../utils'; interface rfNode extends Node { isRootParentNode?: boolean; diff --git a/src/components/flytegraph/constants.ts b/src/components/flytegraph/constants.ts index 6916edbab9..9f15cd774b 100644 --- a/src/components/flytegraph/constants.ts +++ b/src/components/flytegraph/constants.ts @@ -1,6 +1,3 @@ -import { colors } from './theme'; -import { GraphConfig } from './types'; - export const componentIds = { arrowhead: 'arrowhead', }; @@ -12,22 +9,3 @@ export const layoutSize = 1000; // Adjusts the amount of room between edges of adjacent nodes. // Greater values lead to more space. export const nodeSpacingMultiplier = 1.5; - -export const defaultGraphConfig: GraphConfig = { - node: { - cornerRounding: 10, - fillColor: colors.white, - fontSize: 14, - selectStrokeColor: colors.blue, - selectStrokeWidth: 4, - strokeColor: colors.darkGray1, - strokeWidth: 2, - textPadding: 10, - }, - nodeLink: { - strokeColor: colors.gray4, - strokeWidth: 1, - }, -}; - -export const logPrefix = 'flytegraph'; diff --git a/src/components/flytegraph/layoutUtils.ts b/src/components/flytegraph/layoutUtils.ts index 92f641b590..7cc6647eb7 100644 --- a/src/components/flytegraph/layoutUtils.ts +++ b/src/components/flytegraph/layoutUtils.ts @@ -1,9 +1,10 @@ import * as d3 from 'd3-dag'; import { cloneDeep } from 'lodash'; +import { createDebugLogger } from 'common/log'; import { layoutSize, nodeSpacingMultiplier } from './constants'; import { createTimer } from './timer'; import { GraphConfig, GraphInputNode, GraphLayoutResult, RenderableNode } from './types'; -import { createDebugLogger, groupBy } from './utils'; +import { groupBy } from './utils'; const log = createDebugLogger('layout'); diff --git a/src/components/flytegraph/utils.ts b/src/components/flytegraph/utils.ts index 98f46bfd07..f8b58855b6 100644 --- a/src/components/flytegraph/utils.ts +++ b/src/components/flytegraph/utils.ts @@ -1,9 +1,5 @@ -import debug from 'debug'; -import { logPrefix } from './constants'; import { Point } from './types'; -export const createDebugLogger = (namespace: string) => debug(`${logPrefix}:${namespace}`); - /** Simple helper to get the midpoint between two points a & b */ export function getMidpoint(a: Point, b: Point) { return { diff --git a/src/models/Task/constants.ts b/src/models/Task/constants.ts index a9ffcc8ef1..110dfe54c1 100644 --- a/src/models/Task/constants.ts +++ b/src/models/Task/constants.ts @@ -12,6 +12,10 @@ export enum TaskType { UNKNOWN = 'unknown', WAITABLE = 'waitable', MPI = 'mpi', + + // plugins + ARRAY_AWS = 'aws-batch', + ARRAY_K8S = 'k8s-array', } export const taskSortFields = { diff --git a/src/models/Task/task.test.ts b/src/models/Task/task.test.ts new file mode 100644 index 0000000000..3d68720298 --- /dev/null +++ b/src/models/Task/task.test.ts @@ -0,0 +1,17 @@ +import { TaskType } from './constants'; +import { isMapTaskType } from './utils'; + +describe('models/Task', () => { + it('isMapTaskType propely identifies mapped tasks', async () => { + // when no task is provided - to be false + expect(isMapTaskType()).toBeFalsy(); + + // when mapped task is provided - to be true + expect(isMapTaskType(TaskType.ARRAY)).toBeTruthy(); + expect(isMapTaskType(TaskType.ARRAY_AWS)).toBeTruthy(); + expect(isMapTaskType(TaskType.ARRAY_K8S)).toBeTruthy(); + + // when regular task is provided - to be false + expect(isMapTaskType(TaskType.PYTHON)).toBeFalsy(); + }); +}); diff --git a/src/models/Task/utils.ts b/src/models/Task/utils.ts index 5053415c20..40af208498 100644 --- a/src/models/Task/utils.ts +++ b/src/models/Task/utils.ts @@ -3,6 +3,7 @@ import { createPaginationTransformer } from 'models/AdminEntity/utils'; import { endpointPrefixes } from 'models/Common/constants'; import { IdentifierScope } from 'models/Common/types'; import { makeIdentifierPath } from 'models/Common/utils'; +import { TaskType } from './constants'; import { Task } from './types'; /** Generate the correct path for retrieving a task or list of tasks based on the @@ -14,3 +15,12 @@ export function makeTaskPath(scope: IdentifierScope) { /** Transformer to coerce an `Admin.TaskList` into a standard shape */ export const taskListTransformer = createPaginationTransformer('tasks'); + +/** Returns true if tasks schema is treated as a map task */ +export function isMapTaskType(taskType?: string): boolean { + return ( + taskType === TaskType.ARRAY || + taskType === TaskType.ARRAY_AWS || + taskType === TaskType.ARRAY_K8S + ); +}