Skip to content

Commit

Permalink
Proof of concept: hierarchical data
Browse files Browse the repository at this point in the history
  • Loading branch information
oandregal committed Oct 25, 2024
1 parent 1f4875a commit c21c98e
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 4 deletions.
121 changes: 118 additions & 3 deletions packages/dataviews/src/dataviews-layouts/table/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ interface TableColumnFieldProps< Item > {
primaryField?: NormalizedField< Item >;
field: NormalizedField< Item >;
item: Item;
parent?: string;
level?: number;
}

interface TableColumnCombinedProps< Item > {
Expand All @@ -54,13 +56,17 @@ interface TableColumnProps< Item > {
primaryField?: NormalizedField< Item >;
fields: NormalizedField< Item >[];
item: Item;
parent?: string;
level?: number;
column: string;
view: ViewTableType;
}

interface TableRowProps< Item > {
hasBulkActions: boolean;
item: Item;
parent?: string;
level?: number;
actions: Action< Item >[];
fields: NormalizedField< Item >[];
id: string;
Expand Down Expand Up @@ -100,17 +106,27 @@ function TableColumn< Item >( {

function TableColumnField< Item >( {
primaryField,
parent,
level,
item,
field,
}: TableColumnFieldProps< Item > ) {
const isPrimaryField = primaryField?.id === field.id;
return (
<div
className={ clsx( 'dataviews-view-table__cell-content-wrapper', {
'dataviews-view-table__primary-field':
primaryField?.id === field.id,
'dataviews-view-table__primary-field': isPrimaryField,
} ) }
>
{ isPrimaryField && level !== undefined && (
<span className="dataviews-view-table__level">
{ '— '.repeat( level ) }
</span>
) }
<field.render { ...{ item } } />
{ isPrimaryField && parent && (
<span className="dataviews-view-table__parent">{ `Parent: ${ parent }` }</span>
) }
</div>
);
}
Expand All @@ -132,6 +148,8 @@ function TableColumnCombined< Item >( {
function TableRow< Item >( {
hasBulkActions,
item,
parent,
level,
actions,
fields,
id,
Expand Down Expand Up @@ -216,6 +234,8 @@ function TableRow< Item >( {
primaryField={ primaryField }
fields={ fields }
item={ item }
parent={ parent }
level={ level }
column={ column }
view={ view }
/>
Expand Down Expand Up @@ -296,6 +316,99 @@ function ViewTable< Item >( {
( field ) => field.id === view.layout?.primaryField
);

const getPrimaryFieldValue = ( item: Item ) => {
return primaryField?.getValue( { item } );
};

const getAllDescendants = (
children: Item[][],
index: number,
levels: number[],
levelIndex: number
): Item[] => {
const nested: Item[] = [];

if ( children[ index ] ) {
children[ index ]?.forEach( ( child: Item ) => {
const itemId = +getItemId( child );
nested.push( child );
levels[ itemId ] = levelIndex;
nested.push(
...getAllDescendants(
children,
itemId,
levels,
levelIndex + 1
)
);
} );
}

return nested;
};

const rows: Item[] = [];
const topLevel: Item[] = [];
const children: Item[][] = [];
const primaryFieldValues: string[] = [];
const levels: number[] = [];
if ( !! view.layout?.hierarchical ) {
const hierarchicalField = view.layout?.hierarchical;
data.forEach( ( item: Item ) => {
const parentId = ( item as Record< string, number > )[
hierarchicalField
];
if ( parentId === 0 ) {
topLevel[ +getItemId( item ) ] = item;
primaryFieldValues[ +getItemId( item ) ] =
getPrimaryFieldValue( item );
} else {
if ( ! children[ parentId ] ) {
children[ parentId ] = [];
}
children[ parentId ].push( item );
primaryFieldValues[ +getItemId( item ) ] =
getPrimaryFieldValue( item );
}
} );

topLevel.forEach( ( item, index ) => {
rows.push( item );
levels[ index ] = 0;
rows.push( ...getAllDescendants( children, index, levels, 1 ) );
} );
} else {
rows.push( ...data );
}

const getItemLevel = ( item: Item ) => {
if ( ! view.layout?.hierarchical ) {
return;
}

return levels[ +getItemId( item ) ];
};

const getItemParent = ( item: Item ) => {
if ( ! view.layout?.hierarchical ) {
return;
}

const parent = ( item as Record< string, any > )?.[
view.layout?.hierarchical
];

if ( parent === 0 ) {
return;
}

if ( ! primaryFieldValues[ parent ] ) {
return;
}

return primaryFieldValues[ parent ];
};

return (
<>
<table
Expand Down Expand Up @@ -379,10 +492,12 @@ function ViewTable< Item >( {
</thead>
<tbody>
{ hasData &&
data.map( ( item, index ) => (
rows.map( ( item, index ) => (
<TableRow
key={ getItemId( item ) }
item={ item }
parent={ getItemParent( item ) }
level={ getItemLevel( item ) }
hasBulkActions={ hasBulkActions }
actions={ actions }
fields={ fields }
Expand Down
4 changes: 4 additions & 0 deletions packages/dataviews/src/dataviews-layouts/table/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@
opacity: 1;
}
}

.dataviews-view-table__parent {
background-color: #f0f0f0;
}
}

/* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */
Expand Down
5 changes: 5 additions & 0 deletions packages/dataviews/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,11 @@ export interface ViewTable extends ViewBase {
* The styles for the columns.
*/
styles?: Record< string, ColumnStyle >;

/**
* The field to visualize hierarchical data.
*/
hierarchical?: string;
};
}

Expand Down
2 changes: 1 addition & 1 deletion packages/edit-site/src/components/post-fields/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ function usePostFields( viewType ) {
() => [
featuredImageField,
{
id: 'id',
id: 'id', // TODO: remove field
label: __( 'ID' ),
type: 'integer',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const defaultLayouts = {
[ LAYOUT_TABLE ]: {
layout: {
primaryField: 'title',
hierarchical: 'parent',
styles: {
title: {
maxWidth: 300,
Expand All @@ -41,12 +42,14 @@ export const defaultLayouts = {
layout: {
mediaField: 'featured_media',
primaryField: 'title',
hierarchical: 'parent', // TODO: remove this
},
},
[ LAYOUT_LIST ]: {
layout: {
primaryField: 'title',
mediaField: 'featured_media',
hierarchical: 'parent', // TODO: remove this
},
},
};
Expand Down

0 comments on commit c21c98e

Please sign in to comment.