My subscription product updates (#40752)
* Marketplace: Populate the table rows with components * Marketplace: add links to dropdown menu and fix fallback product icons * Marketplace: fix popover width * Add My subscriptions install (#40630) * Marketplace: add plugin install from the subscriptions page Co-authored-by: berislav grgičak <berislav.grgicak@gmail.com> * Marketplace: Use the activation function to show install button --------- Co-authored-by: raicem <unalancem@gmail.com> * Add WP updates script to the extensions page * Add update button * Add update data to subscriptions * Update plugins * Prevent update if license unavailable * Add changefile(s) from automation for the following project(s): woocommerce * Remove all data from API * Linter fixes * Linter fixes * Remove merge string * Update link style * Add comment for updates.js * Prevent updates if required data is missing * Return removed slug code * My subscriptions action modals (#40934) * Add renew modal * Update install to run until new data loaded * Add activate modal * Add connect modal * Add renew button * Renewal button * Rename activate to connect * Add subscribe button * Add action buttons * Remove unused const * Add changefile(s) from automation for the following project(s): woocommerce * Update plugins/woocommerce-admin/client/marketplace/components/my-subscriptions/my-subscriptions.scss Co-authored-by: And Finally <andfinally@users.noreply.github.com> * Update import path --------- Co-authored-by: And Finally <andfinally@users.noreply.github.com> Co-authored-by: github-actions <github-actions@github.com> --------- Co-authored-by: raicem <unalancem@gmail.com> Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: And Finally <andfinally@users.noreply.github.com>
This commit is contained in:
parent
83b7b95850
commit
53c4fe6afb
|
@ -7,3 +7,4 @@ export const MARKETPLACE_CATEGORY_API_PATH =
|
|||
'/wp-json/wccom-extensions/1.0/categories';
|
||||
export const MARKETPLACE_ITEMS_PER_PAGE = 60;
|
||||
export const MARKETPLACE_SEARCH_RESULTS_PER_PAGE = 8;
|
||||
export const MARKETPLACE_CART_PATH = MARKETPLACE_HOST + '/cart/';
|
||||
|
|
|
@ -102,6 +102,19 @@
|
|||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.woocommerce-marketplace__my-subscriptions-version {
|
||||
padding: 6px 12px;
|
||||
}
|
||||
.woocommerce-marketplace__my-subscriptions__table__header--version > span {
|
||||
display: inline-block;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.woocommerce-marketplace__my-subscriptions__table .components-button.is-link {
|
||||
text-decoration: none;
|
||||
padding: 6px 12px;
|
||||
}
|
||||
|
||||
.woocommerce-marketplace__my-subscriptions--connect {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -131,3 +144,16 @@
|
|||
margin-bottom: $grid-unit-30;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-marketplace__my-subscriptions__table__header--actions {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.woocommerce-marketplace__my-subscriptions__actions {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
|
||||
.components-button {
|
||||
margin-right: $grid-unit-10;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Button, Icon } from '@wordpress/components';
|
||||
import { useDispatch } from '@wordpress/data';
|
||||
import { useContext, useState } from '@wordpress/element';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { SubscriptionsContext } from '~/marketplace/contexts/subscriptions-context';
|
||||
import { connectProduct } from '~/marketplace/utils/functions';
|
||||
import { Subscription } from '../../types';
|
||||
|
||||
interface ConnectProps {
|
||||
subscription: Subscription;
|
||||
onClose?: () => void;
|
||||
variant?: Button.ButtonVariant;
|
||||
}
|
||||
|
||||
export default function ConnectButton( props: ConnectProps ) {
|
||||
const [ isConnecting, setIsConnecting ] = useState( false );
|
||||
const { createWarningNotice, createSuccessNotice } =
|
||||
useDispatch( 'core/notices' );
|
||||
const { loadSubscriptions } = useContext( SubscriptionsContext );
|
||||
|
||||
const connect = () => {
|
||||
setIsConnecting( true );
|
||||
connectProduct( props.subscription.product_key )
|
||||
.then( () => {
|
||||
loadSubscriptions( false ).then( () => {
|
||||
createSuccessNotice(
|
||||
sprintf(
|
||||
// translators: %s is the product name.
|
||||
__( '%s successfully connected.', 'woocommerce' ),
|
||||
props.subscription.product_name
|
||||
),
|
||||
{
|
||||
icon: <Icon icon="yes" />,
|
||||
}
|
||||
);
|
||||
setIsConnecting( false );
|
||||
if ( props.onClose ) {
|
||||
props.onClose();
|
||||
}
|
||||
} );
|
||||
} )
|
||||
.catch( () => {
|
||||
createWarningNotice(
|
||||
sprintf(
|
||||
// translators: %s is the product name.
|
||||
__( '%s couldn’t be connected.', 'woocommerce' ),
|
||||
props.subscription.product_name
|
||||
),
|
||||
{
|
||||
actions: [
|
||||
{
|
||||
label: __( 'Try again', 'woocommerce' ),
|
||||
onClick: connect,
|
||||
},
|
||||
],
|
||||
}
|
||||
);
|
||||
setIsConnecting( false );
|
||||
if ( props.onClose ) {
|
||||
props.onClose();
|
||||
}
|
||||
} );
|
||||
};
|
||||
return (
|
||||
<Button
|
||||
onClick={ connect }
|
||||
variant={ props.variant ?? 'secondary' }
|
||||
isBusy={ isConnecting }
|
||||
disabled={ isConnecting }
|
||||
>
|
||||
{ __( 'Connect', 'woocommerce' ) }
|
||||
</Button>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Button, ButtonGroup, Modal } from '@wordpress/components';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Subscription } from '../../types';
|
||||
import ConnectButton from './connect-button';
|
||||
|
||||
interface ConnectProps {
|
||||
subscription: Subscription;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export default function ConnectModal( props: ConnectProps ) {
|
||||
return (
|
||||
<Modal
|
||||
title={ __( 'Connect to update', 'woocommerce' ) }
|
||||
onRequestClose={ props.onClose }
|
||||
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">
|
||||
{ sprintf(
|
||||
// translators: %s is the product version number (e.g. 1.0.2).
|
||||
__(
|
||||
'Version %s is available. To enable this update you need to connect your subscription to this store.',
|
||||
'woocommerce'
|
||||
),
|
||||
props.subscription.version
|
||||
) }
|
||||
</p>
|
||||
<ButtonGroup className="woocommerce-marketplace__header-account-modal-button-group">
|
||||
<Button
|
||||
variant="tertiary"
|
||||
onClick={ props.onClose }
|
||||
className="woocommerce-marketplace__header-account-modal-button"
|
||||
>
|
||||
{ __( 'Cancel', 'woocommerce' ) }
|
||||
</Button>
|
||||
<ConnectButton
|
||||
subscription={ props.subscription }
|
||||
onClose={ props.onClose }
|
||||
variant="primary"
|
||||
/>
|
||||
</ButtonGroup>
|
||||
</Modal>
|
||||
);
|
||||
}
|
|
@ -1,23 +1,23 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { Button, Icon } from '@wordpress/components';
|
||||
import { useContext, useState } from '@wordpress/element';
|
||||
import { useDispatch } from '@wordpress/data';
|
||||
import { useContext, useState } from '@wordpress/element';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Subscription } from '../../types';
|
||||
import { installProduct } from '../../../../utils/functions';
|
||||
import { SubscriptionsContext } from '../../../../contexts/subscriptions-context';
|
||||
import { installProduct } from '../../../../utils/functions';
|
||||
import { Subscription } from '../../types';
|
||||
|
||||
interface ActivationToggleProps {
|
||||
interface InstallProps {
|
||||
subscription: Subscription;
|
||||
}
|
||||
|
||||
export default function Install( props: ActivationToggleProps ) {
|
||||
export default function Install( props: InstallProps ) {
|
||||
const [ loading, setLoading ] = useState( false );
|
||||
const { createWarningNotice, createSuccessNotice } =
|
||||
useDispatch( 'core/notices' );
|
||||
|
@ -27,17 +27,19 @@ export default function Install( props: ActivationToggleProps ) {
|
|||
setLoading( true );
|
||||
installProduct( props.subscription.product_key )
|
||||
.then( () => {
|
||||
loadSubscriptions( false );
|
||||
createSuccessNotice(
|
||||
sprintf(
|
||||
// translators: %s is the product name.
|
||||
__( '%s successfully installed.', 'woocommerce' ),
|
||||
props.subscription.product_name
|
||||
),
|
||||
{
|
||||
icon: <Icon icon="yes" />,
|
||||
}
|
||||
);
|
||||
loadSubscriptions( false ).then( () => {
|
||||
createSuccessNotice(
|
||||
sprintf(
|
||||
// translators: %s is the product name.
|
||||
__( '%s successfully installed.', 'woocommerce' ),
|
||||
props.subscription.product_name
|
||||
),
|
||||
{
|
||||
icon: <Icon icon="yes" />,
|
||||
}
|
||||
);
|
||||
setLoading( false );
|
||||
} );
|
||||
} )
|
||||
.catch( () => {
|
||||
createWarningNotice(
|
||||
|
@ -55,8 +57,6 @@ export default function Install( props: ActivationToggleProps ) {
|
|||
],
|
||||
}
|
||||
);
|
||||
} )
|
||||
.finally( () => {
|
||||
setLoading( false );
|
||||
} );
|
||||
};
|
||||
|
@ -71,7 +71,7 @@ export default function Install( props: ActivationToggleProps ) {
|
|||
|
||||
return (
|
||||
<Button
|
||||
variant="primary"
|
||||
variant="link"
|
||||
isBusy={ loading }
|
||||
disabled={ loading }
|
||||
onClick={ install }
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Button } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { MARKETPLACE_CART_PATH } from '~/marketplace/components/constants';
|
||||
import { appendURLParams } from '~/marketplace/utils/functions';
|
||||
import { Subscription } from '../../types';
|
||||
|
||||
interface RenewProps {
|
||||
subscription: Subscription;
|
||||
variant?: Button.ButtonVariant;
|
||||
}
|
||||
|
||||
export default function RenewButton( props: RenewProps ) {
|
||||
const renewUrl = appendURLParams( MARKETPLACE_CART_PATH, [
|
||||
[ 'renew_product', props.subscription.product_id.toString() ],
|
||||
[ 'product_key', props.subscription.product_key ],
|
||||
[ 'order_id', props.subscription.order_id.toString() ],
|
||||
] );
|
||||
|
||||
return (
|
||||
<Button href={ renewUrl } variant={ props.variant ?? 'secondary' }>
|
||||
{ __( 'Renew', 'woocommerce' ) }
|
||||
</Button>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Button, ButtonGroup, Modal } from '@wordpress/components';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Subscription } from '../../types';
|
||||
import RenewButton from './renew-button';
|
||||
|
||||
interface RenewProps {
|
||||
subscription: Subscription;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export default function RenewModal( props: RenewProps ) {
|
||||
return (
|
||||
<Modal
|
||||
title={ __( 'Renew to update', 'woocommerce' ) }
|
||||
onRequestClose={ props.onClose }
|
||||
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">
|
||||
{ sprintf(
|
||||
// translators: %s is the product version number (e.g. 1.0.2).
|
||||
__(
|
||||
'Version %s is available. To enable this update you need to renew your subscription.',
|
||||
'woocommerce'
|
||||
),
|
||||
props.subscription.version
|
||||
) }
|
||||
</p>
|
||||
<ButtonGroup className="woocommerce-marketplace__header-account-modal-button-group">
|
||||
<Button
|
||||
variant="tertiary"
|
||||
onClick={ props.onClose }
|
||||
className="woocommerce-marketplace__header-account-modal-button"
|
||||
>
|
||||
{ __( 'Cancel', 'woocommerce' ) }
|
||||
</Button>
|
||||
<RenewButton
|
||||
subscription={ props.subscription }
|
||||
variant="primary"
|
||||
/>
|
||||
</ButtonGroup>
|
||||
</Modal>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Button } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { MARKETPLACE_CART_PATH } from '../../../constants';
|
||||
import { appendURLParams } from '../../../../utils/functions';
|
||||
import { Subscription } from '../../types';
|
||||
|
||||
interface SubscribeProps {
|
||||
subscription: Subscription;
|
||||
variant?: Button.ButtonVariant;
|
||||
}
|
||||
|
||||
export default function SubscribeButton( props: SubscribeProps ) {
|
||||
const subscribeUrl = appendURLParams( MARKETPLACE_CART_PATH, [
|
||||
[ 'add-to-cart', props.subscription.product_id.toString() ],
|
||||
] );
|
||||
return (
|
||||
<Button href={ subscribeUrl } variant={ props.variant ?? 'secondary' }>
|
||||
{ __( 'Subscribe', 'woocommerce' ) }
|
||||
</Button>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Button, ButtonGroup, Modal } from '@wordpress/components';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Subscription } from '../../types';
|
||||
import SubscribeButton from './subscribe-button';
|
||||
|
||||
interface SubscribeProps {
|
||||
subscription: Subscription;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export default function SubscribeModal( props: SubscribeProps ) {
|
||||
return (
|
||||
<Modal
|
||||
title={ __( 'Subscribe to update', 'woocommerce' ) }
|
||||
onRequestClose={ props.onClose }
|
||||
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">
|
||||
{ sprintf(
|
||||
// translators: %s is the product version number (e.g. 1.0.2).
|
||||
__(
|
||||
'Version %s is available. To enable this update you need to purchase a subscription.',
|
||||
'woocommerce'
|
||||
),
|
||||
props.subscription.version
|
||||
) }
|
||||
</p>
|
||||
<ButtonGroup className="woocommerce-marketplace__header-account-modal-button-group">
|
||||
<Button
|
||||
variant="tertiary"
|
||||
onClick={ props.onClose }
|
||||
className="woocommerce-marketplace__header-account-modal-button"
|
||||
>
|
||||
{ __( 'Cancel', 'woocommerce' ) }
|
||||
</Button>
|
||||
<SubscribeButton
|
||||
subscription={ props.subscription }
|
||||
variant="primary"
|
||||
/>
|
||||
</ButtonGroup>
|
||||
</Modal>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Button, Icon } from '@wordpress/components';
|
||||
import { useDispatch } from '@wordpress/data';
|
||||
import { useContext, useState } from '@wordpress/element';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { SubscriptionsContext } from '../../../../contexts/subscriptions-context';
|
||||
import { Subscription } from '../../types';
|
||||
import ConnectModal from './connect-modal';
|
||||
import RenewModal from './renew-modal';
|
||||
import SubscribeModal from './subscribe-modal';
|
||||
|
||||
interface UpdateProps {
|
||||
subscription: Subscription;
|
||||
}
|
||||
|
||||
export default function Update( props: UpdateProps ) {
|
||||
const [ showModal, setShowModal ] = useState( false );
|
||||
const [ isUpdating, setIsUpdating ] = useState( false );
|
||||
const { createWarningNotice, createSuccessNotice } =
|
||||
useDispatch( 'core/notices' );
|
||||
const { loadSubscriptions } = useContext( SubscriptionsContext );
|
||||
|
||||
const canUpdate =
|
||||
props.subscription.active &&
|
||||
props.subscription.local &&
|
||||
props.subscription.local.slug &&
|
||||
props.subscription.local.path;
|
||||
|
||||
function update() {
|
||||
if ( ! canUpdate ) {
|
||||
setShowModal( true );
|
||||
return;
|
||||
}
|
||||
if ( ! window.wp.updates ) {
|
||||
createWarningNotice(
|
||||
sprintf(
|
||||
// translators: %s is the product name.
|
||||
__( '%s couldn’t be updated.', 'woocommerce' ),
|
||||
props.subscription.product_name
|
||||
),
|
||||
{
|
||||
actions: [
|
||||
{
|
||||
label: __(
|
||||
'Reload page and try again',
|
||||
'woocommerce'
|
||||
),
|
||||
onClick: () => {
|
||||
window.location.reload();
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
setIsUpdating( true );
|
||||
|
||||
const action =
|
||||
props.subscription.local.type === 'plugin'
|
||||
? 'update-plugin'
|
||||
: 'update-theme';
|
||||
window.wp.updates
|
||||
.ajax( action, {
|
||||
slug: props.subscription.local.slug,
|
||||
plugin: props.subscription.local.path,
|
||||
theme: props.subscription.local.path,
|
||||
} )
|
||||
.then( () => {
|
||||
loadSubscriptions( false );
|
||||
createSuccessNotice(
|
||||
sprintf(
|
||||
// translators: %s is the product name.
|
||||
__( '%s updated successfully.', 'woocommerce' ),
|
||||
props.subscription.product_name
|
||||
),
|
||||
{
|
||||
icon: <Icon icon="yes" />,
|
||||
}
|
||||
);
|
||||
} )
|
||||
.catch( () => {
|
||||
createWarningNotice(
|
||||
sprintf(
|
||||
// translators: %s is the product name.
|
||||
__( '%s couldn’t be updated.', 'woocommerce' ),
|
||||
props.subscription.product_name
|
||||
),
|
||||
{
|
||||
actions: [
|
||||
{
|
||||
label: __( 'Try again', 'woocommerce' ),
|
||||
onClick: update,
|
||||
},
|
||||
],
|
||||
}
|
||||
);
|
||||
} )
|
||||
.always( () => {
|
||||
setIsUpdating( false );
|
||||
} );
|
||||
}
|
||||
|
||||
const modal = () => {
|
||||
if ( ! showModal ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( props.subscription.product_key === '' ) {
|
||||
return (
|
||||
<SubscribeModal
|
||||
onClose={ () => setShowModal( false ) }
|
||||
subscription={ props.subscription }
|
||||
/>
|
||||
);
|
||||
} else if ( props.subscription.expired ) {
|
||||
return (
|
||||
<RenewModal
|
||||
subscription={ props.subscription }
|
||||
onClose={ () => setShowModal( false ) }
|
||||
/>
|
||||
);
|
||||
} else if ( ! props.subscription.active ) {
|
||||
return (
|
||||
<ConnectModal
|
||||
subscription={ props.subscription }
|
||||
onClose={ () => setShowModal( false ) }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{ modal() }
|
||||
<Button
|
||||
variant="link"
|
||||
className="woocommerce-marketplace__my-subscriptions-update"
|
||||
onClick={ update }
|
||||
isBusy={ isUpdating }
|
||||
disabled={ isUpdating }
|
||||
label={ sprintf(
|
||||
// translators: %s is the product version.
|
||||
__( 'Update to %s', 'woocommerce' ),
|
||||
props.subscription.version
|
||||
) }
|
||||
showTooltip={ true }
|
||||
tooltipPosition="top center"
|
||||
>
|
||||
{ isUpdating
|
||||
? __( 'Updating', 'woocommerce' )
|
||||
: __( 'Update', 'woocommerce' ) }
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { ToggleControl } from '@wordpress/components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Subscription } from '../../types';
|
||||
import Install from './install';
|
||||
|
||||
interface ActivationToggleProps {
|
||||
subscription: Subscription;
|
||||
}
|
||||
|
||||
export default function ActivationToggle( props: ActivationToggleProps ) {
|
||||
if (
|
||||
props.subscription.local.installed === false &&
|
||||
props.subscription.maxed === false
|
||||
) {
|
||||
return <Install subscription={ props.subscription } />;
|
||||
}
|
||||
|
||||
return <ToggleControl checked={ props.subscription.active } />;
|
||||
}
|
|
@ -1,18 +1,23 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { TableRow } from '@woocommerce/components/build-types/table/types';
|
||||
import { Icon, plugins } from '@wordpress/icons';
|
||||
import { gmdateI18n } from '@wordpress/date';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { Icon, plugins } from '@wordpress/icons';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Subscription } from '../../types';
|
||||
import StatusPopover from './status-popover';
|
||||
import ActivationToggle from './activation-toggle';
|
||||
import ConnectButton from '../actions/connect-button';
|
||||
import Install from '../actions/install';
|
||||
import RenewButton from '../actions/renew-button';
|
||||
import SubscribeButton from '../actions/subscribe-button';
|
||||
import Update from '../actions/update';
|
||||
import ActionsDropdownMenu from './actions-dropdown-menu';
|
||||
import StatusPopover from './status-popover';
|
||||
import Version from './version';
|
||||
|
||||
// TODO: Add explanations.
|
||||
function getStatus( subscription: Subscription ): {
|
||||
|
@ -56,21 +61,21 @@ function getStatus( subscription: Subscription ): {
|
|||
};
|
||||
}
|
||||
|
||||
function getVersion( subscription: Subscription ): string {
|
||||
function getVersion( subscription: Subscription ): string | JSX.Element {
|
||||
if ( subscription.local.version === subscription.version ) {
|
||||
return subscription.local.version;
|
||||
return <Version span={ subscription.local.version } />;
|
||||
}
|
||||
|
||||
if ( subscription.local.version && subscription.version ) {
|
||||
return subscription.local.version + ' > ' + subscription.version;
|
||||
return <Update subscription={ subscription } />;
|
||||
}
|
||||
|
||||
if ( subscription.version ) {
|
||||
return subscription.version;
|
||||
return <Version span={ subscription.version } />;
|
||||
}
|
||||
|
||||
if ( subscription.local.version ) {
|
||||
return subscription.local.version;
|
||||
return <Version span={ subscription.local.version } />;
|
||||
}
|
||||
|
||||
return '';
|
||||
|
@ -175,16 +180,26 @@ export function version( subscription: Subscription ): TableRow {
|
|||
};
|
||||
}
|
||||
|
||||
export function activation( subscription: Subscription ): TableRow {
|
||||
const displayElement = <ActivationToggle subscription={ subscription } />;
|
||||
|
||||
export function actions( subscription: Subscription ): TableRow {
|
||||
let actionButton = null;
|
||||
if ( subscription.product_key === '' ) {
|
||||
actionButton = <SubscribeButton subscription={ subscription } />;
|
||||
} else if ( subscription.expired ) {
|
||||
actionButton = <RenewButton subscription={ subscription } />;
|
||||
} else if ( subscription.local.installed === false ) {
|
||||
actionButton = <Install subscription={ subscription } />;
|
||||
} else if ( subscription.active === false ) {
|
||||
actionButton = (
|
||||
<ConnectButton subscription={ subscription } variant="link" />
|
||||
);
|
||||
}
|
||||
return {
|
||||
display: displayElement,
|
||||
};
|
||||
}
|
||||
|
||||
export function actions(): TableRow {
|
||||
return {
|
||||
display: <ActionsDropdownMenu />,
|
||||
display: (
|
||||
<div className="woocommerce-marketplace__my-subscriptions__actions">
|
||||
{ actionButton }
|
||||
|
||||
<ActionsDropdownMenu />
|
||||
</div>
|
||||
),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
interface VersionProps {
|
||||
span: string;
|
||||
}
|
||||
|
||||
export default function Version( props: VersionProps ) {
|
||||
return (
|
||||
<span className="woocommerce-marketplace__my-subscriptions-version">
|
||||
{ props.span }
|
||||
</span>
|
||||
);
|
||||
}
|
|
@ -7,13 +7,12 @@ import { TableRow } from '@woocommerce/components/build-types/table/types';
|
|||
*/
|
||||
import { Subscription } from '../types';
|
||||
import {
|
||||
actions,
|
||||
autoRenew,
|
||||
expiry,
|
||||
productName,
|
||||
status,
|
||||
expiry,
|
||||
autoRenew,
|
||||
version,
|
||||
activation,
|
||||
actions,
|
||||
} from './rows/functions';
|
||||
|
||||
export function availableSubscriptionRow( item: Subscription ): TableRow[] {
|
||||
|
@ -23,8 +22,7 @@ export function availableSubscriptionRow( item: Subscription ): TableRow[] {
|
|||
expiry( item ),
|
||||
autoRenew( item ),
|
||||
version( item ),
|
||||
activation( item ),
|
||||
actions(),
|
||||
actions( item ),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -35,7 +33,6 @@ export function installedSubscriptionRow( item: Subscription ): TableRow[] {
|
|||
expiry( item ),
|
||||
autoRenew( item ),
|
||||
version( item ),
|
||||
activation( item ),
|
||||
actions(),
|
||||
actions( item ),
|
||||
];
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Table, TablePlaceholder } from '@woocommerce/components';
|
||||
import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@woocommerce/components/build-types/table/types';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const tableHeadersDefault = [
|
||||
{
|
||||
|
@ -45,10 +45,19 @@ function SubscriptionsTable( props: {
|
|||
);
|
||||
}
|
||||
|
||||
const headersWithClasses = props.headers.map( ( header ) => {
|
||||
return {
|
||||
...header,
|
||||
cellClassName:
|
||||
'woocommerce-marketplace__my-subscriptions__table__header--' +
|
||||
header.key,
|
||||
};
|
||||
} );
|
||||
|
||||
return (
|
||||
<Table
|
||||
className="woocommerce-marketplace__my-subscriptions__table"
|
||||
headers={ props.headers }
|
||||
headers={ headersWithClasses }
|
||||
rows={ props.rows }
|
||||
/>
|
||||
);
|
||||
|
@ -60,10 +69,6 @@ export function InstalledSubscriptionsTable( props: {
|
|||
} ) {
|
||||
const headers = [
|
||||
...tableHeadersDefault,
|
||||
{
|
||||
key: 'activated',
|
||||
label: __( 'Activated', 'woocommerce' ),
|
||||
},
|
||||
{
|
||||
key: 'actions',
|
||||
label: __( 'Actions', 'woocommerce' ),
|
||||
|
@ -85,10 +90,6 @@ export function AvailableSubscriptionsTable( props: {
|
|||
} ) {
|
||||
const headers = [
|
||||
...tableHeadersDefault,
|
||||
{
|
||||
key: 'install',
|
||||
label: __( 'Install', 'woocommerce' ),
|
||||
},
|
||||
{
|
||||
key: 'actions',
|
||||
label: __( 'Actions', 'woocommerce' ),
|
||||
|
|
|
@ -4,6 +4,7 @@ export type Subscription = {
|
|||
product_name: string;
|
||||
product_url: string;
|
||||
product_icon: string;
|
||||
zip_slug: string;
|
||||
key_type: string;
|
||||
key_type_label: string;
|
||||
autorenew: boolean;
|
||||
|
@ -30,6 +31,9 @@ export interface SubscriptionLocal {
|
|||
installed: boolean;
|
||||
active: boolean;
|
||||
version: string;
|
||||
type: string;
|
||||
slug: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
export interface SubscriptionShare {
|
||||
|
|
|
@ -13,7 +13,7 @@ import { fetchSubscriptions } from '../utils/functions';
|
|||
export const SubscriptionsContext = createContext< SubscriptionsContextType >( {
|
||||
subscriptions: [],
|
||||
setSubscriptions: () => {},
|
||||
loadSubscriptions: () => {},
|
||||
loadSubscriptions: () => new Promise( () => {} ),
|
||||
isLoading: true,
|
||||
setIsLoading: () => {},
|
||||
} );
|
||||
|
@ -31,7 +31,7 @@ export function SubscriptionsContextProvider( props: {
|
|||
setIsLoading( true );
|
||||
}
|
||||
|
||||
fetchSubscriptions()
|
||||
return fetchSubscriptions()
|
||||
.then( ( subscriptionResponse ) => {
|
||||
setSubscriptions( subscriptionResponse );
|
||||
} )
|
||||
|
@ -42,12 +42,14 @@ export function SubscriptionsContextProvider( props: {
|
|||
} );
|
||||
};
|
||||
|
||||
useEffect( () => loadSubscriptions( true ), [] );
|
||||
useEffect( () => {
|
||||
loadSubscriptions( true );
|
||||
}, [] );
|
||||
|
||||
const contextValue = {
|
||||
subscriptions,
|
||||
setSubscriptions,
|
||||
loadSubscriptions,
|
||||
loadSubscriptions: () => loadSubscriptions(),
|
||||
isLoading,
|
||||
setIsLoading,
|
||||
};
|
||||
|
|
|
@ -13,7 +13,7 @@ export type MarketplaceContextType = {
|
|||
export type SubscriptionsContextType = {
|
||||
subscriptions: Subscription[];
|
||||
setSubscriptions: ( subscriptions: Subscription[] ) => void;
|
||||
loadSubscriptions: ( toggleLoading?: boolean ) => void;
|
||||
loadSubscriptions: ( toggleLoading?: boolean ) => Promise< void >;
|
||||
isLoading: boolean;
|
||||
setIsLoading: ( isLoading: boolean ) => void;
|
||||
};
|
||||
|
|
|
@ -6,20 +6,20 @@ import apiFetch from '@wordpress/api-fetch';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { LOCALE } from '../../utils/admin-settings';
|
||||
import { CategoryAPIItem } from '../components/category-selector/types';
|
||||
import {
|
||||
MARKETPLACE_CATEGORY_API_PATH,
|
||||
MARKETPLACE_HOST,
|
||||
MARKETPLACE_SEARCH_API_PATH,
|
||||
} from '../components/constants';
|
||||
import { Subscription } from '../components/my-subscriptions/types';
|
||||
import {
|
||||
Product,
|
||||
ProductType,
|
||||
SearchAPIProductType,
|
||||
SearchAPIJSONType,
|
||||
SearchAPIProductType,
|
||||
} from '../components/product-list/types';
|
||||
import {
|
||||
MARKETPLACE_HOST,
|
||||
MARKETPLACE_CATEGORY_API_PATH,
|
||||
MARKETPLACE_SEARCH_API_PATH,
|
||||
} from '../components/constants';
|
||||
import { CategoryAPIItem } from '../components/category-selector/types';
|
||||
import { LOCALE } from '../../utils/admin-settings';
|
||||
import { Subscription } from '../components/my-subscriptions/types';
|
||||
|
||||
interface ProductGroup {
|
||||
id: string;
|
||||
|
@ -199,6 +199,20 @@ function installProduct( productKey: string ): Promise< void > {
|
|||
} );
|
||||
}
|
||||
|
||||
function connectProduct( productKey: string ): Promise< void > {
|
||||
const url = '/wc/v3/marketplace/subscriptions/activate';
|
||||
const data = new URLSearchParams();
|
||||
data.append( 'product_key', productKey );
|
||||
return apiFetch( {
|
||||
path: url.toString(),
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: data,
|
||||
} );
|
||||
}
|
||||
|
||||
// Append UTM parameters to a URL, being aware of existing query parameters
|
||||
const appendURLParams = (
|
||||
url: string,
|
||||
|
@ -219,11 +233,12 @@ const appendURLParams = (
|
|||
};
|
||||
|
||||
export {
|
||||
fetchSearchResults,
|
||||
fetchDiscoverPageData,
|
||||
fetchCategories,
|
||||
fetchSubscriptions,
|
||||
installProduct,
|
||||
ProductGroup,
|
||||
appendURLParams,
|
||||
connectProduct,
|
||||
fetchCategories,
|
||||
fetchDiscoverPageData,
|
||||
fetchSearchResults,
|
||||
fetchSubscriptions,
|
||||
installProduct,
|
||||
};
|
||||
|
|
|
@ -36,6 +36,15 @@ declare global {
|
|||
'shipping-setting-tour': boolean;
|
||||
};
|
||||
wp: {
|
||||
updates?: {
|
||||
ajax: ( action, data: {
|
||||
slug: string;
|
||||
plugin?: string;
|
||||
theme?: string;
|
||||
success?: function;
|
||||
error?: function;
|
||||
} ) => JQuery.Promise;
|
||||
};
|
||||
autosave?: {
|
||||
server: {
|
||||
postChanged: () => boolean;
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: add
|
||||
|
||||
Add update support to the My subscriptions page.
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: add
|
||||
Comment: Add my subscription action buttons and modals.
|
||||
|
|
@ -1522,6 +1522,9 @@ class WC_Helper {
|
|||
'installed' => false,
|
||||
'active' => false,
|
||||
'version' => null,
|
||||
'type' => null,
|
||||
'slug' => null,
|
||||
'path' => null,
|
||||
);
|
||||
|
||||
$updates = WC_Helper_Updater::get_update_data();
|
||||
|
@ -1538,14 +1541,19 @@ class WC_Helper {
|
|||
|
||||
$subscription['local']['installed'] = true;
|
||||
$subscription['local']['version'] = $local['Version'];
|
||||
$subscription['local']['type'] = $local['_type'];
|
||||
$subscription['local']['path'] = $local['_filename'];
|
||||
$subscription['local']['slug'] = null;
|
||||
|
||||
if ( 'plugin' === $local['_type'] ) {
|
||||
$subscription['local']['slug'] = $local['slug'];
|
||||
if ( is_plugin_active( $local['_filename'] ) ) {
|
||||
$subscription['local']['active'] = true;
|
||||
} elseif ( is_multisite() && is_plugin_active_for_network( $local['_filename'] ) ) {
|
||||
$subscription['local']['active'] = true;
|
||||
}
|
||||
} elseif ( 'theme' === $local['_type'] ) {
|
||||
$subscription['local']['slug'] = $local['_stylesheet'];
|
||||
if ( in_array( $local['_stylesheet'], array( get_stylesheet(), get_template() ), true ) ) {
|
||||
$subscription['local']['active'] = true;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ class Marketplace {
|
|||
final public function init() {
|
||||
if ( FeaturesUtil::feature_is_enabled( 'marketplace' ) ) {
|
||||
add_action( 'admin_menu', array( $this, 'register_pages' ), 70 );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,4 +54,21 @@ class Marketplace {
|
|||
*/
|
||||
return apply_filters( 'woocommerce_marketplace_menu_items', $marketplace_pages );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue update script.
|
||||
*
|
||||
* @param string $hook_suffix The current admin page.
|
||||
*/
|
||||
public function enqueue_scripts( $hook_suffix ) {
|
||||
if ( 'woocommerce_page_wc-admin' !== $hook_suffix ) {
|
||||
return;
|
||||
};
|
||||
if ( ! isset( $_GET['path'] ) || '/extensions' !== $_GET['path'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Enqueue WordPress updates script to enable plugin and theme installs and updates.
|
||||
wp_enqueue_script( 'updates' );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue