diff --git a/app/javascript/components/set-service-ownership-form/index.jsx b/app/javascript/components/set-service-ownership-form/index.jsx new file mode 100644 index 00000000000..a2286de7ad0 --- /dev/null +++ b/app/javascript/components/set-service-ownership-form/index.jsx @@ -0,0 +1,57 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { Grid } from 'patternfly-react'; +import MiqFormRenderer from '../../forms/data-driven-form'; +import { http } from '../../http_api'; +import { cleanVirtualDom } from '../../miq-component/helpers'; +import createSchema from './schema'; + +class SetServiceOwnershipForm extends Component { + state = { + initialValues: {}, + } + + componentDidMount() { + cleanVirtualDom(); + const { ownershipIds } = this.props; + this.loadInitialData(ownershipIds); + } + + loadInitialData = objectIds => + http.post('/service/ownership_form_fields', { object_ids: objectIds }) + .then(data => this.setState({ initialValues: data })) + + + handleSubmit = (values, objectIds, url) => miqAjaxButton(url, { + objectIds, + ...values, + }) + + render() { + const { groupOptions, ownerOptions, ownershipIds } = this.props; + const { initialValues } = this.state; + const cancelUrl = '/service/ownership_update/?button=cancel'; + const submitUrl = '/service/ownership_update/?button=save'; + + return ( + + this.handleSubmit(values, ownershipIds, submitUrl)} + onReset={() => add_flash(__('All changes have been reset'), 'warn')} + onCancel={() => miqAjaxButton(cancelUrl)} + canReset + /> + + ); + } +} + +SetServiceOwnershipForm.propTypes = { + ownershipIds: PropTypes.arrayOf(PropTypes.string).isRequired, + groupOptions: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)).isRequired, + ownerOptions: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)).isRequired, +}; + +export default SetServiceOwnershipForm; diff --git a/app/javascript/components/set-service-ownership-form/schema.js b/app/javascript/components/set-service-ownership-form/schema.js new file mode 100644 index 00000000000..8a1700bbfa2 --- /dev/null +++ b/app/javascript/components/set-service-ownership-form/schema.js @@ -0,0 +1,25 @@ +import { componentTypes } from '@data-driven-forms/react-form-renderer'; + +const createSchema = (ownerOptions, groupOptions) => ({ + fields: [{ + component: componentTypes.SELECT_COMPONENT, + name: 'user', + id: 'user_name', + label: __('Select an Owner:'), + options: ownerOptions.map(([label, value]) => ({ + label, + value, + })), + }, { + component: componentTypes.SELECT_COMPONENT, + name: 'group', + id: 'group_name', + label: __('Select a Group:'), + options: groupOptions.map(([label, value]) => ({ + label, + value, + })), + }], +}); + +export default createSchema; diff --git a/app/javascript/packs/component-definitions-common.js b/app/javascript/packs/component-definitions-common.js index 78f8e4c0feb..6c524306a7d 100644 --- a/app/javascript/packs/component-definitions-common.js +++ b/app/javascript/packs/component-definitions-common.js @@ -8,6 +8,7 @@ import FormButtonsRedux from '../forms/form-buttons-redux'; import MiqAboutModal from '../components/miq-about-modal'; import CloudTenantForm from '../components/cloud-tenant-form/cloud-tenant-form'; import ServiceForm from '../components/service-form'; +import SetServiceOwnershipForm from '../components/set-service-ownership-form'; /** * Add component definitions to this file. @@ -26,3 +27,4 @@ ManageIQ.component.addReact('FormButtonsRedux', FormButtonsRedux); ManageIQ.component.addReact('MiqAboutModal', MiqAboutModal); ManageIQ.component.addReact('CloudTenantForm', CloudTenantForm); ManageIQ.component.addReact('ServiceForm', ServiceForm); +ManageIQ.component.addReact('SetServiceOwnershipForm', SetServiceOwnershipForm); diff --git a/app/javascript/spec/set-service-ownership-form/set-service-ownership-form.spec.js b/app/javascript/spec/set-service-ownership-form/set-service-ownership-form.spec.js new file mode 100644 index 00000000000..ae46c41cf8d --- /dev/null +++ b/app/javascript/spec/set-service-ownership-form/set-service-ownership-form.spec.js @@ -0,0 +1,81 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import FormRenderer from '@data-driven-forms/react-form-renderer'; +import SetServiceOwnershipForm from '../../components/set-service-ownership-form'; +import createSchema from '../../components/set-service-ownership-form/schema'; +import { http } from '../../http_api'; + +describe('Set service ownership form component', () => { + let initialProps; + const httpSpy = jest.spyOn(http, 'post'); + const submitSpy = jest.spyOn(window, 'miqAjaxButton'); + const flashSpy = jest.spyOn(window, 'add_flash'); + + beforeEach(() => { + initialProps = { + ownershipIds: ['123456'], + groupOptions: [['Foo', '1'], ['Bar', '2']], + ownerOptions: [['Baz', '3'], ['Quxx', '4']], + }; + }); + + afterEach(() => { + submitSpy.mockReset(); + flashSpy.mockReset(); + }); + + it('should correctly map group and owner options ', () => { + const expectedResult = [ + expect.objectContaining({ + options: [{ + value: '3', + label: 'Baz', + }, { + value: '4', + label: 'Quxx', + }], + }), + expect.objectContaining({ + options: [{ + value: '1', + label: 'Foo', + }, { + value: '2', + label: 'Bar', + }], + }), + ]; + const { fields } = createSchema(initialProps.ownerOptions, initialProps.groupOptions); + expect(fields).toEqual(expectedResult); + }); + + // TO DO replace with actual request mock + it('should request initialForm values after mount', () => { + mount(); + expect(httpSpy).toHaveBeenCalledWith('/service/ownership_form_fields', { object_ids: ['123456'] }); + }); + + it('should send correct data on save', () => { + const wrapper = mount(); + const Form = wrapper.find(FormRenderer).childAt(0); + Form.instance().form.change('user', 'foo'); + wrapper.find('button').at(0).simulate('click'); + expect(submitSpy).toHaveBeenCalledWith('/service/ownership_update/?button=save', { objectIds: ['123456'], user: 'foo' }); + }); + + it('should send correct data on cancel', () => { + const wrapper = mount(); + wrapper.find('button').last().simulate('click'); + expect(submitSpy).toHaveBeenCalledWith('/service/ownership_update/?button=cancel'); + }); + + it('should reset formValues and add flash messages on reset click', () => { + const wrapper = mount(); + const Form = wrapper.find(FormRenderer).childAt(0); + Form.instance().form.change('user', 'foo'); + expect(Form.instance().form.getState().values).toEqual({ user: 'foo' }); + wrapper.find('button').at(1).simulate('click'); + expect(Form.instance().form.getState().values).toEqual({}); + expect(flashSpy).toHaveBeenCalledWith(expect.any(String), 'warn'); + }); +});