From 457607cb7b653bdeafb09c6d661b62aa9f40b977 Mon Sep 17 00:00:00 2001 From: JEFFREY-Bonson Date: Tue, 21 Nov 2023 11:25:53 +0530 Subject: [PATCH] Integrating react-markdown with miq-structured-list and adding a markdown preview --- app/helpers/catalog_helper.rb | 6 +- .../components/MarkdownPreview/helper.js | 8 + .../components/MarkdownPreview/index.jsx | 98 ++ .../components/MiqMarkdown/index.jsx | 16 + .../components/miq-custom-tab/index.jsx | 18 +- .../components/miq-structured-list/helpers.js | 1 + .../value-tags/miq-structured-list-inputs.jsx | 6 + .../actions/miq-custom-tab-actions.js | 7 + .../miq-redux/miq-custom-tab-reducer.js | 10 + app/javascript/miq-redux/store.js | 2 + .../packs/component-definitions-common.js | 4 + .../__snapshots__/action-form.spec.js.snap | 1 + ...d-remove-security-groups-form.spec.js.snap | 4 + .../ansible-credentials-form.spec.js.snap | 2 + .../ansible-edit-catalog-form.spec.js.snap | 3 + .../button-group-form.spec.js.snap | 2 + .../c-and-u-collections-form.spec.js.snap | 2 + .../cloud-database-form.spec.js.snap | 1 + ...d-object-store-container-form.spec.js.snap | 3 + .../cloud-tenant-form.spec.js.snap | 1 + .../cloud-volume-actions-form.spec.js.snap | 6 + .../cloud-volume-backup-form.spec.js.snap | 2 + ...tach-detach-cloud-volume-form.spec.js.snap | 6 + .../custom-button-form.spec.js.snap | 2 + .../__snapshots__/datastore-form.spec.js.snap | 2 + .../diagnostics-collect-log-form.spec.js.snap | 3 + .../__snapshots__/evacuate-form.spec.js.snap | 3 + .../filter-dropdown.spec.js.snap | 1 + .../generic-objects-form.spec.js.snap | 3 + .../host-aggregate-form.spec.js.snap | 2 + .../__snapshots__/host-edit-form.spec.js.snap | 2 + .../host-initiator-group.spec.js.snap | 1 + .../live-migrate-form.spec.js.snap | 3 + .../__snapshots__/miq-custom-tab.spec.js.snap | 1070 +++++++++++++++-- .../miq-custom-tab/miq-custom-tab.spec.js | 32 +- .../physical-storage-form.spec.js.snap | 1 + .../policy-profile-form.spec.js.snap | 2 + ...e-customization-template-form.spec.js.snap | 3 + .../pxe-image-type-form.spec.js.snap | 2 + .../pxe-iso-datastore-form.spec.js.snap | 1 + .../pxe-iso-image-form.spec.js.snap | 1 + .../reconfigure-vm-form.spec.js.snap | 9 + .../retirement-form.spec.js.snap | 2 + .../__snapshots__/schedule-form.spec.js.snap | 3 + .../service-request-default-form.spec.js.snap | 1 + .../settings-category-form.spec.js.snap | 2 + .../settings-time-profile-form.spec.js.snap | 5 + .../__snapshots__/subnet-form.spec.js.snap | 1 + .../tenant-quota-form.spec.js.snap | 2 + .../__snapshots__/timeline-chart.spec.js.snap | 1 + .../vm-common-rename-form.spec.js.snap | 1 + .../__snapshots__/vm-edit-form.spec.js.snap | 5 + .../vm-floating-ips-form.spec.js.snap | 4 + .../__snapshots__/vm-resize-form.spec.js.snap | 2 + .../__snapshots__/widget-wrapper.spec.js.snap | 3 + ...kflow-credential-mapping-form.spec.js.snap | 2 + .../workflow-credentials-form.spec.js.snap | 2 + .../__snapshots__/zone-form.spec.js.snap | 1 + app/stylesheet/catalog-custom-component.scss | 26 + .../catalog/_form_details_info.html.haml | 15 +- package.json | 1 + yarn.lock | 953 ++++++++++----- 62 files changed, 1944 insertions(+), 440 deletions(-) create mode 100644 app/javascript/components/MarkdownPreview/helper.js create mode 100644 app/javascript/components/MarkdownPreview/index.jsx create mode 100644 app/javascript/components/MiqMarkdown/index.jsx create mode 100644 app/javascript/miq-redux/actions/miq-custom-tab-actions.js create mode 100644 app/javascript/miq-redux/miq-custom-tab-reducer.js diff --git a/app/helpers/catalog_helper.rb b/app/helpers/catalog_helper.rb index 0fdeaecfb94..1dc6ec28925 100644 --- a/app/helpers/catalog_helper.rb +++ b/app/helpers/catalog_helper.rb @@ -45,7 +45,7 @@ def service_catalog_summary(record, sb_data) {:cells => image}, row_data(_('Name'), record.name), row_data(_('Description'), record.description), - row_data(_('Long Description'), record.long_description), + row_data(_('Long Description'), {:input => 'markdown', :props => {:content => record.long_description}}), row_data(_('Dialog'), sb_data[:dialog_label]), ] if record.currency && record.price @@ -174,8 +174,8 @@ def catalog_custom_image(record) end def catalog_details(record) - data = {:title => _('Details'), :mode => "miq_catalog_details"} - data[:rows] = [row_data(_('Long Description'), record.long_description)] + data = {:title => _('Long Description'), :mode => "miq_catalog_details"} + data[:rows] = [row_data('', {:input => 'markdown', :props => {:content => record.long_description}})] miq_structured_list(data) end diff --git a/app/javascript/components/MarkdownPreview/helper.js b/app/javascript/components/MarkdownPreview/helper.js new file mode 100644 index 00000000000..64ffa288ba2 --- /dev/null +++ b/app/javascript/components/MarkdownPreview/helper.js @@ -0,0 +1,8 @@ +/** Configuration to idendify the usage of the Markdown component and the props needed. */ +export const previewConfiguration = { + CATALOG_EDIT_LONG_DESCRIPTION: { + title: __('Long Description'), + field: 'long_description', + mode: 'htmlmixed', + }, +}; diff --git a/app/javascript/components/MarkdownPreview/index.jsx b/app/javascript/components/MarkdownPreview/index.jsx new file mode 100644 index 00000000000..93157272652 --- /dev/null +++ b/app/javascript/components/MarkdownPreview/index.jsx @@ -0,0 +1,98 @@ +import React, { useState, useEffect } from 'react'; +import { useSelector } from 'react-redux'; +import PropTypes from 'prop-types'; +import { Controlled as CodeMirror } from 'react-codemirror2'; +import MiqMarkdown from '../MiqMarkdown'; +import { previewConfiguration } from './helper'; + +/** Component to preview the markdown contents on-the-fly. */ +const MarkdownPreview = ({ + content, url, type, +}) => { + const miqCustomTabReducer = useSelector((state) => state.miqCustomTabReducer); + const { title, mode, field } = previewConfiguration[type]; + + const [data, setData] = useState({ + editorContent: content, + oneTrans: 0, + }); + + /** The textField present in the ruby form has to be updated when data in the CodeMirror is changed. */ + useEffect(() => { + const textArea = document.getElementById(field); + textArea.value = data.editorContent; + if (data.oneTrans === 1) { + // To enable the form's save/cancel buttons (w.r.t pervious code-mirror implementation). + window.miqSendOneTrans(url); + } + }, [data.editorContent]); + + /** The code-mirror component needs to be refreshed when the tab selection is changed. + * If this is not used, then the code mirror will not load its default value. + */ + useEffect(() => { + window.miq_refresh_code_mirror(); + }, [miqCustomTabReducer]); + + /** Function to render the title of editor and preview sections. */ + const renderTitle = (type) => ( +
+ {`${title} - ${type}`} +
+ ); + + /** Function to render the code-mirror editor. */ + const renderEditor = () => ( +
+ {renderTitle(__('Editor'))} +
+ setData({ + ...data, + editorContent: value, + oneTrans: data.oneTrans + 1, + })} + value={data.editorContent} + /> +
+
+ ); + + /** Function to render the preview of the data entered in code-mirror editor. */ + const renderPreview = () => ( +
+ {renderTitle(__('Preview'))} +
+ +
+
+ ); + + return ( +
+ {renderEditor()} + {renderPreview()} +
+ ); +}; + +MarkdownPreview.propTypes = { + content: PropTypes.string, + url: PropTypes.string.isRequired, + type: PropTypes.string.isRequired, +}; + +MarkdownPreview.defaultProps = { + content: undefined, +}; + +export default MarkdownPreview; diff --git a/app/javascript/components/MiqMarkdown/index.jsx b/app/javascript/components/MiqMarkdown/index.jsx new file mode 100644 index 00000000000..a0a5d3d2c0f --- /dev/null +++ b/app/javascript/components/MiqMarkdown/index.jsx @@ -0,0 +1,16 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ReactMarkdown from 'react-markdown'; + +/** Component to render the markdown contents. */ +const MiqMarkdown = ({ content }) => {content}; + +MiqMarkdown.propTypes = { + content: PropTypes.string, +}; + +MiqMarkdown.defaultProps = { + content: undefined, +}; + +export default MiqMarkdown; diff --git a/app/javascript/components/miq-custom-tab/index.jsx b/app/javascript/components/miq-custom-tab/index.jsx index 7971a9c2c1b..c42a03081b7 100644 --- a/app/javascript/components/miq-custom-tab/index.jsx +++ b/app/javascript/components/miq-custom-tab/index.jsx @@ -1,12 +1,15 @@ import React, { useState } from 'react'; import PropTypes from 'prop-types'; import { Tabs, Tab } from 'carbon-components-react'; +import { useDispatch } from 'react-redux'; +import { miqCustomTabActions } from '../../miq-redux/actions/miq-custom-tab-actions'; const MiqCustomTab = ({ containerId, tabLabels, type }) => { + const dispatch = useDispatch(); const [data, setData] = useState({ loading: false }); const tabConfigurations = (name) => [ { type: 'CATALOG_SUMMARY' }, - { type: 'CATALOG_EDIT' }, + { type: 'CATALOG_EDIT', js: () => name === 'detail' && dispatch(miqCustomTabActions.incrementClickCount()) }, { type: 'CATALOG_REQUEST_INFO', url: `/miq_request/prov_field_changed?tab_id=${name}&edit_mode=true` }, { type: 'UTILIZATION' }, ]; @@ -37,13 +40,14 @@ const MiqCustomTab = ({ containerId, tabLabels, type }) => { }; /** Function to load the tab contents which are already available within the page. */ - const staticContents = (name) => { + const staticContents = (name, config) => { const tabs = containerTabs(); tabs.forEach((child) => { if (child.parentElement.id === containerId) { child.classList.remove('active'); if (child.id === `${name}`) { child.classList.add('active'); + if (config.js) config.js(); } } }); @@ -53,10 +57,10 @@ const MiqCustomTab = ({ containerId, tabLabels, type }) => { /** Function to load tab contents after a url is executed. * After the url is executed, the selected tab contents are displayes using the staticContents function. */ - const dynamicContents = (name, url) => { + const dynamicContents = (name, config) => { clearTabContents(); - window.miqJqueryRequest(url).then(() => { - staticContents(name); + window.miqJqueryRequest(config.url).then(() => { + staticContents(name, config); setData({ loading: false }); }); }; @@ -66,14 +70,14 @@ const MiqCustomTab = ({ containerId, tabLabels, type }) => { if (!data.loading) { miqSparkleOn(); const config = configuration(name); - return config && config.url ? dynamicContents(name, config.url) : staticContents(name); + return config && config.url ? dynamicContents(name, config) : staticContents(name, config); } return data; }; /** Function to render the tabs from the tabLabels props */ const renderTabs = () => tabLabels.map(({ name, text }) => ( - onTabSelect(name)} /> + onTabSelect(name)} /> )); return ( diff --git a/app/javascript/components/miq-structured-list/helpers.js b/app/javascript/components/miq-structured-list/helpers.js index 40f83033b74..f38e4dc6b86 100644 --- a/app/javascript/components/miq-structured-list/helpers.js +++ b/app/javascript/components/miq-structured-list/helpers.js @@ -9,6 +9,7 @@ export const InputTypes = { COMPONENT: 'component', DROPDOWN: 'dropdown', CODEMIRROR: 'code_mirror', + MARKDOWN: 'markdown', }; export const DynamicReactComponents = { diff --git a/app/javascript/components/miq-structured-list/miq-structured-list-body/value-tags/miq-structured-list-inputs.jsx b/app/javascript/components/miq-structured-list/miq-structured-list-body/value-tags/miq-structured-list-inputs.jsx index bfad4a4d7e7..4143f0f5bb1 100644 --- a/app/javascript/components/miq-structured-list/miq-structured-list-body/value-tags/miq-structured-list-inputs.jsx +++ b/app/javascript/components/miq-structured-list/miq-structured-list-body/value-tags/miq-structured-list-inputs.jsx @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { Checkbox, TextArea, Dropdown } from 'carbon-components-react'; import { Controlled as CodeMirror } from 'react-codemirror2'; import { DynamicReactComponents, InputTypes } from '../../helpers'; +import MiqMarkdown from '../../../MiqMarkdown'; /** Component to render textarea / checkbox / react components */ const MiqStructuredListInputs = ({ value, action }) => { @@ -50,6 +51,9 @@ const MiqStructuredListInputs = ({ value, action }) => { value={payload} /> ); + + const renderMarkdownComponent = ({ props: { content } }) => ; + switch (value.input) { case InputTypes.TEXTAREA: return renderTextArea(value); @@ -61,6 +65,8 @@ const MiqStructuredListInputs = ({ value, action }) => { return renderDropDownComponent(value); case InputTypes.CODEMIRROR: return renderCodeMirrorComponent(value); + case InputTypes.MARKDOWN: + return renderMarkdownComponent(value); default: return null; } diff --git a/app/javascript/miq-redux/actions/miq-custom-tab-actions.js b/app/javascript/miq-redux/actions/miq-custom-tab-actions.js new file mode 100644 index 00000000000..fded0e1e15f --- /dev/null +++ b/app/javascript/miq-redux/actions/miq-custom-tab-actions.js @@ -0,0 +1,7 @@ +const incrementClickCount = () => ({ + type: 'INCREMENT_CLICK_COUNT', +}); + +export const miqCustomTabActions = { + incrementClickCount, +}; diff --git a/app/javascript/miq-redux/miq-custom-tab-reducer.js b/app/javascript/miq-redux/miq-custom-tab-reducer.js new file mode 100644 index 00000000000..fa9b34325ef --- /dev/null +++ b/app/javascript/miq-redux/miq-custom-tab-reducer.js @@ -0,0 +1,10 @@ +const miqCustomTabReducer = (clickCount = 0, action) => { + switch (action.type) { + case 'INCREMENT_CLICK_COUNT': + return clickCount + 1; + default: + return clickCount; + } +}; + +export default miqCustomTabReducer; diff --git a/app/javascript/miq-redux/store.js b/app/javascript/miq-redux/store.js index 7ecdc858a5d..85b861f10cb 100644 --- a/app/javascript/miq-redux/store.js +++ b/app/javascript/miq-redux/store.js @@ -5,6 +5,7 @@ import { history } from '../miq-component/react-history.js'; import { notificationReducer } from './notification-reducer'; import formButtonsReducer from '../forms/form-buttons-reducer'; +import miqCustomTabReducer from './miq-custom-tab-reducer'; const initialState = {}; @@ -23,6 +24,7 @@ const initializeStore = () => { store.asyncReducers = { FormButtons: formButtonsReducer, notificationReducer, + miqCustomTabReducer, }; /** diff --git a/app/javascript/packs/component-definitions-common.js b/app/javascript/packs/component-definitions-common.js index 7533fdc6836..d9ff0611302 100644 --- a/app/javascript/packs/component-definitions-common.js +++ b/app/javascript/packs/component-definitions-common.js @@ -65,10 +65,12 @@ import ImportDatastoreViaGit from '../components/automate-import-export-form/imp import InterfacesForm from '../components/network-routers-interfaces-form'; import ISODatastoreTable from '../components/data-tables/iso-datastore-table'; import LiveMigrateForm from '../components/live-migrate-form'; +import MarkdownPreview from '../components/MarkdownPreview'; import MiqAboutModal from '../components/miq-about-modal/miq-about-modal'; import MiqAlertSetForm from '../components/miq-alert-set-form'; import MiqCustomTab from '../components/miq-custom-tab'; import MiqDataTable from '../components/miq-data-table'; +import MiqMarkdown from '../components/MiqMarkdown'; import MiqPagination from '../components/miq-pagination'; import MiqStructuredList from '../components/miq-structured-list'; import MiqStructuredListHeader from '../components/miq-structured-list/miq-structured-list-header'; @@ -233,10 +235,12 @@ ManageIQ.component.addReact('ISODatastoreTable', ISODatastoreTable); ManageIQ.component.addReact('LiveMigrateForm', LiveMigrateForm); ManageIQ.component.addReact('menu.MainMenu', MainMenu); ManageIQ.component.addReact('menu.Navbar', Navbar); +ManageIQ.component.addReact('MarkdownPreview', MarkdownPreview); ManageIQ.component.addReact('MiqAboutModal', MiqAboutModal); ManageIQ.component.addReact('MiqAlertSetForm', MiqAlertSetForm); ManageIQ.component.addReact('MiqCustomTab', MiqCustomTab); ManageIQ.component.addReact('MiqDataTable', MiqDataTable); +ManageIQ.component.addReact('MiqMarkdown', MiqMarkdown); ManageIQ.component.addReact('MiqPagination', MiqPagination); ManageIQ.component.addReact('MiqStructuredList', MiqStructuredList); ManageIQ.component.addReact('MiqStructuredListHeader', MiqStructuredListHeader); diff --git a/app/javascript/spec/action-form/__snapshots__/action-form.spec.js.snap b/app/javascript/spec/action-form/__snapshots__/action-form.spec.js.snap index 8676fa810bf..02ea491c270 100644 --- a/app/javascript/spec/action-form/__snapshots__/action-form.spec.js.snap +++ b/app/javascript/spec/action-form/__snapshots__/action-form.spec.js.snap @@ -6,6 +6,7 @@ exports[`Action Form Component should render adding a new action 1`] = ` Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/add-remove-security-groups-form/__snapshots__/add-remove-security-groups-form.spec.js.snap b/app/javascript/spec/add-remove-security-groups-form/__snapshots__/add-remove-security-groups-form.spec.js.snap index 31dc1d87b11..e2cebd9a263 100644 --- a/app/javascript/spec/add-remove-security-groups-form/__snapshots__/add-remove-security-groups-form.spec.js.snap +++ b/app/javascript/spec/add-remove-security-groups-form/__snapshots__/add-remove-security-groups-form.spec.js.snap @@ -6,6 +6,7 @@ exports[`Add/remove security groups form component should add security group 1`] Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -73,6 +74,7 @@ exports[`Add/remove security groups form component should remove security group Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -140,6 +142,7 @@ exports[`Add/remove security groups form component should render add security gr Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -207,6 +210,7 @@ exports[`Add/remove security groups form component should render remove security Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/ansible-credentials-form/__snapshots__/ansible-credentials-form.spec.js.snap b/app/javascript/spec/ansible-credentials-form/__snapshots__/ansible-credentials-form.spec.js.snap index 896984f3206..22735e680a0 100644 --- a/app/javascript/spec/ansible-credentials-form/__snapshots__/ansible-credentials-form.spec.js.snap +++ b/app/javascript/spec/ansible-credentials-form/__snapshots__/ansible-credentials-form.spec.js.snap @@ -6,6 +6,7 @@ exports[`Ansible Credential Form Component should render adding a new credential Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -1487,6 +1488,7 @@ exports[`Ansible Credential Form Component should render editing a credential 1` Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/ansible-edit-catalog-form/__snapshots__/ansible-edit-catalog-form.spec.js.snap b/app/javascript/spec/ansible-edit-catalog-form/__snapshots__/ansible-edit-catalog-form.spec.js.snap index 7c1320b04fb..1e7a19a331e 100644 --- a/app/javascript/spec/ansible-edit-catalog-form/__snapshots__/ansible-edit-catalog-form.spec.js.snap +++ b/app/javascript/spec/ansible-edit-catalog-form/__snapshots__/ansible-edit-catalog-form.spec.js.snap @@ -6,6 +6,7 @@ exports[`Ansible playbook edit catalog Form Component should not render some fie Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], "tenants_tree": [Function], }, @@ -58342,6 +58343,7 @@ exports[`Ansible playbook edit catalog Form Component should render correct form Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], "tenants_tree": [Function], }, @@ -119648,6 +119650,7 @@ exports[`Ansible playbook edit catalog Form Component should render retirement p Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], "tenants_tree": [Function], }, diff --git a/app/javascript/spec/button-group/__snapshots__/button-group-form.spec.js.snap b/app/javascript/spec/button-group/__snapshots__/button-group-form.spec.js.snap index 1eb463067c6..b3e2f084eb3 100644 --- a/app/javascript/spec/button-group/__snapshots__/button-group-form.spec.js.snap +++ b/app/javascript/spec/button-group/__snapshots__/button-group-form.spec.js.snap @@ -26,6 +26,7 @@ exports[`Button Group form component should render the editing form 1`] = ` Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -96,6 +97,7 @@ exports[`Button Group form component should render the editing form for generic Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/c-and-u-collections-form/__snapshots__/c-and-u-collections-form.spec.js.snap b/app/javascript/spec/c-and-u-collections-form/__snapshots__/c-and-u-collections-form.spec.js.snap index c95fdd2f8c0..6767882aef0 100644 --- a/app/javascript/spec/c-and-u-collections-form/__snapshots__/c-and-u-collections-form.spec.js.snap +++ b/app/javascript/spec/c-and-u-collections-form/__snapshots__/c-and-u-collections-form.spec.js.snap @@ -6,6 +6,7 @@ exports[`DiagnosticsCURepairForm Component Should add a record from DiagnosticsC Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -29,6 +30,7 @@ exports[`DiagnosticsCURepairForm Component Should render a new DiagnosticsCURepa Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/cloud-database-form/__snapshots__/cloud-database-form.spec.js.snap b/app/javascript/spec/cloud-database-form/__snapshots__/cloud-database-form.spec.js.snap index 30af461a9f4..32f7b230477 100644 --- a/app/javascript/spec/cloud-database-form/__snapshots__/cloud-database-form.spec.js.snap +++ b/app/javascript/spec/cloud-database-form/__snapshots__/cloud-database-form.spec.js.snap @@ -44,6 +44,7 @@ exports[`Cloud Database form component should render "Edit" form 1`] = ` Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/cloud-object-store-container-form/__snapshots__/cloud-object-store-container-form.spec.js.snap b/app/javascript/spec/cloud-object-store-container-form/__snapshots__/cloud-object-store-container-form.spec.js.snap index 470131bfa5d..999db67d916 100644 --- a/app/javascript/spec/cloud-object-store-container-form/__snapshots__/cloud-object-store-container-form.spec.js.snap +++ b/app/javascript/spec/cloud-object-store-container-form/__snapshots__/cloud-object-store-container-form.spec.js.snap @@ -6,6 +6,7 @@ exports[`Cloud Object Store Container form component should add Amazon cloud obj Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -926,6 +927,7 @@ exports[`Cloud Object Store Container form component should add Openstack cloud Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -1846,6 +1848,7 @@ exports[`Cloud Object Store Container form component should render add cloud obj Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/cloud-tenant-form/__snapshots__/cloud-tenant-form.spec.js.snap b/app/javascript/spec/cloud-tenant-form/__snapshots__/cloud-tenant-form.spec.js.snap index 17eb2c2c989..2400e58994f 100644 --- a/app/javascript/spec/cloud-tenant-form/__snapshots__/cloud-tenant-form.spec.js.snap +++ b/app/javascript/spec/cloud-tenant-form/__snapshots__/cloud-tenant-form.spec.js.snap @@ -68,6 +68,7 @@ exports[`Cloud tenant form component should render editing form variant 1`] = ` Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/cloud-volume-actions-form/__snapshots__/cloud-volume-actions-form.spec.js.snap b/app/javascript/spec/cloud-volume-actions-form/__snapshots__/cloud-volume-actions-form.spec.js.snap index df2474e031c..2ff4c9ff5d8 100644 --- a/app/javascript/spec/cloud-volume-actions-form/__snapshots__/cloud-volume-actions-form.spec.js.snap +++ b/app/javascript/spec/cloud-volume-actions-form/__snapshots__/cloud-volume-actions-form.spec.js.snap @@ -6,6 +6,7 @@ exports[`Cloud Volume Backup Create form component should render the cloud volum Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -1545,6 +1546,7 @@ exports[`Cloud Volume Backup Create form component when adding a new backup of c Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -3084,6 +3086,7 @@ exports[`Cloud Volume Restore from backup form component should render the cloud Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -4203,6 +4206,7 @@ exports[`Cloud Volume Restore from backup form component when restoring cloud vo Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -5322,6 +5326,7 @@ exports[`Cloud Volume Snapshot Create form component should render the cloud vol Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -6172,6 +6177,7 @@ exports[`Cloud Volume Snapshot Create form component when adding a new snapshot Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/cloud-volume-backup-form/__snapshots__/cloud-volume-backup-form.spec.js.snap b/app/javascript/spec/cloud-volume-backup-form/__snapshots__/cloud-volume-backup-form.spec.js.snap index add89822886..8dc07e7b3a8 100644 --- a/app/javascript/spec/cloud-volume-backup-form/__snapshots__/cloud-volume-backup-form.spec.js.snap +++ b/app/javascript/spec/cloud-volume-backup-form/__snapshots__/cloud-volume-backup-form.spec.js.snap @@ -6,6 +6,7 @@ exports[`Cloud Volume backup form component should render the restore cloud volu Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -31,6 +32,7 @@ exports[`Cloud Volume backup form component when restoring cloud volume from bac Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/cloud-volume-form/__snapshots__/attach-detach-cloud-volume-form.spec.js.snap b/app/javascript/spec/cloud-volume-form/__snapshots__/attach-detach-cloud-volume-form.spec.js.snap index 80ab5c0cc94..9d578db641d 100644 --- a/app/javascript/spec/cloud-volume-form/__snapshots__/attach-detach-cloud-volume-form.spec.js.snap +++ b/app/javascript/spec/cloud-volume-form/__snapshots__/attach-detach-cloud-volume-form.spec.js.snap @@ -6,6 +6,7 @@ exports[`Attach / Detach form component should render Attach Cloud Volume to the Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -1271,6 +1272,7 @@ exports[`Attach / Detach form component should render Attach Selected Cloud Volu Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -2536,6 +2538,7 @@ exports[`Attach / Detach form component should render Detach Cloud Volume from t Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -3581,6 +3584,7 @@ exports[`Attach / Detach form component should render Detach Selected Cloud Volu Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -4628,6 +4632,7 @@ exports[`Attach / Detach form component should submit Attach API call 1`] = ` Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -4677,6 +4682,7 @@ exports[`Attach / Detach form component should submit Detach API call 1`] = ` Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/custom-buttom-form/__snapshots__/custom-button-form.spec.js.snap b/app/javascript/spec/custom-buttom-form/__snapshots__/custom-button-form.spec.js.snap index 223e96a5d48..1a9c20f82cd 100644 --- a/app/javascript/spec/custom-buttom-form/__snapshots__/custom-button-form.spec.js.snap +++ b/app/javascript/spec/custom-buttom-form/__snapshots__/custom-button-form.spec.js.snap @@ -346,6 +346,7 @@ exports[`Custom Button form component should edit a generic object custom button Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -805,6 +806,7 @@ exports[`Custom Button form component should render the editing form for generic Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/data-store-fore/__snapshots__/datastore-form.spec.js.snap b/app/javascript/spec/data-store-fore/__snapshots__/datastore-form.spec.js.snap index 3a0de2f81ab..3853b1db167 100644 --- a/app/javascript/spec/data-store-fore/__snapshots__/datastore-form.spec.js.snap +++ b/app/javascript/spec/data-store-fore/__snapshots__/datastore-form.spec.js.snap @@ -72,6 +72,7 @@ exports[`Datastore form component Datastore domain form component should render Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -1656,6 +1657,7 @@ exports[`Datastore form component Datastore namespace form component should rend Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/diagnostics-collect-log-form/__snapshots__/diagnostics-collect-log-form.spec.js.snap b/app/javascript/spec/diagnostics-collect-log-form/__snapshots__/diagnostics-collect-log-form.spec.js.snap index 3305834cf48..c7ad703e657 100644 --- a/app/javascript/spec/diagnostics-collect-log-form/__snapshots__/diagnostics-collect-log-form.spec.js.snap +++ b/app/javascript/spec/diagnostics-collect-log-form/__snapshots__/diagnostics-collect-log-form.spec.js.snap @@ -6,6 +6,7 @@ exports[`Diagnostics Collect Log form component should render edit DiagnosticsCo Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -1555,6 +1556,7 @@ exports[`Diagnostics Collect Log form component should render edit DiagnosticsCo Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -3104,6 +3106,7 @@ exports[`Diagnostics Collect Log form component should render new DiagnosticsCol Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/evacuate-form/__snapshots__/evacuate-form.spec.js.snap b/app/javascript/spec/evacuate-form/__snapshots__/evacuate-form.spec.js.snap index a043a0e6e7e..80b85edd8c0 100644 --- a/app/javascript/spec/evacuate-form/__snapshots__/evacuate-form.spec.js.snap +++ b/app/javascript/spec/evacuate-form/__snapshots__/evacuate-form.spec.js.snap @@ -6,6 +6,7 @@ exports[`evacuate form component should render evacuate form when hosts empty 1` Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -1917,6 +1918,7 @@ exports[`evacuate form component should render evacuate form with host options 1 Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -4250,6 +4252,7 @@ exports[`evacuate form component should render evacuate form with multiple insta Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/filter-dropdown/__snapshots__/filter-dropdown.spec.js.snap b/app/javascript/spec/filter-dropdown/__snapshots__/filter-dropdown.spec.js.snap index f698694a1c2..7238ef7deee 100644 --- a/app/javascript/spec/filter-dropdown/__snapshots__/filter-dropdown.spec.js.snap +++ b/app/javascript/spec/filter-dropdown/__snapshots__/filter-dropdown.spec.js.snap @@ -6,6 +6,7 @@ exports[`Filter Dropdown form should handle cancel 1`] = ` Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/generic-objects-form/__snapshots__/generic-objects-form.spec.js.snap b/app/javascript/spec/generic-objects-form/__snapshots__/generic-objects-form.spec.js.snap index 403ae656bcb..c70e4cb9f32 100644 --- a/app/javascript/spec/generic-objects-form/__snapshots__/generic-objects-form.spec.js.snap +++ b/app/javascript/spec/generic-objects-form/__snapshots__/generic-objects-form.spec.js.snap @@ -6,6 +6,7 @@ exports[`Generic Object Form Component should render adding a new generic object Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -4602,6 +4603,7 @@ exports[`Generic Object Form Component should render editing a generic object wi Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -12242,6 +12244,7 @@ exports[`Generic Object Form Component should render editing a generic object wi Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/host-aggregate-form/__snapshots__/host-aggregate-form.spec.js.snap b/app/javascript/spec/host-aggregate-form/__snapshots__/host-aggregate-form.spec.js.snap index c45a9cd8191..7bef9cac297 100644 --- a/app/javascript/spec/host-aggregate-form/__snapshots__/host-aggregate-form.spec.js.snap +++ b/app/javascript/spec/host-aggregate-form/__snapshots__/host-aggregate-form.spec.js.snap @@ -34,6 +34,7 @@ exports[`Host aggregate form component should render add host form variant (remv Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -974,6 +975,7 @@ exports[`Host aggregate form component should render editing form variant 1`] = Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/host-edit-form/__snapshots__/host-edit-form.spec.js.snap b/app/javascript/spec/host-edit-form/__snapshots__/host-edit-form.spec.js.snap index c505fee6902..7c002b3d22e 100644 --- a/app/javascript/spec/host-edit-form/__snapshots__/host-edit-form.spec.js.snap +++ b/app/javascript/spec/host-edit-form/__snapshots__/host-edit-form.spec.js.snap @@ -6,6 +6,7 @@ exports[`Show Edit Host Form Component should render form for *one* host 1`] = ` Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -5490,6 +5491,7 @@ exports[`Show Edit Host Form Component should render form for multiple hosts 1`] Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/host-initiator-group-form/__snapshots__/host-initiator-group.spec.js.snap b/app/javascript/spec/host-initiator-group-form/__snapshots__/host-initiator-group.spec.js.snap index 9a892258df7..be58b81fb1a 100644 --- a/app/javascript/spec/host-initiator-group-form/__snapshots__/host-initiator-group.spec.js.snap +++ b/app/javascript/spec/host-initiator-group-form/__snapshots__/host-initiator-group.spec.js.snap @@ -6,6 +6,7 @@ exports[`Host Initiator Group Form Loads data and renders 1`] = ` Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/live-migrate-form/__snapshots__/live-migrate-form.spec.js.snap b/app/javascript/spec/live-migrate-form/__snapshots__/live-migrate-form.spec.js.snap index 82f2186ef6d..5191c8a36a3 100644 --- a/app/javascript/spec/live-migrate-form/__snapshots__/live-migrate-form.spec.js.snap +++ b/app/javascript/spec/live-migrate-form/__snapshots__/live-migrate-form.spec.js.snap @@ -6,6 +6,7 @@ exports[`Live Migrate form component should render live migrate form when hosts Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -1861,6 +1862,7 @@ exports[`Live Migrate form component should render live migrate form with host o Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], @@ -4138,6 +4140,7 @@ exports[`Live Migrate form component should render live migrate form with multip Object { "asyncReducers": Object { "FormButtons": [Function], + "miqCustomTabReducer": [Function], "notificationReducer": [Function], }, "dispatch": [Function], diff --git a/app/javascript/spec/miq-custom-tab/__snapshots__/miq-custom-tab.spec.js.snap b/app/javascript/spec/miq-custom-tab/__snapshots__/miq-custom-tab.spec.js.snap index 86354a51a21..2233b740d96 100644 --- a/app/javascript/spec/miq-custom-tab/__snapshots__/miq-custom-tab.spec.js.snap +++ b/app/javascript/spec/miq-custom-tab/__snapshots__/miq-custom-tab.spec.js.snap @@ -1,131 +1,965 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`MiqCustomTab component should render tabs for catalog edit page 1`] = ` - - - - - + + + +
+ +
    + +
  • + +
  • +
    + +
  • + +
  • +
    + +
  • + +
  • +
    +
+ +
+