Update to use ReactInput

This commit is contained in:
Eric Schultz 2018-07-12 11:39:28 -05:00
parent 5ff8fdc86b
commit 0ac08c8ce0
9 changed files with 55 additions and 70 deletions

View file

@ -5,15 +5,16 @@ import {Field} from "../../../../types/mobx-react-form";
import LabeledFieldComponent from "./LabeledFieldComponent"; import LabeledFieldComponent from "./LabeledFieldComponent";
import {injectIntl, InjectedIntl} from 'react-intl'; import {injectIntl, InjectedIntl} from 'react-intl';
import {HoudiniField} from "../../lib/houdini_form"; import {HoudiniField} from "../../lib/houdini_form";
import ReactInput from "./form/ReactInput";
export const BasicField = injectIntl(observer((props:{field:Field, intl?:InjectedIntl, wrapperClassName?:string}) =>{ export const BasicField = observer((props:{field:Field, placeholder?:string, label?:string, wrapperClassName?:string}) =>{
let field = props.field as HoudiniField let field = props.field as HoudiniField
return <LabeledFieldComponent return <LabeledFieldComponent
inputId={props.field.id} labelText={field.label} inError={field.hasError} error={field.error} inputId={props.field.id} labelText={field.label} inError={field.hasError} error={field.error}
inStickyError={field.hasServerError} stickyError={field.serverError} inStickyError={field.hasServerError} stickyError={field.serverError}
className={props.wrapperClassName} > className={props.wrapperClassName} >
<input {...props.field.bind()} placeholder={field.placeholder ? props.intl.formatMessage({id:field.placeholder}) : undefined} className="form-control"/> <ReactInput field={field} label={props.label} placeholder={props.placeholder} className="form-control"/>
</LabeledFieldComponent> </LabeledFieldComponent>
})) })

View file

@ -10,7 +10,8 @@ export interface ReactFormProps
} }
///Mostly useless class but, at some point, will replace all our form elements ///Mostly useless class but, at some point, will replace all our form elements
class ReactForm extends React.Component<ReactFormProps, {}> { @observer
export class ReactForm extends React.Component<ReactFormProps, {}> {
@ -43,7 +44,6 @@ class ReactForm extends React.Component<ReactFormProps, {}> {
} }
} }
export default observer(ReactForm)

View file

@ -3,11 +3,11 @@ import * as React from 'react';
import 'jest'; import 'jest';
import ReactInput from './ReactInput' import ReactInput from './ReactInput'
import {Form} from "mobx-react-form"; import {Form} from "mobx-react-form";
import ReactForm from "./ReactForm";
import {mount} from 'enzyme'; import {mount} from 'enzyme';
import {toJS, observable, action, runInAction} from 'mobx'; import {toJS, observable, action, runInAction} from 'mobx';
import {observer} from 'mobx-react'; import {observer} from 'mobx-react';
import {InputHTMLAttributes} from 'react'; import {InputHTMLAttributes} from 'react';
import {ReactForm} from "./ReactForm";
@ -99,7 +99,9 @@ describe('ReactInput', () => {
let res = mount(<TestChange/>) let res = mount(<TestChange/>)
let f = res.find('ReactForm').instance() as ReactForm // The two casts are needed because Typescript was going blowing up without the 'any' first.
// Why was it? *shrugs*
let f = res.find('ReactForm').instance() as any as ReactForm
expect(f.form.size).toEqual(1) expect(f.form.size).toEqual(1)
res.find('input').simulate('change', {target: { value: 'something' } }) res.find('input').simulate('change', {target: { value: 'something' } })
@ -146,7 +148,7 @@ describe('ReactInput', () => {
let res = mount(<TestChange> let res = mount(<TestChange>
<WrappedInput/> <WrappedInput/>
</TestChange>) </TestChange>)
let f = res.find('ReactForm').instance() as ReactForm let f = res.find('ReactForm').instance() as any as ReactForm
res.find('input').simulate('change', {target: { value: 'something' } }) res.find('input').simulate('change', {target: { value: 'something' } })
expect(f.form.$('name').value).toEqual('something') expect(f.form.$('name').value).toEqual('something')

View file

@ -6,12 +6,13 @@ import {Field} from "mobx-react-form";
import {observable, action, toJS, runInAction} from 'mobx'; import {observable, action, toJS, runInAction} from 'mobx';
import {InputHTMLAttributes} from 'react'; import {InputHTMLAttributes} from 'react';
export interface ReactInputProps export interface ReactInputProps
{ {
field:Field field:Field
label?:string label?:string
placeholder?:string placeholder?:string
children: React.ReactElement<InputHTMLAttributes<HTMLInputElement>>
} }
function castToNullIfUndef(i:any){ function castToNullIfUndef(i:any){

View file

@ -17,47 +17,31 @@ export interface NonprofitInfoFormProps
export const FieldDefinitions : Array<FieldDefinition> = [ export const FieldDefinitions : Array<FieldDefinition> = [
{ {
name: 'organization_name', name: 'organization_name',
label: 'registration.wizard.nonprofit.name.label',
placeholder: 'registration.wizard.nonprofit.name.placeholder',
type: 'text',
validators: [Validations.isFilled] validators: [Validations.isFilled]
}, },
{ {
name: 'website', name: 'website',
label: 'registration.wizard.nonprofit.website.label',
placeholder: 'registration.wizard.nonprofit.website.placeholder',
validators: [Validations.optional(Validations.isUrl)] validators: [Validations.optional(Validations.isUrl)]
}, },
{ {
name: 'org_email', name: 'org_email',
label: 'registration.wizard.nonprofit.email.label',
placeholder: 'registration.wizard.nonprofit.email.placeholder',
validators: [Validations.optional(Validations.isEmail)] validators: [Validations.optional(Validations.isEmail)]
}, },
{ {
name: 'org_phone', name: 'org_phone',
label: 'registration.wizard.nonprofit.phone.label',
placeholder: 'registration.wizard.nonprofit.phone.placeholder',
type: "tel" type: "tel"
}, },
{ {
name: 'city', name: 'city',
label: 'registration.wizard.nonprofit.city.label',
placeholder: 'registration.wizard.nonprofit.city.placeholder',
validators: [Validations.isFilled] validators: [Validations.isFilled]
}, },
{ {
name: 'state', name: 'state',
label: 'registration.wizard.nonprofit.state.label',
placeholder: 'registration.wizard.nonprofit.state.placeholder',
type: 'text',
validators: [Validations.isFilled] validators: [Validations.isFilled]
}, },
{ {
name: 'zip', name: 'zip',
label: 'registration.wizard.nonprofit.zip.label',
placeholder: 'registration.wizard.nonprofit.zip.placeholder',
validators: [Validations.isFilled] validators: [Validations.isFilled]
} }
] ]
@ -67,17 +51,33 @@ class NonprofitInfoForm extends React.Component<NonprofitInfoFormProps & Injecte
render() { render() {
return <fieldset > return <fieldset >
<BasicField field={this.props.form.$("organization_name")}/> <BasicField field={this.props.form.$("organization_name")}
<BasicField field={this.props.form.$('website')}/> label={this.props.intl.formatMessage({id:'registration.wizard.nonprofit.name.label' })}
placeholder={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.name.placeholder'})}
/>
<BasicField field={this.props.form.$('website')}
label={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.website.label'})}
placeholder={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.website.placeholder'})}/>
<TwoColumnFields> <TwoColumnFields>
<BasicField field={this.props.form.$('org_email')}/> <BasicField field={this.props.form.$('org_email')}
<BasicField field={this.props.form.$('org_phone')}/> label={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.email.label'})}
placeholder={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.email.placeholder'})}/>
<BasicField field={this.props.form.$('org_phone')}
label={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.phone.label'})}
placeholder={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.phone.placeholder'})}/>
</TwoColumnFields> </TwoColumnFields>
<ThreeColumnFields> <ThreeColumnFields>
<BasicField field={this.props.form.$('city')}/> <BasicField field={this.props.form.$('city')}
<BasicField field={this.props.form.$('state')}/> label={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.city.label'})}
<BasicField field={this.props.form.$('zip')}/> placeholder={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.city.placeholder'})}/>
<BasicField field={this.props.form.$('state')}
label={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.state.label'})}
placeholder={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.state.placeholder'})}/>
<BasicField field={this.props.form.$('zip')}
label={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.zip.label' })}
placeholder={this.props.intl.formatMessage({id: 'registration.wizard.nonprofit.zip.placeholder'})}/>
</ThreeColumnFields> </ThreeColumnFields>
<ProgressableButton onClick={this.props.form.onSubmit} className="button" disabled={!this.props.form.isValid} buttonText={this.props.intl.formatMessage({id: this.props.buttonText})} <ProgressableButton onClick={this.props.form.onSubmit} className="button" disabled={!this.props.form.isValid} buttonText={this.props.intl.formatMessage({id: this.props.buttonText})}
inProgress={this.props.form.submitting || this.props.form.container().submitting} disableOnProgress={true}/> inProgress={this.props.form.submitting || this.props.form.container().submitting} disableOnProgress={true}/>

View file

@ -175,24 +175,6 @@ export class InnerRegistrationWizard extends React.Component<RegistrationWizardP
this.form.signinApi = this.props.ApiManager.get(WebUserSignInOut) this.form.signinApi = this.props.ApiManager.get(WebUserSignInOut)
} }
//set up labels
let label: {[props:string]: string} = {
'nonprofitTab[organization_name]': "registration.wizard.nonprofit.name.label",
"nonprofitTab[website]": 'registration.wizard.nonprofit.website.label',
"nonprofitTab[org_email]": 'registration.wizard.nonprofit.email.label',
'nonprofitTab[org_phone]': 'registration.wizard.nonprofit.phone.label',
'nonprofitTab[city]': 'registration.wizard.nonprofit.city.label',
'nonprofitTab[state]': 'registration.wizard.nonprofit.state.label',
'nonprofitTab[zip]': 'registration.wizard.nonprofit.zip.label',
'userTab[name]': 'registration.wizard.contact.name.label',
'userTab[email]': 'registration.wizard.contact.email.label',
'userTab[password]': 'registration.wizard.contact.password.label',
'userTab[password_confirmation]': 'registration.wizard.contact.password_confirmation.label'
}
for (let key in label){
this.form.$(key).set('label', this.props.intl.formatMessage({id: label[key]}))
}
return <Wizard wizardState={this.registrationWizardState} disableTabs={this.form.submitting}> return <Wizard wizardState={this.registrationWizardState} disableTabs={this.form.submitting}>
<NonprofitInfoPanel tab={this.registrationWizardState.tabsByName['nonprofitTab']} <NonprofitInfoPanel tab={this.registrationWizardState.tabsByName['nonprofitTab']}
buttonText="registration.wizard.next"/> buttonText="registration.wizard.next"/>

View file

@ -12,8 +12,6 @@ import {areWeOrAnyParentSubmitting} from "../../lib/houdini_form";
export const FieldDefinitions : Array<FieldDefinition> = [ export const FieldDefinitions : Array<FieldDefinition> = [
{ {
name: 'name', name: 'name',
label: 'registration.wizard.contact.name.label',
placeholder: 'registration.wizard.contact.name.placeholder',
validators: [Validations.isFilled] validators: [Validations.isFilled]
}, },
{ {
@ -24,14 +22,12 @@ export const FieldDefinitions : Array<FieldDefinition> = [
}, },
{ {
name: 'password', name: 'password',
label: 'registration.wizard.contact.password.label',
type: 'password', type: 'password',
validators: [Validations.isFilled], validators: [Validations.isFilled],
related: ['userTab.password_confirmation'] related: ['userTab.password_confirmation']
}, },
{ {
name: 'password_confirmation', name: 'password_confirmation',
label: 'registration.wizard.contact.password_confirmation.label',
type: 'password', type: 'password',
validators: [Validations.shouldBeEqualTo("userTab.password")] validators: [Validations.shouldBeEqualTo("userTab.password")]
} }
@ -50,12 +46,22 @@ class UserInfoForm extends React.Component<UserInfoFormProps & InjectedIntlProps
render() { render() {
return <fieldset> return <fieldset>
<TwoColumnFields> <TwoColumnFields>
<BasicField field={this.props.form.$("name")}/> <BasicField field={this.props.form.$("name")}
<BasicField field={this.props.form.$('email')}/> label={
this.props.intl.formatMessage({id: "registration.wizard.contact.name.label"})}
placeholder={this.props.intl.formatMessage({id: "registration.wizard.contact.name.placeholder"})}/>
<BasicField field={this.props.form.$('email')}
label={this.props.intl.formatMessage({id: "registration.wizard.contact.email.label"})}
placeholder={this.props.intl.formatMessage({id: "registration.wizard.contact.email.placeholder"})}
/>
</TwoColumnFields> </TwoColumnFields>
<BasicField field={this.props.form.$('password')}/> <BasicField field={this.props.form.$('password')}
<BasicField field={this.props.form.$('password_confirmation')}/> label={this.props.intl.formatMessage({id:'registration.wizard.contact.password.label'})}
/>
<BasicField field={this.props.form.$('password_confirmation')}
label={this.props.intl.formatMessage({id:'registration.wizard.contact.password_confirmation.label'})}
/>
<ProgressableButton onClick={this.props.form.onSubmit} <ProgressableButton onClick={this.props.form.onSubmit}

View file

@ -23,13 +23,11 @@ export interface SessionLoginFormProps
export const FieldDefinitions : Array<FieldDefinition> = [ export const FieldDefinitions : Array<FieldDefinition> = [
{ {
name: 'email', name: 'email',
label: 'email',
type: 'text', type: 'text',
validators: [Validations.isFilled] validators: [Validations.isFilled]
}, },
{ {
name: 'password', name: 'password',
label: 'password',
type: 'password', type: 'password',
validators: [Validations.isFilled] validators: [Validations.isFilled]
} }
@ -100,20 +98,14 @@ class InnerSessionLoginForm extends React.Component<SessionLoginFormProps & Inje
if(!this.form.signinApi){ if(!this.form.signinApi){
this.form.signinApi = this.props.ApiManager.get(WebUserSignInOut) this.form.signinApi = this.props.ApiManager.get(WebUserSignInOut)
} }
let label: {[props:string]: string} = {
'email': "login.email",
"password": 'login.password',
}
for (let key in label){
this.form.$(key).set('label', this.props.intl.formatMessage({id: label[key]}))
}
let errorDiv = !this.form.isValid ? <div className="form-group has-error"><div className="help-block" role="alert">{(this.form as any).error}</div></div> : '' let errorDiv = !this.form.isValid ? <div className="form-group has-error"><div className="help-block" role="alert">{(this.form as any).error}</div></div> : ''
return <form onSubmit={this.form.onSubmit}> return <form onSubmit={this.form.onSubmit}>
<BasicField field={this.form.$('email')}/> <BasicField field={this.form.$('email')}
<BasicField field={this.form.$('password')}/> label={this.props.intl.formatMessage({id: 'login.email'})}/>
<BasicField field={this.form.$('password')}
label={this.props.intl.formatMessage({id: 'login.password'})}/>
{errorDiv} {errorDiv}
<div className={'form-group'}> <div className={'form-group'}>
<ProgressableButton onClick={this.form.onSubmit} className="button" disabled={!this.form.isValid || this.form.submitting} inProgress={this.form.submitting} <ProgressableButton onClick={this.form.onSubmit} className="button" disabled={!this.form.isValid || this.form.submitting} inProgress={this.form.submitting}

View file

@ -311,6 +311,7 @@ export class Form implements Base {
protected validator :any protected validator :any
readonly isValid :boolean; readonly isValid :boolean;
readonly size:number
} }