-
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.
- Loading branch information
1 parent
f9d74a6
commit 2009602
Showing
44 changed files
with
17,381 additions
and
171 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
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 |
---|---|---|
@@ -1,12 +1,54 @@ | ||
require 'byebug' | ||
module MiqRequestHelper | ||
include RequestInfoHelper | ||
include RequestDetailsHelper | ||
include OrderServiceHelper | ||
|
||
def row_data(label, value) | ||
{:cells => {:label => label, :value => value}} | ||
end | ||
|
||
def request_task_configuration_script_ids(miq_request) | ||
miq_request.miq_request_tasks.map { |task| task.options&.dig(:configuration_script_id) }.compact | ||
miq_request.miq_request_tasks.filter_map { |task| task.options&.dig(:configuration_script_id) } | ||
end | ||
|
||
def select_box_options(options) | ||
options.map do |item| | ||
if /Classification::(\d+)/.match?(item) | ||
classification_id = item.match(/Classification::(\d+)/)[1] | ||
classification = Classification.find_by(:id => classification_id) | ||
if classification | ||
{:label => classification.description, :value => classification.id.to_s} | ||
end | ||
else | ||
classification = Classification.find_by(:id => item) | ||
if classification | ||
{:label => classification.description, :value => classification.id.to_s} | ||
end | ||
end | ||
end | ||
end | ||
|
||
def dialog_field_values(dialog, wf) | ||
|
||
transformed_data = dialog.transform_keys { |key| key.sub('Array::', '') } | ||
transformed_data.transform_values do |value| | ||
if value.to_s.include?("\u001F") | ||
select_box_options(value.split("\u001F")) | ||
elsif value.to_s.include?("::") | ||
model, id = value.split("::") | ||
record = model.constantize.find_by(:id => id) | ||
record ? [{:label => record.description, :value => record.id}] : value | ||
else | ||
value | ||
end | ||
end | ||
end | ||
|
||
def service_request_data(request_options, wf) | ||
{ | ||
:dialogId => request_options[:workflow_settings][:dialog_id], | ||
:requestDialogOptions => dialog_field_values(request_options[:dialog], wf), | ||
} | ||
end | ||
end |
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,20 @@ | ||
module OrderServiceHelper | ||
def order_service_data(dialog) | ||
{ | ||
:dialogId => dialog[:dialog_id], | ||
:params => { | ||
:resourceActionId => dialog[:resource_action_id], | ||
:targetId => dialog[:target_id], | ||
:targetType => dialog[:target_type], | ||
:realTargetType => dialog[:real_target_type], | ||
}, | ||
:urls => { | ||
:apiSubmitEndpoint => dialog[:api_submit_endpoint], | ||
:apiAction => dialog[:api_action], | ||
:cancelEndPoint => dialog[:cancel_endpoint], | ||
:finishSubmitEndpoint => dialog[:finish_submit_endpoint], | ||
:openUrl => dialog[:open_url], | ||
} | ||
} | ||
end | ||
end |
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,77 @@ | ||
import React, { useContext } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import classNames from 'classnames'; | ||
import { DIALOG_FIELD_TYPES } from './constants'; | ||
import CheckboxField from './dialogFieldItems/CheckboxField'; | ||
import DateField from './dialogFieldItems/DateField'; | ||
import DateTimeField from './dialogFieldItems/DateTimeField'; | ||
import DropDownField from './dialogFieldItems/DropDownField'; | ||
import RadioField from './dialogFieldItems/RadioField'; | ||
import RefreshField from './RefreshField'; | ||
import ServiceContext from './ServiceContext'; | ||
import TagField from './dialogFieldItems/TagField'; | ||
import TextInputField from './dialogFieldItems/TextInputField'; | ||
import TextAreaField from './dialogFieldItems/TextAreaField'; | ||
|
||
/** Function to render fields based on type */ | ||
const renderFieldContent = (field) => { | ||
switch (field.type) { | ||
case DIALOG_FIELD_TYPES.checkBox: | ||
return <CheckboxField field={field} />; | ||
case DIALOG_FIELD_TYPES.date: | ||
return <DateField field={field} />; | ||
case DIALOG_FIELD_TYPES.dateTime: | ||
return <DateTimeField field={field} />; | ||
case DIALOG_FIELD_TYPES.dropDown: | ||
return <DropDownField field={field} />; | ||
case DIALOG_FIELD_TYPES.radio: | ||
return <RadioField field={field} />; | ||
case DIALOG_FIELD_TYPES.tag: | ||
return <TagField field={field} />; | ||
case DIALOG_FIELD_TYPES.textBox: | ||
return <TextInputField field={field} />; | ||
case DIALOG_FIELD_TYPES.textArea: | ||
return <TextAreaField field={field} />; | ||
default: | ||
return <>{__('Field not supported')}</>; | ||
} | ||
}; | ||
|
||
/** Function to render a field. */ | ||
const renderFieldItem = (field, data) => { | ||
const isRefreshing = data.fieldsToRefresh.includes(field.name); | ||
return ( | ||
<div | ||
className={classNames('section-field-row', isRefreshing && 'field-refresh-in-progress')} | ||
key={field.id.toString()} | ||
id={`section-field-row-${field.name}`} | ||
> | ||
<div className="field-item"> | ||
{ | ||
renderFieldContent(field) | ||
} | ||
</div> | ||
<RefreshField field={field} /> | ||
</div> | ||
); | ||
}; | ||
|
||
/** Component to render the Fields in the Service/DialogTabs/DialogGroups component */ | ||
const DialogFields = ({ dialogFields }) => { | ||
const { data } = useContext(ServiceContext); | ||
return ( | ||
<> | ||
{ | ||
dialogFields.map((field) => ( | ||
field.visible ? renderFieldItem(field, data) : <span key={field.id.toString()} /> | ||
)) | ||
} | ||
</> | ||
); | ||
}; | ||
|
||
DialogFields.propTypes = { | ||
dialogFields: PropTypes.arrayOf(PropTypes.any).isRequired, | ||
}; | ||
|
||
export default DialogFields; |
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,27 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import DialogFields from './DialogFields'; | ||
|
||
/** Component to render the Groups in the Service/DialogTabs component */ | ||
const DialogGroups = ({ dialogGroups }) => ( | ||
<> | ||
{ | ||
dialogGroups.map((item) => ( | ||
<div className="section" key={item.id.toString()}> | ||
<div className="section-label"> | ||
{item.label} | ||
</div> | ||
<div className="section-fields"> | ||
<DialogFields dialogFields={item.dialog_fields} /> | ||
</div> | ||
</div> | ||
)) | ||
} | ||
</> | ||
); | ||
|
||
DialogGroups.propTypes = { | ||
dialogGroups: PropTypes.arrayOf(PropTypes.any).isRequired, | ||
}; | ||
|
||
export default DialogGroups; |
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,40 @@ | ||
import React, { useContext } from 'react'; | ||
import { Tabs, Tab, Loading } from 'carbon-components-react'; | ||
import DialogGroups from './DialogGroups'; | ||
import ServiceContext from './ServiceContext'; | ||
import { extractDialogTabs } from './helper'; | ||
|
||
/** Component to render the Tabs in the Service component */ | ||
const DialogTabs = () => { | ||
const { data } = useContext(ServiceContext); | ||
const dialogTabs = extractDialogTabs(data.apiResponse); | ||
|
||
const tabLabel = (label, tabIndex) => { | ||
const { fieldsToRefresh, groupFieldsByTab } = data; | ||
const refreshInProgress = fieldsToRefresh.some((field) => groupFieldsByTab[tabIndex].includes(field)); | ||
return refreshInProgress | ||
? ( | ||
<div className="tab-label"> | ||
{label} | ||
<Loading active small withOverlay={false} className="loading" /> | ||
</div> | ||
) | ||
: label; | ||
}; | ||
|
||
return ( | ||
<Tabs className="miq_custom_tabs"> | ||
{ | ||
dialogTabs.map((tab, tabIndex) => ( | ||
<Tab key={tab.id.toString()} label={tabLabel(tab.label, tabIndex)}> | ||
<div className="tabs"> | ||
<DialogGroups dialogGroups={tab.dialog_groups} /> | ||
</div> | ||
</Tab> | ||
)) | ||
} | ||
</Tabs> | ||
); | ||
}; | ||
|
||
export default DialogTabs; |
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,62 @@ | ||
import React, { useContext } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { Button, Loading } from 'carbon-components-react'; | ||
import { Renew16 } from '@carbon/icons-react'; | ||
import ServiceContext from './ServiceContext'; | ||
import ServiceValidator from './ServiceValidator'; | ||
import { defaultFieldValue } from './helper'; | ||
import { fieldProperties } from './helper.field'; | ||
|
||
/** Function to reset the dialogField data when the field refresh button is clicked. */ | ||
const resetDialogField = (dialogFields, field) => { | ||
const { value, valid } = ServiceValidator.validateField({ field, value: defaultFieldValue(field) }); | ||
dialogFields[field.name] = { value, valid }; | ||
return { ...dialogFields }; | ||
}; | ||
|
||
const RefreshField = ({ field }) => { | ||
const { data, setData } = useContext(ServiceContext); | ||
const { isDisabled } = fieldProperties(field, data); | ||
|
||
const { fieldsToRefresh } = data; | ||
const inProgress = fieldsToRefresh.includes(field.name); | ||
return ( | ||
<div className="refresh-field-item"> | ||
{ | ||
!!(field.dynamic && field.show_refresh_button) && !inProgress && ( | ||
<Button | ||
hasIconOnly | ||
disabled={isDisabled} | ||
className="refresh-field-button" | ||
onClick={() => { | ||
setData({ | ||
...data, | ||
fieldsToRefresh: [field.name], | ||
dialogFields: resetDialogField(data.dialogFields, field), | ||
}); | ||
}} | ||
iconDescription={__(`Refresh ${field.label}`)} | ||
tooltipAlignment="start" | ||
tooltipPosition="left" | ||
renderIcon={Renew16} | ||
/> | ||
) | ||
} | ||
{ | ||
inProgress && <Loading active small withOverlay={false} className="loading" /> | ||
} | ||
</div> | ||
); | ||
}; | ||
|
||
RefreshField.propTypes = { | ||
field: PropTypes.shape({ | ||
label: PropTypes.string, | ||
dynamic: PropTypes.bool, | ||
show_refresh_button: PropTypes.bool, | ||
dialog_field_responders: PropTypes.arrayOf(PropTypes.string), | ||
name: PropTypes.string, | ||
}).isRequired, | ||
}; | ||
|
||
export default RefreshField; |
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,84 @@ | ||
import React, { useContext, useEffect } from 'react'; | ||
import { Button } from 'carbon-components-react'; | ||
import ServiceContext from './ServiceContext'; | ||
import { omitValidation } from './helper'; | ||
import miqRedirectBack from '../../helpers/miq-redirect-back'; | ||
|
||
const ServiceButtons = React.memo(() => { | ||
const { data, setData } = useContext(ServiceContext); | ||
const { | ||
apiAction, apiSubmitEndpoint, openUrl, finishSubmitEndpoint, | ||
} = data.urls; | ||
|
||
useEffect(() => { | ||
if (data.locked) { | ||
const handleSubmission = async() => { | ||
const values = omitValidation(data.dialogFields); | ||
let submitData = { action: 'order', ...values }; | ||
|
||
if (apiSubmitEndpoint.includes('/generic_objects/')) { | ||
submitData = { action: apiAction, parameters: values }; | ||
} else if (apiAction === 'reconfigure') { | ||
submitData = { action: apiAction, resource: values }; | ||
} | ||
|
||
try { | ||
const response = await API.post(apiSubmitEndpoint, submitData, { skipErrors: [400] }); | ||
if (openUrl === 'true') { | ||
const taskResponse = await API.wait_for_task(response) | ||
.then(() => | ||
// eslint-disable-next-line no-undef | ||
$http.post('open_url_after_dialog', { targetId, realTargetType })); | ||
|
||
if (taskResponse.data.open_url) { | ||
window.open(response.data.open_url); | ||
miqRedirectBack(__('Order Request was Submitted'), 'success', finishSubmitEndpoint); | ||
} else { | ||
add_flash(__('Automate failed to obtain URL.'), 'error'); | ||
miqSparkleOff(); | ||
} | ||
} else { | ||
miqRedirectBack(__('Order Request was Submitted'), 'success', finishSubmitEndpoint); | ||
} | ||
} catch (_error) { | ||
// Handle error if needed | ||
} | ||
}; | ||
|
||
handleSubmission(); | ||
} | ||
}, [data.locked]); | ||
|
||
const formValid = data.dialogFields ? Object.values(data.dialogFields).every((field) => field.valid) : false; | ||
|
||
const submitForm = () => { | ||
miqSparkleOn(); | ||
setData({ | ||
...data, | ||
locked: true, | ||
}); | ||
}; | ||
|
||
return ( | ||
<div className="service-action-buttons"> | ||
<Button | ||
disabled={!formValid || data.locked} | ||
onClick={submitForm} | ||
> | ||
{ | ||
data.locked ? __('Submitting...') : __('Submit') | ||
} | ||
</Button> | ||
|
||
<Button | ||
kind="secondary" | ||
disabled={data.locked || data.fieldsToRefresh.length > 0} | ||
onClick={() => miqRedirectBack(__('Dialog Cancelled'), 'warning', '/catalog')} | ||
> | ||
{__('Cancel')} | ||
</Button> | ||
</div> | ||
); | ||
}); | ||
|
||
export default ServiceButtons; |
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,4 @@ | ||
import { createContext } from 'react'; | ||
|
||
const ServiceContext = createContext(); | ||
export default ServiceContext; |
Oops, something went wrong.