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

Homepage Plugins nudge - UI #350

Merged
merged 24 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
110884b
Home page plugins nudge
aratidgr8 Sep 11, 2024
0451508
Logic to display solutions banner component on Home page
aratidgr8 Sep 11, 2024
e05643e
Logic to display solutions banner component on Home page
aratidgr8 Sep 11, 2024
e291d37
Remove WPSolutionsBanner from Ecommerce and load directly in BlueHost
aratidgr8 Sep 11, 2024
50098e6
Export WPSolutionsBanner file as component from Ecommerce module to B…
aratidgr8 Sep 11, 2024
c3867d2
No existing plan view of Homepage - PRESS0-2229
aratidgr8 Sep 13, 2024
f6f3af3
No existing plan view of Homepage - PRESS0-2229
aratidgr8 Sep 13, 2024
aefdd57
PRESS0-2231: Store page CTA for Plugins & Tools page
aratidgr8 Sep 16, 2024
1db15d8
PRESS0-1719: Add WP entitlements to Next Steps
aratidgr8 Sep 24, 2024
e9517a1
Merge branch 'trunk' into PRESS0-2212
wpscholar Sep 26, 2024
405515f
Updated Solutions Banner Component as per entitlements API response
aratidgr8 Sep 30, 2024
3932eba
Updated code for homepage banner as per solutions API call response -…
aratidgr8 Oct 1, 2024
e253bc4
Remove whitespace difference change from src/components/OnboardingScr…
aratidgr8 Oct 1, 2024
2083610
Added TODO comment
aratidgr8 Oct 1, 2024
f1ff71a
Correct error text color
aratidgr8 Oct 1, 2024
6d279d4
Code updated as per Solutions Entitlement API
aratidgr8 Oct 4, 2024
316fbae
Remove commented code
aratidgr8 Oct 4, 2024
4903755
Add HTML tags handling for No existing plans features section
aratidgr8 Oct 4, 2024
13fbb5a
Remove commented code
aratidgr8 Oct 4, 2024
abc71ee
Organize Imports
aratidgr8 Oct 4, 2024
8e13162
Code review comments resolved
aratidgr8 Oct 8, 2024
fff299d
custom button text
aratidgr8 Oct 8, 2024
bcde247
Plugin install & activate logic added in Homepage Banner
aratidgr8 Oct 9, 2024
d634220
PR comments
aratidgr8 Oct 9, 2024
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
2 changes: 1 addition & 1 deletion build/index.asset.php
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<?php return array('dependencies' => array('lodash', 'moment', 'react', 'react-dom', 'wp-api-fetch', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '00a9f8f0dd08a3e19f74');
<?php return array('dependencies' => array('lodash', 'moment', 'react', 'react-dom', 'wp-api-fetch', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '9c0b6e7c532590756eee');
19 changes: 18 additions & 1 deletion includes/Data/Plugins.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,23 @@ final class Plugins {
),
);

/**
* An associative array of premium plugins with their corresponding admin page URLs and file paths.
*
* @var array<string, array<string, string>> $free_plugins
*/
public static $premium_plugins = array(
// TODO: More plugins to be added here as once their data is available
'wp-seo' => array(
'url' => 'wp-admin/admin.php?page=wpseo_dashboard#top#first-time-configuration',
'file' => 'wordpress-seo/wp-seo.php'
),
'sensei-lms' => array(
'url' => 'wp-admin/admin.php?page=wpseo_dashboard#top#first-time-configuration',
'file' => 'sensei-lms/sensei-lms.php'
),
);

/**
* An associative array of supported plugins with their corresponding file paths and admin page URLs.
*
Expand Down Expand Up @@ -120,6 +137,6 @@ final class Plugins {
* @return array<string, array<string, string>> A combined array of supported and free plugins.
*/
public static function supported_plugins() {
return array_merge( self::$supported_plugins, self::$free_plugins );
return array_merge( self::$supported_plugins, self::$free_plugins, self::$premium_plugins );
}
}
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
},
"dependencies": {
"@faizaanceg/pandora": "^1.1.1",
"uuid": "^9.0.1",
"@heroicons/react": "2.1.3",
"@newfold-labs/js-utility-ui-analytics": "^1.2.0",
"@newfold-labs/wp-module-runtime": "^1.0.0",
Expand All @@ -32,8 +31,9 @@
"@wordpress/element": "^5.32.0",
"@wordpress/i18n": "^4.55.0",
"classnames": "2.5.1",
"moment": "^2.29.4",
"swr": "2.1.5"
"moment": "^2.29.4",
"swr": "2.1.5",
"uuid": "^9.0.1"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.7",
Expand Down
80 changes: 80 additions & 0 deletions src/components/NoExistingPlan.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { Button } from "@newfold/ui-component-library";
import { __ } from "@wordpress/i18n";
import { ReactComponent as FiftyOff } from "../icons/fifty-off.svg";
import { ReactComponent as GreenTick } from "../icons/green-tick.svg";
import { Section } from "./Section";


export function NoExistingPlan(props){
const { availableSolutions } = props;

const HtmlContent = ({ htmlString }) => {
return (
<div
dangerouslySetInnerHTML={{ __html: htmlString }}
/>
);
};


return(
<Section.Container className="nfd-container">
<Section.Header
title={__("Upgrade your plan for success.", "wp-module-ecommerce")}
subTitle={__("Choose the set of plugins and services that's right for your needs. You're covered by our no-quibble, 30 day money back guarantee.", "wp-module-ecommerce")}
/>
<Section.Content className="nfd-app-section-home">
{
availableSolutions?.map((solution) => {
return(
<div className="nfd-border nfd-border-[#E2E8F0] nfd-p-6 nfd-rounded-lg nfd-mb-6 nfd-relative">
<FiftyOff className="nfd-absolute nfd-top-0 nfd-right-0 nfd-hidden" />
<h2 className="nfd-text-[#0F172A] nfd-text-lg nfd-font-semibold nfd-mb-5">
{ __(`${solution.name.toUpperCase()}`, "wp-module-ecommerce") }
</h2>
<div className="nfd-flex nfd-flex-row">
<p className="nfd-text-[#0F172A] nfd-text-base nfd-mb-7 nfd-w-[480px]">
{__(`${solution.description}`, "wp-module-ecommerce")}
</p>
<p className="nfd-text-[#000000] nfd-text-4xl nfd-font-extrabold nfd-ml-auto nfd-mr-10">
{solution.price}
<span className="nfd-text-2xl nfd-text-[#000000] nfd-font-semibold nfd-relative nfd--top-[5px]">
{__("/mo", "wp-module-ecommerce")}
</span>
<br />
<span className="nfd-text-sm nfd-text-[#404040] nfd-font-normal nfd-relative nfd--top-9 nfd-hidden">
<span>{__("Original price ", "wp-module-ecommerce")}</span>
<span className="nfd-line-through">{solution.fullPrice}</span>
<span>{__("/mo", "wp-module-ecommerce")}</span>
</span>
</p>
</div>
<div className="nfd-flex nfd-flex-row nfd--mt-8">
<ul className="nfd-mr-6 nfd-grid nfd-grid-cols-2 nfd-gap-x-6 nfd-mt-6">
{
solution?.features.map((feat, index) => {
return(
<li className={classNames( "nfd-flex", "nfd-flex-row", "nfd-items-center",
{ 'nfd-border-b nfd-border-[#cccccc] nfd-mb-3 nfd-pb-3': (index === 0 || index === 1) })}
>
<GreenTick className="nfd-mt-1.5 nfd-mr-2" />
<span className="nfd-text-[#404040] nfd-text-base">
<HtmlContent htmlString={__(`${feat}`, "wp-module-ecommerce")} />
</span>
</li>
)
})
}
</ul>
<Button as="a" href={solution.url} className="nfd-button nfd-button--secondary nfd-self-end nfd-ml-auto">
{__("Learn more", "wp-module-ecommerce")}
</Button>
</div>
</div>
)
})
}
</Section.Content>
</Section.Container>
)
}
147 changes: 147 additions & 0 deletions src/components/WPSolutionsBanner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
import { Button, Spinner } from "@newfold/ui-component-library";
import apiFetch from '@wordpress/api-fetch';
import { useEffect, useState } from "@wordpress/element";
import { __ } from "@wordpress/i18n";
import useSWR from "swr";
import { myPluginsAndToolsPageLink, solutionButtonTextObject, wpSolutionsPromotedPluginsList } from "../constants";
import { ReactComponent as RightArrow } from "../icons/right-arrow.svg";
import { NewfoldRuntime } from "../sdk/NewfoldRuntime";
import { PluginsSdk } from "../sdk/plugins";
import { NoExistingPlan } from "./NoExistingPlan";
import { Section } from "./Section";


export function WPSolutionsBanner() {

const entitlementsEndPoint = NewfoldRuntime.createApiUrl("/newfold-solutions/v1/entitlements");
const [ error, setError ] = useState(null);
const [ apiResponse, setApiResponse ] = useState(null);
const [ isLoaded, setIsLoaded ] = useState( false );
const [ purchasedSolution, setPurchasedSolution] = useState(null)
const [ availableSolutions, setAvailableSolutions] = useState([]);
const [ pluginActiveStatusArray, setPluginActiveStatusArray] = useState([]);
let currentSolution = [];

//TODO: To add slug information for all premium plugins once data is available
let premiumPluginStatus = useSWR(
"nfd_slug_wonder_cart",
() =>
PluginsSdk.queries
.status("nfd_slug_wonder_cart", "sensei-lms", "wp-seo")
.then(res => {
setPluginActiveStatusArray(res?.details)
}),
{ refreshInterval: 30 * 1000 }
);

const routeChange = () =>{
location.href = myPluginsAndToolsPageLink;
}

useEffect( () => {
apiFetch( { url: `${ entitlementsEndPoint }` } ).then(
( result ) => {
setIsLoaded(true);
setApiResponse(result)
setPurchasedSolution(result['solution'])
setAvailableSolutions(result['solutions'])
},
( error ) => {
setIsLoaded(true);
setError(error);
}
);
}, [] );

if ( error ) {
//Uncomment below line, to debug error in API response
//console.log(error.message, "error");
return (
<div className="nfd-flex nfd-p-6 nfd-bg-white nfd-w-full nfd-rounded-lg nfd-text-red-700">
<ExclamationTriangleIcon className="nfd-w-[24px] nfd-h-[24px]" />
<span className="nfd-ml-1.5">{__("Oops! something went wrong. Please try again later", "wp-module-ecommerce")}</span>
</div>
);
}
else if (!isLoaded){
return (
<div className="nfd-flex nfd-items-center nfd-text-center nfd-justify-center nfd-h-full">
<Spinner size="8" className="nfd-text-primary" />
</div>
);
}
else if (apiResponse) {
if (purchasedSolution === null) {
return (<NoExistingPlan availableSolutions={availableSolutions} />);
}
else{
currentSolution = purchasedSolution === "WP_SOLUTION_CREATOR" ?
wpSolutionsPromotedPluginsList[0]['WP_SOLUTION_CREATOR'] :
purchasedSolution === "WP_SOLUTION_SERVICE" ?
wpSolutionsPromotedPluginsList[0]['WP_SOLUTION_SERVICE'] : wpSolutionsPromotedPluginsList[0]['WP_SOLUTION_COMMERCE'];
let solutionsCards = Object.values(currentSolution);
return(
<Section.Container className="nfd-container">
<Section.Header
title={__("Explore Your Plugins and Tools", "wp-module-ecommerce")}
subTitle={__("Improve your site with the tools and services included in your plan.", "wp-module-ecommerce")}
secondaryAction={{title : __( `View ${solutionButtonTextObject[purchasedSolution]} tools`, "wp-module-ecommerce" ), className: false, onClick: routeChange }}
/>
<Section.Content className="nfd-app-section-home">
<div className="nfd-flex nfd-flex-row nfd-flex-wrap">
{
solutionsCards?.map((details, index) => {
return (<div key="index" className={"nfd-flex nfd-flex-col nfd-bg-[#F1F5F7] nfd-p-6 nfd-rounded-lg nfd-border nfd-border-[#E2E8F0] nfd-box-content "+ (index === 0 ? "nfd-w-[38.33%] nfd-mr-6 nfd-mb-6" : index === 1 ? "nfd-w-6/12 nfd-mb-6" : index === 2 ? "nfd-w-6/12 nfd-mr-6" : "nfd-w-[38.33%]") }>
<h2 className="nfd-text-[#0F172A] nfd-text-lg nfd-leading-5 nfd-font-semibold nfd-mb-4">
{ __(`${details['title']}`,"wp-module-ecommerce") }
</h2>
<p className="nfd-text-[#0F172A] nfd-text-lg nfd-leading-5 nfd-font-normal nfd-mb-10">
{ __(`${details['description']}`,"wp-module-ecommerce") }
</p>
{
details.slug !== "" ?
Object.entries(pluginActiveStatusArray).map(([slug, { status, url }]) => (
details.slug === slug ?
status === "active" ?
<Button className="nfd-button nfd-button--primary nfd-mt-9 nfd-mt-auto nfd-self-start" as="a" href={url}>
{ __(`${details['buttonText']}`,"wp-module-ecommerce") }
<RightArrow className="nfd-mt-2.5" />
</Button>
:
status === "need_to_install" || "installing" ?
<Button
className="nfd-button nfd-button--primary nfd-mt-9 nfd-mt-auto nfd-self-start"
as="button"
data-nfd-installer-plugin-slug={slug}
data-nfd-installer-plugin-provider={details.providerName}
data-nfd-installer-plugin-activate={true}
isLoading={status==="installing"}
>
{ status==="installing" ? __("Installing","wp-module-ecommerce") : __("Install","wp-module-ecommerce") }
<RightArrow className="nfd-mt-2.5" />
</Button> : null
:
null
))
:
<Button className="nfd-button nfd-button--primary nfd-mt-9 nfd-mt-auto nfd-self-start" as="button" disabled={true}>
{ __(`${details['buttonText']}`,"wp-module-ecommerce") }
<RightArrow className="nfd-mt-2.5" />
</Button>
}
</div>)
})
}
</div>

<Button as="a" href={myPluginsAndToolsPageLink} className="nfd-button nfd-button--secondary nfd-flex nfd-w-56 nfd-mx-auto nfd-mt-3">
{__(`View all ${solutionButtonTextObject[purchasedSolution]} tools`, "wp-module-ecommerce")}
</Button>
</Section.Content>
</Section.Container>
)
}

}
}
18 changes: 11 additions & 7 deletions src/components/YITHPlugins.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { Button, Modal, Spinner } from "@newfold/ui-component-library";
import apiFetch from "@wordpress/api-fetch";
import { useEffect, useState } from "@wordpress/element";
import { __ } from "@wordpress/i18n";
import { Modal, Spinner } from "@newfold/ui-component-library";
import classNames from "classnames";
import { YITHPluginsDefinitions } from "../configs/YITHPlugins.config";
import { myPluginsAndToolsPageLink } from "../constants";
import lightchest from '../icons/light-chest.svg';
import { NewfoldRuntime } from "../sdk/NewfoldRuntime";
import { LoadingPanel } from "./LoadingPanel";
import { Section } from "./Section";
import { useCardManager } from "./useCardManager";
import classNames from "classnames";
import { useEffect, useState } from "@wordpress/element";
import apiFetch from "@wordpress/api-fetch";
import { NewfoldRuntime } from "../sdk/NewfoldRuntime";
import { YithFeatureCard } from "./YithFeatureCard";
import lightchest from '../icons/light-chest.svg';
import { LoadingPanel } from "./LoadingPanel";

export function YITHPlugins({ wpModules }) {
const [isOpen, setIsOpen] = useState(false);
Expand Down Expand Up @@ -127,6 +128,9 @@ export function YITHPlugins({ wpModules }) {
"Unlock the full power of your plan with access to a range of exclusive WooCommerce tools powered by \nYITH. Enhance your store and keep your customers coming back for more!",
"wp-module-ecommerce"
)}
<Button as="a" href={myPluginsAndToolsPageLink} className="nfd-button nfd-button--secondary nfd-flex nfd-self-end nfd-ml-auto">
{__( "View all Commerce tools", "wp-module-ecommerce" )}
</Button>
</div>
</div>
<Section.Content className={"nfd-pt-4 nfd-pl-4 nfd-pr-4"}>
Expand Down
Loading