Skip to content

Commit

Permalink
Refactor QueryControls component to TypeScript (#46721)
Browse files Browse the repository at this point in the history
* Begin conversion of QueryControls to TypeScript

* Remove the extra value properties

* Fix failing unit test

* Create a TermsWithChildren type

* Change the id to a string

* Make onCategoryChange an intersection type

* Shorten the JSDoc lines

* Correct the React import

* Make the properties of QueryControlsProps optional

* Alphabetize types.ts

* Fix the suggestions

* Rename Term to Entity

It can also be an author,
so Term isn't right.

* Fix the type of categorySuggestions

* Correct the JSDoc summary for QueryControls

* Make SelectControl accept a number

* Change the order of number and string

* Empty commit to trigger CI/CD

* Remove needless change of id type

* Update README.md based on types.ts

* Let TS infer the return type of buildTermsTree()

* Change array to object, as that's what categorySuggestions is

* Add a CHANGELOG entry

* Add basic stories for QueryControls

* Correct the type for selectedCategories

* Correct the type of categorySuggestions

* Update the types in README.md

* Commit Marco's suggestion: Update packages/components/src/query-controls/terms.ts

Co-authored-by: Marco Ciampini <[email protected]>

* Add hideCancelButton back in

* Revert change to SelectControl and TreeSelect, instead change what's passed to TreeSelect

* Revert README.md change to select-control

* Commit Marco's suggestions for flatTerms verbatim

* Commit Marco's suggestion for parameters

* Remove fallback to ''

* Save the author as a Number

* Fix the order and orderBy types

* Alphabetize the QueryControls props

* Fix unit tests for the ID being a string

* Disable controls for values that you can change via the UI

For other components that you can control via the UI
like RangeControl,
the value control is disabled.
https://github.com/WordPress/gutenberg/blob/a35b3f245a9672e2a276d8c4c1785f42b3342f84/packages/components/src/range-control/stories/index.tsx#L46

* Apply Marco's suggestion for selected*Id

* Commit Marco's suggestion to prevent type casting

* Part 1: Commit Marco's changes that handle multiple types

* Part 2: Commit Marco's change that handle multiple types

#46721 (comment)

* Update README.md for Marco's changes

* Remove Category type entirely, replace with Entity intersection

* Make the category name optional

* Remove the name from selectedCategories in the unit test

* Remove needless casting

* Commit Marco's formatting diff

#46721 (comment)

* Commit Marco's diff verbatim to fix the types

#46721 (comment)

* Update README.md for categorySuggestions

* Move CHANGELOG entry to Unreleased

* Marco's diff: Update packages/components/src/query-controls/README.md

Co-authored-by: Marco Ciampini <[email protected]>

* Marco's diff for types.ts DocBlocks

#46721 (comment)

* Marco's update to types.ts and README.md

#46721 (comment)

Co-authored-by: Marco Ciampini <[email protected]>
  • Loading branch information
kienstra and ciampo authored Jan 26, 2023
1 parent 843220e commit 3dbd681
Show file tree
Hide file tree
Showing 14 changed files with 775 additions and 293 deletions.
1 change: 1 addition & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- `ColorPalette`, `BorderControl`, `GradientPicker`: refine types and logic around single vs multiple palettes
([#47384](https://github.com/WordPress/gutenberg/pull/47384)).
- `Button`: Convert to TypeScript ([#46997](https://github.com/WordPress/gutenberg/pull/46997)).
- `QueryControls`: Convert to TypeScript ([#46721](https://github.com/WordPress/gutenberg/pull/46721)).

### Bug Fix

Expand Down
111 changes: 55 additions & 56 deletions packages/components/src/query-controls/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ const QUERY_DEFAULTS = {
},
],
maxItems: 20,
minItems: 1,
minItems: 1,
numberOfItems: 10,
order: 'asc',
orderBy: 'title',
orderBy: 'title',
};

const MyQueryControls = () => {
Expand Down Expand Up @@ -66,24 +66,35 @@ The `QueryControls` component now supports multiple category selection, to repla
const QUERY_DEFAULTS = {
orderBy: 'title',
order: 'asc',
selectedCategories: [ 1 ],
categories: [
selectedCategories: [
{
id: 1,
name: 'Category 1',
value: 'Category 1',
parent: 0,
},
{
id: 2,
value: 'Category 1b',
parent: 1,
},
],
categories: {
'Category 1': {
id: 1,
name: 'Category 1',
parent: 0,
},
'Category 1b': {
id: 2,
name: 'Category 1b',
parent: 1,
},
{
'Category 2': {
id: 3,
name: 'Category 2',
parent: 0,
},
],
},
numberOfItems: 10,
};

Expand Down Expand Up @@ -111,132 +122,120 @@ const MyQueryControls = () => {
};
```

The format of the categories list also needs to be updated to match what `FormTokenField` expects for making suggestions.
The format of the categories list also needs to be updated to match the expected type for the category suggestions.

### Props

#### authorList
#### `authorList`: `Author[]`

An array of author IDs that is passed into an `AuthorSelect` sub-component.
An array of the authors to select from.

- Type: `Array`
- Required: No
- Platform: Web

#### selectedAuthorId
#### `categoriesList`: `Category[]`

The selected author ID.
An array of categories. When passed in conjunction with the `onCategoryChange` prop, it causes the component to render UI that allows selecting one category at a time.

- Type: `Number`
- Required: No
- Platform: Web

#### categoriesList
#### `categorySuggestions`: `Record< Category[ 'name' ], Category >`

An array of category IDs; renders a `CategorySelect` sub-component when passed in conjunction with `onCategoryChange`.
An object of categories with the category name as the key. When passed in conjunction with the `onCategoryChange` prop, it causes the component to render UI that enables multiple selection.

- Type: `Array`
- Required: No
- Platform: Web

#### categorySuggestions
#### `maxItems`: `number`

An array of category names; renders a `FormTokenField` component when passed in conjunction with `onCategoryChange`.
The maximum number of items.

- Type: `Array`
- Required: No
- Default: 100
- Platform: Web

#### maxItems
#### `minItems`: `number`

The minimum number of items.

- Type: `Number`
- Required: No
- Default: 100
- Default: 1
- Platform: Web

#### minItems
#### `numberOfItems`: `number`

The selected number of items to retrieve via the query.

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

#### numberOfItems
#### `onAuthorChange`: `( newAuthor: string ) => void`

The selected number of items to retrieve via the query.
A function that receives the new author value. If not specified, the author controls are not rendered.

- Type: `Number`
- Required: No
- Platform: Web

#### onAuthorChange
#### `onCategoryChange`: `CategorySelectProps[ 'onChange' ] | FormTokenFieldProps[ 'onChange' ]`

A function that receives the new author value. If this is not specified, the author controls are not included.
A function that receives the new category value. If not specified, the category controls are not rendered.

- Type: `Function`
- Required: No
- Platform: Web

#### onCategoryChange
#### `onNumberOfItemsChange`: `( newNumber?: number ) => void`

A function that receives the new category value. If this is not specified, the category controls are not included.
A function that receives the new number of items. If not specified, then the number of items range control is not rendered.

- Type: `Function`
- Required: No
- Platform: Web

#### onNumberOfItemsChange
#### `onOrderChange`: `( newOrder: 'asc' | 'desc' ) => void`

A function that receives the new number of items value. If this is not specified, then the number of items range control is not included.
A function that receives the new order value. If this prop or the `onOrderByChange` prop are not specified, then the order controls are not rendered.

- Type: `Function`
- Required: No
- Platform: Web

#### onOrderChange
#### `onOrderByChange`: `( newOrderBy: 'date' | 'title' ) => void`

A function that receives the new order value. If this or onOrderByChange are not specified, then the order controls are not included.
A function that receives the new orderby value. If this prop or the `onOrderChange` prop are not specified, then the order controls are not rendered.

- Type: `Function`
- Required: No
- Platform: Web

#### onOrderByChange
#### `order`: `'asc' | 'desc'`

A function that receives the new orderby value. If this or onOrderChange are not specified, then the order controls are not included.
The order in which to retrieve posts.

- Type: `Function`
- Required: No
- Platform: Web

#### order
#### `orderBy`: `'date' | 'title'`

The order in which to retrieve posts. Can be 'asc' or 'desc'.
The meta key by which to order posts.

- Type: `String`
- Required: No
- Platform: Web

#### orderBy
#### `selectedAuthorId`: `number`

The meta key by which to order posts. Can be 'date' or 'title'.
The selected author ID.

- Type: `String`
- Required: No
- Platform: Web

#### selectedCategories
#### `selectedCategories`: `Category[]`

The selected categories for the `categorySuggestions`.
The selected categories for the `categorySuggestions` prop.

- Type: `Array`
- Required: No
- Platform: Web

#### selectedCategoryId
#### `selectedCategoryId`: `number`

The selected category for the `categoriesList`.
The selected category for the `categoriesList` prop.

- Type: `Number`
- Required: No
- Platform: Web
23 changes: 0 additions & 23 deletions packages/components/src/query-controls/author-select.js

This file was deleted.

37 changes: 37 additions & 0 deletions packages/components/src/query-controls/author-select.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Internal dependencies
*/
import { buildTermsTree } from './terms';
import TreeSelect from '../tree-select';
import type { TreeSelectProps } from '../tree-select/types';
import type { AuthorSelectProps } from './types';

export default function AuthorSelect( {
label,
noOptionLabel,
authorList,
selectedAuthorId,
onChange: onChangeProp,
}: AuthorSelectProps ) {
if ( ! authorList ) return null;
const termsTree = buildTermsTree( authorList );
return (
<TreeSelect
{ ...{
label,
noOptionLabel,
// Since the `multiple` attribute is not passed to `TreeSelect`, it is
// safe to assume that the argument of `onChange` cannot be `string[]`.
// The correct solution would be to type `SelectControl` better, so that
// the type of `value` and `onChange` vary depending on `multiple`.
onChange: onChangeProp as TreeSelectProps[ 'onChange' ],
} }
tree={ termsTree }
selectedId={
selectedAuthorId !== undefined
? String( selectedAuthorId )
: undefined
}
/>
);
}
31 changes: 0 additions & 31 deletions packages/components/src/query-controls/category-select.js

This file was deleted.

46 changes: 46 additions & 0 deletions packages/components/src/query-controls/category-select.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* Internal dependencies
*/
import { buildTermsTree } from './terms';
import TreeSelect from '../tree-select';
import type { TreeSelectProps } from '../tree-select/types';

/**
* WordPress dependencies
*/
import { useMemo } from '@wordpress/element';
import type { CategorySelectProps } from './types';

export default function CategorySelect( {
label,
noOptionLabel,
categoriesList,
selectedCategoryId,
onChange: onChangeProp,
...props
}: CategorySelectProps ) {
const termsTree = useMemo( () => {
return buildTermsTree( categoriesList );
}, [ categoriesList ] );

return (
<TreeSelect
{ ...{
label,
noOptionLabel,
// Since the `multiple` attribute is not passed to `TreeSelect`, it is
// safe to assume that the argument of `onChange` cannot be `string[]`.
// The correct solution would be to type `SelectControl` better, so that
// the type of `value` and `onChange` vary depending on `multiple`.
onChange: onChangeProp as TreeSelectProps[ 'onChange' ],
} }
tree={ termsTree }
selectedId={
selectedCategoryId !== undefined
? String( selectedCategoryId )
: undefined
}
{ ...props }
/>
);
}
Loading

0 comments on commit 3dbd681

Please sign in to comment.