Skip to content

Commit

Permalink
Social: Create a social service connect button
Browse files Browse the repository at this point in the history
This is currently a proof of concept where we get the available external
services and render a connect button, which in turn triggers the
authentication flow for each service.

To test it, the site must be sandboxed with D146389-code applied.
  • Loading branch information
pablinos committed May 2, 2024
1 parent 9b64103 commit 81e44f8
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 2 deletions.
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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 @@ -5,6 +5,7 @@ import './src/social-store';

export { default as Connection } from './src/components/connection';
export { default as ConnectionVerify } from './src/components/connection-verify';
export { default as ConnectButton } from './src/components/connect-button';
export { default as Form } from './src/components/form';
export { default as SocialPreviewsModal } from './src/components/social-previews/modal';
export { default as SocialPreviewsPanel } from './src/components/social-previews/panel';
Expand Down
1 change: 1 addition & 0 deletions projects/js-packages/publicize-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@automattic/jetpack-components": "workspace:*",
"@automattic/jetpack-connection": "workspace:*",
"@automattic/jetpack-shared-extension-utils": "workspace:*",
"@automattic/popup-monitor": "1.0.2",
"@automattic/social-previews": "2.0.1-beta.13",
"@wordpress/annotations": "2.56.0",
"@wordpress/api-fetch": "6.53.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Button } from '@automattic/jetpack-components';
import { useCallback } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { requestExternalAccess } from '../../utils/request-external-access.js';

const ConnectButton = ( { connectUrl, onClose, className } ) => {
const requestConnection = useCallback(
() => requestExternalAccess( connectUrl, onClose ),
[ connectUrl, onClose ]
);
return (
<Button className={ className } variant="secondary" onClick={ requestConnection }>
{ __( 'Connect', 'jetpack' ) }
</Button>
);
};

export default ConnectButton;
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,14 @@ export function getConnectionProfileDetails( state, service, { forceDefaults = f

return { displayName, profileImage, username };
}

/**
* Returns the services list from the store.
*
* @param {import("../types").SocialStoreState} state - State object.
*
* @returns {Array} The services list
*/
export function getServices( state ) {
return state.connectionData?.services ?? [];
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './get-share-message-max-length';
export * from './get-supported-additional-connections';
export * from './request-external-access';
export * from './types';
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import PopupMonitor from '@automattic/popup-monitor';

/**
* The callback function of the requestExternalAccess utility.
* @callback requestCallback
* @param {object} result - Received authentication data.
* @param {number} result.keyring_id
* @param {string} result.id_token
* @param {object} result.user
*/

/**
* Utility for requesting authorization of sharing services.
* @param {string} url - The URL to be loaded in the newly opened window.
* @param {requestCallback} cb - The callback that handles the response.
*/
export const requestExternalAccess = ( url, cb ) => {
const popupMonitor = new PopupMonitor();
let lastMessage;

popupMonitor.open(
url,
null,
'toolbar=0,location=0,status=0,menubar=0,' + popupMonitor.getScreenCenterSpecs( 780, 700 )
);

popupMonitor.once( 'close', () => {
cb( lastMessage?.ID ? lastMessage : {} );
} );

popupMonitor.on( 'message', message => {
lastMessage = message?.data;
} );
};
16 changes: 16 additions & 0 deletions projects/plugins/social/src/class-jetpack-social.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use Automattic\Jetpack\Admin_UI\Admin_Menu;
use Automattic\Jetpack\Assets;
use Automattic\Jetpack\Connection\Client;
use Automattic\Jetpack\Connection\Initial_State as Connection_Initial_State;
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
use Automattic\Jetpack\Connection\Rest_Authentication as Connection_Rest_Authentication;
Expand Down Expand Up @@ -256,6 +257,7 @@ public function initial_state() {
'connectionData' => array(
'connections' => $publicize->get_all_connections_for_user(), // TODO: Sanitize the array
'adminUrl' => esc_url_raw( $publicize->publicize_connections_url( 'jetpack-social-connections-admin-page' ) ),
'services' => $this->get_services(),
),
'sharesData' => $publicize->get_publicize_shares_info( Jetpack_Options::get_option( 'id' ) ),
),
Expand All @@ -266,6 +268,20 @@ public function initial_state() {
return $state;
}

public function get_services() {

Check failure on line 271 in projects/plugins/social/src/class-jetpack-social.php

View workflow job for this annotation

GitHub Actions / PHP Code Sniffer (non-excluded files only)

Missing doc comment for function get_services() (Squiz.Commenting.FunctionComment.Missing)
$site_id = Connection_Manager::get_site_id();
if ( is_wp_error( $site_id ) ) {
return [];

Check failure on line 274 in projects/plugins/social/src/class-jetpack-social.php

View workflow job for this annotation

GitHub Actions / PHP Code Sniffer (non-excluded files only)

Short array syntax is not allowed (Universal.Arrays.DisallowShortArraySyntax.Found)
}
$path = sprintf( '/sites/%d/external-services', $site_id );
$response = Client::wpcom_json_api_request_as_user( $path );
if ( is_wp_error( $response ) ) {
return [];

Check failure on line 279 in projects/plugins/social/src/class-jetpack-social.php

View workflow job for this annotation

GitHub Actions / PHP Code Sniffer (non-excluded files only)

Short array syntax is not allowed (Universal.Arrays.DisallowShortArraySyntax.Found)
}
$body = json_decode( wp_remote_retrieve_body( $response ) );
return array_values( (array) $body->services ) ?? [];

Check failure on line 282 in projects/plugins/social/src/class-jetpack-social.php

View workflow job for this annotation

GitHub Actions / PHP Code Sniffer (non-excluded files only)

Short array syntax is not allowed (Universal.Arrays.DisallowShortArraySyntax.Found)
}

/**
* Returns a boolean as to whether we have a plan that supports
* sharing beyond the free limit.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Button, Text, useBreakpointMatch } from '@automattic/jetpack-components';
import { SOCIAL_STORE_ID } from '@automattic/jetpack-publicize-components';
import { SOCIAL_STORE_ID, ConnectButton } from '@automattic/jetpack-publicize-components';
import { ExternalLink } from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
Expand All @@ -9,12 +9,13 @@ import { SocialStoreSelectors } from '../types/types';
import styles from './styles.module.scss';

const SocialModuleToggle: React.FC = () => {
const { connectionsAdminUrl, isModuleEnabled, isUpdating } = useSelect( select => {
const { connectionsAdminUrl, isModuleEnabled, isUpdating, services } = useSelect( select => {
const store = select( SOCIAL_STORE_ID ) as SocialStoreSelectors;
return {
isModuleEnabled: store.isModuleEnabled(),
isUpdating: store.isUpdatingJetpackSettings(),
connectionsAdminUrl: store.getConnectionsAdminUrl(),
services: store.getServices(),
};
}, [] );

Expand Down Expand Up @@ -59,6 +60,16 @@ const SocialModuleToggle: React.FC = () => {
{ __( 'Manage social media connections', 'jetpack-social' ) }
</Button>
) }
{ services.map( service =>
service.type === 'publicize' ? (
<ConnectButton
connectUrl={ service.connect_URL }
onClose={ res => console.log( res ) }

Check failure on line 67 in projects/plugins/social/src/js/components/social-module-toggle/index.tsx

View workflow job for this annotation

GitHub Actions / ESLint (non-excluded files only)

JSX props should not use arrow functions

Check failure on line 67 in projects/plugins/social/src/js/components/social-module-toggle/index.tsx

View workflow job for this annotation

GitHub Actions / ESLint (non-excluded files only)

Unexpected console statement
className={ styles.button }
key={ service.ID }
/>
) : null
) }
</ToggleSection>
);
};
Expand Down

0 comments on commit 81e44f8

Please sign in to comment.