diff --git a/demo/presets.js b/demo/presets.js index de27347..1111318 100644 --- a/demo/presets.js +++ b/demo/presets.js @@ -116,5 +116,13 @@ export default [ layoutName: 'edit', formTitle: 'Edit contact', schema: require('./presets/componentsFieldGroup.txt') + }, + { + name: 'Layout Tabs', + displayName: 'Layout Tabs', + entityName: 'contact', + layoutName: 'edit', + formTitle: 'Edit contact', + schema: require('./presets/layoutsTabs.txt') } ] \ No newline at end of file diff --git a/demo/presets/layoutsTabs.txt b/demo/presets/layoutsTabs.txt new file mode 100644 index 0000000..1041a10 --- /dev/null +++ b/demo/presets/layoutsTabs.txt @@ -0,0 +1,77 @@ +{ + entities: [ + { + name: "contact", + fields: [ + { name: "f1", displayName: "Field 1", type: "string" }, + { name: "f2", displayName: "Field 2", type: "string" }, + { name: "f3", displayName: "Field 3", type: "string" }, + { name: "f4", displayName: "Field 4", type: "string" }, + { name: "f5", displayName: "Field 5", type: "string" }, + { name: "f6", displayName: "Field 6", type: "string" }, + { name: "f7", displayName: "Field 7", type: "string" }, + { name: "f8", displayName: "Field 8", type: "string" }, + ], + layouts: [ + { + name: 'edit', + type: 'tabs', + groups: [ + { + title: 'First', + fields: [ + { + name: 'f1' + }, + { + name: 'f2', + size: 8 + } + ] + }, + { + title: 'Second', + orientation: 'horizontal', + fields: [ + { + name: 'f3' + }, + { + name: 'f4' + } + ] + }, + { + title: 'Third', + orientation: 'horizontal', + fields: [ + { + name: 'f5', + size: 4 + }, + { + name: 'f6', + size: 8 + } + ] + }, + { + title: 'Fourth', + orientation: 'horizontal', + fields: [ + { + name: 'f7', + innerSize: 3 + }, + { + name: 'f8', + innerSize: 3 + } + ] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/package.json b/package.json index 0b6e904..078d8b2 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "homepage": "https://github.com/redux-autoform/redux-autoform-bootstrap-ui#readme", "dependencies": { "bootstrap": "^3.3.6", + "font-awesome": "^4.6.3", "isomorphic-fetch": "^2.2.1", "react": "^15.1.0", "react-bootstrap": "^0.30.0", diff --git a/src/components/common/AlertMessage.js b/src/components/common/AlertMessage.js new file mode 100644 index 0000000..0d573e6 --- /dev/null +++ b/src/components/common/AlertMessage.js @@ -0,0 +1,15 @@ +import React, { Component, PropTypes } from 'react'; +import { Alert } from 'react-bootstrap'; + +const AlertMessage = ({ error }) => ( + +

+ Could not render the MetaFormGroup component. The schema is not valid. +

+

Detailed information: + { error.message } +

+
+); + +export default AlertMessage; \ No newline at end of file diff --git a/src/components/ArrayContainerItem.js b/src/components/common/ArrayContainerItem.js similarity index 100% rename from src/components/ArrayContainerItem.js rename to src/components/common/ArrayContainerItem.js diff --git a/src/components/FormControl.js b/src/components/common/FormControl.js similarity index 100% rename from src/components/FormControl.js rename to src/components/common/FormControl.js diff --git a/src/components/FormGroup.js b/src/components/common/FormGroup.js similarity index 100% rename from src/components/FormGroup.js rename to src/components/common/FormGroup.js diff --git a/src/components/FormGroupInline.js b/src/components/common/FormGroupInline.js similarity index 100% rename from src/components/FormGroupInline.js rename to src/components/common/FormGroupInline.js diff --git a/src/components/FormGroupInlineContent.js b/src/components/common/FormGroupInlineContent.js similarity index 100% rename from src/components/FormGroupInlineContent.js rename to src/components/common/FormGroupInlineContent.js diff --git a/src/components/FormGroupInlineControlLabel.js b/src/components/common/FormGroupInlineControlLabel.js similarity index 100% rename from src/components/FormGroupInlineControlLabel.js rename to src/components/common/FormGroupInlineControlLabel.js diff --git a/src/components/FormGroupStacked.js b/src/components/common/FormGroupStacked.js similarity index 100% rename from src/components/FormGroupStacked.js rename to src/components/common/FormGroupStacked.js diff --git a/src/components/GlyphButton.js b/src/components/common/GlyphButton.js similarity index 100% rename from src/components/GlyphButton.js rename to src/components/common/GlyphButton.js diff --git a/src/components/common/Header.js b/src/components/common/Header.js new file mode 100644 index 0000000..159d1ff --- /dev/null +++ b/src/components/common/Header.js @@ -0,0 +1,17 @@ +import React, { Component, PropTypes } from 'react'; + +const Header = ({ title }) => { + if (title) { + return ( +
+ + {title} + +
+ ) + } + + return null; +}; + +export default Header; \ No newline at end of file diff --git a/src/components/Input.js b/src/components/common/Input.js similarity index 100% rename from src/components/Input.js rename to src/components/common/Input.js diff --git a/src/components/fieldComponents/ArrayContainer.js b/src/components/field/ArrayContainer.js similarity index 95% rename from src/components/fieldComponents/ArrayContainer.js rename to src/components/field/ArrayContainer.js index 4b94ddb..5c30af3 100644 --- a/src/components/fieldComponents/ArrayContainer.js +++ b/src/components/field/ArrayContainer.js @@ -1,8 +1,8 @@ import React, { Component, PropTypes } from 'react'; -import GlyphButton from '../GlyphButton.js'; +import GlyphButton from '../common/GlyphButton.js'; import Alert from 'react-bootstrap/lib/Alert'; -import FormGroup from '../FormGroup'; -import ArrayContainerItem from '../ArrayContainerItem'; +import FormGroup from '../common/FormGroup'; +import ArrayContainerItem from '../common/ArrayContainerItem'; class ArrayContainer extends Component { static propTypes = { diff --git a/src/components/fieldComponents/CheckBox.js b/src/components/field/CheckBox.js similarity index 100% rename from src/components/fieldComponents/CheckBox.js rename to src/components/field/CheckBox.js diff --git a/src/components/fieldComponents/DateTimePicker.js b/src/components/field/DateTimePicker.js similarity index 98% rename from src/components/fieldComponents/DateTimePicker.js rename to src/components/field/DateTimePicker.js index 812e216..e68c2e0 100644 --- a/src/components/fieldComponents/DateTimePicker.js +++ b/src/components/field/DateTimePicker.js @@ -1,7 +1,7 @@ import React, { Component, PropTypes } from 'react'; import {DateTimePicker as ReactWidgetsDateTimePicker} from 'react-widgets'; import { getDateLocalizer } from 'redux-autoform-utils'; -import FormGroup from '../FormGroup'; +import FormGroup from '../common/FormGroup'; class DateTimePicker extends Component { static propTypes = { diff --git a/src/components/fieldComponents/FieldGroup.js b/src/components/field/FieldGroup.js similarity index 97% rename from src/components/fieldComponents/FieldGroup.js rename to src/components/field/FieldGroup.js index 4d738d6..133eaef 100644 --- a/src/components/fieldComponents/FieldGroup.js +++ b/src/components/field/FieldGroup.js @@ -1,5 +1,5 @@ import React, { Component, PropTypes } from 'react'; -import FormGroup from '../FormGroup'; +import FormGroup from '../common/FormGroup'; class FieldGroup extends Component { static propTypes = { diff --git a/src/components/fieldComponents/Lookup.js b/src/components/field/Lookup.js similarity index 96% rename from src/components/fieldComponents/Lookup.js rename to src/components/field/Lookup.js index 9e1b5a4..8d0d30e 100644 --- a/src/components/fieldComponents/Lookup.js +++ b/src/components/field/Lookup.js @@ -1,5 +1,5 @@ import React, { Component, PropTypes } from 'react'; -import FormGroup from '../FormGroup'; +import FormGroup from '../common/FormGroup'; import Select from 'react-select-plus'; class Lookup extends Component { diff --git a/src/components/fieldComponents/Radio.js b/src/components/field/Radio.js similarity index 96% rename from src/components/fieldComponents/Radio.js rename to src/components/field/Radio.js index 1d725e0..4ac1662 100644 --- a/src/components/fieldComponents/Radio.js +++ b/src/components/field/Radio.js @@ -1,6 +1,6 @@ import React, { Component, PropTypes } from 'react'; import { Radio as BootstrapRadio } from 'react-bootstrap'; -import FormGroup from '../FormGroup'; +import FormGroup from '../common/FormGroup'; class Radio extends Component { handleChange = (event) => { diff --git a/src/components/fieldComponents/Select.js b/src/components/field/Select.js similarity index 96% rename from src/components/fieldComponents/Select.js rename to src/components/field/Select.js index 1b69e76..b29155e 100644 --- a/src/components/fieldComponents/Select.js +++ b/src/components/field/Select.js @@ -1,6 +1,6 @@ import React, { Component, PropTypes } from 'react'; -import FormGroup from '../FormGroup'; -import Input from '../Input'; +import FormGroup from '../common/FormGroup'; +import Input from '../common/Input'; import ReactSelect from 'react-select-plus'; import fetch from 'isomorphic-fetch'; diff --git a/src/components/fieldComponents/Static.js b/src/components/field/Static.js similarity index 84% rename from src/components/fieldComponents/Static.js rename to src/components/field/Static.js index e981aed..99456a9 100644 --- a/src/components/fieldComponents/Static.js +++ b/src/components/field/Static.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; -import FormGroup from '../FormGroup'; -import {FormControl} from 'react-bootstrap'; +import FormGroup from '../common/FormGroup'; +import { FormControl } from 'react-bootstrap'; class Static extends Component { render() { diff --git a/src/components/fieldComponents/TextArea.js b/src/components/field/TextArea.js similarity index 77% rename from src/components/fieldComponents/TextArea.js rename to src/components/field/TextArea.js index 6dc6f5b..0018b3b 100644 --- a/src/components/fieldComponents/TextArea.js +++ b/src/components/field/TextArea.js @@ -1,5 +1,5 @@ import React, { Component, PropTypes } from 'react'; -import Input from '../Input'; +import Input from '../common/Input'; class TextArea extends Component { static propTypes = { @@ -15,9 +15,7 @@ class TextArea extends Component { }; render() { - let { rows } = this.props; - - return ; + return ; } } diff --git a/src/components/fieldComponents/TextBox.js b/src/components/field/TextBox.js similarity index 93% rename from src/components/fieldComponents/TextBox.js rename to src/components/field/TextBox.js index 01d917b..177a502 100644 --- a/src/components/fieldComponents/TextBox.js +++ b/src/components/field/TextBox.js @@ -1,5 +1,5 @@ import React, { Component, PropTypes } from 'react'; -import Input from '../Input'; +import Input from '../common/Input'; class TextBox extends Component { static propTypes = { diff --git a/src/components/form/NormalForm.js b/src/components/form/NormalForm.js new file mode 100644 index 0000000..cd3eee0 --- /dev/null +++ b/src/components/form/NormalForm.js @@ -0,0 +1,26 @@ +import React, { Component, PropTypes } from 'react'; +import Header from '../common/Header'; + +export default class NormalForm extends Component { + static propTypes = { + content: PropTypes.array.isRequired, + title: PropTypes.string.isRequired + }; + + render() { + let { title, content } = this.props; + + return ( +
+
+
+
+
+ { content } +
+
+
+
+ ); + } +} diff --git a/src/components/form/TabsForm.js b/src/components/form/TabsForm.js new file mode 100644 index 0000000..f942b90 --- /dev/null +++ b/src/components/form/TabsForm.js @@ -0,0 +1,43 @@ +import React, { Component, PropTypes } from 'react'; +import { Nav, NavItem } from 'react-bootstrap'; + +export default class TabsForm extends Component { + static propTypes = { + content: PropTypes.array.isRequired, + layout: PropTypes.object.isRequired + }; + + state = { + position: 0 + }; + + handleSelect = (eventKey) => { + this.setState({ position: eventKey }); + }; + + render() { + let { layout, content } = this.props; + let { position } = this.state; + + return ( +
+
+
+ +
+ { content[position] } +
+
+
+
+ ); + } +} diff --git a/src/components/groupComponents/Group.js b/src/components/group/Group.js similarity index 68% rename from src/components/groupComponents/Group.js rename to src/components/group/Group.js index f0347a2..ff0b97b 100644 --- a/src/components/groupComponents/Group.js +++ b/src/components/group/Group.js @@ -1,5 +1,7 @@ import React, { Component, PropTypes } from 'react'; -import { Alert } from 'react-bootstrap'; +import AlertMessage from '../common/AlertMessage'; +import NormalForm from './../form/NormalForm'; +import TabsForm from './../form/TabsForm'; class Group extends Component { static propTypes = { @@ -79,56 +81,28 @@ class Group extends Component { ); }); }; - - getHeader = () => { - let { layout } = this.props; - - if (layout.title) { - return ( -
- - { layout.title } - -
- ); - } else { - return null; - } - }; render() { - + let { layout } = this.props; + // the passed in layout can contain either fields or groups. // in case it contains 'fields', we're gonna render each of the fields. - // in case it contains 'groups', we're gonna render render each group, passing the fields as a parameter + // in case it contains 'groups', we're gonna render each group, passing the fields as a parameter try { let content = this.getContent(); - let header = this.getHeader(); - - return ( -
-
-
- { header } -
- { content } -
-
-
-
- ); - + + if (layout.type) { + switch (layout.type) { + case 'tabs': + return ; + default: + return + } + } + + return } catch (ex) { - return ( - -

- Could not render the MetaFormGroup component. The schema is not valid. -

-

Detailed information: - { ex.message } -

-
- ) + return } } } diff --git a/src/factory/BootstrapFactory.js b/src/factory/BootstrapFactory.js index 9224e36..2d9c39f 100644 --- a/src/factory/BootstrapFactory.js +++ b/src/factory/BootstrapFactory.js @@ -1,15 +1,15 @@ import ComponentFactory from 'redux-autoform-utils/lib/factory/ComponentFactory'; -import TextBox from '../components/fieldComponents/TextBox'; -import Select from '../components/fieldComponents/Select'; -import TextArea from '../components/fieldComponents/TextArea'; -import Group from '../components/groupComponents/Group'; -import ArrayContainer from '../components/fieldComponents/ArrayContainer'; -import DateTimePicker from '../components/fieldComponents/DateTimePicker'; -import Lookup from '../components/fieldComponents/Lookup'; -import Static from '../components/fieldComponents/Static'; -import FieldGroup from '../components/fieldComponents/FieldGroup'; -import Checkbox from '../components/fieldComponents/CheckBox'; -import Radio from '../components/fieldComponents/Radio'; +import TextBox from '../components/field/TextBox'; +import Select from '../components/field/Select'; +import TextArea from '../components/field/TextArea'; +import Group from '../components/group/Group'; +import ArrayContainer from '../components/field/ArrayContainer'; +import DateTimePicker from '../components/field/DateTimePicker'; +import Lookup from '../components/field/Lookup'; +import Static from '../components/field/Static'; +import FieldGroup from '../components/field/FieldGroup'; +import Checkbox from '../components/field/CheckBox'; +import Radio from '../components/field/Radio'; class BootstrapFactory extends ComponentFactory { constructor(config) {