-
Notifications
You must be signed in to change notification settings - Fork 356
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8782 from jeffibm/workflow-status-list
Introducing workflow status list in request's show page (cherry picked from commit cf29c3a)
- Loading branch information
Showing
8 changed files
with
277 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/** Types of workflow state status */ | ||
export const workflowStateTypes = { | ||
success: { text: 'success', tagType: 'green' }, | ||
error: { text: 'error', tagType: 'red' }, | ||
failed: { text: 'failed', tagType: 'gray' }, | ||
pending: { text: 'pending', tagType: 'gray' }, | ||
}; | ||
|
||
/** Function to get the header data of workflow states table. */ | ||
const headerData = () => ([ | ||
{ | ||
key: 'name', | ||
header: __('Name'), | ||
}, | ||
{ | ||
key: 'enteredTime', | ||
header: __('Entered Time'), | ||
}, | ||
{ | ||
key: 'finishedTime', | ||
header: __('Finished Time'), | ||
}, | ||
{ | ||
key: 'duration', | ||
header: __('Duration'), | ||
}, | ||
]); | ||
|
||
// const convertDate = (date) => `${moment(date).format('MM/DD/YYYY')} ${moment(date).format('h:mm:ss A')}`; | ||
const convertDate = (date) => { | ||
const utcDate = new Date(date); | ||
const year = utcDate.getUTCFullYear(); | ||
const month = (utcDate.getUTCMonth() + 1).toString().padStart(2, '0'); | ||
const day = utcDate.getUTCDate().toString().padStart(2, '0'); | ||
const hours = utcDate.getUTCHours(); | ||
const minutes = utcDate.getUTCMinutes().toString().padStart(2, '0'); | ||
const period = hours < 12 ? 'AM' : 'PM'; | ||
const hours12 = hours % 12 || 12; // Convert 0 to 12 for 12:00 AM | ||
|
||
const formattedDate = `${month}/${day}/${year} ${hours12}:${minutes} ${period}`; | ||
return formattedDate.toString(); | ||
}; | ||
|
||
/** Function to get the row data of workflow states table. */ | ||
const rowData = ({ StateHistory }) => StateHistory.map((item) => ({ | ||
id: item.Guid.toString(), | ||
name: item.Name, | ||
enteredTime: convertDate(item.EnteredTime.toString()), | ||
finishedTime: convertDate(item.FinishedTime.toString()), | ||
duration: item.Duration.toFixed(3).toString(), | ||
})); | ||
|
||
/** Function to return the header, row and status data required for the RequestWorkflowStatus component. */ | ||
export const workflowStatusData = (response) => { | ||
const type = 'ManageIQ::Providers::Workflows::AutomationManager::WorkflowInstance'; | ||
if (response.type !== type) { | ||
return undefined; | ||
} | ||
const rows = response.context ? rowData(response.context) : []; | ||
const headers = headerData(); | ||
const name = response.name || response.description; | ||
return { | ||
headers, rows, status: response.status, name, parentId: response.parent_id, id: response.id, type: response.type, | ||
}; | ||
}; |
18 changes: 18 additions & 0 deletions
18
app/javascript/components/request-workflow-status/index.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import RequestWorkflowStatusItem from './request-workflow-status-item'; | ||
|
||
/** Component to render the Workflow status in /miq_request/show/#{id} page */ | ||
const RequestWorkflowStatus = ({ ids }) => ( | ||
<div className="workflow-states-list-container"> | ||
{ ids.map((id) => ( | ||
<RequestWorkflowStatusItem recordId={id} key={id} /> | ||
))} | ||
</div> | ||
); | ||
|
||
RequestWorkflowStatus.propTypes = { | ||
ids: PropTypes.arrayOf(PropTypes.number).isRequired, | ||
}; | ||
|
||
export default RequestWorkflowStatus; |
147 changes: 147 additions & 0 deletions
147
app/javascript/components/request-workflow-status/request-workflow-status-item.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import React, { useEffect, useState, useRef } from 'react'; | ||
import { | ||
Tag, Loading, Link, | ||
} from 'carbon-components-react'; | ||
import PropTypes from 'prop-types'; | ||
import { workflowStatusData, workflowStateTypes } from './data'; | ||
import MiqDataTable from '../miq-data-table'; | ||
import NotificationMessage from '../notification-message'; | ||
|
||
/** Component to render the Workflow status in /miq_request/show/#{id} page */ | ||
const RequestWorkflowStatusItem = ({ recordId }) => { | ||
const RELOAD = 2000; // Time interval to reload the RequestWorkflowStatus component. | ||
const reloadLimit = 5; // This is to handle the Auto refresh issue causing the the server to burn out with multiple requests. | ||
const reloadCount = useRef(0); | ||
|
||
const [data, setData] = useState( | ||
{ | ||
isLoading: true, | ||
responseData: undefined, | ||
message: undefined, | ||
list: [], | ||
parentName: undefined, | ||
validType: false, | ||
} | ||
); | ||
|
||
/** Function to get the Workflow */ | ||
const getWorkflow = async() => { | ||
reloadCount.current += 1; | ||
const url = `/api/configuration_scripts/${recordId}`; | ||
API.get(url, { skipErrors: [404, 400, 500] }) | ||
.then((response) => { | ||
const responseData = workflowStatusData(response); | ||
if (responseData) { | ||
API.get(`/api/configuration_script_payloads/${responseData.parentId}`).then((response2) => { | ||
if (response.context) { | ||
setData({ | ||
...data, | ||
responseData, | ||
isLoading: false, | ||
parentName: response2.name, | ||
validType: true, | ||
message: responseData && responseData.status === workflowStateTypes.error.text | ||
? __('An error has occurred with this workflow') : undefined, | ||
}); | ||
} else { | ||
setData({ | ||
...data, | ||
responseData, | ||
isLoading: false, | ||
parentName: response2.name, | ||
validType: true, | ||
message: sprintf(__('Context is not available for "%s"'), response.name), | ||
}); | ||
} | ||
}); | ||
} else { | ||
setData({ | ||
...data, | ||
validType: false, | ||
responseData: undefined, | ||
isLoading: false, | ||
}); | ||
} | ||
}); | ||
}; | ||
|
||
/** Logic to reload the component every so often (RELOAD). */ | ||
useEffect(() => { | ||
const omitStatus = [workflowStateTypes.success.text, workflowStateTypes.error.text]; | ||
if (reloadCount.current <= reloadLimit && data.responseData && data.responseData.status && !omitStatus.includes(data.responseData.status)) { | ||
const interval = setInterval(() => { | ||
setData({ ...data, isLoading: true }); | ||
getWorkflow(); | ||
}, RELOAD); | ||
return () => clearInterval(interval); // This represents the unmount function, in which you need to clear your interval to prevent memory leaks. | ||
} | ||
return undefined; | ||
}, [data.responseData]); | ||
|
||
useEffect(() => { | ||
if (recordId) { | ||
getWorkflow(); | ||
} | ||
}, [recordId]); | ||
|
||
/** Function to render the status of workflow. */ | ||
const renderStatusTag = () => { | ||
const status = workflowStateTypes[data.responseData.status]; | ||
return ( | ||
<Tag type={status.tagType} title={status.text}> | ||
{status.text.toUpperCase()} | ||
</Tag> | ||
); | ||
}; | ||
|
||
/** Function to render the status of workflow status. */ | ||
const renderWorkflowStatus = () => ( | ||
<div className="workflow-status-container"> | ||
<div className="workflow-status-tag"> | ||
{data.responseData && data.responseData.status && renderStatusTag()} | ||
</div> | ||
<div className="workflow-status-label"> | ||
<Link href={`/workflow/show/${data.responseData.parentId}/`}>{data.parentName.toString()}</Link> | ||
</div> | ||
<div className="workflow-status-action"> | ||
{data.isLoading && <Loading active small withOverlay={false} className="loading" />} | ||
</div> | ||
</div> | ||
); | ||
|
||
/** Function to render the notification. */ | ||
const renderNotitication = () => ( | ||
<div className="workflow-notification-container"> | ||
<NotificationMessage type="error" message={data.message} /> | ||
</div> | ||
); | ||
|
||
/** Function to render the list. */ | ||
const renderList = ({ headers, rows }) => ( | ||
<MiqDataTable | ||
headers={headers} | ||
rows={rows} | ||
mode="request-workflow-status" | ||
/> | ||
); | ||
|
||
return ( | ||
<> | ||
{ | ||
data.validType && ( | ||
<div className="workflow-states-container"> | ||
{data.responseData && renderWorkflowStatus()} | ||
{data.message && renderNotitication()} | ||
{data.responseData && data.responseData.status && renderList(data.responseData)} | ||
</div> | ||
) | ||
} | ||
</> | ||
); | ||
}; | ||
|
||
RequestWorkflowStatusItem.propTypes = { | ||
recordId: PropTypes.number.isRequired, | ||
}; | ||
|
||
export default RequestWorkflowStatusItem; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
.workflow-states-list-container { | ||
margin-bottom: 20px; | ||
|
||
.workflow-states-container { | ||
padding: 10px; | ||
border: 1px solid lightgray; | ||
border-bottom: 0; | ||
|
||
&:last-child { | ||
border-bottom: 1px solid lightgray; | ||
} | ||
|
||
.workflow-status-container { | ||
display: flex; | ||
flex-direction: row; | ||
align-items: center; | ||
|
||
.workflow-status-label { | ||
font-weight:bold; | ||
font-size: 14px; | ||
margin-right: 5px; | ||
} | ||
|
||
.workflow-status-tag { | ||
margin-right: 5px; | ||
} | ||
} | ||
|
||
.workflow-notification-container { | ||
margin-top: 10px; | ||
} | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters