diff --git a/app/javascript/components/ansible-playbook-workflow/index.jsx b/app/javascript/components/ansible-playbook-workflow/index.jsx new file mode 100644 index 00000000000..77bd68030e3 --- /dev/null +++ b/app/javascript/components/ansible-playbook-workflow/index.jsx @@ -0,0 +1,55 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Controlled as CodeMirror } from 'react-codemirror2'; +import { Tabs, Tab } from 'carbon-components-react'; +import NotificationMessage from '../notification-message'; + +/** The AnsiblePlaybookWorkflow is used to render the payload received from the Ansible Playbook's show page */ +const AnsiblePlaybookWorkflow = ({ payload, payloadType }) => { + /** Function to render a notification message. */ + const renderMessage = () => <NotificationMessage type="info" message={__('Payload is not avaible.')} />; + + /** Function to render the payload using CodeMirror. */ + const renderCodeMirror = () => ( + <CodeMirror + className="miq-codemirror ansible-playbook-workflow-payload" + options={{ + mode: payloadType, + theme: 'eclipse', + lint: true, + lineNumbers: true, + lineWrapping: true, + autoCloseBrackets: true, + styleActiveLine: true, + gutters: ['CodeMirror-lint-markers'], + }} + value={payload} + /> + ); + + /** Function to render the tab contents. Only one tab named 'Text' is required for ansible. */ + const renderTabContents = () => ( + <Tabs className="miq_custom_tabs"> + <Tab key="tab_text" label={__('Text')}> + { renderCodeMirror() } + </Tab> + </Tabs> + ); + + return ( + <div className="row"> + <div className="col-md-12 col-lg-6"> + { + payload ? renderTabContents() : renderMessage() + } + </div> + </div> + ); +}; + +AnsiblePlaybookWorkflow.propTypes = { + payload: PropTypes.string.isRequired, + payloadType: PropTypes.string.isRequired, +}; + +export default AnsiblePlaybookWorkflow; diff --git a/app/javascript/packs/component-definitions-common.js b/app/javascript/packs/component-definitions-common.js index 296be0c4522..b85d87a4f70 100644 --- a/app/javascript/packs/component-definitions-common.js +++ b/app/javascript/packs/component-definitions-common.js @@ -8,6 +8,7 @@ import ActionForm from '../components/action-form'; import AddRemoveSecurityGroupForm from '../components/vm-cloud-add-remove-security-group-form'; import AggregateStatusCard from '../components/aggregate_status_card'; import AnsibleCredentialsForm from '../components/ansible-credentials-form'; +import AnsiblePlaybookWorkflow from '../components/ansible-playbook-workflow'; import AnsibleRepositoryForm from '../components/ansible-repository-form'; import AuthKeypairCloudForm from '../components/auth-key-pair-cloud'; import { BreadcrumbsBar } from '../components/breadcrumbs'; @@ -174,6 +175,7 @@ import DiagnosticsCURepairForm from '../components/c-and-u-collections-form'; ManageIQ.component.addReact('ActionForm', ActionForm); ManageIQ.component.addReact('AddRemoveSecurityGroupForm', AddRemoveSecurityGroupForm); ManageIQ.component.addReact('AggregateStatusCard', AggregateStatusCard); +ManageIQ.component.addReact('AnsiblePlaybookWorkflow', AnsiblePlaybookWorkflow); ManageIQ.component.addReact('AnsibleCredentialsForm', AnsibleCredentialsForm); ManageIQ.component.addReact('AnsibleRepositoryForm', AnsibleRepositoryForm); ManageIQ.component.addReact('AuthKeypairCloudForm', AuthKeypairCloudForm); diff --git a/app/javascript/spec/ansible-playbook-workflow/__snapshots__/ansible-playbook-workflow.spec.js.snap b/app/javascript/spec/ansible-playbook-workflow/__snapshots__/ansible-playbook-workflow.spec.js.snap new file mode 100644 index 00000000000..aa3530c090e --- /dev/null +++ b/app/javascript/spec/ansible-playbook-workflow/__snapshots__/ansible-playbook-workflow.spec.js.snap @@ -0,0 +1,93 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AnsiblePlaybookWorkflow component should render the AnsiblePlaybookWorkflow with payload 1`] = ` +<div + className="row" +> + <div + className="col-md-12 col-lg-6" + > + <Tabs + className="miq_custom_tabs" + scrollDebounceWait={150} + scrollIntoView={true} + selected={0} + selectionMode="automatic" + type="default" + > + <Tab + key="tab_text" + label="Text" + onClick={[Function]} + onKeyDown={[Function]} + selected={false} + > + <Controlled + className="miq-codemirror ansible-playbook-workflow-payload" + options={ + Object { + "autoCloseBrackets": true, + "gutters": Array [ + "CodeMirror-lint-markers", + ], + "lineNumbers": true, + "lineWrapping": true, + "lint": true, + "mode": "yaml", + "styleActiveLine": true, + "theme": "eclipse", + } + } + value={ + Object { + "address": Object { + "city": "Anytown", + "street": "123 Main St", + "zip": 12345, + }, + "age": 30, + "email": "johndoe@example.com", + "hobbies": Array [ + "Reading", + "Hiking", + "Cooking", + ], + "name": "John Doe", + } + } + /> + </Tab> + </Tabs> + </div> +</div> +`; + +exports[`AnsiblePlaybookWorkflow component should render the AnsiblePlaybookWorkflow without payload and display a notification 1`] = ` +<AnsiblePlaybookWorkflow + payloadType="yaml" +> + <div + className="row" + > + <div + className="col-md-12 col-lg-6" + > + <NotificationMessage + message="Payload is not avaible." + type="info" + > + <div + className="miq-notification-message-container alert alert-info" + > + <span + className="pficon pficon-info" + /> + <strong> + Payload is not avaible. + </strong> + </div> + </NotificationMessage> + </div> + </div> +</AnsiblePlaybookWorkflow> +`; diff --git a/app/javascript/spec/ansible-playbook-workflow/ansible-playbook-workflow.data.js b/app/javascript/spec/ansible-playbook-workflow/ansible-playbook-workflow.data.js new file mode 100644 index 00000000000..efe98937672 --- /dev/null +++ b/app/javascript/spec/ansible-playbook-workflow/ansible-playbook-workflow.data.js @@ -0,0 +1,15 @@ +export const ansiblePlaybookData = { + id: 1000, + payload: { + name: 'John Doe', + age: 30, + email: 'johndoe@example.com', + address: { + street: '123 Main St', + city: 'Anytown', + zip: 12345, + }, + hobbies: ['Reading', 'Hiking', 'Cooking'], + }, + payloadType: 'yaml', +}; diff --git a/app/javascript/spec/ansible-playbook-workflow/ansible-playbook-workflow.spec.js b/app/javascript/spec/ansible-playbook-workflow/ansible-playbook-workflow.spec.js new file mode 100644 index 00000000000..9fe78280169 --- /dev/null +++ b/app/javascript/spec/ansible-playbook-workflow/ansible-playbook-workflow.spec.js @@ -0,0 +1,25 @@ +import React from 'react'; +import toJson from 'enzyme-to-json'; +import { shallow, mount } from 'enzyme'; +import AnsiblePlaybookWorkflow from '../../components/ansible-playbook-workflow'; +import { ansiblePlaybookData } from './ansible-playbook-workflow.data'; +import NotificationMessage from '../../components/notification-message'; + +describe('AnsiblePlaybookWorkflow component', () => { + it('should render the AnsiblePlaybookWorkflow with payload', () => { + const wrapper = shallow(<AnsiblePlaybookWorkflow + payload={ansiblePlaybookData.payload} + payloadType={ansiblePlaybookData.payloadType} + />); + expect(toJson(wrapper)).toMatchSnapshot(); + }); + + it('should render the AnsiblePlaybookWorkflow without payload and display a notification', () => { + const wrapper = mount(<AnsiblePlaybookWorkflow + payload={undefined} + payloadType={ansiblePlaybookData.payloadType} + />); + expect(toJson(wrapper)).toMatchSnapshot(); + expect(wrapper.find(NotificationMessage)).toHaveLength(1); + }); +}); diff --git a/app/views/ansible_playbook/show.html.haml b/app/views/ansible_playbook/show.html.haml index 85bcff0f54e..3fa0251b941 100644 --- a/app/views/ansible_playbook/show.html.haml +++ b/app/views/ansible_playbook/show.html.haml @@ -1,2 +1,3 @@ #main_div = render :partial => 'layouts/textual_groups_generic' + = react('AnsiblePlaybookWorkflow', { :payload => @record.payload , :payloadType => @record.payload_type })