Skip to content

Commit

Permalink
Fieldsets
Browse files Browse the repository at this point in the history
  • Loading branch information
jsomsanith committed May 11, 2017
1 parent 7e39984 commit f7fc2d0
Show file tree
Hide file tree
Showing 13 changed files with 213 additions and 50 deletions.
3 changes: 0 additions & 3 deletions packages/forms/src/FieldMessage/index.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { PropTypes } from 'react';

export default function FieldMessage(props) {
export default function Message(props) {
const {
errorMessage,
description,
Expand All @@ -17,7 +17,7 @@ export default function FieldMessage(props) {
null;
}

FieldMessage.propTypes = {
Message.propTypes = {
errorMessage: PropTypes.string,
description: PropTypes.string,
isValid: PropTypes.bool,
Expand Down
3 changes: 3 additions & 0 deletions packages/forms/src/UIForm/Message/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Message from './Message.component';

export default Message;
41 changes: 14 additions & 27 deletions packages/forms/src/UIForm/UIForm.component.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import React, { PropTypes } from 'react';
import { reduxForm } from 'redux-form';
import { merge, validate } from 'talend-json-schema-form-core';

import {
merge,
sfPath,
validate,
} from 'talend-json-schema-form-core';

import validateAll from '../utils/validation';
import widgets from '../utils/widgets';
import { getValue, mutateValue } from '../utils/properties';
import Widget from './Widget';
import validateAll from './utils/validation';
import { mutateValue } from './utils/properties';

class UIForm extends React.Component {
constructor(props) {
Expand Down Expand Up @@ -93,24 +88,16 @@ class UIForm extends React.Component {
return (
<form onSubmit={this.submit}>
{
this.state.mergedSchema.map((nextSchema) => {
const { key, type, validationMessage } = nextSchema;
const id = sfPath.name(key, '-', formName);
const { error, valid } = validations[nextSchema.key] || {};
const errorMessage = validationMessage || (error && error.message);
const Widget = widgets[type];
return Widget && (
<Widget
id={id}
isValid={valid}
key={id}
errorMessage={errorMessage}
onChange={this.consolidate}
schema={nextSchema}
value={getValue(properties, key)}
/>
);
})
this.state.mergedSchema.map((nextSchema, index) => (
<Widget
key={index}
formName={formName}
onChange={this.consolidate}
schema={nextSchema}
properties={properties}
validations={validations}
/>
))
}
<button type="submit" className="btn btn-primary">Submit</button>
</form>
Expand Down
40 changes: 40 additions & 0 deletions packages/forms/src/UIForm/Widget/Widget.component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { PropTypes } from 'react';
import { sfPath } from 'talend-json-schema-form-core';

import widgets from '../utils/widgets';
import { getValue } from '../utils/properties';

export default function Widget({ formName, onChange, properties, schema, validations }) {
const { key, type, validationMessage } = schema;
const id = sfPath.name(key, '-', formName);
const { error, valid } = validations[key] || {};
const errorMessage = validationMessage || (error && error.message);
const WidgetImpl = widgets[type];
return WidgetImpl ?
(
<WidgetImpl
id={id}
key={id}
errorMessage={errorMessage}
formName={formName}
isValid={valid}
onChange={onChange}
properties={properties}
schema={schema}
validations={validations}
value={getValue(properties, key)}
/>
) : null;
}

Widget.propTypes = {
formName: PropTypes.string,
onChange: PropTypes.func,
schema: PropTypes.shape({
key: PropTypes.array,
type: PropTypes.string.isRequired,
validationMessage: PropTypes.string,
}).isRequired,
properties: PropTypes.object, // eslint-disable-line react/forbid-prop-types
validations: PropTypes.object, // eslint-disable-line react/forbid-prop-types
};
3 changes: 3 additions & 0 deletions packages/forms/src/UIForm/Widget/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Widget from './Widget.component';

export default Widget;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { PropTypes } from 'react';
import classNames from 'classnames';

import FieldMessage from '../FieldMessage';
import Message from '../Message';

function convertValue(type, value) {
if (type === 'number') {
Expand All @@ -10,7 +10,7 @@ function convertValue(type, value) {
return value;
}

export default function TextField(props) {
export default function Text(props) {
const { id, isValid, errorMessage, onChange, schema, value } = props;
const { description, placeholder, readOnly, title, type } = schema;

Expand All @@ -31,7 +31,7 @@ export default function TextField(props) {
value={value}
/>
<label htmlFor={id} className="control-label">{title}</label>
<FieldMessage
<Message
errorMessage={errorMessage}
description={description}
isValid={isValid}
Expand All @@ -40,7 +40,7 @@ export default function TextField(props) {
);
}

TextField.propTypes = {
Text.propTypes = {
id: PropTypes.string,
isValid: PropTypes.bool,
errorMessage: PropTypes.string,
Expand All @@ -54,7 +54,7 @@ TextField.propTypes = {
}),
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
};
TextField.defaultProps = {
Text.defaultProps = {
isValid: true,
value: '',
};
27 changes: 27 additions & 0 deletions packages/forms/src/UIForm/fieldsets/Fieldset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { PropTypes } from 'react';
import Widget from '../Widget';

export default function Fieldset(props) {
const { schema, ...restProps } = props;
const { title, items } = schema;

return (
<fieldset className="form-group">
{title && (<legend>{title}</legend>)}
{items.map((itemSchema, index) => (
<Widget
{...restProps}
key={index}
schema={itemSchema}
/>
))}
</fieldset>
);
}

Fieldset.propTypes = {
schema: PropTypes.shape({
items: PropTypes.array.isRequired,
title: PropTypes.string,
}).isRequired,
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
* @param {array} key The key chain (array of strings) to access to the value
*/
export function getValue(properties, key) {
if (!key) {
return undefined;
}

return key.reduce(
(accu, nextKey) => accu[nextKey],
properties
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,25 @@ import { validate } from 'talend-json-schema-form-core';
import { getValue } from './properties';

/**
* Validate values. This supports only 1 level of fields for now
* Validate values.
* @param mergedSchema The merged schema.
* @param properties The values.
* @returns {object} The validation result by field.
*/
export default function validateAll(mergedSchema, properties) {
const validations = {};
mergedSchema.forEach((schema) => {
validations[schema.key] = validate(
schema,
getValue(properties, schema.key)
);
const { key, items } = schema;
if (key) {
validations[key] = validate(
schema,
getValue(properties, key)
);
}
if (items) {
const subValidations = validateAll(items, properties);
Object.assign(validations, subValidations);
}
});
return validations;
}
10 changes: 10 additions & 0 deletions packages/forms/src/UIForm/utils/widgets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Fieldset from '../fieldsets/Fieldset';
import Text from '../fields/Text';

const widgets = {
fieldset: Fieldset,
number: Text,
text: Text,
};

export default widgets;
8 changes: 0 additions & 8 deletions packages/forms/src/utils/widgets.js

This file was deleted.

93 changes: 93 additions & 0 deletions packages/forms/stories/json/core-fieldset.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
{
"jsonSchema": {
"type": "object",
"title": "Comment",
"properties": {
"name": {
"type": "string"
},
"lastname": {
"type": "string"
},
"firstname": {
"type": "string"
},
"age": {
"type": "number"
},
"nochange": {
"type": "string"
},
"email": {
"type": "string",
"pattern": "^\\S+@\\S+$"
},
"comment": {
"type": "string",
"maxLength": 20
}
},
"required": [
"name",
"firstname",
"email",
"comment"
]
},
"uiSchema": [
{
"type": "fieldset",
"title": "My awesome USER form",
"items": [
{
"key": "name",
"title": "Name"
},
{
"key": "lastname",
"title": "Last Name (with description)",
"description": "Hint: this is the last name"
},
{
"key": "firstname",
"title": "First Name (with placeholder)",
"placeholder": "Enter your firstname here"
},
{
"key": "age",
"title": "Age"
}
]
},
{
"type": "fieldset",
"title": "My awesome OTHER form",
"items": [
{
"key": "email",
"title": "Email (with pattern validation and custom validation message)",
"description": "Email will be used for evil.",
"validationMessage": "Please enter a valid email address, e.g. [email protected]"
},
{
"key": "nochange",
"title": "Field (read only mode)",
"readOnly": true
},
{
"key": "comment",
"type": "textarea",
"title": "Comment",
"placeholder": "Make a comment",
"validationMessage": "Don't be greedy!"
}
]
}
],
"properties": {
"name": "Chuck Norris",
"nochange": "You can't change that",
"email": "[email protected]",
"comment": "lol"
}
}

0 comments on commit f7fc2d0

Please sign in to comment.