mirror of
https://github.com/ansible/awx.git
synced 2026-03-25 21:05:03 -02:30
Fetch full resource object and replace the matching node
This commit is contained in:
@@ -28,12 +28,16 @@ function hasPromptData(launchData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formatTimeout(timeout) {
|
function formatTimeout(timeout) {
|
||||||
if (typeof timeout === "undefined" || timeout === null) {
|
if (typeof timeout === 'undefined' || timeout === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const minutes = Math.floor(timeout / 60);
|
const minutes = Math.floor(timeout / 60);
|
||||||
const seconds = timeout - Math.floor(timeout / 60) * 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 = {} }) {
|
function PromptDetail({ i18n, resource, launchConfig = {} }) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export function initReducer() {
|
|||||||
nodes: [],
|
nodes: [],
|
||||||
nodeToDelete: null,
|
nodeToDelete: null,
|
||||||
nodeToEdit: null,
|
nodeToEdit: null,
|
||||||
|
nodeToView: null,
|
||||||
showDeleteAllNodesModal: false,
|
showDeleteAllNodesModal: false,
|
||||||
showLegend: false,
|
showLegend: false,
|
||||||
showTools: false,
|
showTools: false,
|
||||||
@@ -93,6 +94,8 @@ export default function visualizerReducer(state, action) {
|
|||||||
return updateLink(state, action.linkType);
|
return updateLink(state, action.linkType);
|
||||||
case 'UPDATE_NODE':
|
case 'UPDATE_NODE':
|
||||||
return updateNode(state, action.node);
|
return updateNode(state, action.node);
|
||||||
|
case 'REFRESH_NODE':
|
||||||
|
return refreshNode(state, action.node);
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unrecognized action type: ${action.type}`);
|
throw new Error(`Unrecognized action type: ${action.type}`);
|
||||||
}
|
}
|
||||||
@@ -607,3 +610,17 @@ function updateNode(state, editedNode) {
|
|||||||
unsavedChanges: true,
|
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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ const defaultState = {
|
|||||||
nodes: [],
|
nodes: [],
|
||||||
nodeToDelete: null,
|
nodeToDelete: null,
|
||||||
nodeToEdit: null,
|
nodeToEdit: null,
|
||||||
|
nodeToView: null,
|
||||||
showDeleteAllNodesModal: false,
|
showDeleteAllNodesModal: false,
|
||||||
showLegend: false,
|
showLegend: false,
|
||||||
showTools: false,
|
showTools: false,
|
||||||
|
|||||||
@@ -11,44 +11,105 @@ import ContentError from '@components/ContentError';
|
|||||||
import ContentLoading from '@components/ContentLoading';
|
import ContentLoading from '@components/ContentLoading';
|
||||||
import PromptDetail from '@components/PromptDetail';
|
import PromptDetail from '@components/PromptDetail';
|
||||||
import useRequest from '@util/useRequest';
|
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 }) {
|
function NodeViewModal({ i18n }) {
|
||||||
const dispatch = useContext(WorkflowDispatchContext);
|
const dispatch = useContext(WorkflowDispatchContext);
|
||||||
const { nodeToView } = useContext(WorkflowStateContext);
|
const { nodeToView } = useContext(WorkflowStateContext);
|
||||||
const { unifiedJobTemplate } = nodeToView;
|
const { unifiedJobTemplate } = nodeToView;
|
||||||
const jobType =
|
const [nodeType, nodeAPI] = getNodeType(unifiedJobTemplate);
|
||||||
unifiedJobTemplate.unified_job_type || unifiedJobTemplate.type;
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
result: launchConfig,
|
result: launchConfig,
|
||||||
isLoading,
|
isLoading: isLaunchConfigLoading,
|
||||||
error,
|
error: launchConfigError,
|
||||||
request: fetchLaunchConfig,
|
request: fetchLaunchConfig,
|
||||||
} = useRequest(
|
} = useRequest(
|
||||||
useCallback(async () => {
|
useCallback(async () => {
|
||||||
const readLaunch = ['workflow_job', 'workflow_job_template'].includes(
|
const readLaunch =
|
||||||
jobType
|
nodeType === 'workflow_job_template'
|
||||||
)
|
? WorkflowJobTemplatesAPI.readLaunch(unifiedJobTemplate.id)
|
||||||
? WorkflowJobTemplatesAPI.readLaunch(unifiedJobTemplate.id)
|
: JobTemplatesAPI.readLaunch(unifiedJobTemplate.id);
|
||||||
: JobTemplatesAPI.readLaunch(unifiedJobTemplate.id);
|
|
||||||
|
|
||||||
const { data } = await readLaunch;
|
const { data } = await readLaunch;
|
||||||
|
|
||||||
return data;
|
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(() => {
|
useEffect(() => {
|
||||||
if (
|
if (nodeType === 'workflow_job_template' || nodeType === 'job_template') {
|
||||||
['workflow_job', 'workflow_job_template', 'job', 'job_template'].includes(
|
|
||||||
jobType
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
fetchLaunchConfig();
|
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 = () => {
|
const handleEdit = () => {
|
||||||
dispatch({ type: 'SET_NODE_TO_VIEW', value: null });
|
dispatch({ type: 'SET_NODE_TO_VIEW', value: null });
|
||||||
@@ -56,11 +117,10 @@ function NodeViewModal({ i18n }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let Content;
|
let Content;
|
||||||
|
if (isLaunchConfigLoading || isNodeDetailLoading) {
|
||||||
if (isLoading) {
|
|
||||||
Content = <ContentLoading />;
|
Content = <ContentLoading />;
|
||||||
} else if (error) {
|
} else if (launchConfigError || nodeDetailError) {
|
||||||
Content = <ContentError error={error} />;
|
Content = <ContentError error={launchConfigError || nodeDetailError} />;
|
||||||
} else {
|
} else {
|
||||||
Content = (
|
Content = (
|
||||||
<PromptDetail launchConfig={launchConfig} resource={unifiedJobTemplate} />
|
<PromptDetail launchConfig={launchConfig} resource={unifiedJobTemplate} />
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import NodeViewModal from './NodeViewModal';
|
|||||||
jest.mock('@api/models/JobTemplates');
|
jest.mock('@api/models/JobTemplates');
|
||||||
jest.mock('@api/models/WorkflowJobTemplates');
|
jest.mock('@api/models/WorkflowJobTemplates');
|
||||||
WorkflowJobTemplatesAPI.readLaunch.mockResolvedValue({});
|
WorkflowJobTemplatesAPI.readLaunch.mockResolvedValue({});
|
||||||
|
WorkflowJobTemplatesAPI.readDetail.mockResolvedValue({});
|
||||||
JobTemplatesAPI.readLaunch.mockResolvedValue({});
|
JobTemplatesAPI.readLaunch.mockResolvedValue({});
|
||||||
|
|
||||||
const dispatch = jest.fn();
|
const dispatch = jest.fn();
|
||||||
|
|||||||
Reference in New Issue
Block a user