Add/user menu component (#39383)
User Menu: Create component and add to header - Create initial component design - We may need to return to implement the helper connection URLs once those are in place. - Some PHPCS errors still exist - this is to be expected for now. # Conflicts: # plugins/woocommerce-admin/client/marketplace/stylesheets/_variables.scss Co-authored-by: And Finally <andfinally@users.noreply.github.com> Co-authored-by: raicem <unalancem@gmail.com>
This commit is contained in:
parent
55b2bb33ac
commit
a807040208
|
@ -0,0 +1,61 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import { useState } from '@wordpress/element';
|
||||||
|
import { Button, ButtonGroup, Modal } from '@wordpress/components';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface HeaderAccountModalProps {
|
||||||
|
setIsModalOpen: ( value: boolean ) => void;
|
||||||
|
disconnectURL: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function HeaderAccountModal(
|
||||||
|
props: HeaderAccountModalProps
|
||||||
|
): JSX.Element {
|
||||||
|
const { setIsModalOpen, disconnectURL } = props;
|
||||||
|
const [ isBusy, setIsBusy ] = useState( false );
|
||||||
|
const toggleIsBusy = () => setIsBusy( ! isBusy );
|
||||||
|
const closeModal = () => setIsModalOpen( false );
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title={ __( 'Are you sure?', 'woocommerce' ) }
|
||||||
|
onRequestClose={ closeModal }
|
||||||
|
focusOnMount={ true }
|
||||||
|
className="woocommerce-marketplace__header-account-modal"
|
||||||
|
style={ { borderRadius: 4 } }
|
||||||
|
overlayClassName="woocommerce-marketplace__header-account-modal-overlay"
|
||||||
|
>
|
||||||
|
<p className="woocommerce-marketplace__header-account-modal-text">
|
||||||
|
{ __(
|
||||||
|
'Keep your your account connected to manage your subscriptions, get updates and support for your extensions and themes.',
|
||||||
|
'woocommerce'
|
||||||
|
) }
|
||||||
|
</p>
|
||||||
|
<ButtonGroup className="woocommerce-marketplace__header-account-modal-button-group">
|
||||||
|
<Button
|
||||||
|
variant="tertiary"
|
||||||
|
href={ disconnectURL }
|
||||||
|
onClick={ toggleIsBusy }
|
||||||
|
isBusy={ isBusy }
|
||||||
|
isDestructive={ true }
|
||||||
|
className="woocommerce-marketplace__header-account-modal-button"
|
||||||
|
>
|
||||||
|
{ __( 'Disconnect account', 'woocommerce' ) }
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="primary"
|
||||||
|
onClick={ closeModal }
|
||||||
|
className="woocommerce-marketplace__header-account-modal-button"
|
||||||
|
>
|
||||||
|
{ __( 'Keep connected', 'woocommerce' ) }
|
||||||
|
</Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
@import '../../stylesheets/_variables.scss';
|
||||||
|
|
||||||
|
.woocommerce-marketplace {
|
||||||
|
&__menu-item span {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__menu-avatar-image {
|
||||||
|
border-radius: 50%;
|
||||||
|
height: $grid-unit-30;
|
||||||
|
width: $grid-unit-30;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__menu-icon {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: $grid-unit-10;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__menu-text {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__sub-text {
|
||||||
|
color: $gray-700;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__header-account-modal {
|
||||||
|
|
||||||
|
&__header-account-modal-text {
|
||||||
|
margin-bottom: $grid-unit-10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__header-account-modal-overlay {
|
||||||
|
// This is to ensure the modal is above the user menu popover.
|
||||||
|
z-index: 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__header-account-modal-button-group {
|
||||||
|
display: inline-flex;
|
||||||
|
gap: $grid-unit-10;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: $grid-unit-30;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.woocommerce-marketplace__header-account-modal-button,
|
||||||
|
.woocommerce-marketplace__header-account-modal-button.is-primary {
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: $break-small) {
|
||||||
|
.woocommerce-marketplace {
|
||||||
|
&__header-account-modal {
|
||||||
|
max-width: 350px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,32 +1,143 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
|
import { useState } from '@wordpress/element';
|
||||||
|
import { DropdownMenu, MenuGroup, MenuItem } from '@wordpress/components';
|
||||||
|
import { Icon, commentAuthorAvatar, external, linkOff } from '@wordpress/icons';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
|
import './header-account.scss';
|
||||||
|
import { getAdminSetting } from '../../../utils/admin-settings';
|
||||||
|
import HeaderAccountModal from './header-account-modal';
|
||||||
|
|
||||||
export default function HeaderAccount() {
|
export default function HeaderAccount(): JSX.Element {
|
||||||
return (
|
const [ isModalOpen, setIsModalOpen ] = useState( false );
|
||||||
<a
|
const openModal = () => setIsModalOpen( true );
|
||||||
className="woocommerce-marketplace__header-account"
|
|
||||||
href="https://woocommerce.com/my-account/"
|
const wccomSettings = getAdminSetting( 'wccomHelper', {} );
|
||||||
>
|
const isConnected = wccomSettings?.isConnected ?? false;
|
||||||
<svg
|
const connectionURL = wccomSettings?.connectURL ?? '';
|
||||||
width="24"
|
const userEmail = wccomSettings?.userEmail;
|
||||||
height="24"
|
const avatarURL = wccomSettings?.userAvatar ?? commentAuthorAvatar;
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
// This is a hack to prevent TypeScript errors. The MenuItem component passes these as an href prop to the underlying button
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
// component. That component is either an anchor with href if provided or a button that won't accept an href if no href is provided.
|
||||||
>
|
// Due to early erroring of TypeScript, it only takes the button version into account which doesn't accept href.
|
||||||
<path
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
id="Union"
|
const accountURL: any = 'https://woocommerce.com/my-dashboard/';
|
||||||
fillRule="evenodd"
|
const accountOrConnect = isConnected ? accountURL : connectionURL;
|
||||||
clipRule="evenodd"
|
|
||||||
d="M7.25 16.4371C6.16445 15.2755 5.5 13.7153 5.5 12C5.5 8.41015 8.41015 5.5 12 5.5C15.5899 5.5 18.5 8.41015 18.5 12C18.5 13.7153 17.8356 15.2755 16.75 16.4371V16C16.75 14.4812 15.5188 13.25 14 13.25L10 13.25C8.48122 13.25 7.25 14.4812 7.25 16V16.4371ZM8.75 17.6304C9.70606 18.1835 10.8161 18.5 12 18.5C13.1839 18.5 14.2939 18.1835 15.25 17.6304V16C15.25 15.3096 14.6904 14.75 14 14.75L10 14.75C9.30964 14.75 8.75 15.3096 8.75 16V17.6304ZM4 12C4 7.58172 7.58172 4 12 4C16.4183 4 20 7.58172 20 12C20 16.4183 16.4183 20 12 20C7.58172 20 4 16.4183 4 12ZM14 10C14 11.1046 13.1046 12 12 12C10.8954 12 10 11.1046 10 10C10 8.89543 10.8954 8 12 8C13.1046 8 14 8.89543 14 10Z"
|
const avatar = () => {
|
||||||
fill="black"
|
if ( ! isConnected ) {
|
||||||
|
return commentAuthorAvatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
src={ avatarURL }
|
||||||
|
alt=""
|
||||||
|
className="woocommerce-marketplace__menu-avatar-image"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const connectionStatusText = isConnected
|
||||||
|
? __( 'Connected', 'woocommerce' )
|
||||||
|
: __( 'Not Connected', 'woocommerce' );
|
||||||
|
|
||||||
|
const connectionDetails = () => {
|
||||||
|
if ( isConnected ) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Icon
|
||||||
|
icon={ commentAuthorAvatar }
|
||||||
|
size={ 24 }
|
||||||
|
className="woocommerce-marketplace__menu-icon"
|
||||||
|
/>
|
||||||
|
<span className="woocommerce-marketplace__main-text">
|
||||||
|
{ userEmail }
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Icon
|
||||||
|
icon={ commentAuthorAvatar }
|
||||||
|
size={ 24 }
|
||||||
|
className="woocommerce-marketplace__menu-icon"
|
||||||
/>
|
/>
|
||||||
</svg>
|
<div className="woocommerce-marketplace__menu-text">
|
||||||
</a>
|
{ __( 'Connect account', 'woocommerce' ) }
|
||||||
|
<span className="woocommerce-marketplace__sub-text">
|
||||||
|
{ __(
|
||||||
|
'Manage your subscriptions, get updates and support for your extensions and themes.',
|
||||||
|
'woocommerce'
|
||||||
|
) }
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<DropdownMenu
|
||||||
|
className="woocommerce-marketplace__user-menu"
|
||||||
|
icon={ avatar() }
|
||||||
|
label={ __( 'User options', 'woocommerce' ) }
|
||||||
|
>
|
||||||
|
{ () => (
|
||||||
|
<>
|
||||||
|
<MenuGroup
|
||||||
|
className="woocommerce-layout__homescreen-display-options"
|
||||||
|
label={ connectionStatusText }
|
||||||
|
>
|
||||||
|
<MenuItem
|
||||||
|
className="woocommerce-marketplace__menu-item"
|
||||||
|
href={ accountOrConnect }
|
||||||
|
>
|
||||||
|
{ connectionDetails() }
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem href={ accountURL }>
|
||||||
|
<Icon
|
||||||
|
icon={ external }
|
||||||
|
size={ 24 }
|
||||||
|
className="woocommerce-marketplace__menu-icon"
|
||||||
|
/>
|
||||||
|
{ __(
|
||||||
|
'WooCommerce.com account',
|
||||||
|
'woocommerce'
|
||||||
|
) }
|
||||||
|
</MenuItem>
|
||||||
|
</MenuGroup>
|
||||||
|
{ isConnected && (
|
||||||
|
<MenuGroup className="woocommerce-layout__homescreen-display-options">
|
||||||
|
<MenuItem onClick={ openModal }>
|
||||||
|
<Icon
|
||||||
|
icon={ linkOff }
|
||||||
|
size={ 24 }
|
||||||
|
className="woocommerce-marketplace__menu-icon"
|
||||||
|
/>
|
||||||
|
{ __(
|
||||||
|
'Disconnect account',
|
||||||
|
'woocommerce'
|
||||||
|
) }
|
||||||
|
</MenuItem>
|
||||||
|
</MenuGroup>
|
||||||
|
) }
|
||||||
|
</>
|
||||||
|
) }
|
||||||
|
</DropdownMenu>
|
||||||
|
{ isModalOpen && (
|
||||||
|
<HeaderAccountModal
|
||||||
|
setIsModalOpen={ setIsModalOpen }
|
||||||
|
disconnectURL={ connectionURL }
|
||||||
|
/>
|
||||||
|
) }
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
|
|
||||||
.woocommerce-marketplace__header-meta {
|
.woocommerce-marketplace__header-meta {
|
||||||
grid-area: mktpl-meta;
|
grid-area: mktpl-meta;
|
||||||
height: $grid-unit-30;
|
|
||||||
justify-self: end;
|
justify-self: end;
|
||||||
|
|
||||||
@media (width <= $breakpoint-medium) {
|
@media (width <= $breakpoint-medium) {
|
||||||
|
@ -55,3 +54,28 @@
|
||||||
padding: 0 $content-spacing-small;
|
padding: 0 $content-spacing-small;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.woocommerce-marketplace__search {
|
||||||
|
grid-area: mktpl-search;
|
||||||
|
background: #f0f0f0;
|
||||||
|
border-radius: 2px;
|
||||||
|
display: flex;
|
||||||
|
height: 40px;
|
||||||
|
margin-right: $medium-gap;
|
||||||
|
padding: 4px 8px 4px 12px;
|
||||||
|
|
||||||
|
input[type='search'] {
|
||||||
|
all: unset;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width <= $breakpoint-medium) {
|
||||||
|
margin: $content-spacing-small;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.woocommerce-marketplace__search-button {
|
||||||
|
all: unset;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
.woocommerce-marketplace__search {
|
.woocommerce-marketplace__search {
|
||||||
grid-area: mktpl-search;
|
grid-area: mktpl-search;
|
||||||
background: $gutenberg-gray-100;
|
background: $gray-0;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
@import '@wordpress/base-styles/_colors.native.scss';
|
||||||
|
|
||||||
// Spacings
|
// Spacings
|
||||||
// Taken from base style system
|
// Taken from base style system
|
||||||
// @wordpress/base-styles/_variables.scss
|
// @wordpress/base-styles/_variables.scss
|
||||||
|
@ -23,10 +25,10 @@ $header-height-desktop: 89px;
|
||||||
$header-height-mobile: 129px;
|
$header-height-mobile: 129px;
|
||||||
|
|
||||||
// Colours
|
// Colours
|
||||||
$gutenberg-gray-100: #f0f0f0;
|
$gutenberg-gray-100: $gray-0; // replaced with closest colour from _colors.native.scss
|
||||||
$gutenberg-gray-300: $gray-300;
|
$gutenberg-gray-300: $gray-300; // anything above gray-100 is from the default _colors.scss
|
||||||
$gutenberg-gray-700: #757575;
|
$gutenberg-gray-700: $gray-700;
|
||||||
$gutenberg-gray-900: $gray-900;
|
$gutenberg-gray-900: $gray-900;
|
||||||
$mauve-light-12: #1a1523;
|
$mauve-light-12: $gray-900;
|
||||||
$woo-purple-50: #7f54b3;
|
$woo-purple-50: #7f54b3;
|
||||||
$wp-gray-50: #646970;
|
$wp-gray-50: $gray-50;
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* WooCommerce Admin Helper - React admin interface
|
||||||
|
*
|
||||||
|
* @package WooCommerce\Admin\Helper
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WC_Helper Class
|
||||||
|
*
|
||||||
|
* The main entry-point for all things related to the Helper.
|
||||||
|
* The Helper manages the connection between the store and
|
||||||
|
* an account on WooCommerce.com.
|
||||||
|
*/
|
||||||
|
class WC_Helper_Admin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the class, runs on init
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function load() {
|
||||||
|
add_filter( 'woocommerce_admin_shared_settings', array( __CLASS__, 'add_marketplace_settings' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes settings onto the WooCommerce Admin global settings object (wcSettings).
|
||||||
|
*
|
||||||
|
* @param mixed $settings The settings object we're amending.
|
||||||
|
*
|
||||||
|
* @return mixed $settings
|
||||||
|
*/
|
||||||
|
public static function add_marketplace_settings( $settings ) {
|
||||||
|
$auth_user_data = WC_Helper_Options::get( 'auth_user_data', array() );
|
||||||
|
$auth_user_email = isset( $auth_user_data['email'] ) ? $auth_user_data['email'] : '';
|
||||||
|
|
||||||
|
$settings['wccomHelper'] = array(
|
||||||
|
'isConnected' => WC_Helper::is_site_connected(),
|
||||||
|
'connectURL' => self::get_connection_url(),
|
||||||
|
'userEmail' => $auth_user_email,
|
||||||
|
'userAvatar' => get_avatar_url( $auth_user_email, array( 'size' => '48' ) ),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the URL for connecting or disconnecting the store to/from WooCommerce.com.
|
||||||
|
* Approach taken from existing helper code that isn't exposed.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function get_connection_url() {
|
||||||
|
// No active connection.
|
||||||
|
if ( ! WC_Helper::is_site_connected() ) {
|
||||||
|
$connect_url = add_query_arg(
|
||||||
|
array(
|
||||||
|
'page' => 'wc-addons',
|
||||||
|
'section' => 'helper',
|
||||||
|
'wc-helper-connect' => 1,
|
||||||
|
'wc-helper-nonce' => wp_create_nonce( 'connect' ),
|
||||||
|
),
|
||||||
|
admin_url( 'admin.php' )
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: this may be needed to make the URL work.
|
||||||
|
// include WC_Helper::get_view_filename( 'html-oauth-start.php' );
|
||||||
|
return $connect_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
$connect_url = add_query_arg(
|
||||||
|
array(
|
||||||
|
'page' => 'wc-addons',
|
||||||
|
'section' => 'helper',
|
||||||
|
'wc-helper-disconnect' => 1,
|
||||||
|
'wc-helper-nonce' => wp_create_nonce( 'disconnect' ),
|
||||||
|
),
|
||||||
|
admin_url( 'admin.php' )
|
||||||
|
);
|
||||||
|
|
||||||
|
return $connect_url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WC_Helper_Admin::load();
|
|
@ -58,6 +58,7 @@ class WC_Helper {
|
||||||
include_once dirname( __FILE__ ) . '/class-wc-helper-updater.php';
|
include_once dirname( __FILE__ ) . '/class-wc-helper-updater.php';
|
||||||
include_once dirname( __FILE__ ) . '/class-wc-helper-plugin-info.php';
|
include_once dirname( __FILE__ ) . '/class-wc-helper-plugin-info.php';
|
||||||
include_once dirname( __FILE__ ) . '/class-wc-helper-compat.php';
|
include_once dirname( __FILE__ ) . '/class-wc-helper-compat.php';
|
||||||
|
include_once dirname( __FILE__ ) . '/class-wc-helper-admin.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue