Skip to content

Commit

Permalink
Make it work with Taxonomies Terms
Browse files Browse the repository at this point in the history
Signed-off-by: guido <[email protected]>
  • Loading branch information
widoz committed Jan 1, 2024
1 parent b69ab8d commit 1e3ab83
Show file tree
Hide file tree
Showing 14 changed files with 225 additions and 42 deletions.
14 changes: 12 additions & 2 deletions @types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default EntitiesSearch;
declare namespace EntitiesSearch {
type Post<C extends Context = 'view'> = BaseEntityRecords.Post<C>;
type PostType<C extends Context = 'view'> = BaseEntityRecords.Type<C>;
type Taxonomy<C extends Context = 'view'> = BaseEntityRecords.Taxonomy<C>;

interface PostEntityFields
extends Readonly<{
Expand All @@ -32,6 +33,15 @@ declare namespace EntitiesSearch {
: PostType<'edit'>[K];
}>;

// TODO Need Type Test.
type ViewableTaxonomy = Readonly<{
[K in keyof Taxonomy<'edit'>]: K extends 'visibility'
? BaseEntityRecords.TaxonomyVisibility & {
publicly_queryable: true;
}
: Taxonomy<'edit'>[K];
}>;

type EntitiesRecords<Entity> = Readonly<{
records(): OrderedSet<Entity>;
isResolving(): boolean;
Expand Down Expand Up @@ -98,9 +108,9 @@ declare namespace EntitiesSearch {
extends Readonly<{
postType: PostTypeControl<T>;
posts: Omit<PostsControl<P>, 'options'>;
searchPosts: (
searchEntities: (
phrase: string,
postType: PostTypeControl<T>['value'],
kind: PostTypeControl<T>['value'],
queryArguments?: Record<string, unknown>
) => Promise<PostsControl<P>['options']>;
children(
Expand Down
11 changes: 7 additions & 4 deletions sources/js/src/api/search-posts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { OrderedSet, Set } from 'immutable';

import { fetch } from './fetch';

// TODO Parametrize the fields
// TODO Parametrize the fields.
// TODO Write the underline search function.
export async function searchPosts<E>(
type: string,
// TODO Make the `queryArguments` optional.
export async function searchEntities<E>(
kindName: string,
entityName: string,
phrase: string,
queryArguments: {
exclude: Set<string>;
Expand All @@ -32,8 +34,9 @@ export async function searchPosts<E>(
include: include?.toArray() ?? [],
...restArguments,
},
type: kindName,
search: phrase,
subtype: type,
subtype: entityName,
_fields: serializeFields(fields),
});

Expand Down
24 changes: 12 additions & 12 deletions sources/js/src/components/composite-posts-post-types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import { uniqueControlOptions } from '../utils/unique-control-options';
type SearchPhrase = Parameters<EntitiesSearch.Search['search']>[0];
type PostType<V> = EntitiesSearch.PostTypeControl<V>['value'];
type Posts<V> = EntitiesSearch.PostsControl<V>['value'];
type SearchPosts<P, T> = EntitiesSearch.CompositePostsPostTypes<
type SearchEntities<P, T> = EntitiesSearch.CompositePostsPostTypes<
P,
T
>['searchPosts'];
>['searchEntities'];

export function CompositePostsPostTypes<P, T>(
props: EntitiesSearch.CompositePostsPostTypes<P, T>
Expand All @@ -25,17 +25,17 @@ export function CompositePostsPostTypes<P, T>(
});

useEffect(() => {
let promises = Set<ReturnType<SearchPosts<P, T>>>().asMutable();
let promises = Set<ReturnType<SearchEntities<P, T>>>().asMutable();

Check failure on line 28 in sources/js/src/components/composite-posts-post-types.tsx

View workflow job for this annotation

GitHub Actions / build

'promises' is never reassigned. Use 'const' instead

promises.add(
props.searchPosts('', valuesState.postType, {
props.searchEntities('', valuesState.postType, {
exclude: valuesState.posts,
})
);

if (valuesState.posts.size > 0) {
promises.add(
props.searchPosts('', valuesState.postType, {
props.searchEntities('', valuesState.postType, {
include: valuesState.posts,
per_page: '-1',
})
Expand All @@ -62,7 +62,7 @@ export function CompositePostsPostTypes<P, T>(
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const searchPostsByPostType = async (
const searchEntitiesByKind = async (
phrase: string,
postType: PostType<T>
) => {
Expand All @@ -71,7 +71,7 @@ export function CompositePostsPostTypes<P, T>(
}

props
.searchPosts(phrase, postType, {
.searchEntities(phrase, postType, {
exclude: valuesState.posts,
})
.then((result) =>
Expand Down Expand Up @@ -108,11 +108,11 @@ export function CompositePostsPostTypes<P, T>(
return;
}

let promises = Set<ReturnType<SearchPosts<P, T>>>([
props.searchPosts(searchPhrase, valuesState.postType, {
let promises = Set<ReturnType<SearchEntities<P, T>>>([

Check failure on line 111 in sources/js/src/components/composite-posts-post-types.tsx

View workflow job for this annotation

GitHub Actions / build

'promises' is never reassigned. Use 'const' instead
props.searchEntities(searchPhrase, valuesState.postType, {
exclude: posts,
}),
props.searchPosts('', valuesState.postType, {
props.searchEntities('', valuesState.postType, {
include: posts,
per_page: '-1',
}),
Expand Down Expand Up @@ -140,7 +140,7 @@ export function CompositePostsPostTypes<P, T>(
props.posts.onChange(posts);

props
.searchPosts('', postType, {
.searchEntities('', postType, {
exclude: valuesState.posts,
})
.then((result) => {
Expand Down Expand Up @@ -196,7 +196,7 @@ export function CompositePostsPostTypes<P, T>(
return;
}

searchPostsByPostType(_phrase, valuesState.postType);
searchEntitiesByKind(_phrase, valuesState.postType);
}
)}
</>
Expand Down
29 changes: 29 additions & 0 deletions sources/js/src/hooks/use-query-viewable-taxonomies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import EntitiesSearch from '@types';
import { OrderedSet } from 'immutable';

import { useEntityRecords } from './use-entity-records';

/**
* Hook to obtain the `viewable` taxonomies only.
* This is an api on top of `useEntityRecords` to facilitate the usage of the `viewable` taxonomies.
*
* @public
*/
export function useQueryViewableTaxonomies(): EntitiesSearch.EntitiesRecords<EntitiesSearch.ViewableTaxonomy> {
const entitiesRecords = useEntityRecords<EntitiesSearch.Taxonomy<'edit'>>(
'root',
'taxonomy',
{ per_page: -1 }
);

const viewableTaxonomies = entitiesRecords
.records()
.filter(
(taxonomy) => taxonomy.visibility.publicly_queryable
) as OrderedSet<EntitiesSearch.ViewableTaxonomy>;

return {
...entitiesRecords,
records: () => OrderedSet(viewableTaxonomies),
};
}
3 changes: 2 additions & 1 deletion sources/js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ export * from './components/search';

export * from './hooks/use-entity-records';
export * from './hooks/use-query-viewable-post-types';
export * from './hooks/use-query-viewable-taxonomies';

export * from './utils/convert-post-type-entities-to-control-options';
export * from './utils/convert-entities-to-control-options';
export * from './utils/convert-post-entities-to-control-options';

export * from './api/fetch';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ import { OrderedSet } from 'immutable';

import { makeControlOption } from './make-control-option';

type Entity = EntitiesSearch.PostType;
type Entity = {
name: string;
slug: string;
};
type ControlOption = EntitiesSearch.ControlOption<Entity['slug']>;

export function convertPostTypeEntitiesToControlOptions(
// TODO Not used, can be removed and also it's invalid.
export function convertEntitiesToControlOptions(
entities: OrderedSet<Entity>
): OrderedSet<ControlOption> {
const mutableOptions = entities.map((entity) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { OrderedSet } from 'immutable';
import { makeControlOption } from './make-control-option';

type FieldsNames = keyof EntitiesSearch.PostEntityFields;

// TODO See if this function can be generalized. See convertEntitiesToControlOptions too.
export function convertPostEntitiesToControlOptions(
postsEntities: OrderedSet<EntitiesSearch.PostEntityFields>,
labelKey: FieldsNames,
Expand Down
12 changes: 12 additions & 0 deletions sources/php/src/Modules/E2e/Module.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,20 @@ private static function postTypesExample(Modularity\Properties\Properties $prope
true,
);

\wp_register_script(
'widoz-entities-search-e2e-taxonomies-example-block',
"{$baseUrl}/sources/php/src/Modules/E2e/resources/js/taxonomies-example-block/index.js",
['widoz-entities-search', 'immutable'],
'0.0.0',
true,
);

\register_block_type_from_metadata(
__DIR__ . '/resources/js/post-types-example-block/block.json',
);

\register_block_type_from_metadata(
__DIR__ . '/resources/js/taxonomies-example-block/block.json',
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ document.addEventListener('DOMContentLoaded', () => {
const { Spinner } = wp.components;

const {
searchPosts,
searchEntities,
PostTypeRadio,
PostsToggle,
Search,
CompositePostsPostTypes,
useQueryViewablePostTypes,
convertPostTypeEntitiesToControlOptions,
convertEntitiesToControlOptions,
convertPostEntitiesToControlOptions,
} = entitiesSearch;

Expand All @@ -41,8 +41,13 @@ document.addEventListener('DOMContentLoaded', () => {
CompositePostsPostTypes,
{
// TODO Wrap around a throttle or debounce function
searchPosts: async (phrase, postType, queryArguments) => {
const postsEntities = await searchPosts(
searchEntities: async (
phrase,
postType,
queryArguments
) => {
const postsEntities = await searchEntities(
'post',
postType,
phrase,
queryArguments
Expand All @@ -60,7 +65,7 @@ document.addEventListener('DOMContentLoaded', () => {
},
postType: {
value: props.attributes.postType,
options: convertPostTypeEntitiesToControlOptions(
options: convertEntitiesToControlOptions(
postTypesEntities
.records()
.filter(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"apiVersion": 3,
"title": "Taxonomies Example Block",
"name": "widoz-entities-search/taxonomies-example-block",
"category": "uncategorized",
"icon": "wordpress",
"editorScript": "widoz-entities-search-e2e-taxonomies-example-block",
"attributes": {
"taxonomy": {
"type": "string",
"default": "category"
},
"terms": {
"type": "array",
"default": []
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
document.addEventListener('DOMContentLoaded', () => {
const { wp, entitiesSearch, Immutable } = window;

const { createElement } = wp.element;
const { registerBlockType } = wp.blocks;
const { useBlockProps } = wp.blockEditor;
const { Spinner } = wp.components;

const {
searchEntities,
PostTypeRadio,
PostsToggle,
Search,
CompositePostsPostTypes,
useQueryViewableTaxonomies,
convertEntitiesToControlOptions,
convertPostEntitiesToControlOptions,
} = entitiesSearch;

// TODO Check why the object form does not work.
registerBlockType('widoz-entities-search/taxonomies-example-block', {
apiVersion: 2,
title: 'Taxonomies Example Block',
category: 'uncategorized',
icon: 'wordpress',
editorScript: 'widoz-entities-search-e2e-taxonomies-example-block',
edit: function Edit(props) {
const blockProps = useBlockProps({
className: 'widoz-entities-search-e2e-taxonomies-example-block',
});

const taxonomiesEntities = useQueryViewableTaxonomies();

if (taxonomiesEntities.isResolving()) {
return Spinner();
}

const TermTaxonomiesControllerElement = createElement(
CompositePostsPostTypes,
{
// TODO Wrap around a throttle or debounce function
searchEntities: async (
phrase,
entityName,
queryArguments
) => {
const entities = await searchEntities(
'term',
entityName,
phrase,
queryArguments
);
return convertPostEntitiesToControlOptions(
entities,
'title',
'id'
);
},
posts: {
value: Immutable.Set(props.attributes.terms),
onChange: (terms) =>
props.setAttributes({ terms: terms?.toArray() }),
},
postType: {
value: props.attributes.taxonomy,
options: convertEntitiesToControlOptions(
taxonomiesEntities.records()
),
onChange: (taxonomy) =>
props.setAttributes({ taxonomy }),
},
},
(posts, type, search) => {
return [
createElement(PostTypeRadio, {
...type,
key: 'taxonomy-radio',
}),
createElement(Search, { search, key: 'search' }),
createElement(PostsToggle, {
...posts,
key: 'terms-toggle',
}),
];
}
);

return createElement(
'div',
blockProps,
TermTaxonomiesControllerElement
);
},
save: () => null,
});
});
Loading

0 comments on commit 1e3ab83

Please sign in to comment.