New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace service form #4985
Replace service form #4985
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import React, { Component } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { Grid } from 'patternfly-react'; | ||
import createSchema from './schema'; | ||
import MiqFormRenderer from '../../forms/data-driven-form'; | ||
import { http } from '../../http_api'; | ||
import { cleanVirtualDom } from '../../miq-component/helpers'; | ||
|
||
class ServiceForm extends Component { | ||
constructor(props) { | ||
super(props); | ||
this.state = { | ||
schema: createSchema(props.maxNameLen, props.maxDescLen), | ||
}; | ||
} | ||
componentDidMount() { | ||
cleanVirtualDom(); | ||
miqSparkleOn(); | ||
http.get(`/service/service_form_fields/${this.props.serviceFormId}`) | ||
.then(data => this.setState({ initialValues: { ...data } }, miqSparkleOff())); | ||
} | ||
render() { | ||
const { serviceFormId } = this.props; | ||
const cancelUrl = `/service/service_edit/${serviceFormId}?button=cancel`; | ||
const submitUrl = `/service/service_edit/${serviceFormId}?button=save`; | ||
return ( | ||
<Grid fluid style={{ paddingTop: 20 }}> | ||
<MiqFormRenderer | ||
initialValues={this.state.initialValues} | ||
schema={this.state.schema} | ||
onSubmit={values => miqAjaxButton(submitUrl, values)} | ||
onCancel={() => miqAjaxButton(cancelUrl)} | ||
onReset={() => add_flash(__('All changes have been reset'), 'warn')} | ||
canReset | ||
buttonsLabels={{ | ||
submitLabel: __('Save'), | ||
resetLabel: __('Reset'), | ||
cancelLabel: __('Cancel'), | ||
}} | ||
/> | ||
</Grid> | ||
); | ||
} | ||
} | ||
|
||
ServiceForm.propTypes = { | ||
maxNameLen: PropTypes.number.isRequired, | ||
maxDescLen: PropTypes.number.isRequired, | ||
serviceFormId: PropTypes.number.isRequired, | ||
}; | ||
|
||
export default ServiceForm; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
function createSchema(maxNameLen, maxDescLen) { | ||
return { | ||
fields: [{ | ||
component: 'text-field', | ||
name: 'name', | ||
maxLength: maxNameLen, | ||
label: __('Name'), | ||
validateOnMount: true, | ||
autoFocus: true, | ||
validate: [{ | ||
type: 'required-validator', | ||
}], | ||
}, { | ||
component: 'text-field', | ||
name: 'description', | ||
maxLength: maxDescLen, | ||
label: __('Description'), | ||
validateOnMount: true, | ||
autoFocus: true, | ||
validate: [{ | ||
type: 'required-validator', | ||
}], | ||
}], | ||
}; | ||
} | ||
|
||
export default createSchema; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,5 +10,4 @@ const MiqFormRenderer = props => ( | |
{...props} | ||
/> | ||
); | ||
|
||
export default MiqFormRenderer; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import React from 'react'; | ||
import { mount } from 'enzyme'; | ||
import fetchMock from 'fetch-mock'; | ||
import FormRender from '@data-driven-forms/react-form-renderer'; | ||
import ServiceForm from '../../components/service-form'; | ||
|
||
describe('Cloud tenant form component', () => { | ||
let initialProps; | ||
let submitSpy; | ||
let flashSpy; | ||
|
||
beforeEach(() => { | ||
initialProps = { | ||
maxNameLen: 1, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Submit can't ever be undisabled when validation fails, right? This needs to be at least EDIT: fixed in #5018 |
||
maxDescLen: 2, | ||
serviceFormId: 3, | ||
}; | ||
submitSpy = jest.spyOn(window, 'miqAjaxButton'); | ||
flashSpy = jest.spyOn(window, 'add_flash'); | ||
}); | ||
|
||
afterEach(() => { | ||
fetchMock.reset(); | ||
fetchMock.restore(); | ||
submitSpy.mockRestore(); | ||
}); | ||
|
||
it('should request data after mount and set to state', (done) => { | ||
fetchMock | ||
.getOnce('/service/service_form_fields/3', { | ||
foo: 'bar', | ||
}); | ||
const wrapper = mount(<ServiceForm {...initialProps} />); | ||
expect(fetchMock.lastUrl()).toEqual('/service/service_form_fields/3'); | ||
setImmediate(() => { | ||
wrapper.update(); | ||
expect(wrapper.state().initialValues).toEqual({ foo: 'bar' }); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should call cancel action', (done) => { | ||
fetchMock | ||
.getOnce('/service/service_form_fields/3', { | ||
name: 'foo', | ||
description: 'bar', | ||
}); | ||
const wrapper = mount(<ServiceForm {...initialProps} />); | ||
|
||
setImmediate(() => { | ||
wrapper.find('button').last().simulate('click'); | ||
expect(submitSpy).toHaveBeenCalledWith('/service/service_edit/3?button=cancel'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should enable reset button and call reset callback', (done) => { | ||
fetchMock | ||
.getOnce('/service/service_form_fields/3', {}); | ||
const wrapper = mount(<ServiceForm {...initialProps} />); | ||
|
||
setImmediate(() => { | ||
// reset should be disabled | ||
wrapper.find('button').at(1).simulate('click'); | ||
expect(flashSpy).not.toHaveBeenCalled(); | ||
// change value of some input to enable reset button | ||
wrapper.find('input').first().simulate('change', { | ||
target: { | ||
value: 'foo', | ||
}, | ||
}); | ||
wrapper.find('button').at(1).simulate('click'); | ||
expect(flashSpy).toHaveBeenCalledWith(expect.any(String), 'warn'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should enable submit button and call submit callback', (done) => { | ||
fetchMock | ||
.getOnce('/service/service_form_fields/3', {}); | ||
const wrapper = mount(<ServiceForm {...initialProps} />); | ||
|
||
setImmediate(() => { | ||
// reset should be disabled | ||
wrapper.find('button').at(0).simulate('click'); | ||
// change form state to enable reset button | ||
wrapper.find(FormRender).childAt(0).instance().form.change('name', 'foo'); | ||
wrapper.find(FormRender).childAt(0).instance().form.change('description', 'bar'); | ||
wrapper.find('button').at(0).simulate('click'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's still disabled, (probably fixed in #5018) |
||
expect(submitSpy).toHaveBeenCalledWith('/service/service_edit/3?button=save', { name: 'foo', description: 'bar' }); | ||
done(); | ||
}); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,2 @@ | ||
- @angular_form = true | ||
|
||
%form.form-horizontal#form_div{"name" => "angularForm", | ||
"ng-controller" => "serviceFormController as vm", | ||
"ng-show" => "vm.afterGet", | ||
"model" => "vm.serviceModel", | ||
"model-copy" => "vm.modelCopy", | ||
"miq-form" => true, | ||
"form-changed" => true} | ||
= render :partial => "layouts/flash_msg" | ||
%div | ||
%div | ||
.form-group{"ng-class" => "{'has-error': angularForm.name.$invalid}"} | ||
%div | ||
%div | ||
.form-group{"ng-class" => "{'has-error': angularForm.name.$invalid}"} | ||
%label.col-md-2.control-label{"for" => "name"} | ||
= _("Name") | ||
.col-md-8 | ||
%input.form-control{"type" => "text", | ||
"id" => "name", | ||
"name" => "name", | ||
"ng-model" => "vm.serviceModel.name", | ||
"maxlength" => "#{ViewHelper::MAX_NAME_LEN}", | ||
"required" => true, | ||
"auto-focus" => ""} | ||
%span.help-block{"ng-show" => "angularForm.name.$error.miqrequired"} | ||
= _("Required") | ||
.form-group{"ng-class" => "{'has-error': angularForm.description.$invalid}"} | ||
%label.col-md-2.control-label{"for" => "description"} | ||
= _("Description") | ||
.col-md-8 | ||
%input.form-control{"type" => "text", | ||
"id" => "description", | ||
"name" => "description", | ||
"ng-model" => "vm.serviceModel.description", | ||
"maxlength" => "#{ViewHelper::MAX_DESC_LEN}", | ||
"required" => true} | ||
= render :partial => "layouts/angular/generic_form_buttons" | ||
|
||
:javascript | ||
ManageIQ.angular.app.value('serviceFormId', '#{@service.id}'); | ||
miq_bootstrap('#form_div'); | ||
= render :partial => "layouts/flash_msg" | ||
= react('ServiceForm', { :maxNameLen => ViewHelper::MAX_NAME_LEN, :maxDescLen => ViewHelper::MAX_DESC_LEN, :serviceFormId => @service.id}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cloud tenant != Service
EDIT: fixed in #5018