From 95943cfab0fb7341be567977f6864ca527ba7aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:01:50 +0200 Subject: [PATCH 01/24] Visualize parent --- .../edit-site/src/components/sidebar-dataviews/default-views.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index c08a2c1a57c58e..9250cbf9fe8944 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -44,7 +44,7 @@ const DEFAULT_POST_BASE = { }, titleField: 'title', mediaField: 'featured_media', - fields: [ 'author', 'status' ], + fields: [ 'parent', 'author', 'status' ], ...defaultLayouts[ LAYOUT_LIST ], }; From 65dd5639c9420544bf2a447e2e044b67225148f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:54:52 +0100 Subject: [PATCH 02/24] Sort by title asc --- .../src/components/sidebar-dataviews/default-views.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 9250cbf9fe8944..38f809756828db 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -39,8 +39,8 @@ const DEFAULT_POST_BASE = { page: 1, perPage: 20, sort: { - field: 'date', - direction: 'desc', + field: 'title', + direction: 'asc', }, titleField: 'title', mediaField: 'featured_media', From 0fb533b4391b0f0e66dfdc4954bd795fac377c6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Thu, 28 Nov 2024 18:27:50 +0100 Subject: [PATCH 03/24] Return posts sorted by hierarchy --- .../class-gutenberg-hierarchical-sort.php | 201 ++++++++++++++++++ lib/load.php | 1 + ...class-gutenberg-hierarchical-sort-test.php | 127 +++++++++++ 3 files changed, 329 insertions(+) create mode 100644 lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php create mode 100644 phpunit/class-gutenberg-hierarchical-sort-test.php diff --git a/lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php b/lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php new file mode 100644 index 00000000000000..fb49df0f59f5ab --- /dev/null +++ b/lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php @@ -0,0 +1,201 @@ + 'id=>parent', + 'posts_per_page' => -1, + ) + ); + $query = new WP_Query( $new_args ); + $posts = $query->posts; + $result = self::sort( $posts ); + + self::$post_ids = $result['post_ids']; + self::$levels = $result['levels']; + } + + /** + * Check if the request is eligible for hierarchical sorting. + * + * @param array $request The request data. + * + * @return bool Return true if the request is eligible for hierarchical sorting. + */ + public static function is_eligible( $request ) { + if ( ! isset( $request['orderby_hierarchy'] ) || true !== $request['orderby_hierarchy'] ) { + return false; + } + + return true; + } + + public static function get_ancestor( $post_id ) { + $ancestor = get_post( $post_id ); + if ( null === $ancestor ) { + return 0; + } + + return $ancestor->post_parent; + } + + /** + * Sort the post ids by hierarchy. + * + * Example: $posts is + * [ + * ['ID' => 4, 'post_parent' => 2], + * ['ID' => 2, 'post_parent' => 0], + * ['ID' => 3, 'post_parent' => 2], + * ] + * + * and we want to return: [2, 3, 4] + * + * @param array $posts The posts to sort. + * @param array $args The arguments to sort the posts by. + * + * @return array Return the sorted post_ids and the corresponding levels. + */ + public static function sort( $posts ) { + /* + * Arrange pages in two arrays: + * + * - $top_level: posts whose parent is 0 + * - $children: post ID as the key and an array of children post IDs as the value. + * Example: $children[10][] contains all sub-pages whose parent is 10. + * + * Additionally, keep track of the levels of each post in $levels. + * Example: $levels[10] = 0 means the post ID is a top-level page. + * + */ + $top_level = array(); + $children = array(); + foreach ( $posts as $post ) { + if ( 0 === $post->post_parent ) { + $top_level[] = $post->ID; + } else { + $children[ $post->post_parent ][] = $post->ID; + } + } + + $ids = array(); + $levels = array(); + self::add_hierarchical_ids( $ids, $levels, 0, $top_level, $children ); + + // Process remaining children. + if ( ! empty( $children ) ) { + foreach ( $children as $parent_id => $child_ids ) { + $root_not_found = true; + $ancestors = 0; + $ancestor = $parent_id; + while( $root_not_found ) { + $ancestors++; + $ancestor = self::get_ancestor( $ancestor ); + if ( 0 === $ancestor ) { + $root_not_found = false; + } + } + self::add_hierarchical_ids( $ids, $levels, $ancestors, $child_ids, $children ); + } + } + + return array( + 'post_ids' => $ids, + 'levels' => $levels, + ); + } + + private static function add_hierarchical_ids( &$ids, &$levels, $level, $to_process, $children ) { + foreach ( $to_process as $id ) { + if ( in_array( $id, $ids, true ) ) { + continue; + } + $ids[] = $id; + $levels[ $id ] = $level; + + if ( isset( $children[ $id ] ) ) { + self::add_hierarchical_ids( $ids, $levels, $level + 1, $children[ $id ], $children ); + unset( $children[ $id ] ); + } + } + } + + public static function get_post_ids() { + return self::$post_ids; + } + + public static function get_levels() { + return self::$levels; + } +} + +add_filter( + 'rest_page_collection_params', + function ( $params ) { + $params['orderby_hierarchy'] = array( + 'description' => 'Sort pages by hierarchy.', + 'type' => 'boolean', + 'default' => false, + ); + return $params; + } +); + +add_filter( + 'rest_page_query', + function ( $args, $request ) { + if ( ! Gutenberg_Hierarchical_Sort::is_eligible( $request ) ) { + return $args; + } + + $hs = Gutenberg_Hierarchical_Sort::init(); + $hs->run( $args ); + + // Reconfigure the args to display only the ids in the list. + $args['post__in'] = $hs->get_post_ids(); + $args['orderby'] = 'post__in'; + + return $args; + }, + 10, + 2 +); + +add_filter( + 'rest_prepare_page', + function ( $response, $post, $request ) { + if ( ! Gutenberg_Hierarchical_Sort::is_eligible( $request ) ) { + return $response; + } + + $hs = Gutenberg_Hierarchical_Sort::init(); + $response->data['level'] = $hs->get_levels()[ $post->ID ]; + + return $response; + }, + 10, + 3 +); diff --git a/lib/load.php b/lib/load.php index 26af78f3173c53..371f9c54e5fc4a 100644 --- a/lib/load.php +++ b/lib/load.php @@ -45,6 +45,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.8/block-comments.php'; require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php'; require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-post-types-controller-6-8.php'; + require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php'; require __DIR__ . '/compat/wordpress-6.8/rest-api.php'; // Plugin specific code. diff --git a/phpunit/class-gutenberg-hierarchical-sort-test.php b/phpunit/class-gutenberg-hierarchical-sort-test.php new file mode 100644 index 00000000000000..ff0f2dbabc04ad --- /dev/null +++ b/phpunit/class-gutenberg-hierarchical-sort-test.php @@ -0,0 +1,127 @@ + 11, + 'post_parent' => 9, + ), + (object) array( + 'ID' => 2, + 'post_parent' => 0, + ), + (object) array( + 'ID' => 8, + 'post_parent' => 0, + ), + (object) array( + 'ID' => 3, + 'post_parent' => 2, + ), + (object) array( + 'ID' => 5, + 'post_parent' => 3, + ), + (object) array( + 'ID' => 7, + 'post_parent' => 4, + ), + (object) array( + 'ID' => 9, + 'post_parent' => 8, + ), + (object) array( + 'ID' => 4, + 'post_parent' => 2, + ), + (object) array( + 'ID' => 6, + 'post_parent' => 3, + ), + (object) array( + 'ID' => 10, + 'post_parent' => 8, + ), + ); + + $hs = Gutenberg_Hierarchical_Sort::init(); + $result = $hs->sort( $input ); + $this->assertEquals( array( 2, 3, 5, 6, 4, 7, 8, 9, 11, 10 ), $result['post_ids'] ); + $this->assertEquals( + array( + 2 => 0, + 3 => 1, + 5 => 2, + 6 => 2, + 4 => 1, + 7 => 2, + 8 => 0, + 9 => 1, + 11 => 2, + 10 => 1, + ), + $result['levels'] + ); + } + + public function test_return_orphans() { + /* + * Keep this updated as the input array changes. + * The sorted hierarchy would be as follows: + * + * - 3 (orphan) + * - 4 (orphan) + * -- 7 + * + */ + $input = array( + (object) array( + 'ID' => 3, + 'post_parent' => 2, + ), + (object) array( + 'ID' => 7, + 'post_parent' => 4, + ), + (object) array( + 'ID' => 4, + 'post_parent' => 2, + ), + ); + + $hs = Gutenberg_Hierarchical_Sort::init(); + $result = $hs->sort( $input ); + $this->assertEquals( array( 3, 4, 7 ), $result['post_ids'] ); + $this->assertEquals( + array( + 3 => 1, + 4 => 1, + 7 => 2, + ), + $result['levels'] + ); + } +} From a05899534d1c3044c017fe81afc346cc5027e7e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:04:34 +0100 Subject: [PATCH 04/24] Visualize hierarchy --- packages/dataviews/CHANGELOG.md | 8 ++++++-- packages/dataviews/README.md | 15 +++++++++++++++ .../src/components/dataviews-context/index.ts | 2 ++ .../src/components/dataviews-layout/index.tsx | 2 ++ .../dataviews/src/components/dataviews/index.tsx | 4 ++++ .../dataviews-layouts/table/column-primary.tsx | 7 +++++++ .../src/dataviews-layouts/table/index.tsx | 9 +++++++++ .../src/dataviews-layouts/table/style.scss | 1 + packages/dataviews/src/types.ts | 6 ++++++ .../edit-site/src/components/post-list/index.js | 2 ++ 10 files changed, 54 insertions(+), 2 deletions(-) diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 887c279714ec01..6218e1d2dee016 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -6,9 +6,13 @@ - Fixed commonjs export ([#67962](https://github.com/WordPress/gutenberg/pull/67962)) +### Features + +- Add support for hierarchical visualization of data. `DataViews` gets a new prop `getItemLevel` that should return the hierarchical level of the item. By default, it uses `item.level`. + ## 4.10.0 (2024-12-11) -## Breaking Changes +### Breaking Changes - Support showing or hiding title, media and description fields ([#67477](https://github.com/WordPress/gutenberg/pull/67477)). - Unify the `title`, `media` and `description` fields for the different layouts. So instead of the previous `view.layout.mediaField`, `view.layout.primaryField` and `view.layout.columnFields`, all the layouts now support these three fields with the following config ([#67477](https://github.com/WordPress/gutenberg/pull/67477)): @@ -23,7 +27,7 @@ const view = { }; ``` -## Internal +### Internal - Upgraded `@ariakit/react` (v0.4.13) and `@ariakit/test` (v0.4.5) ([#65907](https://github.com/WordPress/gutenberg/pull/65907)). - Upgraded `@ariakit/react` (v0.4.15) and `@ariakit/test` (v0.4.7) ([#67404](https://github.com/WordPress/gutenberg/pull/67404)). diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 6f74a13d8f197a..2c18022cfd777e 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -87,6 +87,21 @@ Example: } ``` +#### `getItemLevel`: `function` + +A function that receives an item and returns its hierarchical level. + +It's optional. The field will get a default implementation by `DataViews` that returns the value of the `item[ level ]`. + +Example: + +```js +// Custom getItemLevel function. +{ + getItemLevel={ ( item ) => item.level.number } +} +``` + #### `fields`: `Object[]` The fields describe the visible items for each record in the dataset and how they behave (how to sort them, display them, etc.). See "Fields API" for a description of every property. diff --git a/packages/dataviews/src/components/dataviews-context/index.ts b/packages/dataviews/src/components/dataviews-context/index.ts index 4bef3ecdbcbb4a..46976b4e5e2f22 100644 --- a/packages/dataviews/src/components/dataviews-context/index.ts +++ b/packages/dataviews/src/components/dataviews-context/index.ts @@ -26,6 +26,7 @@ type DataViewsContextType< Item > = { openedFilter: string | null; setOpenedFilter: ( openedFilter: string | null ) => void; getItemId: ( item: Item ) => string; + getItemLevel: ( item: Item ) => number; onClickItem?: ( item: Item ) => void; isItemClickable: ( item: Item ) => boolean; }; @@ -44,6 +45,7 @@ const DataViewsContext = createContext< DataViewsContextType< any > >( { setOpenedFilter: () => {}, openedFilter: null, getItemId: ( item ) => item.id, + getItemLevel: ( item ) => item.level, isItemClickable: () => true, } ); diff --git a/packages/dataviews/src/components/dataviews-layout/index.tsx b/packages/dataviews/src/components/dataviews-layout/index.tsx index ebc251eae36a7a..d30b1d39c6524d 100644 --- a/packages/dataviews/src/components/dataviews-layout/index.tsx +++ b/packages/dataviews/src/components/dataviews-layout/index.tsx @@ -21,6 +21,7 @@ export default function DataViewsLayout() { data, fields, getItemId, + getItemLevel, isLoading, view, onChangeView, @@ -40,6 +41,7 @@ export default function DataViewsLayout() { data={ data } fields={ fields } getItemId={ getItemId } + getItemLevel={ getItemLevel } isLoading={ isLoading } onChangeView={ onChangeView } onChangeSelection={ onChangeSelection } diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index 99d9b6d684b08c..e245f60b6808bc 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -47,11 +47,13 @@ type DataViewsProps< Item > = { onClickItem?: ( item: Item ) => void; isItemClickable?: ( item: Item ) => boolean; header?: ReactNode; + getItemLevel?: ( item: Item ) => number; } & ( Item extends ItemWithId ? { getItemId?: ( item: Item ) => string } : { getItemId: ( item: Item ) => string } ); const defaultGetItemId = ( item: ItemWithId ) => item.id; +const defaultGetItemLevel = ( item: any ) => item.level; const defaultIsItemClickable = () => true; const EMPTY_ARRAY: any[] = []; @@ -64,6 +66,7 @@ export default function DataViews< Item >( { actions = EMPTY_ARRAY, data, getItemId = defaultGetItemId, + getItemLevel = defaultGetItemLevel, isLoading = false, paginationInfo, defaultLayouts, @@ -115,6 +118,7 @@ export default function DataViews< Item >( { openedFilter, setOpenedFilter, getItemId, + getItemLevel, isItemClickable, onClickItem, } } diff --git a/packages/dataviews/src/dataviews-layouts/table/column-primary.tsx b/packages/dataviews/src/dataviews-layouts/table/column-primary.tsx index 6db65be72bdd4c..6ac4057b0973ba 100644 --- a/packages/dataviews/src/dataviews-layouts/table/column-primary.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/column-primary.tsx @@ -14,6 +14,7 @@ import getClickableItemProps from '../utils/get-clickable-item-props'; function ColumnPrimary< Item >( { item, + level, titleField, mediaField, descriptionField, @@ -21,6 +22,7 @@ function ColumnPrimary< Item >( { isItemClickable, }: { item: Item; + level?: number; titleField?: NormalizedField< Item >; mediaField?: NormalizedField< Item >; descriptionField?: NormalizedField< Item >; @@ -44,6 +46,11 @@ function ColumnPrimary< Item >( { { titleField && (
+ { level !== undefined && ( + + { '—'.repeat( level ) }  + + ) }
) } diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index b010b3ff154fbb..719a6cf224d6b3 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -40,6 +40,7 @@ interface TableColumnFieldProps< Item > { interface TableRowProps< Item > { hasBulkActions: boolean; item: Item; + level?: number; actions: Action< Item >[]; fields: NormalizedField< Item >[]; id: string; @@ -75,6 +76,7 @@ function TableColumnField< Item >( { function TableRow< Item >( { hasBulkActions, item, + level, actions, fields, id, @@ -160,6 +162,7 @@ function TableRow< Item >( { ( { data, fields, getItemId, + getItemLevel, isLoading = false, onChangeView, onChangeSelection, @@ -375,6 +379,11 @@ function ViewTable< Item >( { { data: Item[]; fields: NormalizedField< Item >[]; getItemId: ( item: Item ) => string; + getItemLevel: ( item: Item ) => number; isLoading?: boolean; onChangeView: ( view: View ) => void; onChangeSelection: SetSelection; diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index bbf5d654ddb57a..15b3121e9fac0a 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -300,6 +300,8 @@ export default function PostList( { postType } ) { _embed: 'author', order: view.sort?.direction, orderby: view.sort?.field, + orderby_hierarchy: + view.type === 'table' && !! view.layout?.hierarchicalSort, search: view.search, ...filters, }; From 4ef527c3254ad543facece612a3d04dbea12233e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Tue, 3 Dec 2024 11:34:03 +0100 Subject: [PATCH 05/24] Add view config control to switch on/off hierarchical vizualization --- .../dataviews/src/dataviews-layouts/index.ts | 4 +- .../table/sort-hierarchical.tsx | 37 +++++++++++++++++++ .../table/view-config-options.tsx | 16 ++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 packages/dataviews/src/dataviews-layouts/table/sort-hierarchical.tsx create mode 100644 packages/dataviews/src/dataviews-layouts/table/view-config-options.tsx diff --git a/packages/dataviews/src/dataviews-layouts/index.ts b/packages/dataviews/src/dataviews-layouts/index.ts index f2455f81f1560c..5ab8a91b8f94d9 100644 --- a/packages/dataviews/src/dataviews-layouts/index.ts +++ b/packages/dataviews/src/dataviews-layouts/index.ts @@ -17,7 +17,7 @@ import ViewGrid from './grid'; import ViewList from './list'; import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../constants'; import PreviewSizePicker from './grid/preview-size-picker'; -import DensityPicker from './table/density-picker'; +import TableViewConfigOptions from './table/view-config-options'; export const VIEW_LAYOUTS = [ { @@ -25,7 +25,7 @@ export const VIEW_LAYOUTS = [ label: __( 'Table' ), component: ViewTable, icon: blockTable, - viewConfigOptions: DensityPicker, + viewConfigOptions: TableViewConfigOptions, }, { type: LAYOUT_GRID, diff --git a/packages/dataviews/src/dataviews-layouts/table/sort-hierarchical.tsx b/packages/dataviews/src/dataviews-layouts/table/sort-hierarchical.tsx new file mode 100644 index 00000000000000..c92db6d3138ec0 --- /dev/null +++ b/packages/dataviews/src/dataviews-layouts/table/sort-hierarchical.tsx @@ -0,0 +1,37 @@ +/** + * WordPress dependencies + */ +import { ToggleControl } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { useContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import DataViewsContext from '../../components/dataviews-context'; +import type { ViewTable } from '../../types'; + +function SortHierarchicalControl() { + const context = useContext( DataViewsContext ); + const view = context.view as ViewTable; + const onChangeView = context.onChangeView; + + return ( + { + onChangeView( { + ...view, + layout: { + ...view.layout, + hierarchicalSort: checked, + }, + } ); + } } + /> + ); +} + +export default SortHierarchicalControl; diff --git a/packages/dataviews/src/dataviews-layouts/table/view-config-options.tsx b/packages/dataviews/src/dataviews-layouts/table/view-config-options.tsx new file mode 100644 index 00000000000000..082aa45d81758e --- /dev/null +++ b/packages/dataviews/src/dataviews-layouts/table/view-config-options.tsx @@ -0,0 +1,16 @@ +/** + * Internal dependencies + */ +import DensityPicker from './density-picker'; +import SortHierarchical from './sort-hierarchical'; + +function ViewConfigOptions() { + return ( + <> + + + + ); +} + +export default ViewConfigOptions; From ba3ce47102b146078cbd22bdaa2d9588e5e99477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Thu, 12 Dec 2024 12:18:53 +0100 Subject: [PATCH 06/24] Revert "Add view config control to switch on/off hierarchical vizualization" This reverts commit 2b06468f3f171cdf8a08b10bde7c7e431d230800. --- .../dataviews/src/dataviews-layouts/index.ts | 4 +- .../table/sort-hierarchical.tsx | 37 ------------------- .../table/view-config-options.tsx | 16 -------- 3 files changed, 2 insertions(+), 55 deletions(-) delete mode 100644 packages/dataviews/src/dataviews-layouts/table/sort-hierarchical.tsx delete mode 100644 packages/dataviews/src/dataviews-layouts/table/view-config-options.tsx diff --git a/packages/dataviews/src/dataviews-layouts/index.ts b/packages/dataviews/src/dataviews-layouts/index.ts index 5ab8a91b8f94d9..f2455f81f1560c 100644 --- a/packages/dataviews/src/dataviews-layouts/index.ts +++ b/packages/dataviews/src/dataviews-layouts/index.ts @@ -17,7 +17,7 @@ import ViewGrid from './grid'; import ViewList from './list'; import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../constants'; import PreviewSizePicker from './grid/preview-size-picker'; -import TableViewConfigOptions from './table/view-config-options'; +import DensityPicker from './table/density-picker'; export const VIEW_LAYOUTS = [ { @@ -25,7 +25,7 @@ export const VIEW_LAYOUTS = [ label: __( 'Table' ), component: ViewTable, icon: blockTable, - viewConfigOptions: TableViewConfigOptions, + viewConfigOptions: DensityPicker, }, { type: LAYOUT_GRID, diff --git a/packages/dataviews/src/dataviews-layouts/table/sort-hierarchical.tsx b/packages/dataviews/src/dataviews-layouts/table/sort-hierarchical.tsx deleted file mode 100644 index c92db6d3138ec0..00000000000000 --- a/packages/dataviews/src/dataviews-layouts/table/sort-hierarchical.tsx +++ /dev/null @@ -1,37 +0,0 @@ -/** - * WordPress dependencies - */ -import { ToggleControl } from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import { useContext } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import DataViewsContext from '../../components/dataviews-context'; -import type { ViewTable } from '../../types'; - -function SortHierarchicalControl() { - const context = useContext( DataViewsContext ); - const view = context.view as ViewTable; - const onChangeView = context.onChangeView; - - return ( - { - onChangeView( { - ...view, - layout: { - ...view.layout, - hierarchicalSort: checked, - }, - } ); - } } - /> - ); -} - -export default SortHierarchicalControl; diff --git a/packages/dataviews/src/dataviews-layouts/table/view-config-options.tsx b/packages/dataviews/src/dataviews-layouts/table/view-config-options.tsx deleted file mode 100644 index 082aa45d81758e..00000000000000 --- a/packages/dataviews/src/dataviews-layouts/table/view-config-options.tsx +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Internal dependencies - */ -import DensityPicker from './density-picker'; -import SortHierarchical from './sort-hierarchical'; - -function ViewConfigOptions() { - return ( - <> - - - - ); -} - -export default ViewConfigOptions; From 1fb12e385e4848a87241da8fe802ee71174426a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Thu, 12 Dec 2024 12:18:08 +0100 Subject: [PATCH 07/24] Control automatically when hierarchical sort is active --- .../src/components/post-list/index.js | 22 ++++++++++++++++--- .../sidebar-dataviews/default-views.js | 6 ++++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 15b3121e9fac0a..95ad9d9673c230 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -196,6 +196,7 @@ function getItemId( item ) { export default function PostList( { postType } ) { const [ view, setView ] = useView( postType ); + const [ isDirty, setIsDirty ] = useState( false ); const defaultViews = useDefaultViews( { postType } ); const history = useHistory(); const location = useLocation(); @@ -219,11 +220,27 @@ export default function PostList( { postType } ) { }, [ location.path, location.query.isCustom, history ] ); - const getActiveViewFilters = ( views, match ) => { const found = views.find( ( { slug } ) => slug === match ); return found?.filters ?? []; }; + useEffect( () => { + if ( isDirty ) { + return; + } + + // The sort defaults are set in DEFAULT_POST_BASE. + if ( view.sort.field !== 'title' || view.sort.direction !== 'asc' ) { + setIsDirty( true ); + setView( { + ...view, + layout: { + ...( view?.layout || {} ), + hierarchicalSort: false, + }, + } ); + } + }, [ isDirty, view ] ); const { isLoading: isLoadingFields, fields: _fields } = usePostFields( { postType, @@ -300,8 +317,7 @@ export default function PostList( { postType } ) { _embed: 'author', order: view.sort?.direction, orderby: view.sort?.field, - orderby_hierarchy: - view.type === 'table' && !! view.layout?.hierarchicalSort, + orderby_hierarchy: !! view.layout?.hierarchicalSort, search: view.search, ...filters, }; diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 38f809756828db..8ef4c50483687b 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -27,7 +27,11 @@ import { } from '../../utils/constants'; export const defaultLayouts = { - [ LAYOUT_TABLE ]: {}, + [ LAYOUT_TABLE ]: { + layout: { + hierarchicalSort: true, + }, + }, [ LAYOUT_GRID ]: {}, [ LAYOUT_LIST ]: {}, }; From 404d7642e8ea71050ff2f164ac024cd57e65ea04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:19:43 +0100 Subject: [PATCH 08/24] Display parent fields when hierarchy is active --- .../src/dataviews-layouts/table/index.tsx | 18 ++++++++++++++++-- packages/dataviews/src/types.ts | 2 +- .../sidebar-dataviews/default-views.js | 4 ++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index 719a6cf224d6b3..33308023e243b4 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -105,7 +105,7 @@ function TableRow< Item >( { // `onClick` and can be used to exclude touchscreen devices from certain // behaviours. const isTouchDeviceRef = useRef( false ); - const columns = view.fields ?? []; + const columns = getFieldsToDisplay( view ); const hasPrimaryColumn = ( titleField && showTitle ) || ( mediaField && showMedia ) || @@ -208,6 +208,20 @@ function TableRow< Item >( { ); } +const getFieldsToDisplay = ( view: ViewTableType ) => { + if ( + ! view.layout?.hierarchicalSort || + typeof view.layout?.hierarchicalSort === 'boolean' + ) { + return view.fields || []; + } + + // Make parent field the first field after the primary column. + return Array.from( + new Set( [ view.layout?.hierarchicalSort, ...( view.fields || [] ) ] ) + ); +}; + function ViewTable< Item >( { actions, data, @@ -270,7 +284,7 @@ function ViewTable< Item >( { ( titleField && showTitle ) || ( mediaField && showMedia ) || ( descriptionField && showDescription ); - const columns = view.fields ?? []; + const columns = getFieldsToDisplay( view ); const headerMenuRef = ( column: string, index: number ) => ( node: HTMLButtonElement ) => { if ( node ) { diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 8a955fde87fd08..6c5cdeb196c80b 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -360,7 +360,7 @@ export interface ViewTable extends ViewBase { /** * Switch on/off hierarchical sorting. */ - hierarchicalSort?: boolean; + hierarchicalSort?: boolean | string; }; } diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 8ef4c50483687b..452272993599fc 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -29,7 +29,7 @@ import { export const defaultLayouts = { [ LAYOUT_TABLE ]: { layout: { - hierarchicalSort: true, + hierarchicalSort: 'parent', }, }, [ LAYOUT_GRID ]: {}, @@ -48,7 +48,7 @@ const DEFAULT_POST_BASE = { }, titleField: 'title', mediaField: 'featured_media', - fields: [ 'parent', 'author', 'status' ], + fields: [ 'author', 'status' ], ...defaultLayouts[ LAYOUT_LIST ], }; From 3e8946ebb106d48895021b25aabca56b8bd873f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:42:47 +0100 Subject: [PATCH 09/24] Revert "Display parent fields when hierarchy is active" This reverts commit c053e1e291abb3e4cfaa5e866be185e8f5d83cc7. --- .../src/dataviews-layouts/table/index.tsx | 18 ++---------------- packages/dataviews/src/types.ts | 2 +- .../sidebar-dataviews/default-views.js | 4 ++-- 3 files changed, 5 insertions(+), 19 deletions(-) diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index 33308023e243b4..719a6cf224d6b3 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -105,7 +105,7 @@ function TableRow< Item >( { // `onClick` and can be used to exclude touchscreen devices from certain // behaviours. const isTouchDeviceRef = useRef( false ); - const columns = getFieldsToDisplay( view ); + const columns = view.fields ?? []; const hasPrimaryColumn = ( titleField && showTitle ) || ( mediaField && showMedia ) || @@ -208,20 +208,6 @@ function TableRow< Item >( { ); } -const getFieldsToDisplay = ( view: ViewTableType ) => { - if ( - ! view.layout?.hierarchicalSort || - typeof view.layout?.hierarchicalSort === 'boolean' - ) { - return view.fields || []; - } - - // Make parent field the first field after the primary column. - return Array.from( - new Set( [ view.layout?.hierarchicalSort, ...( view.fields || [] ) ] ) - ); -}; - function ViewTable< Item >( { actions, data, @@ -284,7 +270,7 @@ function ViewTable< Item >( { ( titleField && showTitle ) || ( mediaField && showMedia ) || ( descriptionField && showDescription ); - const columns = getFieldsToDisplay( view ); + const columns = view.fields ?? []; const headerMenuRef = ( column: string, index: number ) => ( node: HTMLButtonElement ) => { if ( node ) { diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 6c5cdeb196c80b..8a955fde87fd08 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -360,7 +360,7 @@ export interface ViewTable extends ViewBase { /** * Switch on/off hierarchical sorting. */ - hierarchicalSort?: boolean | string; + hierarchicalSort?: boolean; }; } diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 452272993599fc..8ef4c50483687b 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -29,7 +29,7 @@ import { export const defaultLayouts = { [ LAYOUT_TABLE ]: { layout: { - hierarchicalSort: 'parent', + hierarchicalSort: true, }, }, [ LAYOUT_GRID ]: {}, @@ -48,7 +48,7 @@ const DEFAULT_POST_BASE = { }, titleField: 'title', mediaField: 'featured_media', - fields: [ 'author', 'status' ], + fields: [ 'parent', 'author', 'status' ], ...defaultLayouts[ LAYOUT_LIST ], }; From 3c753ac6669a4a5ebbecf236fd4c6c8b5a1d1519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:43:16 +0100 Subject: [PATCH 10/24] Hide parent field by default --- .../edit-site/src/components/sidebar-dataviews/default-views.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 8ef4c50483687b..fd4b94b5b1b12b 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -48,7 +48,7 @@ const DEFAULT_POST_BASE = { }, titleField: 'title', mediaField: 'featured_media', - fields: [ 'parent', 'author', 'status' ], + fields: [ 'author', 'status' ], ...defaultLayouts[ LAYOUT_LIST ], }; From 6983694336ddfa06ee3a7c41e96c2be7a0eccd40 Mon Sep 17 00:00:00 2001 From: Miguel Fonseca <150562+mcsf@users.noreply.github.com> Date: Mon, 16 Dec 2024 15:31:54 +0000 Subject: [PATCH 11/24] Rename 'init' to 'get_instance' to reflect singleton pattern --- .../wordpress-6.8/class-gutenberg-hierarchical-sort.php | 8 +++----- phpunit/class-gutenberg-hierarchical-sort-test.php | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php b/lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php index fb49df0f59f5ab..d266eed4e74c4d 100644 --- a/lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php +++ b/lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php @@ -8,13 +8,11 @@ */ class Gutenberg_Hierarchical_Sort { - - private static $post_ids = array(); private static $levels = array(); private static $instance; - public static function init() { + public static function get_instance() { if ( null === self::$instance ) { self::$instance = new self(); } @@ -171,7 +169,7 @@ function ( $args, $request ) { return $args; } - $hs = Gutenberg_Hierarchical_Sort::init(); + $hs = Gutenberg_Hierarchical_Sort::get_instance(); $hs->run( $args ); // Reconfigure the args to display only the ids in the list. @@ -191,7 +189,7 @@ function ( $response, $post, $request ) { return $response; } - $hs = Gutenberg_Hierarchical_Sort::init(); + $hs = Gutenberg_Hierarchical_Sort::get_instance(); $response->data['level'] = $hs->get_levels()[ $post->ID ]; return $response; diff --git a/phpunit/class-gutenberg-hierarchical-sort-test.php b/phpunit/class-gutenberg-hierarchical-sort-test.php index ff0f2dbabc04ad..fde8a582103626 100644 --- a/phpunit/class-gutenberg-hierarchical-sort-test.php +++ b/phpunit/class-gutenberg-hierarchical-sort-test.php @@ -67,7 +67,7 @@ public function test_return_all_post_ids() { ), ); - $hs = Gutenberg_Hierarchical_Sort::init(); + $hs = Gutenberg_Hierarchical_Sort::get_instance(); $result = $hs->sort( $input ); $this->assertEquals( array( 2, 3, 5, 6, 4, 7, 8, 9, 11, 10 ), $result['post_ids'] ); $this->assertEquals( @@ -112,7 +112,7 @@ public function test_return_orphans() { ), ); - $hs = Gutenberg_Hierarchical_Sort::init(); + $hs = Gutenberg_Hierarchical_Sort::get_instance(); $result = $hs->sort( $input ); $this->assertEquals( array( 3, 4, 7 ), $result['post_ids'] ); $this->assertEquals( From 1c10d7e8048ee476b03b64eb8b446c20af2270f0 Mon Sep 17 00:00:00 2001 From: Miguel Fonseca <150562+mcsf@users.noreply.github.com> Date: Mon, 16 Dec 2024 15:33:26 +0000 Subject: [PATCH 12/24] GutenbergHierarchicalSortTest: satisfy linter --- phpunit/class-gutenberg-hierarchical-sort-test.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/phpunit/class-gutenberg-hierarchical-sort-test.php b/phpunit/class-gutenberg-hierarchical-sort-test.php index fde8a582103626..877b8d74c2cb54 100644 --- a/phpunit/class-gutenberg-hierarchical-sort-test.php +++ b/phpunit/class-gutenberg-hierarchical-sort-test.php @@ -117,9 +117,9 @@ public function test_return_orphans() { $this->assertEquals( array( 3, 4, 7 ), $result['post_ids'] ); $this->assertEquals( array( - 3 => 1, - 4 => 1, - 7 => 2, + 3 => 1, + 4 => 1, + 7 => 2, ), $result['levels'] ); From c04da3d44039bb874a07a021298bc518241c4feb Mon Sep 17 00:00:00 2001 From: Miguel Fonseca <150562+mcsf@users.noreply.github.com> Date: Mon, 16 Dec 2024 15:34:09 +0000 Subject: [PATCH 13/24] Gutenberg_Hierarchical_Sort::get_ancestor: Refactor using `??` Feel free to revert if you prefer the former structure, of course. --- .../wordpress-6.8/class-gutenberg-hierarchical-sort.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php b/lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php index d266eed4e74c4d..762c59068b5084 100644 --- a/lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php +++ b/lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php @@ -52,12 +52,7 @@ public static function is_eligible( $request ) { } public static function get_ancestor( $post_id ) { - $ancestor = get_post( $post_id ); - if ( null === $ancestor ) { - return 0; - } - - return $ancestor->post_parent; + return get_post( $post_id )->post_parent ?? 0; } /** From affe0710b26277a54b5c72afe08353407bdca963 Mon Sep 17 00:00:00 2001 From: Miguel Fonseca <150562+mcsf@users.noreply.github.com> Date: Mon, 16 Dec 2024 15:35:21 +0000 Subject: [PATCH 14/24] Gutenberg_Hierarchical_Sort::sort: Refactor for clarity - Rename $ancestors to $level - Remove $root_not_found, preferring a better `while` condition - Fix linting issues (spacing, and `++$a` instead of `$a++`) --- .../class-gutenberg-hierarchical-sort.php | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php b/lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php index 762c59068b5084..d3cdf325f13e66 100644 --- a/lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php +++ b/lib/compat/wordpress-6.8/class-gutenberg-hierarchical-sort.php @@ -101,17 +101,13 @@ public static function sort( $posts ) { // Process remaining children. if ( ! empty( $children ) ) { foreach ( $children as $parent_id => $child_ids ) { - $root_not_found = true; - $ancestors = 0; - $ancestor = $parent_id; - while( $root_not_found ) { - $ancestors++; + $level = 0; + $ancestor = $parent_id; + while ( 0 !== $ancestor ) { + ++$level; $ancestor = self::get_ancestor( $ancestor ); - if ( 0 === $ancestor ) { - $root_not_found = false; - } } - self::add_hierarchical_ids( $ids, $levels, $ancestors, $child_ids, $children ); + self::add_hierarchical_ids( $ids, $levels, $level, $child_ids, $children ); } } From ef44147176148a11310247d00f33832156239ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Tue, 17 Dec 2024 11:22:03 +0100 Subject: [PATCH 15/24] Rename hierchicalSort to showLevels --- .../dataviews/src/dataviews-layouts/table/index.tsx | 2 +- packages/dataviews/src/types.ts | 10 +++++----- packages/edit-site/src/components/post-list/index.js | 7 ++----- .../src/components/sidebar-dataviews/default-views.js | 7 ++----- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index 719a6cf224d6b3..98ec406b266569 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -380,7 +380,7 @@ function ViewTable< Item >( { key={ getItemId( item ) } item={ item } level={ - view.layout?.hierarchicalSort + view.showLevels ? getItemLevel( item ) : undefined } diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 8a955fde87fd08..b40498d694a8e2 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -322,6 +322,11 @@ interface ViewBase { * Whether to show the description */ showDescription?: boolean; + + /** + * Whether to show the hierarchical levels. + */ + showLevels?: boolean; } export interface ColumnStyle { @@ -356,11 +361,6 @@ export interface ViewTable extends ViewBase { * The density of the view. */ density?: Density; - - /** - * Switch on/off hierarchical sorting. - */ - hierarchicalSort?: boolean; }; } diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 95ad9d9673c230..0fd414cd4a1e1c 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -234,10 +234,7 @@ export default function PostList( { postType } ) { setIsDirty( true ); setView( { ...view, - layout: { - ...( view?.layout || {} ), - hierarchicalSort: false, - }, + showLevels: false, } ); } }, [ isDirty, view ] ); @@ -317,7 +314,7 @@ export default function PostList( { postType } ) { _embed: 'author', order: view.sort?.direction, orderby: view.sort?.field, - orderby_hierarchy: !! view.layout?.hierarchicalSort, + orderby_hierarchy: !! view.showLevels, search: view.search, ...filters, }; diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index fd4b94b5b1b12b..c6edf7d2dd1203 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -27,11 +27,7 @@ import { } from '../../utils/constants'; export const defaultLayouts = { - [ LAYOUT_TABLE ]: { - layout: { - hierarchicalSort: true, - }, - }, + [ LAYOUT_TABLE ]: {}, [ LAYOUT_GRID ]: {}, [ LAYOUT_LIST ]: {}, }; @@ -46,6 +42,7 @@ const DEFAULT_POST_BASE = { field: 'title', direction: 'asc', }, + showLevels: true, titleField: 'title', mediaField: 'featured_media', fields: [ 'author', 'status' ], From e6c708effa4de3ef2664c7a15743f13091537db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Tue, 17 Dec 2024 12:44:10 +0100 Subject: [PATCH 16/24] Set showLevels internally using onChangeView instead of effect --- .../components/dataviews-view-config/index.tsx | 2 ++ .../table/column-header-menu.tsx | 1 + .../edit-site/src/components/post-list/index.js | 15 --------------- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index bd16f3f9cdca3b..0b3512714e14a4 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -152,6 +152,7 @@ function SortFieldControl() { direction: view?.sort?.direction || 'desc', field: value, }, + showLevels: false, } ); } } /> @@ -194,6 +195,7 @@ function SortDirectionControl() { )?.id || '', }, + showLevels: false, } ); return; } diff --git a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx index 55cd8d867eff40..1d8d22193bbd07 100644 --- a/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/column-header-menu.tsx @@ -142,6 +142,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >( field: fieldId, direction, }, + showLevels: false, } ); } } > diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 0fd414cd4a1e1c..bdf6769d40e715 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -196,7 +196,6 @@ function getItemId( item ) { export default function PostList( { postType } ) { const [ view, setView ] = useView( postType ); - const [ isDirty, setIsDirty ] = useState( false ); const defaultViews = useDefaultViews( { postType } ); const history = useHistory(); const location = useLocation(); @@ -224,20 +223,6 @@ export default function PostList( { postType } ) { const found = views.find( ( { slug } ) => slug === match ); return found?.filters ?? []; }; - useEffect( () => { - if ( isDirty ) { - return; - } - - // The sort defaults are set in DEFAULT_POST_BASE. - if ( view.sort.field !== 'title' || view.sort.direction !== 'asc' ) { - setIsDirty( true ); - setView( { - ...view, - showLevels: false, - } ); - } - }, [ isDirty, view ] ); const { isLoading: isLoadingFields, fields: _fields } = usePostFields( { postType, From e53e69b341fc0ccbf7bd71c5f3b0ed9391978305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Tue, 17 Dec 2024 12:56:30 +0100 Subject: [PATCH 17/24] Do not provide a default implementation for getItemLevel --- packages/dataviews/CHANGELOG.md | 2 +- packages/dataviews/README.md | 15 +++++++-------- .../src/components/dataviews-context/index.ts | 3 +-- .../dataviews/src/components/dataviews/index.tsx | 3 +-- .../src/dataviews-layouts/table/index.tsx | 3 ++- packages/dataviews/src/types.ts | 2 +- .../edit-site/src/components/post-list/index.js | 5 +++++ 7 files changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 6218e1d2dee016..965d98e80d6aea 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -8,7 +8,7 @@ ### Features -- Add support for hierarchical visualization of data. `DataViews` gets a new prop `getItemLevel` that should return the hierarchical level of the item. By default, it uses `item.level`. +- Add support for hierarchical visualization of data. `DataViews` gets a new prop `getItemLevel` that should return the hierarchical level of the item. The view can use `view.showLevels` to display the levels. It's up to the consumer data source to prepare this information. ## 4.10.0 (2024-12-11) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 2c18022cfd777e..5afa353d2f5b03 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -89,16 +89,14 @@ Example: #### `getItemLevel`: `function` -A function that receives an item and returns its hierarchical level. - -It's optional. The field will get a default implementation by `DataViews` that returns the value of the `item[ level ]`. +A function that receives an item and returns its hierarchical level. It's optional, but this property must be passed for DataViews to display the hierarchical levels of the data if `view.showLevels` is true. Example: ```js -// Custom getItemLevel function. +// Example implementation { - getItemLevel={ ( item ) => item.level.number } + getItemLevel={ ( item ) => item.level } } ``` @@ -206,6 +204,7 @@ Properties: - `showTitle`: Whether the title should be shown in the UI. `true` by default. - `showMedia`: Whether the media should be shown in the UI. `true` by default. - `showDescription`: Whether the description should be shown in the UI. `true` by default. +- `showLevels`: Whether to display the hierarchical levels for the data. `false` by default. See related `getItemLevel` DataView prop. - `fields`: a list of remaining field `id` that are visible in the UI and the specific order in which they are displayed. - `layout`: config that is specific to a particular layout type. @@ -317,8 +316,8 @@ const actions = [ RenderModal: ( { items, closeModal, onActionPerformed } ) => (

Are you sure you want to delete { items.length } item(s)?

-