-
Notifications
You must be signed in to change notification settings - Fork 902
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #21417 from Yoast/ai-fix-assesment-upsell-introduc…
…tion-model Ai fix assessment upsell introduction modal
- Loading branch information
Showing
12 changed files
with
501 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
packages/js/src/ai-assessment-fixes/components/modal-content.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* eslint-disable complexity */ | ||
import { useDispatch, useSelect } from "@wordpress/data"; | ||
import { useMemo } from "@wordpress/element"; | ||
import { AiFixAssessmentsUpsell } from "../../shared-admin/components"; | ||
import { __, sprintf } from "@wordpress/i18n"; | ||
|
||
const STORE = "yoast-seo/editor"; | ||
|
||
/** | ||
* @returns {JSX.Element} The element. | ||
*/ | ||
export const ModalContent = () => { | ||
const learnMoreLink = useSelect( select => select( STORE ).selectLink( "https://yoa.st/ai-fix-assessments-learn-more" ), [] ); | ||
const upsellLinkPremium = useSelect( select => select( STORE ).selectLink( "https://yoa.st/ai-fix-assessments-upsell" ), [] ); | ||
|
||
const postModalprops = { | ||
upsellLink: upsellLinkPremium, | ||
title: __( "Fix assessments with AI!", "wordpress-seo" ), | ||
upsellLabel: sprintf( | ||
/* translators: %1$s expands to Yoast SEO Premium. */ | ||
__( "Unlock with %1$s", "wordpress-seo" ), | ||
"Yoast SEO Premium" | ||
), | ||
}; | ||
|
||
const imageLink = useSelect( select => select( STORE ).selectImageLink( "ai-generator-preview.png" ), [] ); | ||
const thumbnail = useMemo( () => ( { | ||
src: imageLink, | ||
width: "432", | ||
height: "244", | ||
} ), [ imageLink ] ); | ||
|
||
const value = useSelect( select => select( STORE ).selectWistiaEmbedPermissionValue(), [] ); | ||
const status = useSelect( select => select( STORE ).selectWistiaEmbedPermissionStatus(), [] ); | ||
const { setWistiaEmbedPermission: set } = useDispatch( STORE ); | ||
const wistiaEmbedPermission = useMemo( () => ( { value, status, set } ), [ value, status, set ] ); | ||
|
||
|
||
return ( | ||
<AiFixAssessmentsUpsell | ||
learnMoreLink={ learnMoreLink } | ||
thumbnail={ thumbnail } | ||
wistiaEmbedPermission={ wistiaEmbedPermission } | ||
{ ...postModalprops } | ||
/> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
144 changes: 144 additions & 0 deletions
144
packages/js/src/shared-admin/components/ai-fix-assessments-upsell.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
import { LockOpenIcon } from "@heroicons/react/outline"; | ||
import { ArrowNarrowRightIcon } from "@heroicons/react/solid"; | ||
import { createInterpolateElement } from "@wordpress/element"; | ||
import { __, sprintf } from "@wordpress/i18n"; | ||
import { Badge, Button, useModalContext } from "@yoast/ui-library"; | ||
import PropTypes from "prop-types"; | ||
import { OutboundLink, VideoFlow } from "."; | ||
|
||
/** | ||
* @param {string} learnMoreLink The learn more link. | ||
* @param {Object} thumbnail The thumbnail: img props. | ||
* @param {Object} wistiaEmbedPermission The value, status and set for the Wistia embed permission. | ||
* @param {string} upsellLink The upsell link. | ||
* @param {string} title The title. | ||
* @param {string} upsellLabel The upsell label. | ||
* @param {string} newToText The new to text. | ||
* @param {string|JSX.Element } bundleNote The bundle note. | ||
* @returns {JSX.Element} The element. | ||
*/ | ||
export const AiFixAssessmentsUpsell = ( { | ||
learnMoreLink, | ||
thumbnail, | ||
wistiaEmbedPermission, | ||
upsellLink, | ||
title, | ||
upsellLabel, | ||
newToText, | ||
bundleNote, | ||
} ) => { | ||
const { onClose, initialFocus } = useModalContext(); | ||
|
||
const learnMoreLinkStructure = { | ||
// eslint-disable-next-line jsx-a11y/anchor-has-content | ||
a: <OutboundLink | ||
href={ learnMoreLink } | ||
className="yst-inline-flex yst-items-center yst-gap-1 yst-no-underline yst-font-medium" | ||
variant="primary" | ||
/>, | ||
ArrowNarrowRightIcon: <ArrowNarrowRightIcon className="yst-w-4 yst-h-4 rtl:yst-rotate-180" />, | ||
}; | ||
|
||
return ( | ||
<div className="yst-flex yst-flex-col yst-items-center yst-p-10"> | ||
<div className="yst-relative yst-w-full"> | ||
<VideoFlow | ||
videoId="vmrahpfjxp" | ||
thumbnail={ thumbnail } | ||
wistiaEmbedPermission={ wistiaEmbedPermission } | ||
/> | ||
<Badge className="yst-absolute yst-top-0 yst-right-2 yst-mt-2 yst-ml-2" variant="info">Beta</Badge> | ||
</div> | ||
<div className="yst-mt-6 yst-text-xs yst-font-medium"> | ||
<span className="yst-introduction-modal-uppercase"> | ||
{ newToText } | ||
</span> | ||
</div> | ||
<div className="yst-mt-4 yst-mx-1.5 yst-text-center"> | ||
<h3 className="yst-text-slate-900 yst-text-lg yst-font-medium"> | ||
{ title } | ||
</h3> | ||
<div className="yst-mt-2 yst-text-slate-600 yst-text-sm"> | ||
{ createInterpolateElement( | ||
sprintf( | ||
/* translators: %1$s and %2$s are anchor tags; %3$s is the arrow icon. */ | ||
__( | ||
"Let AI fix assessments. %1$sLearn more%2$s%3$s", | ||
"wordpress-seo" | ||
), | ||
"<a>", | ||
"<ArrowNarrowRightIcon />", | ||
"</a>" | ||
), | ||
learnMoreLinkStructure | ||
) } | ||
</div> | ||
</div> | ||
<div className="yst-w-full yst-flex yst-mt-10"> | ||
<Button | ||
as="a" | ||
className="yst-grow" | ||
size="extra-large" | ||
variant="upsell" | ||
href={ upsellLink } | ||
target="_blank" | ||
ref={ initialFocus } | ||
> | ||
<LockOpenIcon className="yst--ml-1 yst-mr-2 yst-h-5 yst-w-5" /> | ||
{ upsellLabel } | ||
<span className="yst-sr-only"> | ||
{ | ||
/* translators: Hidden accessibility text. */ | ||
__( "(Opens in a new browser tab)", "wordpress-seo" ) | ||
} | ||
</span> | ||
</Button> | ||
</div> | ||
{ bundleNote } | ||
<Button | ||
as="a" | ||
className="yst-mt-4" | ||
variant="tertiary" | ||
onClick={ onClose } | ||
> | ||
{ __( "Close", "wordpress-seo" ) } | ||
</Button> | ||
</div> | ||
); | ||
}; | ||
AiFixAssessmentsUpsell.propTypes = { | ||
learnMoreLink: PropTypes.string.isRequired, | ||
upsellLink: PropTypes.string.isRequired, | ||
thumbnail: PropTypes.shape( { | ||
src: PropTypes.string.isRequired, | ||
width: PropTypes.string, | ||
height: PropTypes.string, | ||
} ).isRequired, | ||
wistiaEmbedPermission: PropTypes.shape( { | ||
value: PropTypes.bool.isRequired, | ||
status: PropTypes.string.isRequired, | ||
set: PropTypes.func.isRequired, | ||
} ).isRequired, | ||
title: PropTypes.string, | ||
upsellLabel: PropTypes.string, | ||
newToText: PropTypes.string, | ||
bundleNote: PropTypes.oneOfType( [ | ||
PropTypes.string, | ||
PropTypes.element, | ||
] ), | ||
}; | ||
|
||
AiFixAssessmentsUpsell.defaultProps = { | ||
title: __( "Use AI to fix assessments!", "wordpress-seo" ), | ||
upsellLabel: sprintf( | ||
/* translators: %1$s expands to Yoast SEO Premium. */ | ||
__( "Unlock with %1$s", "wordpress-seo" ), | ||
"Yoast SEO Premium" | ||
), | ||
newToText: sprintf( | ||
/* translators: %1$s expands to Yoast SEO Premium. */ | ||
__( "New in %1$s", "wordpress-seo" ), | ||
"Yoast SEO Premium" | ||
), | ||
bundleNote: "", | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
116 changes: 116 additions & 0 deletions
116
...ges/js/tests/shared-admin/components/__snapshots__/ai-fix-assessments-upsell.test.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`AiFixAssessmentsUpsell renders the component correctly 1`] = ` | ||
<div> | ||
<div | ||
class="yst-flex yst-flex-col yst-items-center yst-p-10" | ||
> | ||
<div | ||
class="yst-relative yst-w-full" | ||
> | ||
<div | ||
class="yst-relative yst-w-full yst-h-0 yst-pt-[56.25%] yst-overflow-hidden yst-rounded-md yst-drop-shadow-md yst-bg-white" | ||
> | ||
<div | ||
class="yst-absolute yst-w-full yst-h-full yst-top-0 yst-left-0" | ||
> | ||
<div | ||
class="wistia_embed wistia_async_vmrahpfjxp videoFoam=true" | ||
/> | ||
</div> | ||
</div> | ||
<span | ||
class="yst-badge yst-badge--info yst-absolute yst-top-0 yst-right-2 yst-mt-2 yst-ml-2" | ||
> | ||
Beta | ||
</span> | ||
</div> | ||
<div | ||
class="yst-mt-6 yst-text-xs yst-font-medium" | ||
> | ||
<span | ||
class="yst-introduction-modal-uppercase" | ||
> | ||
Test New To Text | ||
</span> | ||
</div> | ||
<div | ||
class="yst-mt-4 yst-mx-1.5 yst-text-center" | ||
> | ||
<h3 | ||
class="yst-text-slate-900 yst-text-lg yst-font-medium" | ||
> | ||
Test Title | ||
</h3> | ||
<div | ||
class="yst-mt-2 yst-text-slate-600 yst-text-sm" | ||
> | ||
Let AI fix assessments. | ||
<a | ||
class="yst-link yst-link--primary yst-inline-flex yst-items-center yst-gap-1 yst-no-underline yst-font-medium" | ||
href="https://example.com/learn-more" | ||
rel="noopener noreferrer" | ||
target="_blank" | ||
> | ||
Learn more | ||
<svg | ||
aria-hidden="true" | ||
class="yst-w-4 yst-h-4 rtl:yst-rotate-180" | ||
fill="currentColor" | ||
viewBox="0 0 20 20" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<path | ||
clip-rule="evenodd" | ||
d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z" | ||
fill-rule="evenodd" | ||
/> | ||
</svg> | ||
<span | ||
class="yst-sr-only" | ||
> | ||
(Opens in a new browser tab) | ||
</span> | ||
</a> | ||
</div> | ||
</div> | ||
<div | ||
class="yst-w-full yst-flex yst-mt-10" | ||
> | ||
<a | ||
class="yst-button yst-button--upsell yst-button--extra-large yst-grow" | ||
href="https://example.com/upsell" | ||
target="_blank" | ||
> | ||
<svg | ||
aria-hidden="true" | ||
class="yst--ml-1 yst-mr-2 yst-h-5 yst-w-5" | ||
fill="none" | ||
stroke="currentColor" | ||
stroke-width="2" | ||
viewBox="0 0 24 24" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<path | ||
d="M8 11V7a4 4 0 118 0m-4 8v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2z" | ||
stroke-linecap="round" | ||
stroke-linejoin="round" | ||
/> | ||
</svg> | ||
Test Upsell Label | ||
<span | ||
class="yst-sr-only" | ||
> | ||
(Opens in a new browser tab) | ||
</span> | ||
</a> | ||
</div> | ||
Test Bundle Note | ||
<a | ||
class="yst-button yst-button--tertiary yst-mt-4" | ||
> | ||
Close | ||
</a> | ||
</div> | ||
</div> | ||
`; |
28 changes: 28 additions & 0 deletions
28
packages/js/tests/shared-admin/components/ai-fix-assessments-upsell.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { render } from "../../test-utils"; | ||
import { AiFixAssessmentsUpsell } from "../../../src/shared-admin/components/ai-fix-assessments-upsell"; | ||
|
||
describe( "AiFixAssessmentsUpsell", () => { | ||
const props = { | ||
learnMoreLink: "https://example.com/learn-more", | ||
thumbnail: { | ||
src: "thumbnail.jpg", | ||
width: "100", | ||
height: "100", | ||
}, | ||
wistiaEmbedPermission: { | ||
value: true, | ||
status: "granted", | ||
set: jest.fn(), | ||
}, | ||
upsellLink: "https://example.com/upsell", | ||
title: "Test Title", | ||
upsellLabel: "Test Upsell Label", | ||
newToText: "Test New To Text", | ||
bundleNote: "Test Bundle Note", | ||
}; | ||
|
||
it( "renders the component correctly", () => { | ||
const { container } = render( <AiFixAssessmentsUpsell { ...props } /> ); | ||
expect( container ).toMatchSnapshot(); | ||
} ); | ||
} ); |
Oops, something went wrong.