diff --git a/packages/core-data/src/entities.js b/packages/core-data/src/entities.js index 87ae920dba6b6..426745ce1b3cf 100644 --- a/packages/core-data/src/entities.js +++ b/packages/core-data/src/entities.js @@ -154,6 +154,14 @@ export const defaultEntities = [ baseURLParams: { context: 'edit' }, key: 'stylesheet', }, + { + label: __( 'Plugins' ), + name: 'plugin', + kind: 'root', + baseURL: '/wp/v2/plugins', + baseURLParams: { context: 'edit' }, + key: 'plugin', + }, ]; export const kinds = [ diff --git a/packages/edit-site/src/components/list/added-by.js b/packages/edit-site/src/components/list/added-by.js new file mode 100644 index 0000000000000..685d93fbdfb7f --- /dev/null +++ b/packages/edit-site/src/components/list/added-by.js @@ -0,0 +1,179 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { + __experimentalHStack as HStack, + Icon, + Tooltip, +} from '@wordpress/components'; +import { store as coreStore } from '@wordpress/core-data'; +import { useSelect } from '@wordpress/data'; +import { useState } from '@wordpress/element'; +import { layout as themeIcon, plugins as pluginIcon } from '@wordpress/icons'; +import { __ } from '@wordpress/i18n'; + +const TEMPLATE_POST_TYPE_NAMES = [ 'wp_template', 'wp_template_part' ]; + +function CustomizedTooltip( { isCustomized, children } ) { + if ( ! isCustomized ) { + return children; + } + + return ( + + { children } + + ); +} + +function AddedByTheme( { slug, isCustomized } ) { + const theme = useSelect( + ( select ) => select( coreStore ).getTheme( slug ), + [ slug ] + ); + + return ( + + +
+ +
+
+ { theme?.name?.rendered || slug } +
+ ); +} + +function AddedByPlugin( { slug, isCustomized } ) { + const plugin = useSelect( + ( select ) => select( coreStore ).getPlugin( slug ), + [ slug ] + ); + + return ( + + +
+ +
+
+ { plugin?.name || slug } +
+ ); +} + +function AddedByAuthor( { id } ) { + const user = useSelect( ( select ) => select( coreStore ).getUser( id ), [ + id, + ] ); + const [ isImageLoaded, setIsImageLoaded ] = useState( false ); + + return ( + +
+ setIsImageLoaded( true ) } + alt="" + src={ user?.avatar_urls[ 48 ] } + /> +
+ { user?.nickname } +
+ ); +} + +function AddedBySite() { + const { name, logoURL } = useSelect( ( select ) => { + const { getEntityRecord, getMedia } = select( coreStore ); + const siteData = getEntityRecord( 'root', '__unstableBase' ); + + return { + name: siteData.name, + logoURL: siteData?.site_logo + ? getMedia( siteData.site_logo )?.source_url + : undefined, + }; + }, [] ); + const [ isImageLoaded, setIsImageLoaded ] = useState( false ); + + return ( + +
+ setIsImageLoaded( true ) } + alt="" + src={ logoURL } + /> +
+ { name } +
+ ); +} + +export default function AddedBy( { templateType, template } ) { + if ( ! template ) { + return; + } + + if ( TEMPLATE_POST_TYPE_NAMES.includes( templateType ) ) { + // Template originally provided by a theme, but customized by a user. + // Templates originally didn't have the 'origin' field so identify + // older customized templates by checking for no origin and a 'theme' + // or 'custom' source. + if ( + template.has_theme_file && + ( template.origin === 'theme' || + ( ! template.origin && + [ 'theme', 'custom' ].includes( template.source ) ) ) + ) { + return ( + + ); + } + + // Template originally provided by a plugin, but customized by a user. + if ( template.has_theme_file && template.origin === 'plugin' ) { + return ( + + ); + } + + // Template was created from scratch, but has no author. Author support + // was only added to templates in WordPress 5.9. Fallback to showing the + // site logo and title. + if ( + ! template.has_theme_file && + template.source === 'custom' && + ! template.author + ) { + return ; + } + } + + // Simply show the author for templates created from scratch that have an + // author or for any other post type. + return ; +} diff --git a/packages/edit-site/src/components/list/style.scss b/packages/edit-site/src/components/list/style.scss index 575348c7f65ad..f5ab68cd8bfe3 100644 --- a/packages/edit-site/src/components/list/style.scss +++ b/packages/edit-site/src/components/list/style.scss @@ -154,3 +154,55 @@ margin-right: $grid-unit-10; } } + +.edit-site-list-added-by__icon { + display: flex; + flex-shrink: 0; + position: relative; + align-items: center; + justify-content: center; + width: $grid-unit-40; + height: $grid-unit-40; + background: $gray-800; + border-radius: 100%; + + svg { + fill: $white; + } + + &.is-customized::after { + position: absolute; + content: ""; + background: var(--wp-admin-theme-color); + height: $grid-unit-10; + width: $grid-unit-10; + outline: 2px solid $white; + border-radius: 100%; + top: -1px; + right: -1px; + } +} + +.edit-site-list-added-by__avatar { + flex-shrink: 0; + overflow: hidden; + border-radius: 100%; + background: $gray-800; + width: $grid-unit-40; + height: $grid-unit-40; + + img { + width: $grid-unit-40; + height: $grid-unit-40; + object-fit: cover; + opacity: 0; + transition: opacity 0.1s linear; + @include reduce-motion("transition"); + } + + &.is-loaded { + img { + opacity: 1; + } + } +} diff --git a/packages/edit-site/src/components/list/table.js b/packages/edit-site/src/components/list/table.js index 148b6b460c0ff..bcbf48c3939b4 100644 --- a/packages/edit-site/src/components/list/table.js +++ b/packages/edit-site/src/components/list/table.js @@ -14,6 +14,7 @@ import { addQueryArgs } from '@wordpress/url'; * Internal dependencies */ import Actions from './actions'; +import AddedBy from './added-by'; export default function Table( { templateType } ) { const { templates, isLoading, postType } = useSelect( @@ -104,7 +105,10 @@ export default function Table( { templateType } ) { - { template.theme } +