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

feat/154: add a Podcast Platforms Block #241

Merged
merged 13 commits into from Aug 18, 2023
30 changes: 30 additions & 0 deletions assets/css/podcasting-edit-term.css
Expand Up @@ -11,3 +11,33 @@
max-width: 100%;
width: 75px;
}

.simple_podcasting__platforms img {
display: block;
max-width: 42px;
margin: 0 auto;
height: auto;
}

.simple_podcasting__platforms th {
padding: 15px 10px;
text-align: center;
}

.simple_podcasting__platforms td {
vertical-align: middle;
padding: 15px 10px;
}

.simple_podcasting__platforms-url {
min-width: 220px;
}

.simple_podcasting__platforms-icon {
transition: background-color 0.2s ease-out;
}

.simple_podcasting__platforms-icon--darken-bg {
background-color: rgb(28 52 59 / 22%);
transition: background-color 0.2s ease-in;
}
4 changes: 0 additions & 4 deletions assets/css/podcasting-onboarding.scss
Expand Up @@ -2,10 +2,6 @@
box-sizing: border-box;
}

#wpcontent {
padding-left: 0;
}
iamdharmesh marked this conversation as resolved.
Show resolved Hide resolved

#simple-podcasting {
&__onboarding-header {
width: 100%;
Expand Down
Binary file added assets/images/icons/RSS/black-100.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/RSS/black-40.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/RSS/color-100.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/RSS/color-40.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/RSS/white-100.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/RSS/white-40.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/apple-podcasts/black-40.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/apple-podcasts/color-40.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/apple-podcasts/white-40.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/castro/black-100.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/castro/black-40.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/castro/color-100.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/castro/color-40.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/castro/white-100.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/castro/white-40.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/google-podcasts/black-40.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/google-podcasts/color-40.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/google-podcasts/white-40.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/overcast/black-100.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icons/overcast/black-40.png
Binary file added assets/images/icons/overcast/color-100.png
Binary file added assets/images/icons/overcast/color-40.png
Binary file added assets/images/icons/overcast/white-100.png
Binary file added assets/images/icons/overcast/white-40.png
Binary file added assets/images/icons/pandora/black-100.png
Binary file added assets/images/icons/pandora/black-40.png
Binary file added assets/images/icons/pandora/color-100.png
Binary file added assets/images/icons/pandora/color-40.png
Binary file added assets/images/icons/pandora/white-100.png
Binary file added assets/images/icons/pandora/white-40.png
Binary file added assets/images/icons/playerfm/black-100.png
Binary file added assets/images/icons/playerfm/black-40.png
Binary file added assets/images/icons/playerfm/color-100.png
Binary file added assets/images/icons/playerfm/color-40.png
Binary file added assets/images/icons/playerfm/white-100.png
Binary file added assets/images/icons/playerfm/white-40.png
Binary file added assets/images/icons/pocket-casts/black-100.png
Binary file added assets/images/icons/pocket-casts/black-40.png
Binary file added assets/images/icons/pocket-casts/color-100.png
Binary file added assets/images/icons/pocket-casts/color-40.png
Binary file added assets/images/icons/pocket-casts/white-100.png
Binary file added assets/images/icons/pocket-casts/white-40.png
Binary file added assets/images/icons/spotify/black-100.png
Binary file added assets/images/icons/spotify/black-40.png
Binary file added assets/images/icons/spotify/color-100.png
Binary file added assets/images/icons/spotify/color-40.png
Binary file added assets/images/icons/spotify/white-100.png
Binary file added assets/images/icons/spotify/white-40.png
Binary file added assets/images/icons/stitcher/black-100.png
Binary file added assets/images/icons/stitcher/black-40.png
Binary file added assets/images/icons/stitcher/color-100.png
Binary file added assets/images/icons/stitcher/color-40.png
Binary file added assets/images/icons/stitcher/white-100.png
Binary file added assets/images/icons/stitcher/white-40.png
Binary file added assets/images/icons/tunein/black-100.png
Binary file added assets/images/icons/tunein/black-40.png
Binary file added assets/images/icons/tunein/color-100.png
Binary file added assets/images/icons/tunein/color-40.png
Binary file added assets/images/icons/tunein/white-100.png
Binary file added assets/images/icons/tunein/white-40.png
237 changes: 237 additions & 0 deletions assets/js/blocks/podcast-platforms/edit.js
@@ -0,0 +1,237 @@
import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
import { useState, useEffect } from '@wordpress/element';
import apiFetch from '@wordpress/api-fetch';
import { __ } from '@wordpress/i18n';
import { useDebounce } from 'use-debounce';
import {
Panel,
PanelBody,
PanelRow,
RangeControl,
SearchControl,
__experimentalItemGroup as ItemGroup,
__experimentalItem as Item,
BaseControl,
Button,
ButtonGroup,
Icon
} from '@wordpress/components';


function Edit( props ) {
const {
setAttributes,
isSelected,
attributes: {
showId,
iconSize,
align,
},
} = props;

/** State for the search text for the show name. Defaults to empty string. */
const [ searchText, setSearchText ] = useState( '' );

/** Debounced search text so that we don't trigger useEffect() for every character change. */
const [ debouncedSearchText ] = useDebounce( searchText, 300 );

/** State for search results matched by the search text. Defaults to array. */
const [ searchResults, setSearchResults ] = useState( [] );

/** State for the icon theme. Defaults to `color`. */
const [ iconTheme, setIconTheme ] = useState( 'color' );

/** State for platforms returned for a specific show. Defaults to array. */
const [ platforms, setPlatforms ] = useState( [] );

/**
* Hits the `/wp/v2/search` endpoint to search for
* podcast show by name.
*/
useEffect( () => {
const searchPodcastShow = async () => {
if ( ! searchText.length ) {
setSearchResults( [] );
return;
}

/** Query object required by `/wp/v2/search` to search for a term by name. */
const queryObject = {
search: searchText,
type: 'term',
subtype: 'podcasting_podcasts'
};

/** Converts an object to query-string. */
const queryString = new URLSearchParams( queryObject ).toString();

/** Returns the results of the search. */
const searchResults = await apiFetch( {
path: `/wp/v2/search?${ queryString }`,
} );

setSearchResults( searchResults );
};

searchPodcastShow();
}, [ debouncedSearchText ] );

/**
* Fetches the podcasting platforms for a show whenever
* showId updates.
*/
useEffect( () => {
if ( ! showId ) {
return;
}

/**
* Responsible to fetch platforms for a show by show ID.
* @returns void
*/
const fetchPlatforms = async () => {
const result = await apiFetch( {
url: `${ ajaxurl }?show_id=${ showId }&action=get_podcast_platforms`,
} );

if ( ! result.success ) {
return;
}

const {
data: { platforms, theme }
} = result;

setPlatforms( platforms );
setIconTheme( theme );
};

fetchPlatforms();
}, [ showId ] );

/**
* Handler to set the attribute showId.
*
* @param {Int} termId The show ID.
* @returns void
*/
const onShowSelect = ( termId ) => {
setAttributes( { showId: termId } );
iamdharmesh marked this conversation as resolved.
Show resolved Hide resolved
};

/**
* Handler to set size of the icon.
*
* @param {Int} size The icon size in `px`
*/
const setIconSize = ( size ) => {
setAttributes( { iconSize: size } );
};

/**
* Sets the HTML attributes for the root element.
*/
const blockProps = useBlockProps( {
className: isSelected ? 'simple-podcasting__podcast-platforms simple-podcasting__podcast-platforms--selected' : 'simple-podcasting__podcast-platforms',
} );

const platformSlugs = Object.keys( platforms );

return (
<>
<InspectorControls>
<Panel header={ __( 'Customization Controls', 'simple-podacsting' ) }>
<PanelBody>
<BaseControl label={ __( 'Icon size', 'simple-podcasting' ) }/>
<PanelRow>
<RangeControl
min={ 16 }
max={ 96 }
step={ 16 }
value={ iconSize }
onChange={ setIconSize }
/>
</PanelRow>
<BaseControl label={ __( 'Alignment', 'simple-podcasting' ) }/>
<PanelRow>
<ButtonGroup>
<Button
isPressed={ align === 'left' }
variant='ternary'
icon={ <Icon icon='align-left' /> }
onClick={ () => setAttributes( { align: 'left' } ) }
/>
<Button
isPressed={ align === 'center' }
variant='ternary'
icon={ <Icon icon='align-center' /> }
onClick={ () => setAttributes( { align: 'center' } ) }
/>
<Button
isPressed={ align === 'right' }
variant='ternary'
icon={ <Icon icon='align-right' /> }
onClick={ () => setAttributes( { align: 'right' } ) }
/>
</ButtonGroup>
</PanelRow>
</PanelBody>
</Panel>
</InspectorControls>
<div { ...blockProps }>
{
platformSlugs.length ? (
<div className={ `simple-podcasting__podcasting-platform-list simple-podcasting__podcasting-platform-list--${ align }` }>
{
platformSlugs.map( ( platform, index ) => {
return (
<span key={ index } className='simple-podcasting__podcasting-platform-list-item'>
<a href={ platforms[ platform ] } target="_blank">
<img className={ `simple-pocasting__icon-size--${ iconSize }` } src={ `${ podcastingPlatformVars.podcastingUrl }dist/images/icons/${ platform }/${ iconTheme }-100.png` } />
</a>
</span>
);
} )
}
</div>
) : null
}
{
isSelected || ! showId ? (
<div className='simple-podcasting__podcasting-search-controls'>
<SearchControl
placeholder={ __( 'Search a Podcast Show', 'simple-podcasting' ) }
onChange={ ( searchText ) => setSearchText( searchText ) }
value={ searchText }
/>
{
searchResults.length ?
(
<div className='simple-podcasting__podcasting-search-results'>
<ItemGroup
isSeparated
>
{
searchResults.map( ( result ) => (
<Item
key={ result.id }
className='simple-podcasting__podcast-search-results'
onClick={ () => onShowSelect( result.id ) }
>
{ result.title }
</Item>
) )
}
</ItemGroup>
</div>
) : null
}
</div>
) : null
}
</div>
</>
)
}

export default Edit;
42 changes: 42 additions & 0 deletions assets/js/blocks/podcast-platforms/index.js
@@ -0,0 +1,42 @@
/**
* Internal block libraries
*/
import { __ } from '@wordpress/i18n';
import { registerBlockType } from '@wordpress/blocks';

import Edit from './edit';
import './index.scss';

/**
* Register Podcast Platforms block
*/
export default registerBlockType(
'podcasting/podcast-platforms',
{
title: __( 'Podcast Platforms', 'simple-podcasting' ),
description: __( 'Displays the list of platforms where the selected show is available.', 'simple-podcasting' ),
category: 'common',
icon: 'microphone',
supports: {
multiple: false,
},
attributes: {
showId: {
type: 'number',
default: 0,
},
iconSize: {
type: 'number',
default: 48,
},
align: {
type: 'string',
default: 'center',
}
},

edit: Edit,

save: () => null,
},
);