Fetch full resource object and replace the matching node

This commit is contained in:
Marliana Lara 2020-04-01 15:21:42 -04:00
parent c18aa90534
commit 4704e24c24
No known key found for this signature in database
GPG Key ID: 38C73B40DFA809EE
5 changed files with 108 additions and 25 deletions

View File

@ -28,12 +28,16 @@ function hasPromptData(launchData) {
}
function formatTimeout(timeout) {
if (typeof timeout === "undefined" || timeout === null) {
if (typeof timeout === 'undefined' || timeout === null) {
return null;
}
const minutes = Math.floor(timeout / 60);
const seconds = timeout - Math.floor(timeout / 60) * 60;
return <>{minutes} <Trans>min</Trans> {seconds} <Trans>sec</Trans></>;
return (
<>
{minutes} <Trans>min</Trans> {seconds} <Trans>sec</Trans>
</>
);
}
function PromptDetail({ i18n, resource, launchConfig = {} }) {

View File

@ -17,6 +17,7 @@ export function initReducer() {
nodes: [],
nodeToDelete: null,
nodeToEdit: null,
nodeToView: null,
showDeleteAllNodesModal: false,
showLegend: false,
showTools: false,
@ -93,6 +94,8 @@ export default function visualizerReducer(state, action) {
return updateLink(state, action.linkType);
case 'UPDATE_NODE':
return updateNode(state, action.node);
case 'REFRESH_NODE':
return refreshNode(state, action.node);
default:
throw new Error(`Unrecognized action type: ${action.type}`);
}
@ -607,3 +610,17 @@ function updateNode(state, editedNode) {
unsavedChanges: true,
};
}
function refreshNode(state, refreshedNode) {
const { nodeToView, nodes } = state;
const newNodes = [...nodes];
const matchingNode = newNodes.find(node => node.id === nodeToView.id);
matchingNode.unifiedJobTemplate = refreshedNode.nodeResource;
return {
...state,
nodes: newNodes,
nodeToView: matchingNode,
};
}

View File

@ -16,6 +16,7 @@ const defaultState = {
nodes: [],
nodeToDelete: null,
nodeToEdit: null,
nodeToView: null,
showDeleteAllNodesModal: false,
showLegend: false,
showTools: false,

View File

@ -11,44 +11,105 @@ import ContentError from '@components/ContentError';
import ContentLoading from '@components/ContentLoading';
import PromptDetail from '@components/PromptDetail';
import useRequest from '@util/useRequest';
import { JobTemplatesAPI, WorkflowJobTemplatesAPI } from '@api';
import {
InventorySourcesAPI,
JobTemplatesAPI,
ProjectsAPI,
WorkflowJobTemplatesAPI,
} from '@api';
function getNodeType(node) {
const ujtType = node.type || node.unified_job_type;
let nodeType;
let nodeAPI;
switch (ujtType) {
case 'job_template':
case 'job':
nodeType = 'job_template';
nodeAPI = JobTemplatesAPI;
break;
case 'project':
case 'project_update':
nodeType = 'project_sync';
nodeAPI = ProjectsAPI;
break;
case 'inventory_source':
case 'inventory_update':
nodeType = 'inventory_source_sync';
nodeAPI = InventorySourcesAPI;
break;
case 'workflow_job_template':
case 'workflow_job':
nodeType = 'workflow_job_template';
nodeAPI = WorkflowJobTemplatesAPI;
break;
case 'workflow_approval_template':
case 'workflow_approval':
nodeType = 'approval';
nodeAPI = null;
break;
default:
}
return [nodeType, nodeAPI];
}
function NodeViewModal({ i18n }) {
const dispatch = useContext(WorkflowDispatchContext);
const { nodeToView } = useContext(WorkflowStateContext);
const { unifiedJobTemplate } = nodeToView;
const jobType =
unifiedJobTemplate.unified_job_type || unifiedJobTemplate.type;
const [nodeType, nodeAPI] = getNodeType(unifiedJobTemplate);
const {
result: launchConfig,
isLoading,
error,
isLoading: isLaunchConfigLoading,
error: launchConfigError,
request: fetchLaunchConfig,
} = useRequest(
useCallback(async () => {
const readLaunch = ['workflow_job', 'workflow_job_template'].includes(
jobType
)
? WorkflowJobTemplatesAPI.readLaunch(unifiedJobTemplate.id)
: JobTemplatesAPI.readLaunch(unifiedJobTemplate.id);
const readLaunch =
nodeType === 'workflow_job_template'
? WorkflowJobTemplatesAPI.readLaunch(unifiedJobTemplate.id)
: JobTemplatesAPI.readLaunch(unifiedJobTemplate.id);
const { data } = await readLaunch;
return data;
}, [jobType, unifiedJobTemplate]),
}, [nodeType, unifiedJobTemplate.id]),
{}
);
const {
result: nodeDetail,
isLoading: isNodeDetailLoading,
error: nodeDetailError,
request: fetchNodeDetail,
} = useRequest(
useCallback(async () => {
const { data } = await nodeAPI?.readDetail(unifiedJobTemplate.id);
return data;
}, [nodeAPI, unifiedJobTemplate.id]),
null
);
useEffect(() => {
if (
['workflow_job', 'workflow_job_template', 'job', 'job_template'].includes(
jobType
)
) {
if (nodeType === 'workflow_job_template' || nodeType === 'job_template') {
fetchLaunchConfig();
}
}, [jobType, fetchLaunchConfig]);
if (unifiedJobTemplate.unified_job_type && nodeType !== 'approval') {
fetchNodeDetail();
}
}, []); // eslint-disable-line react-hooks/exhaustive-deps
useEffect(() => {
if (nodeDetail) {
dispatch({
type: 'REFRESH_NODE',
node: {
nodeResource: nodeDetail,
},
});
}
}, [nodeDetail]); // eslint-disable-line react-hooks/exhaustive-deps
const handleEdit = () => {
dispatch({ type: 'SET_NODE_TO_VIEW', value: null });
@ -56,11 +117,10 @@ function NodeViewModal({ i18n }) {
};
let Content;
if (isLoading) {
if (isLaunchConfigLoading || isNodeDetailLoading) {
Content = <ContentLoading />;
} else if (error) {
Content = <ContentError error={error} />;
} else if (launchConfigError || nodeDetailError) {
Content = <ContentError error={launchConfigError || nodeDetailError} />;
} else {
Content = (
<PromptDetail launchConfig={launchConfig} resource={unifiedJobTemplate} />

View File

@ -11,6 +11,7 @@ import NodeViewModal from './NodeViewModal';
jest.mock('@api/models/JobTemplates');
jest.mock('@api/models/WorkflowJobTemplates');
WorkflowJobTemplatesAPI.readLaunch.mockResolvedValue({});
WorkflowJobTemplatesAPI.readDetail.mockResolvedValue({});
JobTemplatesAPI.readLaunch.mockResolvedValue({});
const dispatch = jest.fn();