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

Social: Create a social service connect button #37196

Merged
merged 19 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Expand Up @@ -19,6 +19,7 @@ export interface Connection {
description: string;
name: string;
examples?: Array< React.ComponentType >;
connectUrl?: string;
}

export const getSupportedConnections = (): Connection[] => {
Expand Down Expand Up @@ -79,7 +80,7 @@ export const getSupportedConnections = (): Connection[] => {
'Share photos from your site to your Instagram Business account.',
'jetpack'
),
name: 'instagram',
name: 'instagram-business',
examples: [
() => (
<>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,38 @@
import { Button, useBreakpointMatch } from '@automattic/jetpack-components';
import { Modal } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { useCallback, useState } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
import { Icon, chevronDown } from '@wordpress/icons';
import classNames from 'classnames';
import { useCallback, useState } from 'react';
import { store } from '../../social-store';
import ConnectButton from '../connect-button';
import { ConnectPage } from './connect-page/connect-page';
import { getSupportedConnections } from './constants';
import styles from './style.module.scss';

const AddConnectionModal = ( { onCloseModal } ) => {
const supportedServices = useSelect( select => {
const supportedConnections = getSupportedConnections();
const services = select( store )
.getServices()
.filter( service => service.type === 'publicize' )
.reduce(
( serviceData, service ) => ( {
...serviceData,
[ service.ID ]: service.connect_URL,
} ),
{}
);

return supportedConnections
.filter( connection => Object.hasOwn( services, connection.name ) )
.map( connection => ( {
...connection,
connectUrl: services[ connection.name ],
} ) );
}, [] );

const [ currentService, setCurrentService ] = useState( null );

const [ isSmall ] = useBreakpointMatch( 'sm' );
Expand Down Expand Up @@ -53,7 +77,7 @@
</tr>
</thead>
<tbody>
{ getSupportedConnections().map( service => (
{ supportedServices.map( service => (
<tr key={ service.name }>
<td>
<service.icon iconSize={ isSmall ? 36 : 48 } />
Expand All @@ -70,9 +94,12 @@
</td>
<td>
<div className={ styles[ 'column-actions' ] }>
<Button type="submit" variant="primary" size={ isSmall ? 'small' : 'normal' }>
{ __( 'Connect', 'jetpack' ) }
</Button>
<ConnectButton
connectUrl={ service.connectUrl }
onClose={ res => console.log( res ) }

Check failure on line 99 in projects/js-packages/publicize-components/src/components/add-connection-modal/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 99 in projects/js-packages/publicize-components/src/components/add-connection-modal/index.tsx

View workflow job for this annotation

GitHub Actions / ESLint (non-excluded files only)

Unexpected console statement
key={ service.name }
size={ isSmall ? 'small' : 'normal' }
/>
<Button
size={ isSmall ? 'small' : 'normal' }
className={ styles[ 'chevron-button' ] }
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 = null, size = 'normal' } ) => {
const requestConnection = useCallback(
() => requestExternalAccess( connectUrl, onClose ),
[ connectUrl, onClose ]
);
return (
<Button className={ className } variant="primary" onClick={ requestConnection } size={ size }>
{ __( 'Connect', 'jetpack' ) }
manzoorwanijk marked this conversation as resolved.
Show resolved Hide resolved
</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
Expand Up @@ -12,6 +12,7 @@ type JetpackSettingsSelectors = {

type ConnectionDataSelectors = {
getConnections: () => Array< object >;
getServices: () => Array< object >;
getConnectionsAdminUrl: () => string;
hasConnections: () => boolean;
};
Expand Down
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;
} );
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace Automattic\Jetpack\Publicize\Jetpack_Social_Settings;

use Automattic\Jetpack\Connection\Client;
use Automattic\Jetpack\Connection\Manager;
use Automattic\Jetpack\Modules;
use Automattic\Jetpack\Publicize\Publicize;
Expand Down Expand Up @@ -192,6 +193,7 @@
$settings['connectionData'] = array(
'connections' => $publicize->get_all_connections_for_user(),
'adminUrl' => esc_url_raw( $publicize->publicize_connections_url( 'jetpack-social-connections-admin-page' ) ),
'services' => $this->get_services(),
);

$settings['is_publicize_enabled'] = true;
Expand All @@ -206,6 +208,25 @@
return $settings;
}

/**
* Get the list of supported Publicize services.
*
* @return array List of external services and their settings.
*/
public function get_services() {
$site_id = Manager::get_site_id();
if ( is_wp_error( $site_id ) ) {
return [];

Check failure on line 219 in projects/packages/publicize/src/jetpack-social-settings/class-settings.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 224 in projects/packages/publicize/src/jetpack-social-settings/class-settings.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 227 in projects/packages/publicize/src/jetpack-social-settings/class-settings.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)
manzoorwanijk marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Update the settings.
*
Expand Down
17 changes: 17 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,16 +257,32 @@
'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(),
manzoorwanijk marked this conversation as resolved.
Show resolved Hide resolved
),
'sharesData' => $publicize->get_publicize_shares_info( Jetpack_Options::get_option( 'id' ) ),
),
$initial_state
);
}

error_log( print_r( $state, true ) );

Check warning on line 268 in projects/plugins/social/src/class-jetpack-social.php

View workflow job for this annotation

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

error_log() found. Debug code should not normally be used in production. (WordPress.PHP.DevelopmentFunctions.error_log_error_log)

Check warning on line 268 in projects/plugins/social/src/class-jetpack-social.php

View workflow job for this annotation

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

print_r() found. Debug code should not normally be used in production. (WordPress.PHP.DevelopmentFunctions.error_log_print_r)
return $state;
}

public function get_services() {

Check failure on line 272 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();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This API call should probably be cached, so we're not making another API request on each load of the admin page, especially as this data will not change very often

if ( is_wp_error( $site_id ) ) {
return [];

Check failure on line 275 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 280 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 283 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
Loading