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

Data views: Add ability to display fields as a badge in grid layout #60284

Merged
merged 14 commits into from
Apr 5, 2024
21 changes: 20 additions & 1 deletion packages/dataviews/src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,9 @@
line-height: 16px;

&:not(:empty) {
padding: $grid-unit-15;
padding: $grid-unit-15 0;
padding-top: 0;
margin: 0 $grid-unit-15;
}

.dataviews-view-grid__field {
Expand All @@ -355,6 +356,24 @@
}
}
}

.dataviews-view-grid__badge-fields {
&:not(:empty) {
padding: $grid-unit-15;
padding-top: 0;
}

.dataviews-view-grid__field-value {
width: fit-content;
background: $gray-100;
padding: 0 $grid-unit-10;
min-height: $grid-unit-30;
border-radius: $radius-block-ui;
display: flex;
align-items: center;
font-size: 12px;
}
}
}

.dataviews-view-list {
Expand Down
129 changes: 87 additions & 42 deletions packages/dataviews/src/view-grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ function GridItem( {
mediaField,
primaryField,
visibleFields,
badgeFields,
displayAsColumnFields,
} ) {
const hasBulkAction = useHasAPossibleBulkAction( actions, item );
Expand Down Expand Up @@ -99,46 +100,76 @@ function GridItem( {
</HStack>
<ItemActions item={ item } actions={ actions } isCompact />
</HStack>
<VStack className="dataviews-view-grid__fields" spacing={ 3 }>
{ visibleFields.map( ( field ) => {
const renderedValue = field.render( {
item,
} );
if ( ! renderedValue ) {
return null;
}
return (
<Flex
className={ classnames(
'dataviews-view-grid__field',
displayAsColumnFields?.includes( field.id )
? 'is-column'
: 'is-row'
) }
key={ field.id }
gap={ 1 }
justify="flex-start"
expanded
style={ { height: 'auto' } }
direction={
displayAsColumnFields?.includes( field.id )
? 'column'
: 'row'
}
>
<FlexItem className="dataviews-view-grid__field-name">
{ field.header }
</FlexItem>
{ !! badgeFields?.length && (
<HStack
className="dataviews-view-grid__badge-fields"
spacing={ 2 }
wrap
align="top"
justify="flex-start"
>
{ badgeFields.map( ( field ) => {
const renderedValue = field.render( {
item,
} );
if ( ! renderedValue ) {
return null;
}
return (
<FlexItem
className="dataviews-view-grid__field-value"
style={ { maxHeight: 'none' } }
key={ field.id }
className={ 'dataviews-view-grid__field-value' }
>
{ renderedValue }
</FlexItem>
</Flex>
);
} ) }
</VStack>
);
} ) }
</HStack>
) }
{ !! visibleFields?.length && (
<VStack className="dataviews-view-grid__fields" spacing={ 3 }>
{ visibleFields.map( ( field ) => {
const renderedValue = field.render( {
item,
} );
if ( ! renderedValue ) {
return null;
}
return (
<Flex
className={ classnames(
'dataviews-view-grid__field',
displayAsColumnFields?.includes( field.id )
? 'is-column'
: 'is-row'
) }
key={ field.id }
gap={ 1 }
justify="flex-start"
expanded
style={ { height: 'auto' } }
direction={
displayAsColumnFields?.includes( field.id )
? 'column'
: 'row'
}
>
<>
<FlexItem className="dataviews-view-grid__field-name">
{ field.header }
</FlexItem>
<FlexItem
className="dataviews-view-grid__field-value"
style={ { maxHeight: 'none' } }
>
{ renderedValue }
</FlexItem>
</>
</Flex>
);
} ) }
</VStack>
) }
</VStack>
);
}
Expand All @@ -159,12 +190,25 @@ export default function ViewGrid( {
const primaryField = fields.find(
( field ) => field.id === view.layout.primaryField
);
const visibleFields = fields.filter(
( field ) =>
! view.hiddenFields.includes( field.id ) &&
! [ view.layout.mediaField, view.layout.primaryField ].includes(
field.id
)
const { visibleFields, badgeFields } = fields.reduce(
( accumulator, field ) => {
if (
view.hiddenFields.includes( field.id ) ||
[ view.layout.mediaField, view.layout.primaryField ].includes(
field.id
)
) {
return accumulator;
}
// If the field is a badge field, add it to the badgeFields array
// otherwise add it to the rest visibleFields array.
const key = view.layout.badgeFields?.includes( field.id )
? 'badgeFields'
: 'visibleFields';
accumulator[ key ].push( field );
return accumulator;
},
{ visibleFields: [], badgeFields: [] }
);
const hasData = !! data?.length;
return (
Expand All @@ -190,6 +234,7 @@ export default function ViewGrid( {
mediaField={ mediaField }
primaryField={ primaryField }
visibleFields={ visibleFields }
badgeFields={ badgeFields }
displayAsColumnFields={
view.layout.displayAsColumnFields
}
Expand Down
21 changes: 13 additions & 8 deletions packages/edit-site/src/components/page-patterns/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const defaultConfigPerViewType = {
[ LAYOUT_GRID ]: {
mediaField: 'preview',
primaryField: 'title',
badgeFields: [ 'sync-status' ],
Copy link
Contributor

Choose a reason for hiding this comment

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

We're starting to have several kind of displays for fields: primary, media, badge (maybe others in other layouts). It would be good to check if we can consolidate somehow. Maybe visibleFields could support arrays as fields: [ [ { field: 'preview', display: 'media' }], { field: 'title', display: 'primary' }], { field: 'sync-status', display: 'badge' }, 'anyrandomfield' ]

Copy link
Contributor

Choose a reason for hiding this comment

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

I also wonder if want to show the "badge" in the same way in other views. Meaning maybe the field itself (sync status) display as a badge in its render function rather than this begin a config.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes I think so too. I'll create an issue to track this.

},
};
const DEFAULT_VIEW = {
Expand Down Expand Up @@ -314,19 +315,23 @@ export default function DataviewsPatterns() {
];
if ( type === PATTERN_TYPES.theme ) {
_fields.push( {
header: __( 'Sync Status' ),
header: __( 'Sync status' ),
id: 'sync-status',
render: ( { item } ) => {
// User patterns can have their sync statuses checked directly.
// Non-user patterns are all unsynced for the time being.
return (
SYNC_FILTERS.find(
( { value } ) => value === item.syncStatus
)?.label ||
SYNC_FILTERS.find(
( { value } ) =>
value === PATTERN_SYNC_TYPES.unsynced
).label
<span
className={ `edit-site-patterns__field-sync-status-${ item.syncStatus }` }
>
{ SYNC_FILTERS.find(
( { value } ) => value === item.syncStatus
)?.label ||
SYNC_FILTERS.find(
( { value } ) =>
value === PATTERN_SYNC_TYPES.unsynced
).label }
</span>
);
},
type: ENUMERATION_TYPE,
Expand Down
7 changes: 7 additions & 0 deletions packages/edit-site/src/components/page-patterns/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@
.dataviews-pagination {
z-index: z-index(".edit-site-patterns__dataviews-list-pagination");
}

.dataviews-view-grid__badge-fields {
.dataviews-view-grid__field-value:has(.edit-site-patterns__field-sync-status-fully) {
background: rgba(var(--wp-block-synced-color--rgb), 0.04);
color: var(--wp-block-synced-color);
}
}
}

.dataviews-action-modal__duplicate-pattern {
Expand Down
Loading