Move ActionComponent into FormActionComponent

This commit is contained in:
scott1702 2016-03-29 18:07:54 +13:00 committed by Ingo Schommer
parent 2a5c92e491
commit d1e4c563ce
9 changed files with 120 additions and 172 deletions

View File

@ -1,41 +0,0 @@
# Action
This component is used to display a button which is linked to an action.
## Props
### handleClick (function)
The handler for when a button is clicked
#### Arguments
* event - the click event
### text (string)
The text to be shown in the button.
### type (string)
The type of button to be shown, adds a class to the button.
Accepted values are:
* 'danger'
* 'success'
* 'primary'
* 'link'
* 'secondary'
* 'complete'
### icon (string)
The icon to be used on the button, adds font-icon-{this.props.icon} class to the button. See available icons [here](../../../../fonts/incon-reference.html).
### loading (boolean)
If true, replaces the text/icon with a loading icon.
### disabled (boolean)
If true, gives the button a visually disabled state and disables click events.

View File

@ -1,108 +0,0 @@
import React from 'react';
import ReactDOM from 'react-dom';
import SilverStripeComponent from 'silverstripe-component.js';
class ActionComponent extends SilverStripeComponent {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
render() {
return (
<button className={this.getButtonClasses()} onClick={this.handleClick}>
{this.getLoadingIcon()}
{this.props.text}
</button>
);
}
/**
* Returns the necessary button classes based on the given props
*
* @returns string
*/
getButtonClasses() {
var buttonClasses = 'btn';
// If there is no text
if (typeof this.props.text === 'undefined') {
buttonClasses += ' no-text';
}
// Add 'type' class
if (this.props.type === 'danger') {
buttonClasses += ' btn-danger';
} else if (this.props.type === 'success') {
buttonClasses += ' btn-success';
} else if (this.props.type === 'primary') {
buttonClasses += ' btn-primary';
} else if (this.props.type === 'link') {
buttonClasses += ' btn-link';
} else if (this.props.type === 'secondary') {
buttonClasses += ' btn-secondary';
} else if (this.props.type === 'complete') {
buttonClasses += ' btn-success-outline';
}
// Add icon class
if (typeof this.props.icon !== 'undefined') {
buttonClasses += ` font-icon-${this.props.icon}`;
}
// Add loading class
if (this.props.loading === true) {
buttonClasses += ' btn--loading';
}
// Add disabled class
if (this.props.disabled === true) {
buttonClasses += ' disabled';
}
return buttonClasses;
}
/**
* Returns markup for the loading icon
*
* @returns object|null
*/
getLoadingIcon() {
if (this.props.loading) {
return (
<div className="btn__loading-icon" >
<svg viewBox="0 0 44 12">
<circle cx="6" cy="6" r="6" />
<circle cx="22" cy="6" r="6" />
<circle cx="38" cy="6" r="6" />
</svg>
</div>
);
}
return null;
}
/**
* Event handler triggered when a user clicks the button.
*
* @param object event
* @returns null
*/
handleClick(event) {
this.props.handleClick(event);
}
}
ActionComponent.propTypes = {
handleClick: React.PropTypes.func.isRequired,
type: React.PropTypes.string,
icon: React.PropTypes.string,
text: React.PropTypes.string,
loading: React.PropTypes.bool,
disabled: React.PropTypes.bool
};
export default ActionComponent;

View File

@ -4,14 +4,42 @@ Used for form actions. For example a submit button.
## Props ## Props
### className ### handleClick (function - required)
CSS class names to use on the button. Defaults to `btn btn-primary` The handler for when a button is clicked
### label (required) #### Arguments
* event - the click event
### label (string)
The text to display on the button. The text to display on the button.
### type ### type (string)
Used for the button's `type` attribute. Defaults to `button` Used for the button's `type` attribute. Defaults to `button`
### style (string)
The style of button to be shown, adds a class `btn-{style}` to the button. Defaults to `secondary`.
Recommended values are:
* 'danger'
* 'success'
* 'primary'
* 'link'
* 'secondary'
* 'success-outline'
### icon (string)
The icon to be used on the button, adds `font-icon-{icon}` class to the button. See available icons [here](../../../../fonts/incon-reference.html).
### loading (boolean)
If true, replaces the text/icon with a loading icon.
### disabled (boolean)
If true, gives the button a visually disabled state and disables click events.

View File

@ -2,26 +2,101 @@ import React from 'react';
import SilverStripeComponent from 'silverstripe-component.js'; import SilverStripeComponent from 'silverstripe-component.js';
class FormActionComponent extends SilverStripeComponent { class FormActionComponent extends SilverStripeComponent {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
render() { render() {
return ( return (
<button type={this.props.type} className={this.props.className}> <button type={this.props.type} className={this.getButtonClasses()} onClick={this.handleClick}>
{this.getLoadingIcon()}
{this.props.label} {this.props.label}
</button> </button>
); );
} }
/**
* Returns the necessary button classes based on the given props
*
* @returns string
*/
getButtonClasses() {
var buttonClasses = 'btn';
// Add 'type' class
buttonClasses += ` btn-${this.props.style}`;
// If there is no text
if (typeof this.props.label === 'undefined') {
buttonClasses += ' no-text';
}
// Add icon class
if (typeof this.props.icon !== 'undefined') {
buttonClasses += ` font-icon-${this.props.icon}`;
}
// Add loading class
if (this.props.loading === true) {
buttonClasses += ' btn--loading';
}
// Add disabled class
if (this.props.disabled === true) {
buttonClasses += ' disabled';
}
return buttonClasses;
}
/**
* Returns markup for the loading icon
*
* @returns object|null
*/
getLoadingIcon() {
if (this.props.loading) {
return (
<div className="btn__loading-icon" >
<svg viewBox="0 0 44 12">
<circle cx="6" cy="6" r="6" />
<circle cx="22" cy="6" r="6" />
<circle cx="38" cy="6" r="6" />
</svg>
</div>
);
}
return null;
}
/**
* Event handler triggered when a user clicks the button.
*
* @param object event
* @returns null
*/
handleClick(event) {
this.props.handleClick(event);
}
} }
FormActionComponent.propTypes = { FormActionComponent.propTypes = {
className: React.PropTypes.string, handleClick: React.PropTypes.func.isRequired,
label: React.PropTypes.string.isRequired, label: React.PropTypes.string,
type: React.PropTypes.string type: React.PropTypes.string,
loading: React.PropTypes.bool,
icon: React.PropTypes.string,
disabled: React.PropTypes.bool,
style: React.PropTypes.string
}; };
FormActionComponent.defaultProps = { FormActionComponent.defaultProps = {
className: 'btn btn-primary', type: 'button',
type: 'button' style: 'secondary'
}; };
export default FormActionComponent; export default FormActionComponent;

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import SilverStripeComponent from 'silverstripe-component'; import SilverStripeComponent from 'silverstripe-component';
import ActionButton from 'components/action-button'; import FormAction from 'components/form-action';
import i18n from 'i18n'; import i18n from 'i18n';
import NorthHeader from 'components/north-header'; import NorthHeader from 'components/north-header';
import FormBuilder from 'components/form-builder'; import FormBuilder from 'components/form-builder';
@ -20,9 +20,8 @@ class CampaignAdminContainer extends SilverStripeComponent {
return ( return (
<div> <div>
<NorthHeader /> <NorthHeader />
<ActionButton <FormAction
text={i18n._t('Campaigns.ADDCAMPAIGN')} label={i18n._t('Campaigns.ADDCAMPAIGN')}
type={'secondary'}
icon={'plus-circled'} icon={'plus-circled'}
handleClick={this.addCampaign} /> handleClick={this.addCampaign} />
<FormBuilder schemaUrl={schemaUrl} /> <FormBuilder schemaUrl={schemaUrl} />
@ -38,11 +37,9 @@ class CampaignAdminContainer extends SilverStripeComponent {
CampaignAdminContainer.propTypes = { CampaignAdminContainer.propTypes = {
config: React.PropTypes.shape({ config: React.PropTypes.shape({
data: React.PropTypes.shape({ forms: React.PropTypes.shape({
forms: React.PropTypes.shape({ editForm: React.PropTypes.shape({
editForm: React.PropTypes.shape({ schemaUrl: React.PropTypes.string
schemaUrl: React.PropTypes.string
})
}) })
}) })
}), }),

View File

@ -9,5 +9,5 @@
@import "../components/grid-field/styles"; @import "../components/grid-field/styles";
@import "../components/north-header/styles"; @import "../components/north-header/styles";
@import "../components/north-header-breadcrumbs/styles"; @import "../components/north-header-breadcrumbs/styles";
@import "../components/action/styles"; @import "../components/form-action/styles";
@import "../components/hidden-field/styles"; @import "../components/hidden-field/styles";

View File

@ -192,7 +192,6 @@ gulp.task('bundle-lib', function bundleLib() {
.on('update', bundleLib) .on('update', bundleLib)
.on('log', function (msg) { gulpUtil.log('Finished', 'bundled ' + bundleFileName + ' ' + msg) }) .on('log', function (msg) { gulpUtil.log('Finished', 'bundled ' + bundleFileName + ' ' + msg) })
.transform('babelify', babelifyOptions) .transform('babelify', babelifyOptions)
.require(PATHS.ADMIN_JAVASCRIPT_SRC + '/components/action', { expose: 'components/action-button' })
.require(PATHS.ADMIN_JAVASCRIPT_SRC + '/components/form', { expose: 'components/form' }) .require(PATHS.ADMIN_JAVASCRIPT_SRC + '/components/form', { expose: 'components/form' })
.require(PATHS.ADMIN_JAVASCRIPT_SRC + '/components/form-action', { expose: 'components/form-action' }) .require(PATHS.ADMIN_JAVASCRIPT_SRC + '/components/form-action', { expose: 'components/form-action' })
.require(PATHS.ADMIN_JAVASCRIPT_SRC + '/components/form-builder', { expose: 'components/form-builder' }) .require(PATHS.ADMIN_JAVASCRIPT_SRC + '/components/form-builder', { expose: 'components/form-builder' })