Skip to content
Permalink
Browse files

FIX Treat readonly as disabled and fix handling for ui-constructive c…

…lass
  • Loading branch information...
robbieaverill committed Jul 23, 2018
1 parent d3f085e commit a0487e59fc04af0d15e66d4c2874051288b4e63e

Large diffs are not rendered by default.

@@ -15,17 +15,18 @@ class FormAction extends Component {
* @returns {Object}
*/
getButtonProps() {
const { attributes, id, name } = this.props;

// Merge attributes
return Object.assign({},
typeof this.props.attributes === 'undefined' ? {} : this.props.attributes,
{
id: this.props.id,
name: this.props.name,
className: this.getButtonClasses(),
disabled: this.props.disabled,
onClick: this.handleClick,
}
);
const buttonAttributes = typeof attributes === 'undefined' ? {} : attributes;
return {
...buttonAttributes,
id,
name,
className: this.getButtonClasses(),
disabled: this.isDisabled(),
onClick: this.handleClick,
};
}

/**
@@ -34,11 +35,13 @@ class FormAction extends Component {
* @returns string
*/
getButtonClasses() {
const { title, loading, extraClass } = this.props;

const buttonClasses = {
btn: true,
'btn--no-text': (typeof this.props.title !== 'string'),
'btn--loading': this.props.loading,
disabled: this.props.disabled,
'btn--no-text': (typeof title !== 'string'),
'btn--loading': loading,
disabled: this.isDisabled(),
};
// Add 'type' class
const style = this.getButtonStyle();
@@ -53,8 +56,8 @@ class FormAction extends Component {
buttonClasses[`font-icon-${icon}`] = true;
}

if (typeof this.props.extraClass === 'string') {
buttonClasses[this.props.extraClass] = true;
if (typeof extraClass === 'string') {
buttonClasses[extraClass] = true;
}

return classnames(buttonClasses);
@@ -102,7 +105,7 @@ class FormAction extends Component {
/**
* Returns markup for the loading icon
*
* @returns object|null
* @returns {Object|null}
*/
getLoadingIcon() {
if (this.props.loading) {
@@ -119,21 +122,33 @@ class FormAction extends Component {
}

/**
* @return {boolean}
* Returns whether the button is disabled or readonly
*
* @returns {boolean}
*/
isDisabled() {
const { disabled, readOnly } = this.props;

return disabled || readOnly;
}

/**
* @returns {boolean}
*/
isPrimary() {
const extraClasses = this.props.extraClass.split(' ');
const { extraClass, name } = this.props;

const extraClasses = extraClass.split(' ');
return (
this.props.name === 'action_save' ||
extraClasses.find(className => className === 'ss-ui-action-constructive')
name === 'action_save' ||
!!extraClasses.find(className => className === 'ss-ui-action-constructive')
);
}

/**
* Event handler triggered when a user clicks the button.
*
* @param {Object} event
* @return undefined
*/
handleClick(event) {
if (typeof this.props.onClick === 'function') {
@@ -142,7 +157,7 @@ class FormAction extends Component {
}

render() {
const title = this.props.title;
const { title } = this.props;

return (
<button {...this.getButtonProps()}>
@@ -162,6 +177,7 @@ FormAction.propTypes = {
loading: React.PropTypes.bool,
icon: React.PropTypes.string,
disabled: React.PropTypes.bool,
readOnly: React.PropTypes.bool,
data: React.PropTypes.oneOfType([
React.PropTypes.array,
React.PropTypes.shape({
@@ -179,6 +195,7 @@ FormAction.defaultProps = {
attributes: {},
data: {},
disabled: false,
readOnly: false,
};

export default FormAction;
@@ -18,4 +18,5 @@ Used for form actions. For example a submit button.
* `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.
* `readOnly` (boolean): If true, will also cause the button to be disabled.
* `extraClass` (string): Add extra custom classes.
@@ -0,0 +1,72 @@
/* global jest, describe, it, expect, beforeEach */

import React from 'react';
import ReactTestUtils from 'react-addons-test-utils';
import FormAction from '../FormAction';

describe('FormAction', () => {
let props;
let component;

beforeEach(() => {
props = {};
component = null;
});

describe('isPrimary()', () => {
it('detects via the name if the button should be primary', () => {
props = {
...props,
name: 'action_save',
};

component = ReactTestUtils.renderIntoDocument(
<FormAction {...props} />
);

expect(component.isPrimary()).toBe(true);
});

it('detects via a legacy class name if the button should be primary', () => {
props = {
...props,
extraClass: 'foo ss-ui-action-constructive bar',
};

component = ReactTestUtils.renderIntoDocument(
<FormAction {...props} />
);

expect(component.isPrimary()).toBe(true);
});
});

describe('isDisabled()', () => {
it('is true when disabled prop is passed', () => {
props = {
...props,
disabled: true,
};

component = ReactTestUtils.renderIntoDocument(
<FormAction {...props} />
);

expect(component.isDisabled()).toBe(true);
});

it('treats readonly prop as disabled', () => {
props = {
...props,
disabled: false,
readOnly: true,
};

component = ReactTestUtils.renderIntoDocument(
<FormAction {...props} />
);

expect(component.isDisabled()).toBe(true);
});
});
});

0 comments on commit a0487e5

Please sign in to comment.
You can’t perform that action at this time.