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

324 tailwindify the errors and notices in the related keyphrase suggestions modal #21815

Merged
Show file tree
Hide file tree
Changes from all 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
103 changes: 49 additions & 54 deletions packages/js/src/components/SEMrushRelatedKeyphrasesModalContent.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
/* External dependencies */
import { Fragment } from "@wordpress/element";
import { KeyphrasesTable, PremiumUpsell } from "@yoast/related-keyphrase-suggestions";
import { KeyphrasesTable, UserMessage } from "@yoast/related-keyphrase-suggestions";
import { Root } from "@yoast/ui-library";
import { __, sprintf } from "@wordpress/i18n";
import PropTypes from "prop-types";
import { isEmpty } from "lodash";

/* Internal dependencies */
import SEMrushLoading from "./modals/SEMrushLoading";
import SEMrushLimitReached from "./modals/SEMrushLimitReached";
import SEMrushCountrySelector from "./modals/SEMrushCountrySelector";
import SEMrushRequestFailed from "./modals/SEMrushRequestFailed";
import SEMrushMaxRelatedKeyphrases from "./modals/SEMrushMaxRelatedKeyphrases";
import getL10nObject from "../analysis/getL10nObject";
import SEMrushUpsellAlert from "./modals/SEMrushUpsellAlert";
import { makeOutboundLink } from "@yoast/helpers";

/**
Expand All @@ -27,47 +22,47 @@ export function hasError( response ) {
}

/**
* Gets a user message based on the passed props' values.
* Determines whether the maximum amount of related keyphrases has been reached.
*
* @param {Object} props The props to use.
* @param {array} relatedKeyphrases The related keyphrases. Can be empty.
*
* @returns {wp.Element} The user message.
* @returns {boolean} Whether or not the maximum limit has been reached.
*/
export function hasMaximumRelatedKeyphrases( relatedKeyphrases ) {
return relatedKeyphrases && relatedKeyphrases.length >= 4;
}

/**
* Gets a user message variant.
*
* @param {object} props The props to use within the content.
*
* @returns {string} The user message variant.
*/
export function getUserMessage( props ) {
const {
isPending,
requestLimitReached,
isSuccess,
response,
requestHasData,
relatedKeyphrases,
} = props;

if ( isPending ) {
return <SEMrushLoading />;
}

if ( requestLimitReached ) {
return <SEMrushLimitReached />;
return "requestLimitReached";
}

if ( ! isSuccess && hasError( response ) ) {
return <SEMrushRequestFailed />;
return "requestFailed";
}

if ( ! requestHasData ) {
return <p>{ __( "Sorry, there's no data available for that keyphrase/country combination.", "wordpress-seo" ) }</p>;
return "requestEmpty";
}
}

/**
* Determines whether the maximum amount of related keyphrases has been reached.
*
* @param {array} relatedKeyphrases The related keyphrases. Can be empty.
*
* @returns {boolean} Whether or not the maximum limit has been reached.
*/
export function hasMaximumRelatedKeyphrases( relatedKeyphrases ) {
return relatedKeyphrases && relatedKeyphrases.length >= 4;
if ( hasMaximumRelatedKeyphrases( relatedKeyphrases ) ) {
return "maxRelatedKeyphrases";
}
}

/**
Expand All @@ -94,41 +89,39 @@ export default function RelatedKeyphraseModalContent( props ) {
setRequestLimitReached,
isPending,
isRtl,
isPremium,
userLocale,
} = props;

const isPremium = getL10nObject().isPremium;
const GetMoreInsightsLink = makeOutboundLink();
const url = "https://www.semrush.com/analytics/keywordoverview/?q=" + encodeURIComponent( keyphrase ) +
"&db=" + encodeURIComponent( countryCode );

return (
<Root context={ { isRtl } }>
{ ! requestLimitReached && (
<Fragment>
{ ! isPremium && <PremiumUpsell
className="yst-my-6"
url={ window.wpseoAdminL10n[ "shortlinks.semrush.premium_landing_page" ] }
/> }

{ isPremium && hasMaximumRelatedKeyphrases( relatedKeyphrases ) && <SEMrushMaxRelatedKeyphrases /> }
<SEMrushCountrySelector
countryCode={ countryCode }
setCountry={ setCountry }
newRequest={ newRequest }
keyphrase={ keyphrase }
setRequestFailed={ setRequestFailed }
setNoResultsFound={ setNoResultsFound }
setRequestSucceeded={ setRequestSucceeded }
setRequestLimitReached={ setRequestLimitReached }
response={ response }
lastRequestKeyphrase={ lastRequestKeyphrase }
userLocale={ userLocale.split( "_" )[ 0 ] }
/>
</Fragment>
) }

{ getUserMessage( props ) }

{ ! requestLimitReached && ! isPremium && <SEMrushUpsellAlert /> }

{ ! requestLimitReached && <SEMrushCountrySelector
countryCode={ countryCode }
setCountry={ setCountry }
newRequest={ newRequest }
keyphrase={ keyphrase }
setRequestFailed={ setRequestFailed }
setNoResultsFound={ setNoResultsFound }
setRequestSucceeded={ setRequestSucceeded }
setRequestLimitReached={ setRequestLimitReached }
response={ response }
lastRequestKeyphrase={ lastRequestKeyphrase }
userLocale={ userLocale.split( "_" )[ 0 ] }
/> }

{ ! isPending && <UserMessage
variant={ getUserMessage( props ) }
upsellLink={ window.wpseoAdminL10n[ "shortlinks.semrush.prices" ] }
className="yst-my-2"
/> }

<KeyphrasesTable
relatedKeyphrases={ relatedKeyphrases }
columnNames={ response?.results?.columnNames }
Expand Down Expand Up @@ -166,6 +159,7 @@ RelatedKeyphraseModalContent.propTypes = {
isRtl: PropTypes.bool,
userLocale: PropTypes.string,
isPending: PropTypes.bool,
isPremium: PropTypes.bool,
};

RelatedKeyphraseModalContent.defaultProps = {
Expand All @@ -178,4 +172,5 @@ RelatedKeyphraseModalContent.defaultProps = {
isRtl: false,
userLocale: "en_US",
isPending: false,
isPremium: false,
};
2 changes: 2 additions & 0 deletions packages/js/src/containers/SEMrushRelatedKeyphrases.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default compose( [
getSEMrushRequestHasData,
getSEMrushRequestKeyphrase,
getPreference,
getIsPremium,
} = select( "yoast-seo/editor" );

return {
Expand All @@ -30,6 +31,7 @@ export default compose( [
lastRequestKeyphrase: getSEMrushRequestKeyphrase(),
isRtl: getPreference( "isRtl", false ),
userLocale: getPreference( "userLocale", "en_US" ),
isPremium: getIsPremium(),
};
} ),
withDispatch( ( dispatch ) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import * as SEMrushRelatedKeyphrasesModalContent from "../../src/components/SEMrushRelatedKeyphrasesModalContent";
import SEMrushLoading from "../../src/components/modals/SEMrushLoading";
import SEMrushLimitReached from "../../src/components/modals/SEMrushLimitReached";
import SEMrushRequestFailed from "../../src/components/modals/SEMrushRequestFailed";

describe( "SEMrushRelatedKeyphrasesModalContent", () => {
let props = {};
Expand Down Expand Up @@ -41,17 +38,6 @@ describe( "SEMrushRelatedKeyphrasesModalContent", () => {
} );

describe( "getUserMessage", () => {
it( "returns the SEMrushLoading message when request is pending", () => {
props = {
...props,
isPending: true,
};

const actual = SEMrushRelatedKeyphrasesModalContent.getUserMessage( props );

expect( actual ).toEqual( <SEMrushLoading /> );
} );

it( "returns the SEMrushLimitReached message when request limit is reached", () => {
props = {
...props,
Expand All @@ -60,7 +46,7 @@ describe( "SEMrushRelatedKeyphrasesModalContent", () => {

const actual = SEMrushRelatedKeyphrasesModalContent.getUserMessage( props );

expect( actual ).toEqual( <SEMrushLimitReached /> );
expect( actual ).toEqual( "requestLimitReached" );
} );

it( "returns the SEMrushRequestFailed message when request fails", () => {
Expand All @@ -75,13 +61,13 @@ describe( "SEMrushRelatedKeyphrasesModalContent", () => {

const actual = SEMrushRelatedKeyphrasesModalContent.getUserMessage( props );

expect( actual ).toEqual( <SEMrushRequestFailed /> );
expect( actual ).toEqual( "requestFailed" );
} );

it( "returns a message when response contains no data", () => {
const actual = SEMrushRelatedKeyphrasesModalContent.getUserMessage( props );

expect( actual ).toEqual( <p>{ "Sorry, there's no data available for that keyphrase/country combination." }</p> );
expect( actual ).toEqual( "requestEmpty" );
} );
} );

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from "react";
import PropTypes from "prop-types";
import { __, sprintf } from "@wordpress/i18n";
import { Alert } from "@yoast/ui-library";

/**
* Display the message when reaching max related keyphrases.
*
* @param {string} [className=""] The class name for the alert.
*
* @returns {React.Component} The alert for max related keyphrases.
*/
export const MaxRelatedKeyphrases = ( { className = "" } ) => {
return (
<Alert variant="warning" className={ className }>
{ sprintf(
/* translators: %s: Expands to "Yoast SEO". */
__(
// eslint-disable-next-line max-len
"You've reached the maximum amount of 4 related keyphrases. You can change or remove related keyphrases in the %s metabox or sidebar.",
"wordpress-seo",
),
"Yoast SEO",
) }
</Alert>
);
};

MaxRelatedKeyphrases.propTypes = {
className: PropTypes.string,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";
import PropTypes from "prop-types";
import { __ } from "@wordpress/i18n";
import { Alert } from "@yoast/ui-library";

/**
* Display the message for a empty request.
*
* @param {string} [className=""] The class name for the alert.
*
* @returns {React.Component} The message for a empty request.
*/
export const RequestEmpty = ( { className = "" } ) => {
return (
<Alert variant="info" className={ className }>
{ __( "Sorry, there's no data available for that keyphrase/country combination.", "wordpress-seo" ) }
</Alert>
);
};

RequestEmpty.propTypes = {
className: PropTypes.string,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";
import PropTypes from "prop-types";
import { __ } from "@wordpress/i18n";
import { Alert } from "@yoast/ui-library";

/**
* Display the message for a failed request.
*
* @param {string} [className=""] The class name for the alert.
*
* @returns {React.Component} The message for a failed request.
*/
export const RequestFailed = ( { className = "" } ) => {
return (
<Alert variant="error" className={ className }>
{ __( "We've encountered a problem trying to get related keyphrases. Please try again later.", "wordpress-seo" ) }
</Alert>
);
};

RequestFailed.propTypes = {
className: PropTypes.string,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from "react";
import PropTypes from "prop-types";
import { __, sprintf } from "@wordpress/i18n";
import { Alert, Button } from "@yoast/ui-library";
import { ArrowNarrowRightIcon } from "@heroicons/react/outline";

/**
* Display the message for a request that has reached the limit.
*
* @param {String} [upsellLink] The upsell link.
* @param {string} [className=""] The class name for the alert.
*
* @returns {React.Component} The message for limit reached.
*/
export const RequestLimitReached = ( { upsellLink, className = "" } ) => {
return (
<Alert variant="warning" className={ className }>
<div className="yst-flex yst-flex-col yst-items-start">
{ sprintf(
/* translators: %s : Expands to "Semrush". */
__( "You've reached your request limit for today. Check back tomorrow or upgrade your plan over at %s.", "wordpress-seo" ),
"Semrush",
) }

{ upsellLink && <Button
variant="upsell"
className="yst-mt-3 yst-gap-1.5"
as="a"
href={ upsellLink }
target="_blank"
>
{
sprintf(
/* translators: %s : Expands to "Semrush". */
__( "Upgrade your %s plan", "wordpress-seo" ),
"Semrush",
)
}
<ArrowNarrowRightIcon className="yst-w-4 yst-h-4 yst-text-amber-900" />

</Button> }
</div>
</Alert>
);
};

RequestLimitReached.propTypes = {
upsellLink: PropTypes.string,
className: PropTypes.string,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { MaxRelatedKeyphrases } from "./MaxRelatedKeyphrases";
export { RequestFailed } from "./RequestFailed";
export { RequestEmpty } from "./RequestEmpty";
export { RequestLimitReached } from "./RequestLimitReached";
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The alert to display to the user related to the related keyphrases suggestions request or action.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as component } from "./component.md";
Loading