Skip to content
This repository has been archived by the owner on Jul 23, 2024. It is now read-only.

Commit

Permalink
Merge pull request #168 from parodos-dev/FLPATH-423/m2k-input
Browse files Browse the repository at this point in the history
show alert if a call to `status` returns an alertMessage field
  • Loading branch information
dagda1 authored Jun 16, 2023
2 parents 8473c41 + 0642d15 commit 7c6d136
Show file tree
Hide file tree
Showing 13 changed files with 400 additions and 58 deletions.
2 changes: 2 additions & 0 deletions plugins/parodos/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"classnames": "^2.3.2",
"immer": "^9.0.19",
"lodash.get": "^4.4.2",
"lodash.pickby": "^4.6.0",
"lodash.set": "^4.3.2",
"luxon": "^3.2.1",
"mobx": "^5.15.4",
Expand All @@ -71,6 +72,7 @@
"@testing-library/user-event": "^14.0.0",
"@types/lodash.get": "^4.4.7",
"@types/lodash.set": "^4.3.7",
"@types/lodash.pickby": "^4.6.7",
"@types/node": "*",
"cross-fetch": "^3.1.5",
"msw": "^0.49.0",
Expand Down
2 changes: 1 addition & 1 deletion plugins/parodos/src/components/ParodosPage/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ export function Tabs(): JSX.Element {
<span {...tabProps} ref={ref}>
<NavLink to={`${pluginRoutePrefix}${route}`}>
{navigationMap[index].icon}
{tabChildren}
{notifyIcon && (
<Badge
color="secondary"
Expand All @@ -59,6 +58,7 @@ export function Tabs(): JSX.Element {
<NotificationImportantIcon color="secondary" />
</Badge>
)}
{tabChildren}
</NavLink>
</span>
),
Expand Down
9 changes: 8 additions & 1 deletion plugins/parodos/src/components/markdown/renderers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,14 @@ export const renderers: Components = {
ul: Ul,
li: Li,
code: Code,
a: props => <Link to={props.href as string} children={props.children} />,
a: props => (
<Link
target="_blank"
rel="noopener noreferrer"
to={props.href as string}
children={props.children}
/>
),
blockquote: Blockquote,
table: StyledTable,
thead: props => <TableHead children={props.children} />,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ParodosPage } from '../../ParodosPage';
import {
ContentHeader,
InfoCard,
Progress,
SupportButton,
} from '@backstage/core-components';
Expand All @@ -19,13 +20,17 @@ import {
} from '../../../models/workflowTaskSchema';
import { useStore } from '../../../stores/workflowStore/workflowStore';
import { fetchApiRef, useApi } from '@backstage/core-plugin-api';
import { getWorkflowTasksForTopology } from '../../../hooks/getWorkflowDefinitions';
import {
FirstTaskId,
getWorkflowTasksForTopology,
} from '../../../hooks/getWorkflowDefinitions';
import { assert } from 'assert-ts';

const useStyles = makeStyles(_theme => ({
container: {
display: 'flex',
flexDirection: 'column',
flex: 1,
},
badge: {
alignSelf: 'flex-start',
Expand All @@ -40,9 +45,12 @@ const useStyles = makeStyles(_theme => ({
display: 'grid',
minHeight: 0,
},
card: {
height: '100%',
},
}));

export const WorkFlowDetail = () => {
export function WorkFlowDetail(): JSX.Element {
const { projectId, executionId } = useParams();
assert(!!projectId, 'no projectId param');
const project = useStore(state => state.getProjectById(projectId));
Expand All @@ -60,14 +68,20 @@ export const WorkFlowDetail = () => {
useEffect(() => {
const updateWorks = (works: WorkStatus[]) => {
let needUpdate = false;
// TODO: use immer here after demo
const tasks = [...allTasks];
for (const work of works) {
if (work.type === 'TASK') {
const foundTask = tasks.find(task => task.id === work.name);

if (foundTask && foundTask.status !== work.status) {
foundTask.status = work.status;
needUpdate = true;
}
if (foundTask && work.alertMessage !== foundTask?.alertMessage) {
foundTask.alertMessage = work.alertMessage;
needUpdate = true;
}
} else if (work.works) {
updateWorks(work.works);
}
Expand Down Expand Up @@ -100,11 +114,13 @@ export const WorkFlowDetail = () => {
const taskInterval = setInterval(() => {
updateWorksFromApi();
}, 5000);

updateWorksFromApi();

if (status === 'FAILED') {
clearInterval(taskInterval);
}
// TOOD: review after Demo
// if (status === 'FAILED') {
// clearInterval(taskInterval);
// }

return () => clearInterval(taskInterval);
}, [
Expand All @@ -119,6 +135,17 @@ export const WorkFlowDetail = () => {

useEffect(() => {
const updateWorkFlowLogs = async () => {
const selected = allTasks.find(task => task.id === selectedTask);
if (selectedTask === FirstTaskId) {
setLog('Start workflow');
return;
}

if (selected && selected?.status === 'PENDING') {
setLog('Pending....');
return;
}

if (selectedTask === '') {
setLog('');
return;
Expand All @@ -138,7 +165,7 @@ export const WorkFlowDetail = () => {
updateWorkFlowLogs();

return () => clearInterval(logInterval);
}, [executionId, selectedTask, fetch, workflowsUrl]);
}, [executionId, selectedTask, fetch, workflowsUrl, allTasks]);

return (
<ParodosPage className={styles.container}>
Expand All @@ -152,21 +179,29 @@ export const WorkFlowDetail = () => {
<ContentHeader title="Onboarding">
<SupportButton title="Need help?">Lorem Ipsum</SupportButton>
</ContentHeader>
<Typography paragraph>
You are onboarding <strong>{project?.name || '...'}</strong> project,
running workflow "{workflowName}" (execution ID: {executionId})
</Typography>

<Box className={styles.detailContainer}>
{allTasks.length > 0 ? (
<WorkFlowStepper tasks={allTasks} setSelectedTask={setSelectedTask} />
) : (
<Progress />
)}
<div className={styles.viewerContainer}>
{log !== '' && <WorkFlowLogViewer log={log} />}
</div>
</Box>
<InfoCard className={styles.card}>
<Typography paragraph>
Please provide additional information related to your project.
</Typography>
<Typography paragraph>
You are onboarding <strong>{project?.name || '...'}</strong> project,
running workflow "{workflowName}" (execution ID: {executionId})
</Typography>

<Box className={styles.detailContainer}>
{allTasks.length > 0 ? (
<WorkFlowStepper
tasks={allTasks}
setSelectedTask={setSelectedTask}
/>
) : (
<Progress />
)}
<div className={styles.viewerContainer}>
{log !== '' && <WorkFlowLogViewer log={log} />}
</div>
</Box>
</InfoCard>
</ParodosPage>
);
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { assert } from 'assert-ts';
import React, { ReactNode, useContext } from 'react';
import { createContext, useMemo } from 'react';
import { useImmerReducer } from 'use-immer';
import { WorkflowTask } from '../../../models/workflowTaskSchema';

type WorkFlowMode = 'RUNNING' | 'TASK_ALERT';

export interface WorkFlowContext {
workflowMode: WorkFlowMode;
showAlert(workflow: WorkflowTask): void;
clearAlert(): void;
}

export type WorkflowActions =
| {
type: 'TASK_ALERT';
}
| {
type: 'CLEAR_ALERT';
};

interface State {
workflowMode: WorkFlowMode;
}

const reducer = (draft: State, action: WorkflowActions) => {
switch (action.type) {
case 'TASK_ALERT': {
draft.workflowMode = 'TASK_ALERT';
break;
}
case 'CLEAR_ALERT': {
draft.workflowMode = 'RUNNING';
break;
}
default:
throw new Error(`no action`);
}
};

export const WorkflowContext = createContext<WorkFlowContext | undefined>(
undefined,
);

const initialState: State = {
workflowMode: 'RUNNING',
};

export function WorkflowProvider({
children,
}: {
children: ReactNode;
}): JSX.Element {
const [state, dispatch] = useImmerReducer(reducer, initialState);

const value = useMemo(
() => ({
workflowMode: state.workflowMode,
showAlert: () => dispatch({ type: 'TASK_ALERT' }),
clearAlert: () => dispatch({ type: 'CLEAR_ALERT' }),
}),
[dispatch, state.workflowMode],
);

return (
<WorkflowContext.Provider value={value}>
{children}
</WorkflowContext.Provider>
);
}

export function useWorkflowContext() {
const context = useContext(WorkflowContext);

assert(!!context, 'useWorkflowProvider must be within WorkflowProvider');

return context;
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import * as React from 'react';
import React, { useMemo } from 'react';
import { observer } from 'mobx-react';
import {
DEFAULT_LAYER,
DEFAULT_WHEN_OFFSET,
Layer,
Node,
ScaleDetailsLevel,
TaskNode,
TOP_LAYER,
Expand All @@ -13,31 +12,40 @@ import {
WhenDecorator,
WithContextMenuProps,
WithSelectionProps,
type Node,
} from '@patternfly/react-topology';
import { makeStyles } from '@material-ui/core';
import pickBy from 'lodash.pickby';
import cs from 'classnames';
import { useWorkflowContext } from '../WorkflowContext';

type DemoTaskNodeProps = {
element: Node;
} & WithContextMenuProps &
WithSelectionProps;

const useStyles = makeStyles(_theme => ({
disabled: {
'& g': {
opacity: 0.6,
},
},
}));

const DemoTaskNode: any = ({
element,
onContextMenu,
contextMenuOpen,
...rest
}: DemoTaskNodeProps) => {
const { workflowMode } = useWorkflowContext();
const styles = useStyles();
const data = element.getData();
const [hover, hoverRef] = useHover();
const detailsLevel = useDetailsLevel();

const passedData = React.useMemo(() => {
const newData = { ...data };
Object.keys(newData).forEach(key => {
if (newData[key] === undefined) {
delete newData[key];
}
});
return newData;
const passedData: any = useMemo(() => {
return pickBy(data, n => typeof n !== 'undefined');
}, [data]);

const hasTaskIcon = !!(data.taskIconClass || data.taskIcon);
Expand Down Expand Up @@ -69,6 +77,10 @@ const DemoTaskNode: any = ({
{...passedData}
{...rest}
truncateLength={20}
className={cs({
[styles.disabled]:
workflowMode === 'TASK_ALERT' && hasTaskIcon === false,
})}
>
{whenDecorator}
</TaskNode>
Expand Down
Loading

0 comments on commit 7c6d136

Please sign in to comment.