Skip to content

Commit

Permalink
Fix | Publicize remains ON after the post is published (#34289)
Browse files Browse the repository at this point in the history
* Create useSyncPostDataToStore hook

* Use useSyncPostDataToStore

* Add changelog

* Fix tests

* Use usePostJustPublished instead of registry subscribe

* Create SyncPostDataToStore to render the hook

* Clean up

* Render the Sync component

* Allow no dependency

* Add changelog

* I wish @wordpress/editor had better TS types

* Replace core select with useSelect
  • Loading branch information
manzoorwanijk authored Nov 28, 2023
1 parent 17dc392 commit 289d87f
Show file tree
Hide file tree
Showing 12 changed files with 314 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fixed

Fixed the issue of publicize remaining ON after the post is published
1 change: 1 addition & 0 deletions projects/js-packages/publicize-components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ export { default as useDismissNotice } from './src/hooks/use-dismiss-notice';
export * from './src/social-store';
export * from './src/utils';
export * from './src/components/share-post';
export * from './src/hooks/use-sync-post-data-to-store';
export * from './src/hooks/use-saving-post';
export * from './src/components/share-buttons';
2 changes: 1 addition & 1 deletion projects/js-packages/publicize-components/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"private": true,
"name": "@automattic/jetpack-publicize-components",
"version": "0.41.7",
"version": "0.41.8-alpha",
"description": "A library of JS components required by the Publicize editor plugin",
"homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/publicize-components/#readme",
"bugs": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export function usePostJustSaved( fn, deps ) {
* Additionally, it accepts a dependency array which is passed to useEffect hook.
*
* @param {Function} fn - Callback function to run when the post is just published.
* @param {Array} deps - Depencency array.
* @param {Array} [deps] - Depencency array.
*/
export function usePostJustPublished( fn, deps ) {
const isPublishing = useSelect( select => select( editorStore ).isPublishingPost(), [] );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useDispatch, useSelect } from '@wordpress/data';
import { store as editorStore } from '@wordpress/editor';
import { store as socialStore } from '../../social-store';
import { usePostJustPublished } from '../use-saving-post';

/**
* Syncs the post data to the social store.
*/
export function useSyncPostDataToStore() {
const { mergeConnections } = useDispatch( socialStore );

const { didPostSaveRequestSucceed, isCurrentPostPublished, getEditedPostAttribute } = useSelect(
select => select( editorStore ),
[]
);

usePostJustPublished( () => {
/**
* We need to update the connections only when the post is published
* and the save request is successful
* This is because the connections are updated only when the post is published
*/
if ( didPostSaveRequestSucceed() && isCurrentPostPublished() ) {
// get the fresh connections from the store
const freshConnections = getEditedPostAttribute( 'jetpack_publicize_connections' );
// if the connections have changed, merge them into the social store
if ( freshConnections?.length ) {
mergeConnections( freshConnections );
}
}
}, [ didPostSaveRequestSucceed, isCurrentPostPublished, getEditedPostAttribute ] );
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
import { renderHook, act } from '@testing-library/react';
import apiFetch from '@wordpress/api-fetch';
import { store as blockEditorStore } from '@wordpress/block-editor';
import { store as coreStore } from '@wordpress/core-data';
import { createRegistry, RegistryProvider, WPDataRegistry } from '@wordpress/data';
import { store as editorStore } from '@wordpress/editor';
import { store as noticesStore } from '@wordpress/notices';
import { useSyncPostDataToStore } from '../';
import { store as socialStore } from '../../../social-store';

const postId = 44;

const postTypeConfig = {
kind: 'postType',
name: 'post',
baseURL: '/wp/v2/posts',
transientEdits: { blocks: true, selection: true },
mergedEdits: { meta: true },
rawAttributes: [ 'title', 'excerpt', 'content' ],
};

const postTypeEntity = {
slug: 'post',
rest_base: 'posts',
labels: {},
};

const connections = [
{
id: '123456789',
service_name: 'facebook',
display_name: 'Some name',
profile_picture: 'https://wordpress.com/some-url-of-a-picture',
username: 'username',
enabled: true,
connection_id: '987654321',
test_success: true,
},
{
id: '234567891',
service_name: 'tumblr',
display_name: 'Some name',
profile_picture: 'https://wordpress.com/some-url-of-another-picture',
username: 'username',
enabled: true,
connection_id: '198765432',
test_success: false,
},
{
id: '345678912',
service_name: 'mastodon',
display_name: 'somename',
profile_picture: 'https://wordpress.com/some-url-of-one-more-picture',
username: '@somename@mastodon.social',
enabled: true,
connection_id: '219876543',
test_success: 'must_reauth',
},
];

const post = {
id: postId,
type: 'post',
title: 'bar',
content: 'bar',
excerpt: 'crackers',
status: 'draft',
jetpack_publicize_connections: [ connections[ 0 ] ],
};

/**
* Create a registry with stores.
*
* @returns {WPDataRegistry} Registry.
*/
async function createRegistryWithStores() {
// Create a registry.
const registry = createRegistry();

// Register stores.
registry.register( coreStore );
registry.register( blockEditorStore );
registry.register( editorStore );
registry.register( socialStore );
registry.register( noticesStore );

// Register post type entity.
registry.dispatch( coreStore ).addEntities( [ postTypeConfig ] );

// Store post type entity.
registry.dispatch( coreStore ).receiveEntityRecords( 'root', 'postType', [ postTypeEntity ] );

// Store post.
registry.dispatch( coreStore ).receiveEntityRecords( 'postType', 'post', post );

// Setup editor with post.
registry.dispatch( editorStore ).setupEditor( post );

await registry.resolveSelect( socialStore ).getConnections();

return registry;
}

const getMethod = options =>
options.headers?.[ 'X-HTTP-Method-Override' ] || options.method || 'GET';

describe( 'useSyncPostDataToStore', () => {
it( 'should do nothing by default', async () => {
const registry = await createRegistryWithStores();
const prevConnections = registry.select( socialStore ).getConnections();

expect( prevConnections ).not.toEqual( [] );

renderHook( () => useSyncPostDataToStore(), {
wrapper: ( { children } ) => (
<RegistryProvider value={ registry }>{ children }</RegistryProvider>
),
} );

const freshConnections = registry.select( socialStore ).getConnections();

expect( freshConnections ).toEqual( prevConnections );
} );

it( 'should do nothing when post is not being published', async () => {
const registry = await createRegistryWithStores();

const prevConnections = registry.select( socialStore ).getConnections();

renderHook( () => useSyncPostDataToStore(), {
wrapper: ( { children } ) => (
<RegistryProvider value={ registry }>{ children }</RegistryProvider>
),
} );

await act( async () => {
await registry.dispatch( editorStore ).editPost( {
jetpack_publicize_connections: [],
} );
} );

const freshConnections = registry.select( socialStore ).getConnections();

expect( freshConnections ).toEqual( prevConnections );
} );

it( 'should update connections when post is being published', async () => {
const registry = await createRegistryWithStores();

// Mock apiFetch response.
apiFetch.setFetchHandler( async options => {
const method = getMethod( options );
const { path, data } = options;

if ( method === 'PUT' && path.startsWith( `/wp/v2/posts/${ postId }` ) ) {
return { ...post, ...data };
} else if (
// This URL is requested by the actions dispatched in this test.
// They are safe to ignore and are only listed here to avoid triggeringan error.
method === 'GET' &&
path.startsWith( '/wp/v2/types/post' )
) {
return {};
}

throw {
code: 'unknown_path',
message: `Unknown path: ${ method } ${ path }`,
};
} );

const prevConnections = registry.select( socialStore ).getConnections();

renderHook( () => useSyncPostDataToStore(), {
wrapper: ( { children } ) => (
<RegistryProvider value={ registry }>{ children }</RegistryProvider>
),
} );

const updatedConnections = connections.map( () => ( { enabled: false } ) );

await act( async () => {
registry.dispatch( editorStore ).editPost( {
status: 'publish',
jetpack_publicize_connections: updatedConnections,
} );
registry.dispatch( editorStore ).savePost();
} );

const freshConnections = registry.select( socialStore ).getConnections();

expect( freshConnections ).not.toEqual( prevConnections );

expect( freshConnections.map( ( { enabled } ) => ( { enabled } ) ) ).toEqual(
updatedConnections
);
} );
} );
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { select } from '@wordpress/data';
import { store as editorStore } from '@wordpress/editor';
import { setAutoConversionSettings } from './actions/auto-conversion-settings';
import { setConnections } from './actions/connection-data';
Expand Down Expand Up @@ -70,11 +69,11 @@ export function* getAutoConversionSettings() {
* @returns {Function} Resolver
*/
export function getConnections() {
return function ( { dispatch } ) {
return function ( { dispatch, registry } ) {
// Get the initial connections from the post meta
const connections = select( editorStore ).getEditedPostAttribute(
'jetpack_publicize_connections'
);
const connections = registry
.select( editorStore )
.getEditedPostAttribute( 'jetpack_publicize_connections' );

dispatch( setConnections( connections || [] ) );
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: other

Fixed the issue of publicize remaining ON after the post is published
58 changes: 3 additions & 55 deletions projects/plugins/jetpack/extensions/plugins/publicize/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,18 @@
* It also hooks into our dedicated Jetpack plugin sidebar and
* displays the Publicize UI there.
*/
import {
PublicizePanel,
useSocialMediaConnections,
usePublicizeConfig,
SocialImageGeneratorPanel,
PostPublishReviewPrompt,
PostPublishOneClickSharing,
} from '@automattic/jetpack-publicize-components';
import {
JetpackEditorPanelLogo,
useModuleStatus,
} from '@automattic/jetpack-shared-extension-utils';
import { PluginPrePublishPanel } from '@wordpress/edit-post';
import { useModuleStatus } from '@automattic/jetpack-shared-extension-utils';
import { PostTypeSupportCheck } from '@wordpress/editor';
import { __ } from '@wordpress/i18n';
import JetpackPluginSidebar from '../../shared/jetpack-plugin-sidebar';
import { PublicizePlaceholder } from './components/placeholder';
import PublicizeSkeletonLoader from './components/skeleton-loader';
import UpsellNotice from './components/upsell';
import { Settings } from './settings';

import './editor.scss';

export const name = 'publicize';

const PublicizeSettings = () => {
const { hasEnabledConnections } = useSocialMediaConnections();
const { isSocialImageGeneratorAvailable } = usePublicizeConfig();
const { isLoadingModules, isChangingStatus, isModuleActive, changeStatus } =
useModuleStatus( name );

Expand Down Expand Up @@ -61,44 +46,7 @@ const PublicizeSettings = () => {
);
}

return (
<PostTypeSupportCheck supportKeys="publicize">
<JetpackPluginSidebar>
<PublicizePanel>
<UpsellNotice />
</PublicizePanel>
{ isSocialImageGeneratorAvailable && <SocialImageGeneratorPanel /> }
</JetpackPluginSidebar>

<PluginPrePublishPanel
initialOpen={ hasEnabledConnections }
id="publicize-title"
title={
<span id="publicize-defaults" key="publicize-title-span">
{ __( 'Share this post', 'jetpack' ) }
</span>
}
icon={ <JetpackEditorPanelLogo /> }
>
<PublicizePanel prePublish={ true }>
<UpsellNotice />
</PublicizePanel>
</PluginPrePublishPanel>

{ isSocialImageGeneratorAvailable && (
<PluginPrePublishPanel
initialOpen
title={ __( 'Social Image Generator', 'jetpack' ) }
icon={ <JetpackEditorPanelLogo /> }
>
<SocialImageGeneratorPanel prePublish={ true } />
</PluginPrePublishPanel>
) }

<PostPublishOneClickSharing />
<PostPublishReviewPrompt />
</PostTypeSupportCheck>
);
return <Settings />;
};

export const settings = {
Expand Down
Loading

0 comments on commit 289d87f

Please sign in to comment.