Skip to content

Commit

Permalink
Site editor sidebar: refactor page details (WordPress#51093)
Browse files Browse the repository at this point in the history
* - Rolls back exposing getMedia details from the editor package
- Refactors page details and the useSelect callbacks
- Rolls back the generic data list components since we don't need them anywhere else (premature optimization)

* - Ensuring last modified is visible

* Use `availableTemplates` from editor settings to fetch template title using slug

* Checking for templateSlug before performing a find

* Whoops forgot to extract props from featuredMedia object in useSelect.
  • Loading branch information
ramonjd authored and sethrubenstein committed Jul 13, 2023
1 parent 40ef898 commit fe1a85a
Show file tree
Hide file tree
Showing 10 changed files with 269 additions and 291 deletions.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,21 @@ import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { __, _x, sprintf } from '@wordpress/i18n';
import { __, sprintf } from '@wordpress/i18n';
import { useDispatch, useSelect } from '@wordpress/data';
import {
__experimentalUseNavigator as useNavigator,
__experimentalVStack as VStack,
ExternalLink,
__experimentalTruncate as Truncate,
__experimentalHStack as HStack,
__experimentalText as Text,
} from '@wordpress/components';
import {
store as coreStore,
useEntityRecord,
useEntityRecords,
} from '@wordpress/core-data';
import { store as coreStore, useEntityRecord } from '@wordpress/core-data';
import { decodeEntities } from '@wordpress/html-entities';
import { pencil } from '@wordpress/icons';
import { humanTimeDiff } from '@wordpress/date';
import { count as wordCount } from '@wordpress/wordcount';
import { createInterpolateElement } from '@wordpress/element';
import { privateApis as privateEditorApis } from '@wordpress/editor';
import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
import { escapeAttribute } from '@wordpress/escape-html';

Expand All @@ -36,148 +32,44 @@ import { unlock } from '../../private-apis';
import { store as editSiteStore } from '../../store';
import SidebarButton from '../sidebar-button';
import SidebarNavigationSubtitle from '../sidebar-navigation-subtitle';
import SidebarDetails from '../sidebar-navigation-data-list';
import DataListItem from '../sidebar-navigation-data-list/data-list-item';
import StatusLabel from './status-label';

// Taken from packages/editor/src/components/time-to-read/index.js.
const AVERAGE_READING_RATE = 189;

function getPageDetails( page ) {
if ( ! page ) {
return [];
}

const details = [
{
label: __( 'Status' ),
value: (
<StatusLabel
status={ page?.password ? 'protected' : page.status }
date={ page?.date }
/>
),
},
{
label: __( 'Slug' ),
value: <Truncate numberOfLines={ 1 }>{ page.slug }</Truncate>,
},
];

if ( page?.templateTitle ) {
details.push( {
label: __( 'Template' ),
value: page.templateTitle,
} );
}

details.push( {
label: __( 'Parent' ),
value: page?.parentTitle,
} );

/*
* translators: If your word count is based on single characters (e.g. East Asian characters),
* enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'.
* Do not translate into your own language.
*/
const wordCountType = _x( 'words', 'Word count type. Do not translate!' );
const wordsCounted = page?.content?.rendered
? wordCount( page.content.rendered, wordCountType )
: 0;
const readingTime = Math.round( wordsCounted / AVERAGE_READING_RATE );

if ( wordsCounted ) {
details.push(
{
label: __( 'Words' ),
value: wordsCounted.toLocaleString() || __( 'Unknown' ),
},
{
label: __( 'Time to read' ),
value:
readingTime > 1
? sprintf(
/* translators: %s: is the number of minutes. */
__( '%s mins' ),
readingTime.toLocaleString()
)
: __( '< 1 min' ),
}
);
}
return details;
}
import PageDetails from './page-details';

export default function SidebarNavigationScreenPage() {
const { setCanvasMode } = unlock( useDispatch( editSiteStore ) );
const { getFeaturedMediaDetails } = unlock( privateEditorApis );
const {
params: { postId },
} = useNavigator();
const { record } = useEntityRecord( 'postType', 'page', postId );

const {
parentTitle,
featuredMediaDetails: { mediaSourceUrl, altText },
templateSlug,
} = useSelect(
const { featuredMediaAltText, featuredMediaSourceUrl } = useSelect(
( select ) => {
const { getEditedPostContext } = unlock( select( editSiteStore ) );

const { getEntityRecord } = select( coreStore );
// Featured image.
const attachedMedia = record?.featured_media
? select( coreStore ).getEntityRecord(
? getEntityRecord(
'postType',
'attachment',
record?.featured_media
)
: null;

// Parent page title.
let _parentTitle = record?.parent
? select( coreStore ).getEntityRecord(
'postType',
'page',
record.parent,
{ _fields: [ 'title' ] }
)
: null;

if ( _parentTitle?.title ) {
_parentTitle = decodeEntities(
_parentTitle.title?.rendered || __( '(no title)' )
);
} else {
_parentTitle = __( 'Top level' );
}

return {
parentTitle: _parentTitle,
templateSlug: getEditedPostContext()?.templateSlug,
featuredMediaDetails: {
...getFeaturedMediaDetails( attachedMedia, postId ),
altText: escapeAttribute(
attachedMedia?.alt_text ||
attachedMedia?.description?.raw ||
''
),
},
featuredMediaSourceUrl:
attachedMedia?.media_details.sizes?.medium?.source_url ||
attachedMedia?.source_url,
featuredMediaAltText: escapeAttribute(
attachedMedia?.alt_text ||
attachedMedia?.description?.raw ||
''
),
};
},
[ record, postId ]
[ record ]
);

// Match template slug to template title.
const { records: templates, isResolving: areTemplatesLoading } =
useEntityRecords( 'postType', 'wp_template', {
per_page: -1,
} );
const templateTitle =
! areTemplatesLoading && templateSlug
? templates?.find( ( template ) => template?.slug === templateSlug )
?.title?.rendered || templateSlug
: '';
const featureImageAltText = featuredMediaAltText
? decodeEntities( featuredMediaAltText )
: decodeEntities( record?.title?.rendered || __( 'Featured image' ) );

return record ? (
<SidebarNavigationScreen
Expand Down Expand Up @@ -210,21 +102,14 @@ export default function SidebarNavigationScreenPage() {
className={ classnames(
'edit-site-sidebar-navigation-screen-page__featured-image',
{
'has-image': !! mediaSourceUrl,
'has-image': !! featuredMediaSourceUrl,
}
) }
>
{ !! mediaSourceUrl && (
{ !! featuredMediaSourceUrl && (
<img
alt={
altText
? decodeEntities( altText )
: decodeEntities(
record.title?.rendered ||
__( 'Featured image' )
)
}
src={ mediaSourceUrl }
alt={ featureImageAltText }
src={ featuredMediaSourceUrl }
/>
) }
{ ! record?.featured_media && (
Expand All @@ -241,31 +126,35 @@ export default function SidebarNavigationScreenPage() {
</Truncate>
) }
<SidebarNavigationSubtitle>
Details
{ __( 'Details' ) }
</SidebarNavigationSubtitle>
<SidebarDetails
details={ getPageDetails( {
parentTitle,
templateTitle,
...record,
} ) }
/>
<PageDetails id={ postId } />
</>
}
footer={
<DataListItem
label={ __( 'Last modified' ) }
value={ createInterpolateElement(
sprintf(
/* translators: %s: is the relative time when the post was last modified. */
__( '<time>%s</time>' ),
humanTimeDiff( record.modified )
),
{
time: <time dateTime={ record.modified } />,
}
) }
/>
!! record?.modified && (
<HStack
spacing={ 5 }
alignment="left"
className="edit-site-sidebar-navigation-screen-page__details"
>
<Text className="edit-site-sidebar-navigation-screen-page__details-label">
{ __( 'Last modified' ) }
</Text>
<Text className="edit-site-sidebar-navigation-screen-page__details-value">
{ createInterpolateElement(
sprintf(
/* translators: %s: is the relative time when the post was last modified. */
__( '<time>%s</time>' ),
humanTimeDiff( record.modified )
),
{
time: <time dateTime={ record.modified } />,
}
) }
</Text>
</HStack>
)
}
/>
) : null;
Expand Down
Loading

0 comments on commit fe1a85a

Please sign in to comment.