Skip to content

Commit

Permalink
chore: fix breadcrumbs
Browse files Browse the repository at this point in the history
Signed-off-by: Carina Ursu <[email protected]>
  • Loading branch information
ursucarina committed Apr 6, 2023
1 parent 730a04b commit bc8573d
Show file tree
Hide file tree
Showing 5 changed files with 314 additions and 157 deletions.
17 changes: 10 additions & 7 deletions packages/console/src/components/WorkflowGraph/WorkflowGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { NonIdealState } from 'components/common/NonIdealState';
import { CompiledNode } from 'models/Node/types';
import { dNode } from 'models/Graph/types';
import { useDetailsPanel } from 'components/Executions/ExecutionDetails/DetailsPanelContext';
import { ReactFlowBreadCrumbProvider } from 'components/flytegraph/ReactFlow/ReactFlowBreadCrumbProvider';
import t from './strings';

export interface DynamicWorkflowMapping {
Expand Down Expand Up @@ -43,12 +44,14 @@ export const WorkflowGraph: React.FC<WorkflowGraphProps> = ({
}

return (
<ReactFlowGraphComponent
data={mergedDag}
onNodeSelectionChanged={onNodeSelectionChanged}
onPhaseSelectionChanged={setSelectedPhase}
selectedPhase={selectedPhase}
initialNodes={initialNodes}
/>
<ReactFlowBreadCrumbProvider>
<ReactFlowGraphComponent
data={mergedDag}
onNodeSelectionChanged={onNodeSelectionChanged}
onPhaseSelectionChanged={setSelectedPhase}
selectedPhase={selectedPhase}
initialNodes={initialNodes}
/>
</ReactFlowBreadCrumbProvider>
);
};
138 changes: 138 additions & 0 deletions packages/console/src/components/flytegraph/ReactFlow/BreadCrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import { useNodeExecutionDynamicContext } from 'components/Executions/contextProvider/NodeExecutionDetails/NodeExecutionDynamicProvider';
import { COLOR_SPECTRUM } from 'components/Theme/colorSpectrum';
import { NodeExecutionPhase } from 'models';
import React, { PropsWithChildren } from 'react';
import { getNestedContainerStyle } from './utils';

const BREAD_FONT_SIZE = '9px';
const BREAD_COLOR_ACTIVE = COLOR_SPECTRUM.purple60.color;
const BREAD_COLOR_INACTIVE = COLOR_SPECTRUM.black.color;

export const BreadElement = ({
nestedView,
index,
currentNestedDepth,
scopedId,
onClick,
}) => {
const liStyles: React.CSSProperties = {
cursor: 'pointer',
fontSize: BREAD_FONT_SIZE,
color: BREAD_COLOR_ACTIVE,
};

const liStyleInactive: React.CSSProperties = { ...liStyles };
liStyleInactive['color'] = BREAD_COLOR_INACTIVE;

const beforeStyle: React.CSSProperties = {
cursor: 'pointer',
color: BREAD_COLOR_ACTIVE,
padding: '0 .2rem',
fontSize: BREAD_FONT_SIZE,
};
// const onClick =
// currentNestedDepth > index + 1 ? handleNestedViewClick : undefined;
return (
<li
onClick={onClick}
style={index === currentNestedDepth - 1 ? liStyleInactive : liStyles}
id={`${scopedId}_${index}`}
key={`${scopedId}_${index}key`}
>
{index === 0 ? <span style={beforeStyle}>{'>'}</span> : null}
{nestedView}
{index < currentNestedDepth - 1 ? (
<span style={beforeStyle}>{'>'}</span>
) : null}
</li>
);
};

const BorderElement = ({
nodeExecutionStatus,
children,
}: PropsWithChildren<{
nodeExecutionStatus: NodeExecutionPhase;
}>) => {
const { componentProps } = useNodeExecutionDynamicContext();

const borderStyle = getNestedContainerStyle(nodeExecutionStatus);

return (
<div style={borderStyle} {...componentProps}>
{children}
</div>
);
};

export const BorderContainer = ({
nodeExecutionStatus,
currentNestedDepth,
children,
}: PropsWithChildren<{
currentNestedDepth: number;
nodeExecutionStatus: NodeExecutionPhase;
}>) => {
let borders = (
<BorderElement nodeExecutionStatus={nodeExecutionStatus}>
{children}
</BorderElement>
);
for (let i = 0; i < currentNestedDepth; i++) {
borders = (
<BorderElement nodeExecutionStatus={nodeExecutionStatus}>
{borders}
</BorderElement>
);
}

return borders;
};

const breadContainerStyle: React.CSSProperties = {
position: 'absolute',
display: 'flex',
width: '100%',
marginTop: '-1rem',
};
const olStyles: React.CSSProperties = {
margin: 0,
padding: 0,
display: 'flex',
listStyle: 'none',
listStyleImage: 'none',
minWidth: '1rem',
};
const headerStyle: React.CSSProperties = {
color: BREAD_COLOR_ACTIVE,
fontSize: BREAD_FONT_SIZE,
margin: 0,
padding: 0,
};

export const BreadCrumbContainer = ({
text,
currentNestedDepth,
handleRootClick,
children,
}: PropsWithChildren<{
text: string;
currentNestedDepth: number;
handleRootClick: () => void;
}>) => {
const rootClick = currentNestedDepth > 0 ? handleRootClick : undefined;
return (
<div style={breadContainerStyle}>
<header
style={headerStyle}
onClick={e => {
e.stopPropagation();
rootClick?.();
}}
>
{text}
</header>
<ol style={olStyles}>{children}</ol>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { useNodeExecutionsById } from 'components/Executions/contextProvider/NodeExecutionDetails';
import { fetchChildrenExecutions } from 'components/Executions/utils';
import React, {
createContext,
PropsWithChildren,
useContext,
Ref,
useState,
} from 'react';
import { useQueryClient } from 'react-query';
import { isUnFetchedDynamicNode } from './utils';

export type RefType = Ref<Element | null>;
export interface IReactFlowBreadCrumbContext {
currentNestedDepth: number;
currentNestedView: BreadCrumbViews;
setCurrentNestedView: (newLevels: BreadCrumbViews) => void;
onAddNestedView: (view: any, sourceNode?: any) => Promise<void>;
onRemoveNestedView: (viewParent: any, viewIndex: any) => void;
}

export const ReactFlowBreadCrumbContext =
createContext<IReactFlowBreadCrumbContext>({
currentNestedDepth: 0,
currentNestedView: {},
setCurrentNestedView: () => {},
onAddNestedView: () => {
throw new Error('please use NodeExecutionDynamicProvider');
},
onRemoveNestedView: () => {
throw new Error('please use NodeExecutionDynamicProvider');
},
});

export interface BreadCrumbViews {
[key: string]: string[];
}
/** Should wrap "top level" component in Execution view, will build a nodeExecutions tree for specific workflow */
export const ReactFlowBreadCrumbProvider = ({
children,
}: PropsWithChildren<{}>) => {
const queryClient = useQueryClient();
const [currentNestedView, setCurrentNestedView] = useState<BreadCrumbViews>(
{},
);
const currentNestedDepth = (currentNestedView?.length || 0) as any as number;

const { nodeExecutionsById, setCurrentNodeExecutionsById } =
useNodeExecutionsById();

const onAddNestedView = async (view, sourceNode: any = null) => {
if (sourceNode && isUnFetchedDynamicNode(sourceNode)) {
await fetchChildrenExecutions(
queryClient,
sourceNode.scopedId,
nodeExecutionsById,
setCurrentNodeExecutionsById,
);
}

const currentView = currentNestedView[view.parent] || [];
const newView = {
[view.parent]: [...currentView, view.view],
};
setCurrentNestedView(newView);
};

const onRemoveNestedView = (viewParent, viewIndex) => {
const newcurrentNestedView: any = { ...currentNestedView };
newcurrentNestedView[viewParent] = newcurrentNestedView[viewParent]?.filter(
(_item, i) => i <= viewIndex,
);
if (newcurrentNestedView[viewParent]?.length < 1) {
delete newcurrentNestedView[viewParent];
}
setCurrentNestedView(newcurrentNestedView);
};

return (
<ReactFlowBreadCrumbContext.Provider
value={{
currentNestedDepth,
currentNestedView,
setCurrentNestedView,
onAddNestedView,
onRemoveNestedView,
}}
>
{children}
</ReactFlowBreadCrumbContext.Provider>
);
};

export const useReactFlowBreadCrumbContext =
(): IReactFlowBreadCrumbContext => {
return useContext(ReactFlowBreadCrumbContext);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,16 @@ import {
useNodeExecutionsById,
} from 'components/Executions/contextProvider/NodeExecutionDetails';
import { NodeExecutionPhase } from 'models/Execution/enums';
import {
fetchChildrenExecutions,
isNodeGateNode,
} from 'components/Executions/utils';
import { isNodeGateNode } from 'components/Executions/utils';
import { dNode } from 'models/Graph/types';
import { useQueryClient } from 'react-query';
import { extractCompiledNodes } from 'components/hooks/utils';
import { useDetailsPanel } from 'components/Executions/ExecutionDetails/DetailsPanelContext';
import { RFWrapperProps, RFGraphTypes, ConvertDagProps } from './types';
import { getRFBackground, isUnFetchedDynamicNode } from './utils';
import { getRFBackground } from './utils';
import { ReactFlowWrapper } from './ReactFlowWrapper';
import { Legend } from './NodeStatusLegend';
import { PausedTasksComponent } from './PausedTasksComponent';
import { useReactFlowBreadCrumbContext } from './ReactFlowBreadCrumbProvider';

const containerStyle: React.CSSProperties = {
display: 'flex',
Expand All @@ -35,42 +32,44 @@ export const ReactFlowGraphComponent = ({
selectedPhase,
initialNodes,
}) => {
const { nodeExecutionsById, shouldUpdate } =
useNodeExecutionsById();
const { nodeExecutionsById, shouldUpdate } = useNodeExecutionsById();
const { isDetailsTabClosed } = useDetailsPanel();

const { compiledWorkflowClosure } = useNodeExecutionContext();

const [pausedNodes, setPausedNodes] = useState<dNode[]>([]);
const [currentNestedView, setcurrentNestedView] = useState({});

const onAddNestedView = async (view, sourceNode: any = null) => {
// if (sourceNode && isUnFetchedDynamicNode(sourceNode)) {
// await fetchChildrenExecutions(
// queryClient,
// sourceNode.scopedId,
// nodeExecutionsById,
// setCurrentNodeExecutionsById,
// );
// }
const { currentNestedView, onAddNestedView, onRemoveNestedView } =
useReactFlowBreadCrumbContext();
// const [currentNestedView, setcurrentNestedView] = useState({});

const currentView = currentNestedView[view.parent] || [];
const newView = {
[view.parent]: [...currentView, view.view],
};
setcurrentNestedView(newView);
};
// const onAddNestedView = async (view, sourceNode: any = null) => {
// // if (sourceNode && isUnFetchedDynamicNode(sourceNode)) {
// // await fetchChildrenExecutions(
// // queryClient,
// // sourceNode.scopedId,
// // nodeExecutionsById,
// // setCurrentNodeExecutionsById,
// // );
// // }

const onRemoveNestedView = (viewParent, viewIndex) => {
const newcurrentNestedView: any = { ...currentNestedView };
newcurrentNestedView[viewParent] = newcurrentNestedView[viewParent]?.filter(
(_item, i) => i <= viewIndex,
);
if (newcurrentNestedView[viewParent]?.length < 1) {
delete newcurrentNestedView[viewParent];
}
setcurrentNestedView(newcurrentNestedView);
};
// const currentView = currentNestedView[view.parent] || [];
// const newView = {
// [view.parent]: [...currentView, view.view],
// };
// setcurrentNestedView(newView);
// };

// const onRemoveNestedView = (viewParent, viewIndex) => {
// const newcurrentNestedView: any = { ...currentNestedView };
// newcurrentNestedView[viewParent] = newcurrentNestedView[viewParent]?.filter(
// (_item, i) => i <= viewIndex,
// );
// if (newcurrentNestedView[viewParent]?.length < 1) {
// delete newcurrentNestedView[viewParent];
// }
// setcurrentNestedView(newcurrentNestedView);
// };

const rfGraphJson = useMemo(() => {
return ConvertFlyteDagToReactFlows({
Expand Down
Loading

0 comments on commit bc8573d

Please sign in to comment.