Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QueryLimit: A React component for adding a WordPress Range Control input for setting a query's limit clause #484

Merged
merged 17 commits into from
May 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = {
],
'plugins': [
'wordpress',
'jest',
],
env: {
'jest/globals': true,
Expand All @@ -13,9 +14,6 @@ module.exports = {
wpApiSettings: true,
eejsdata: true
},
plugins: [
'jest',
],
overrides: [
{
files: [ 'test/e2e/**/*.js' ],
Expand Down
3 changes: 3 additions & 0 deletions assets/src/components/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
// query components
export { QueryLimit } from './query/limit';
// selection components
export { default as EventSelect } from './selection/event-select';
35 changes: 35 additions & 0 deletions assets/src/components/query/limit/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* External dependencies
*/
import { __ } from '@eventespresso/i18n';

/**
* WordPress dependencies
**/
import { RangeControl } from '@wordpress/components';

const DEFAULT_LIMIT = 10;
const DEFAULT_LABEL = __( 'Limit', 'event_espresso' );
const DEFAULT_MIN = 1;
const DEFAULT_MAX = 100;

export const QueryLimit = ( {
onLimitChange,
limit = DEFAULT_LIMIT,
label = DEFAULT_LABEL,
min = DEFAULT_MIN,
max = DEFAULT_MAX,
} ) => {
return ! onLimitChange ? (
null
) : (
<RangeControl
key={ 'query-limit' }
value={ limit }
label={ label }
min={ min }
max={ max }
onChange={ onLimitChange }
/>
);
Copy link
Contributor

@nerrad nerrad May 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be an exception or some human friendly error message when onLimitChange is undefined? I'm on the fence because it will already be clear something isn't working correctly likely.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya I wondered that myself but I wasn't sure what the convention was within GB components.
I don't see any exceptions or errors thrown in other GB components in similar scenarios.

I think it might be acceptable to throw an exception or at the very least log an error to the console, because this component is primarily intended to be used within another component, so any issues would likely only arise during development and will help speed things along. You also mentioned something about GB having some kind of built in notices now, although that may not be as appropriate for this.

Your call though, exception, or console log, or notice, or something else?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A brief perusal through the GB repo seems to indicate they are doing pretty much what you are doing so let's just leave as is for now. It'll be pretty obvious in development when the component isn't rendered that something isn't working.

};
60 changes: 60 additions & 0 deletions assets/src/components/query/limit/test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* External dependencies
*/
import { mount } from 'enzyme';

/**
* Internal dependencies
*/
import { QueryLimit } from '../';

describe( 'QueryLimit with no optional parameters passed', () => {
it( 'should have default values', () => {
const onChange = jest.fn();
const wrapper = mount( <QueryLimit onLimitChange={ onChange } /> );
// test range input
const limit = wrapper.find( 'input[type="range"]' );
expect( limit.props().value ).toBe( 10 );
expect( limit.props().min ).toBe( 1 );
expect( limit.props().max ).toBe( 100 );
// and label
const label = wrapper.find( 'label' );
expect( label.text() ).toEqual( 'Limit' );
// test onChange
limit.simulate( 'change', { target: { value: '5' } } );
expect( onChange ).toHaveBeenCalledWith( 5 );
} );
} );

describe( 'QueryLimit with all parameters passed', () => {
it( 'should not have default values', () => {
const onChange = jest.fn();
const wrapper = mount(
<QueryLimit
limit={ 25 }
label={ 'No Limit' }
min={ 10 }
max={ 50 }
onLimitChange={ onChange }
/>,
);
// test range input
const limit = wrapper.find( 'input[type="range"]' );
expect( limit.props().value ).toBe( 25 );
expect( limit.props().min ).toBe( 10 );
expect( limit.props().max ).toBe( 50 );
// and label
const label = wrapper.find( 'label' );
expect( label.text() ).toEqual( 'No Limit' );
// test onChange
limit.simulate( 'change', { target: { value: '30' } } );
expect( onChange ).toHaveBeenCalledWith( 30 );
} );
} );

describe( 'QueryLimit with no onLimitChange callback provided', () => {
it( 'should return nothing', () => {
const wrapper = mount( <QueryLimit /> );
expect( wrapper.instance() ).toBe( null );
} );
} );
13 changes: 13 additions & 0 deletions docs/AA--Javascript-in-EE/Blocks-and-Components/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Gutenberg Blocks and Components

### Blocks
The following is a list of Event Espresso Gutenberg Blocks that can be utilized in your site's content:

* [Event Attendees List](blocks/event-attendees.md)

### Components
If you are building your own Gutenberg Block to use within Event Espresso, then the following is a list of additional React components can be utilized:


* [QueryLimit](components/query/limit.md) - A React component for adding a WordPress Range Control input for setting a query's limit clause

Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
QueryLimit
=======

A React component for adding a numeric Range Control input for setting the number of items returned by a query


## Usage Overview

```jsx
<QueryLimit
limit={ 25 }
label={ 'Number of items returned' }
min={ 1 }
max={ 50 }
onLimitChange={
( value ) => onChangeCallback( { limit: value } )
}
/>
```

## Props

### limit

The initial value for the limit attribute

- Type: `Number`
- Required: No
- Default: 10

### label

The text to be used for the input's corresponding label

- Type: `String`
- Required: No
- Default: "Limit"

### min

The lowest value allowed for the range control

- Type: `Number`
- Required: No
- Default: 1

### max

The highest value allowed for the range control

- Type: `Number`
- Required: No
- Default: 100

### onLimitChange

The function called when a change of value is detected. Used for saving the value for the "limit" attribute.

- Type: `Function`
- Required: Yes


## Usage within a Block's edit callback

This is assuming the `QueryLimit` component will be utilized within an `InspectorControls` component

### Step 1
Import the following external dependencies:

```jsx
import { __ } from '@eventespresso/i18n';
import { QueryLimit } from '@eventespresso/components';
import { PanelBody } from '@wordpress/components';
import { InspectorControls } from '@wordpress/editor';
```

### Step 2
Add a "limit" attribute:

```jsx
attributes: {
limit: {
type: 'number',
default: 5,
},
},
```

### Step 3
Wrap the QueryLimit component within the InspectorControls and PanelBody components
(currently shown within a block's edit() function)

```jsx
edit: ( ( { attributes, setAttributes } ) => {
const { limit } = attributes;
return (
<InspectorControls>
<PanelBody>
<QueryLimit
limit={ limit }
onLimitChange={
( value ) => setAttributes( { limit: value } )
}
/>
</PanelBody>
</InspectorControls>
);
})
```