Skip to content

Commit

Permalink
Merge pull request #21646 from Yoast/271-add-problem-card-to-alert-ce…
Browse files Browse the repository at this point in the history
…nter

271 add problem and notification components to alert center
  • Loading branch information
vraja-pro authored Sep 23, 2024
2 parents 7be81ca + dc7396f commit 5723473
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 7 deletions.
38 changes: 38 additions & 0 deletions packages/js/src/dashboard/components/alert-title.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useContext } from "@wordpress/element";
import PropTypes from "prop-types";
import classNames from "classnames";
import { ExclamationCircleIcon } from "@heroicons/react/outline";
import { Title } from "@yoast/ui-library";
import { AlertsContext } from "../contexts/alerts-context";

/**
*
* @param {string} title The title of alerts.
* @param {number} counts The count of the alerts.
* @param {JSX.Node} children The children.
*
* @returns {JSX.Element} The alert title element.
*/
export const AlertTitle = ( {
title,
counts = 0,
children = null,
} ) => {
const { Icon = ExclamationCircleIcon, iconClass = "" } = useContext( AlertsContext );

return (
<div>
<div className="yst-flex yst-justify-between yst-gap-2 yst-items-center">
<Icon className={ classNames( "yst-w-6 yst-h-6", iconClass ) } />
<Title className="yst-grow" as="h2" size="2">{ title } { `(${ counts })` }</Title>
</div>
{ children }
</div>
);
};

AlertTitle.propTypes = {
title: PropTypes.string,
counts: PropTypes.number,
children: PropTypes.node,
};
55 changes: 55 additions & 0 deletions packages/js/src/dashboard/components/alerts-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { useContext } from "@wordpress/element";
import PropTypes from "prop-types";
import { Button } from "@yoast/ui-library";
import { EyeOffIcon, EyeIcon } from "@heroicons/react/outline";
import classNames from "classnames";
import { AlertsContext } from "../contexts/alerts-context";

/**
* @param {string} className The class name.
* @param {Object[]} items The list of items.
* @param {boolean} hidden Whether the items are hidden or not.
*
* @returns {JSX.Element} The list component.
*/
export const AlertsList = ( { className = "", items = [], hidden = false } ) => {
const { bulletClass = "" } = useContext( AlertsContext );

const Eye = hidden ? EyeIcon : EyeOffIcon;

if ( items.length === 0 ) {
return null;
}

return (
<ul className={ className }>
{ items.map( ( item, index ) => (
<li key={ index } className="yst-border-b yst-border-slate-200 last:yst-border-b-0 yst-py-6 first:yst-pt-0 last:yst-pb-0">
<div className="yst-flex yst-justify-between yst-gap-5 yst-items-start">
<div className={ classNames( "yst-mt-1", hidden && "yst-opacity-50" ) }>
<svg width="11" height="11" className={ bulletClass }>
<circle cx="5.5" cy="5.5" r="5.5" />
</svg>
</div>
<p
className={ classNames(
"yst-text-sm yst-text-slate-600 yst-grow",
hidden && "yst-opacity-50" ) }
>{ item.message }</p>
<Button variant="secondary" size="small" className="yst-self-center yst-h-8">
<Eye className="yst-w-4 yst-h-4 yst-text-neutral-700" />
</Button>
</div>
</li>
) ) }
</ul>
);
};

AlertsList.propTypes = {
className: PropTypes.string,
items: PropTypes.arrayOf( PropTypes.shape( {
message: PropTypes.string,
} ) ),
hidden: PropTypes.bool,
};
36 changes: 36 additions & 0 deletions packages/js/src/dashboard/components/collapsible.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import PropTypes from "prop-types";
import { Disclosure } from "@headlessui/react";
import { ChevronDownIcon } from "@heroicons/react/outline";
import classNames from "classnames";

/**
* @param {string} label The label of the collapsible.
* @param {ReactNode} children The children of the collapsible.
* @returns {JSX.Element} The hidden alerts collapsible component.
*/
export const Collapsible = ( { label, children } ) => {
return (
<Disclosure>
{ ( { open } ) => (
<div className="yst-shadow-sm yst-border-slate-300 yst-rounded-md yst-border">
<Disclosure.Button className="yst-w-full yst-flex yst-justify-between yst-py-4 yst-pr-4 yst-pl-6 yst-items-center">
<div className="yst-font-medium">{ label }</div>
<ChevronDownIcon
className={ classNames( "yst-h-5 yst-w-5 flex-shrink-0 yst-text-slate-400",
open ? "yst-rotate-180" : ""
) }
/>
</Disclosure.Button>
<Disclosure.Panel className="yst-px-6">
{ children }
</Disclosure.Panel>
</div>
) }
</Disclosure>
);
};

Collapsible.propTypes = {
label: PropTypes.string,
children: PropTypes.node,
};
3 changes: 3 additions & 0 deletions packages/js/src/dashboard/components/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
export { default as RouteLayout } from "./route-layout";
export { Notifications } from "./notifications";
export { Problems } from "./problems";
export { AlertsList } from "./alerts-list";
export { AlertTitle } from "./alert-title";
export { Collapsible } from "./collapsible";
56 changes: 53 additions & 3 deletions packages/js/src/dashboard/components/notifications.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,62 @@
import { Paper, Title } from "@yoast/ui-library";
import { __, _n } from "@wordpress/i18n";
import { BellIcon } from "@heroicons/react/outline";
import { Paper } from "@yoast/ui-library";
import { AlertsList } from "./alerts-list";
import { AlertTitle } from "./alert-title";
import { Collapsible } from "./collapsible";
import { AlertsContext } from "../contexts/alerts-context";

/**
* @returns {JSX.Element} The notifications component.
*/
export const Notifications = () => {
const notificationsAlertsList = [
{
message: "Your site is not connected to your MyYoast account. Connect your site to get access to all the features.",
},
{
message: "You have a new notification from Yoast SEO. Click here to read it.",
},
];

const hiddenNotificationsAlertsList = [
{
message: "Your site is not connected to your MyYoast account. Connect your site to get access to all the features.",
},
{
message: "You have a new notification from Yoast SEO. Click here to read it.",
},
];

const hiddenNotifications = hiddenNotificationsAlertsList.length;

const hiddenNotificationLabel = _n(
"hidden notification",
"hidden notifications",
hiddenNotifications,
"wordpress-seo"
);

const notificationsTheme = {
Icon: BellIcon,
bulletClass: "yst-fill-blue-500",
iconClass: "yst-text-blue-500",
};

return (
<Paper className="yst-p-8">
<Title>Notifications</Title>
<Paper>
<Paper.Content className="yst-flex yst-flex-col yst-gap-y-6">
<AlertsContext.Provider value={ notificationsTheme }>
<AlertTitle counts={ 2 } title={ __( "Notifications", "wordpress-seo" ) } />
<AlertsList items={ notificationsAlertsList } hidden={ false } />

{ hiddenNotifications > 0 && (
<Collapsible label={ `${ hiddenNotifications } ${ hiddenNotificationLabel }` }>
<AlertsList className="yst-pb-6" items={ hiddenNotificationsAlertsList } hidden={ true } />
</Collapsible>
) }
</AlertsContext.Provider>
</Paper.Content>
</Paper>
);
};
58 changes: 55 additions & 3 deletions packages/js/src/dashboard/components/problems.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,64 @@
import { Paper, Title } from "@yoast/ui-library";
import { __, _n } from "@wordpress/i18n";
import { ExclamationCircleIcon } from "@heroicons/react/outline";
import { Paper } from "@yoast/ui-library";
import { AlertsList } from "./alerts-list";
import { AlertTitle } from "./alert-title";
import { Collapsible } from "./collapsible";
import { AlertsContext } from "../contexts/alerts-context";

/**
* @returns {JSX.Element} The problems component.
*/
export const Problems = () => {
const problemsList = [
{
message: "Huge SEO issue: You're blocking access to robots. If you want search engines to show this site in their results, you must go to your Reading Settings and uncheck the box for Search Engine Visibility. I don't want this site to show in the search results.",
},
{
message: "You still have the default WordPress tagline, even an empty one is probably better. You can fix this in the customizer.",
},
];

const hiddenProblemsList = [
{
message: "Huge SEO issue: You're blocking access to robots. If you want search engines to show this site in their results, you must go to your Reading Settings and uncheck the box for Search Engine Visibility. I don't want this site to show in the search results.",
},
{
message: "You still have the default WordPress tagline, even an empty one is probably better. You can fix this in the customizer.",
},
];

const hiddenProblems = hiddenProblemsList.length;

const hiddenProblemsLabel = _n(
"hidden problem",
"hidden problems",
hiddenProblems,
"wordpress-seo"
);

const problemsTheme = {
Icon: ExclamationCircleIcon,
bulletClass: "yst-fill-red-500",
iconClass: "yst-text-red-500",
};

return (
<Paper className="yst-p-8">
<Title>Problems</Title>
<Paper>
<Paper.Content className="yst-flex yst-flex-col yst-gap-y-6">
<AlertsContext.Provider value={ problemsTheme }>
<AlertTitle title={ __( "Problems", "wordpress-seo" ) } counts={ 2 }>
<p className="yst-mt-2 yst-text-sm">{ __( "We have detected the following issues that affect the SEO of your site.", "wordpress-seo" ) }</p>
</AlertTitle>
<AlertsList items={ problemsList } hidden={ false } />

{ hiddenProblems > 0 && (
<Collapsible label={ `${ hiddenProblems } ${ hiddenProblemsLabel }` }>
<AlertsList className="yst-pb-6" items={ hiddenProblemsList } hidden={ true } />
</Collapsible>
) }
</AlertsContext.Provider>
</Paper.Content>
</Paper>
);
};
6 changes: 6 additions & 0 deletions packages/js/src/dashboard/contexts/alerts-context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { createContext } from "@wordpress/element";

/**
* The context for the alerts.
*/
export const AlertsContext = createContext( { Icon: null, bulletClass: "", iconClass: "" } );
2 changes: 1 addition & 1 deletion packages/js/src/dashboard/routes/alert-center.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const AlertCenter = () => {
</div>
</header>
</Paper>
<div className="yst-grid lg:yst-grid-cols-2 yst-gap-8 yst-my-8">
<div className="yst-grid lg:yst-grid-cols-2 yst-gap-8 yst-my-8 yst-items-start">
<Problems />
<Notifications />
</div>
Expand Down

0 comments on commit 5723473

Please sign in to comment.