summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard')
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/button/index.jsx52
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/card/compact.jsx23
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/card/index.jsx141
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/form-toggle/compact.jsx26
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/form-toggle/index.jsx126
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/index.jsx55
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/store/actions.js61
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/store/reducer.js22
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/store/selectors.js5
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/notice/index.jsx136
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/notice/notice-action.jsx48
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/actions/index.js14
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/actions/jetpack-settings.js73
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/actions/site-plan.js16
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/controls.js55
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/index.js18
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/index.js23
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/jetpack-settings.js22
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/site-data.js5
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/site-plan.js18
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/user-data.js5
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/resolvers.js48
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/index.js18
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/jetpack-settings.js10
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/site-data.js12
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/site-plan.js12
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/user-data.js5
27 files changed, 1049 insertions, 0 deletions
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/button/index.jsx b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/button/index.jsx
new file mode 100644
index 00000000..d945554f
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/button/index.jsx
@@ -0,0 +1,52 @@
+/**
+ * External dependencies
+ */
+import PropTypes from 'prop-types';
+import React from 'react';
+import classNames from 'classnames';
+import { noop } from 'lodash';
+
+/**
+ * Internal dependencies
+ */
+import './style.scss';
+
+export default class Button extends React.Component {
+ static displayName = 'Button';
+
+ static propTypes = {
+ disabled: PropTypes.bool,
+ compact: PropTypes.bool,
+ primary: PropTypes.bool,
+ scary: PropTypes.bool,
+ type: PropTypes.string,
+ href: PropTypes.string,
+ onClick: PropTypes.func,
+ borderless: PropTypes.bool,
+ className: PropTypes.string,
+ };
+
+ static defaultProps = {
+ disabled: false,
+ type: 'button',
+ onClick: noop,
+ borderless: false,
+ };
+
+ render() {
+ const element = this.props.href ? 'a' : 'button';
+ const { primary, compact, scary, borderless, className, ...props } = this.props;
+
+ const buttonClasses = classNames( {
+ 'dops-button': true,
+ 'is-compact': compact,
+ 'is-primary': primary,
+ 'is-scary': scary,
+ 'is-borderless': borderless,
+ } );
+
+ props.className = classNames( className, buttonClasses );
+
+ return React.createElement( element, props, this.props.children );
+ }
+}
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/card/compact.jsx b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/card/compact.jsx
new file mode 100644
index 00000000..7bfacab4
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/card/compact.jsx
@@ -0,0 +1,23 @@
+/**
+ * External dependencies
+ */
+import React from 'react';
+import { assign } from 'lodash';
+import classnames from 'classnames';
+
+/**
+ * Internal dependencies
+ */
+import Card from 'components/card';
+
+export default class CompactCard extends React.Component {
+ static displayName = 'CompactCard';
+
+ render() {
+ const props = assign( {}, this.props, {
+ className: classnames( this.props.className, 'is-compact' ),
+ } );
+
+ return <Card { ...props }>{ this.props.children }</Card>;
+ }
+}
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/card/index.jsx b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/card/index.jsx
new file mode 100644
index 00000000..e8dbf9e1
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/card/index.jsx
@@ -0,0 +1,141 @@
+/**
+ * External dependencies
+ */
+import PropTypes from 'prop-types';
+import React from 'react';
+import classnames from 'classnames';
+import { assign, omit } from 'lodash';
+
+/**
+ * Internal dependencies
+ */
+// TODO change to our own gridicon component, when instant search is migrated.
+import Gridicon from 'gridicons';
+
+import './style.scss';
+
+class CardSection extends React.Component {
+ static propTypes = {
+ title: PropTypes.any,
+ vertical: PropTypes.any,
+ style: PropTypes.object,
+ className: PropTypes.string,
+ device: PropTypes.oneOf( [ 'desktop', 'tablet', 'phone' ] ),
+ };
+
+ static defaultProps = { vertical: null };
+
+ render() {
+ return (
+ <div
+ className={ classnames( 'dops-card-section', this.props.className ) }
+ style={ this.props.style }
+ >
+ { this.props.title ? this._renderWithTitle() : this.props.children }
+ </div>
+ );
+ }
+
+ _renderWithTitle = () => {
+ const orientation = this.props.vertical ? 'vertical' : 'horizontal';
+ const wrapperClassName = 'dops-card-section-orient-' + orientation;
+
+ return (
+ <div className={ wrapperClassName }>
+ <h4 ref="label" className="dops-card-section-label">
+ { this.props.title }
+ </h4>
+ <div ref="content" className="dops-card-section-content">
+ { this.props.children }
+ </div>
+ </div>
+ );
+ };
+}
+
+class CardFooter extends React.Component {
+ render() {
+ return <div className="dops-card-footer">{ this.props.children }</div>;
+ }
+}
+
+class Card extends React.Component {
+ static propTypes = {
+ meta: PropTypes.any,
+ icon: PropTypes.string,
+ iconLabel: PropTypes.any,
+ iconColor: PropTypes.string,
+ style: PropTypes.object,
+ className: PropTypes.string,
+ href: PropTypes.string,
+ onClick: PropTypes.func,
+ title: PropTypes.string,
+ tagName: PropTypes.string,
+ target: PropTypes.string,
+ compact: PropTypes.bool,
+ children: PropTypes.node,
+ };
+
+ static defaultProps = {
+ iconColor: '#787878',
+ className: '',
+ tagName: 'div',
+ onClick: () => {},
+ };
+
+ render() {
+ const className = classnames( 'dops-card', this.props.className, {
+ 'is-card-link': !! this.props.href,
+ 'is-compact': this.props.compact,
+ } );
+
+ const omitProps = [ 'compact', 'tagName', 'meta', 'iconColor' ];
+
+ let linkIndicator;
+ if ( this.props.href ) {
+ linkIndicator = (
+ <Gridicon
+ className="dops-card__link-indicator"
+ icon={ this.props.target ? 'external' : 'chevron-right' }
+ />
+ );
+ } else {
+ omitProps.push( 'href', 'target' );
+ }
+
+ let fancyTitle;
+ if ( this.props.title ) {
+ fancyTitle = (
+ <h2 className="dops-card-title">
+ { this.props.title }
+ { this.props.meta && <span className="dops-card-meta">{ this.props.meta }</span> }
+ { ( this.props.icon || this.props.iconLabel ) && this._renderIcon() }
+ </h2>
+ );
+ }
+
+ return React.createElement(
+ this.props.href ? 'a' : this.props.tagName,
+ assign( omit( this.props, omitProps ), { className } ),
+ linkIndicator,
+ fancyTitle,
+ this.props.children
+ );
+ }
+
+ _renderIcon = () => {
+ return (
+ <span className="dops-card-icon" style={ { color: this.props.iconColor } }>
+ { this.props.icon && (
+ <Gridicon icon={ this.props.icon } style={ { backgroundColor: this.props.iconColor } } />
+ ) }
+ { this.props.iconLabel }
+ </span>
+ );
+ };
+}
+
+Card.Section = CardSection;
+Card.Footer = CardFooter;
+
+export default Card;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/form-toggle/compact.jsx b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/form-toggle/compact.jsx
new file mode 100644
index 00000000..72341c8e
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/form-toggle/compact.jsx
@@ -0,0 +1,26 @@
+/**
+ * External dependencies
+ */
+import React from 'react';
+import classNames from 'classnames';
+import { omit } from 'lodash';
+
+/**
+ * Internal dependencies
+ */
+import Toggle from 'components/form-toggle';
+
+export default class CompactFormToggle extends React.Component {
+ static displayName = 'CompactFormToggle';
+
+ render() {
+ return (
+ <Toggle
+ { ...omit( this.props, 'className' ) }
+ className={ classNames( this.props.className, 'is-compact' ) }
+ >
+ { this.props.children }
+ </Toggle>
+ );
+ }
+}
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/form-toggle/index.jsx b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/form-toggle/index.jsx
new file mode 100644
index 00000000..31739fc8
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/form-toggle/index.jsx
@@ -0,0 +1,126 @@
+/* eslint-disable jsx-a11y/click-events-have-key-events */
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+
+/**
+ * External dependencies
+ */
+import PropTypes from 'prop-types';
+import React, { Component, Fragment } from 'react';
+import classNames from 'classnames';
+
+import './style.scss';
+
+export default class FormToggle extends Component {
+ static propTypes = {
+ onChange: PropTypes.func,
+ onKeyDown: PropTypes.func,
+ checked: PropTypes.bool,
+ disabled: PropTypes.bool,
+ id: PropTypes.string,
+ className: PropTypes.string,
+ toggling: PropTypes.bool,
+ 'aria-label': PropTypes.string,
+ children: PropTypes.node,
+ disabledReason: PropTypes.node,
+ switchClassNames: PropTypes.string,
+ labelClassNames: PropTypes.string,
+ };
+
+ static defaultProps = {
+ checked: false,
+ disabled: false,
+ onKeyDown: () => {},
+ onChange: () => {},
+ disabledReason: '',
+ };
+
+ state = {};
+
+ static idNum = 0;
+
+ constructor() {
+ super( ...arguments );
+
+ this.onKeyDown = this.onKeyDown.bind( this );
+ this.onClick = this.onClick.bind( this );
+ this.onLabelClick = this.onLabelClick.bind( this );
+ }
+
+ UNSAFE_componentWillMount() {
+ this.id = this.constructor.idNum++;
+ }
+
+ onKeyDown( event ) {
+ if ( this.props.disabled ) {
+ return;
+ }
+
+ if ( event.key === 'Enter' || event.key === ' ' ) {
+ event.preventDefault();
+ this.props.onChange();
+ }
+
+ this.props.onKeyDown( event );
+ }
+
+ onClick() {
+ if ( ! this.props.disabled ) {
+ this.props.onChange();
+ }
+ }
+
+ onLabelClick( event ) {
+ if ( this.props.disabled ) {
+ return;
+ }
+
+ const nodeName = event.target.nodeName.toLowerCase();
+ if ( nodeName !== 'a' && nodeName !== 'input' && nodeName !== 'select' ) {
+ event.preventDefault();
+ this.props.onChange();
+ }
+ }
+
+ render() {
+ const id = this.props.id || 'toggle-' + this.id;
+ const toggleClasses = classNames( 'form-toggle', this.props.className, {
+ 'is-toggling': this.props.toggling,
+ } );
+
+ return (
+ <Fragment>
+ <input
+ className={ toggleClasses }
+ type="checkbox"
+ checked={ this.props.checked }
+ readOnly={ true }
+ disabled={ this.props.disabled }
+ />
+
+ <span
+ className={ classNames( 'form-toggle__switch', this.props.switchClassNames ) }
+ disabled={ this.props.disabled }
+ id={ id }
+ onClick={ this.onClick }
+ onKeyDown={ this.onKeyDown }
+ role="checkbox"
+ aria-checked={ this.props.checked }
+ aria-label={ this.props[ 'aria-label' ] }
+ tabIndex={ this.props.disabled ? -1 : 0 }
+ ref="toggleSwitch"
+ />
+ <label
+ className={ classNames( 'form-toggle__label', this.props.labelClassNames ) }
+ htmlFor={ id }
+ >
+ <span
+ className={ classNames( 'form-toggle__label-content', this.props.labelClassNames ) }
+ onClick={ this.onLabelClick }
+ >
+ { this.props.children }
+ </span>
+ </label>
+ </Fragment>
+ );
+ }
+}
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/index.jsx b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/index.jsx
new file mode 100644
index 00000000..c0df631a
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/index.jsx
@@ -0,0 +1,55 @@
+/**
+ * External Dependencies
+ */
+import React from 'react';
+
+/**
+ * Internal Dependencies
+ */
+import SimpleNotice from 'components/notice/index.jsx';
+import NoticeAction from 'components/notice/notice-action';
+
+import './style.scss';
+
+/**
+ * NoticesList component
+ *
+ * @param {*} props - Props
+ * @returns {React.Component} - NoticesList component
+ */
+export default function NoticesList(
+ props = { handleLocalNoticeDismissClick: null, notices: Object.freeze( [] ) }
+) {
+ const noticesList = props.notices.map( function ( notice ) {
+ const onDismissClick = theNotice => () => {
+ theNotice && props.handleLocalNoticeDismissClick( theNotice.id );
+ };
+ return (
+ <SimpleNotice
+ key={ 'notice-' + notice.id }
+ status={ notice.status }
+ duration={ notice.duration || null }
+ text={ notice.text }
+ isCompact={ notice.isCompact }
+ onDismissClick={ onDismissClick( notice ) }
+ showDismiss={ notice.showDismiss }
+ >
+ { notice.button && (
+ <NoticeAction href={ notice.href } onClick={ onDismissClick( notice ) }>
+ { notice.button }
+ </NoticeAction>
+ ) }
+ </SimpleNotice>
+ );
+ } );
+
+ if ( ! noticesList.length ) {
+ return null;
+ }
+
+ return (
+ <div id={ props.id } className="global-notices">
+ { noticesList }
+ </div>
+ );
+}
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/store/actions.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/store/actions.js
new file mode 100644
index 00000000..09c739d0
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/store/actions.js
@@ -0,0 +1,61 @@
+/**
+ * External dependencies
+ */
+import { uniqueId } from 'lodash';
+import { __ } from '@wordpress/i18n';
+
+export const CREATE_NOTICE = 'CREATE_NOTICE';
+export const REMOVE_NOTICE = 'REMOVE_NOTICE';
+
+/**
+ * Create global notice
+ *
+ * @param {*} status - success, error, info or warning.
+ * @param {*} text - the text to show.
+ * @param {*} options - Options.
+ * @returns {object} - action object.
+ */
+export function createNotice( status, text, options = {} ) {
+ const notice = {
+ id: options.id || uniqueId(),
+ duration: options.duration ?? 2000,
+ showDismiss: typeof options.showDismiss === 'boolean' ? options.showDismiss : true,
+ isPersistent: options.isPersistent || false,
+ displayOnNextPage: options.displayOnNextPage || false,
+ status: status,
+ text: text,
+ };
+
+ return {
+ type: CREATE_NOTICE,
+ notice: notice,
+ };
+}
+
+/**
+ * Remove notice by ID
+ *
+ * @param {*} noticeId - noticeID.
+ * @returns {object} - action object.
+ */
+export function removeNotice( noticeId ) {
+ return { type: REMOVE_NOTICE, notice: { id: noticeId } };
+}
+
+export const successNotice = createNotice.bind( null, 'is-success' );
+export const errorNotice = createNotice.bind( null, 'is-error' );
+export const infoNotice = createNotice.bind( null, 'is-info' );
+export const warningNotice = createNotice.bind( null, 'is-warning' );
+export const updatingNotice = ( text = __( 'Updating settings…', 'jetpack-search-pkg' ) ) =>
+ createNotice( 'is-info', text, { duration: 30000, id: 'search-updating-settings' } );
+export const removeUpdatingNotice = () => removeNotice( 'search-updating-settings' );
+
+export default {
+ createNotice,
+ removeNotice,
+ successNotice,
+ errorNotice,
+ warningNotice,
+ updatingNotice,
+ removeUpdatingNotice,
+};
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/store/reducer.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/store/reducer.js
new file mode 100644
index 00000000..e0749197
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/store/reducer.js
@@ -0,0 +1,22 @@
+/**
+ * Internal dependencies
+ */
+import { CREATE_NOTICE, REMOVE_NOTICE } from './actions';
+
+const notices = ( state = { notices: [] }, action ) => {
+ switch ( action.type ) {
+ case CREATE_NOTICE:
+ return {
+ ...state,
+ notices: [ ...state.notices, action.notice ],
+ };
+ case REMOVE_NOTICE:
+ return {
+ ...state,
+ notices: state.notices.filter( notice => notice.id !== action.notice.id ),
+ };
+ }
+ return state;
+};
+
+export default notices;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/store/selectors.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/store/selectors.js
new file mode 100644
index 00000000..da2d9829
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/global-notices/store/selectors.js
@@ -0,0 +1,5 @@
+const noticeSelectors = {
+ getNotices: state => state.notices.notices ?? [],
+};
+
+export default noticeSelectors;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/notice/index.jsx b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/notice/index.jsx
new file mode 100644
index 00000000..9c1b2e88
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/notice/index.jsx
@@ -0,0 +1,136 @@
+/**
+ * External dependencies
+ */
+import PropTypes from 'prop-types';
+import React from 'react';
+import classnames from 'classnames';
+import { noop } from 'lodash';
+
+/**
+ * Internal dependencies
+ */
+// TODO change to our own gridicon component, when instant search is migrated.
+import Gridicon from 'gridicons';
+import './style.scss';
+
+export default class SimpleNotice extends React.Component {
+ static displayName = 'SimpleNotice';
+
+ static defaultProps = {
+ duration: 0,
+ status: null,
+ showDismiss: true,
+ className: '',
+ onDismissClick: noop,
+ };
+
+ static propTypes = {
+ // we should validate the allowed statuses
+ status: PropTypes.string,
+ showDismiss: PropTypes.bool,
+ isCompact: PropTypes.bool,
+ duration: PropTypes.number,
+ text: PropTypes.oneOfType( [
+ PropTypes.oneOfType( [ PropTypes.string, PropTypes.node ] ),
+ PropTypes.arrayOf( PropTypes.oneOfType( [ PropTypes.string, PropTypes.node ] ) ),
+ ] ),
+ icon: PropTypes.string,
+ onDismissClick: PropTypes.func,
+ className: PropTypes.string,
+ };
+
+ dismissTimeout = null;
+
+ componentDidMount() {
+ if ( this.props.duration > 0 ) {
+ this.dismissTimeout = setTimeout( this.props.onDismissClick, this.props.duration );
+ }
+ }
+
+ componentWillUnmount() {
+ if ( this.dismissTimeout ) {
+ clearTimeout( this.dismissTimeout );
+ }
+ }
+
+ getIcon = () => {
+ let icon;
+
+ switch ( this.props.status ) {
+ case 'is-info':
+ icon = 'info';
+ break;
+ case 'is-success':
+ icon = 'checkmark';
+ break;
+ case 'is-error':
+ icon = 'notice';
+ break;
+ case 'is-warning':
+ icon = 'notice';
+ break;
+ default:
+ icon = 'info';
+ break;
+ }
+
+ return icon;
+ };
+
+ clearText = text => {
+ if ( 'string' === typeof text ) {
+ return text.replace( /(<([^>]+)>)/gi, '' );
+ }
+ return text;
+ };
+
+ onKeyDownCallback = callback => event => {
+ if ( event.which === 13 || event.which === 32 ) {
+ callback && callback( event );
+ }
+ };
+
+ render() {
+ const {
+ children,
+ className,
+ icon,
+ isCompact,
+ onDismissClick,
+ showDismiss = ! isCompact, // by default, show on normal notices, don't show on compact ones
+ status,
+ text,
+ dismissText,
+ } = this.props;
+ const classes = classnames( 'dops-notice', status, className, {
+ 'is-compact': isCompact,
+ 'is-dismissable': showDismiss,
+ } );
+
+ return (
+ <div className={ classes }>
+ <span className="dops-notice__icon-wrapper">
+ <Gridicon className="dops-notice__icon" icon={ icon || this.getIcon() } size={ 24 } />
+ </span>
+ <span className="dops-notice__content">
+ <span className="dops-notice__text">{ text ? this.clearText( text ) : children }</span>
+ </span>
+ { text ? children : null }
+ { showDismiss && (
+ <span
+ role="button"
+ onKeyDown={ this.onKeyDownCallback( onDismissClick ) }
+ tabIndex="0"
+ className="dops-notice__dismiss"
+ onClick={ onDismissClick }
+ >
+ <Gridicon icon="cross" size={ 24 } />
+ <span className="dops-notice__screen-reader-text screen-reader-text">
+ { dismissText }
+ </span>
+ </span>
+ ) }
+ </div>
+ );
+ }
+}
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/notice/notice-action.jsx b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/notice/notice-action.jsx
new file mode 100644
index 00000000..5a3e8ebb
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/components/notice/notice-action.jsx
@@ -0,0 +1,48 @@
+/**
+ * External dependencies
+ */
+import PropTypes from 'prop-types';
+import React from 'react';
+
+/**
+ * Internal dependencies
+ */
+// TODO change to our own gridicon component, when instant search is migrated.
+import Gridicon from 'gridicons';
+
+import './style.scss';
+
+export default class NoticeAction extends React.Component {
+ static displayName = 'NoticeAction';
+
+ static propTypes = {
+ href: PropTypes.string,
+ onClick: PropTypes.func,
+ external: PropTypes.bool,
+ icon: PropTypes.string,
+ };
+
+ static defaultProps = {
+ external: false,
+ };
+
+ render() {
+ const attributes = {
+ className: 'dops-notice__action',
+ href: this.props.href,
+ onClick: this.props.onClick,
+ };
+
+ if ( this.props.external ) {
+ attributes.target = '_blank';
+ }
+
+ return (
+ <a { ...attributes }>
+ <span>{ this.props.children }</span>
+ { this.props.icon && <Gridicon icon={ this.props.icon } size={ 24 } /> }
+ { this.props.external && <Gridicon icon="external" size={ 24 } /> }
+ </a>
+ );
+ }
+}
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/actions/index.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/actions/index.js
new file mode 100644
index 00000000..3b831225
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/actions/index.js
@@ -0,0 +1,14 @@
+/**
+ * Internal dependencies
+ */
+import siteSettingActions from './jetpack-settings';
+import sitePlanActions from './site-plan';
+import noticeActions from 'components/global-notices/store/actions';
+
+const actions = {
+ ...siteSettingActions,
+ ...sitePlanActions,
+ ...noticeActions,
+};
+
+export default actions;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/actions/jetpack-settings.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/actions/jetpack-settings.js
new file mode 100644
index 00000000..acf807a9
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/actions/jetpack-settings.js
@@ -0,0 +1,73 @@
+/**
+ * Internal dependencies
+ */
+import {
+ fetchJetpackSettings,
+ updateJetpackSettings as updateJetpackSettingsControl,
+} from '../controls';
+import {
+ removeUpdatingNotice,
+ updatingNotice,
+ errorNotice,
+ successNotice,
+} from 'components/global-notices/store/actions';
+import { __ } from '@wordpress/i18n';
+
+export const SET_JETPACK_SETTINGS = 'SET_JETPACK_SETTINGS';
+export const TOGGLE_SEARCH_MODULE = 'TOGGLE_SEARCH_MODULE';
+
+/**
+ * Yield actions to update Search Settings
+ *
+ * @param {object} settings - settings to apply.
+ * @param {object} oldSettings - Old settings.
+ * @yields {object} - an action object.
+ * @returns {object} - an action object.
+ */
+export function* updateJetpackSettings( settings, oldSettings ) {
+ try {
+ yield updatingNotice();
+ yield setJetpackSettings( settings );
+ yield setUpdatingJetpackSettings();
+ yield updateJetpackSettingsControl( settings );
+ const updatedSettings = yield fetchJetpackSettings();
+ yield setJetpackSettings( updatedSettings );
+ return successNotice( __( 'Updated settings.', 'jetpack-search-pkg' ) );
+ } catch ( e ) {
+ yield setJetpackSettings( oldSettings );
+ return errorNotice( __( 'Error Update settings…', 'jetpack-search-pkg' ) );
+ } finally {
+ yield removeUpdatingNotice();
+ yield setUpdatingJetpackSettingsDone();
+ }
+}
+
+/**
+ * Set state updating action
+ *
+ * @returns {object} - an action object.
+ */
+export function setUpdatingJetpackSettings() {
+ return setJetpackSettings( { is_updating: true } );
+}
+
+/**
+ * Set state updating finished
+ *
+ * @returns {object} - an action object.
+ */
+export function setUpdatingJetpackSettingsDone() {
+ return setJetpackSettings( { is_updating: false } );
+}
+
+/**
+ * Set Jetpack settings action
+ *
+ * @param {object} options - Jetpack settings.
+ * @returns {object} - an action object.
+ */
+export function setJetpackSettings( options ) {
+ return { type: SET_JETPACK_SETTINGS, options };
+}
+
+export default { updateJetpackSettings, setJetpackSettings };
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/actions/site-plan.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/actions/site-plan.js
new file mode 100644
index 00000000..b59c630e
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/actions/site-plan.js
@@ -0,0 +1,16 @@
+export const SET_SEARCH_PLAN_INFO = 'SET_SEARCH_PLAN_INFO';
+
+/**
+ * Action to set plan info
+ *
+ * @param {*} options - plan info.
+ * @returns {object} - an action object.
+ */
+export function setSearchPlanInfo( options ) {
+ return {
+ type: 'SET_SEARCH_PLAN_INFO',
+ options,
+ };
+}
+
+export default { setSearchPlanInfo };
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/controls.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/controls.js
new file mode 100644
index 00000000..055f975c
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/controls.js
@@ -0,0 +1,55 @@
+/**
+ * Internal dependencies
+ */
+import restApi from '@automattic/jetpack-api';
+
+export const FETCH_JETPACK_SETTINGS = 'FETCH_JETPACK_SETTINGS';
+export const UPDATE_JETPACK_SETTINGS = 'UPDATE_JETPACK_SETTINGS';
+export const FETCH_SEARCH_PLAN_INFO = 'FETCH_SEARCH_PLAN_INFO';
+
+/**
+ * fetchJetpackSettings action
+ *
+ * @returns {object} - an action object.
+ */
+export const fetchJetpackSettings = () => {
+ return {
+ type: FETCH_JETPACK_SETTINGS,
+ };
+};
+
+/**
+ * updateJetpackSettings action
+ *
+ * @param {*} settings - Jetpack settings object.
+ * @returns {object} - an action object.
+ */
+export const updateJetpackSettings = settings => {
+ return {
+ type: UPDATE_JETPACK_SETTINGS,
+ settings,
+ };
+};
+
+/**
+ * fetchSearchPlanInfo action
+ *
+ * @returns {object} - an action object.
+ */
+export const fetchSearchPlanInfo = () => {
+ return {
+ type: FETCH_SEARCH_PLAN_INFO,
+ };
+};
+
+export default {
+ [ FETCH_JETPACK_SETTINGS ]: function () {
+ return restApi.fetchSearchSettings();
+ },
+ [ UPDATE_JETPACK_SETTINGS ]: function ( action ) {
+ return restApi.updateSearchSettings( action.settings );
+ },
+ [ FETCH_SEARCH_PLAN_INFO ]: function () {
+ return restApi.fetchSearchPlanInfo();
+ },
+};
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/index.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/index.js
new file mode 100644
index 00000000..56b96527
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/index.js
@@ -0,0 +1,18 @@
+/**
+ * Internal dependencies
+ */
+import reducer from './reducer';
+import actions from './actions';
+import selectors from './selectors';
+import resolvers from './resolvers';
+import controls from './controls';
+
+export const STORE_ID = 'jetpack-search-plugin';
+export const storeConfig = {
+ reducer,
+ actions,
+ selectors,
+ resolvers,
+ controls,
+ initialState: window.JETPACK_SEARCH_DASHBOARD_INITIAL_STATE || {},
+};
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/index.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/index.js
new file mode 100644
index 00000000..cf734005
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/index.js
@@ -0,0 +1,23 @@
+/**
+ * WordPress dependencies
+ */
+import { combineReducers } from '@wordpress/data';
+
+/**
+ * Internal dependencies
+ */
+import siteData from './site-data';
+import userData from './user-data';
+import jetpackSettings from './jetpack-settings';
+import sitePlan from './site-plan';
+import notices from 'components/global-notices/store/reducer';
+
+const reducer = combineReducers( {
+ siteData,
+ jetpackSettings,
+ sitePlan,
+ userData,
+ notices,
+} );
+
+export default reducer;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/jetpack-settings.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/jetpack-settings.js
new file mode 100644
index 00000000..1a1fc138
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/jetpack-settings.js
@@ -0,0 +1,22 @@
+/**
+ * Internal dependencies
+ */
+import { SET_JETPACK_SETTINGS } from '../actions/jetpack-settings';
+
+const jetpackSettings = ( state = {}, action ) => {
+ switch ( action.type ) {
+ case SET_JETPACK_SETTINGS:
+ return {
+ ...state,
+ ...action.options,
+ is_toggling_module:
+ state.module_active !== action.options.module_active && !! action.options.is_updating,
+ is_toggling_instant_search:
+ state.instant_search_enabled !== action.options.instant_search_enabled &&
+ !! action.options.is_updating,
+ };
+ }
+ return state;
+};
+
+export default jetpackSettings;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/site-data.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/site-data.js
new file mode 100644
index 00000000..8e1a578d
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/site-data.js
@@ -0,0 +1,5 @@
+const siteData = ( state = {} ) => {
+ return state;
+};
+
+export default siteData;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/site-plan.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/site-plan.js
new file mode 100644
index 00000000..9fff3d43
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/site-plan.js
@@ -0,0 +1,18 @@
+/**
+ * Internal dependencies
+ */
+import { SET_SEARCH_PLAN_INFO } from '../actions/site-plan';
+
+const sitePlan = ( state = {}, action ) => {
+ switch ( action.type ) {
+ case SET_SEARCH_PLAN_INFO:
+ return {
+ ...state,
+ ...action.options,
+ };
+ }
+
+ return state;
+};
+
+export default sitePlan;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/user-data.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/user-data.js
new file mode 100644
index 00000000..17af1898
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/reducer/user-data.js
@@ -0,0 +1,5 @@
+const userData = ( state = {} ) => {
+ return state;
+};
+
+export default userData;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/resolvers.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/resolvers.js
new file mode 100644
index 00000000..3c5272bc
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/resolvers.js
@@ -0,0 +1,48 @@
+/**
+ * External dependencies
+ */
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import { fetchJetpackSettings, fetchSearchPlanInfo } from './controls';
+import { setJetpackSettings } from './actions/jetpack-settings';
+import { setSearchPlanInfo } from './actions/site-plan';
+import { errorNotice } from '../components/global-notices/store/actions';
+
+/**
+ * Yield actions to get Search Module Status
+ *
+ * @yields {object} - an action object.
+ * @returns {object} - an action object.
+ */
+export function* getSearchModuleStatus() {
+ try {
+ const settings = yield fetchJetpackSettings();
+ if ( settings ) {
+ return setJetpackSettings( settings );
+ }
+ } catch ( e ) {
+ return errorNotice( __( 'Error fetching settings…', 'jetpack-search-pkg' ) );
+ }
+}
+
+/**
+ * Yield actions to get search plan info
+ *
+ * @yields {object} - an action object.
+ * @returns {object} - an action object.
+ */
+export function* getSearchPlanInfo() {
+ try {
+ const planInfo = yield fetchSearchPlanInfo();
+ if ( planInfo ) {
+ return setSearchPlanInfo( planInfo );
+ }
+ } catch ( e ) {
+ return errorNotice( __( 'Error fetching search plan…', 'jetpack-search-pkg' ) );
+ }
+}
+
+export default { getSearchModuleStatus, getSearchPlanInfo };
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/index.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/index.js
new file mode 100644
index 00000000..8020ea19
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/index.js
@@ -0,0 +1,18 @@
+/**
+ * Internal dependencies
+ */
+import siteDataSelectors from './site-data';
+import jetpackSettingSelectors from './jetpack-settings';
+import sitePlanSelectors from './site-plan';
+import userDataSelectors from './user-data';
+import noticeSelectors from 'components/global-notices/store/selectors';
+
+const selectors = {
+ ...siteDataSelectors,
+ ...jetpackSettingSelectors,
+ ...sitePlanSelectors,
+ ...userDataSelectors,
+ ...noticeSelectors,
+};
+
+export default selectors;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/jetpack-settings.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/jetpack-settings.js
new file mode 100644
index 00000000..6cd876c4
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/jetpack-settings.js
@@ -0,0 +1,10 @@
+const jetpackSettingSelectors = {
+ getSearchModuleStatus: state => state.jetpackSettings,
+ isModuleEnabled: state => state.jetpackSettings.module_active,
+ isInstantSearchEnabled: state => state.jetpackSettings.instant_search_enabled,
+ isUpdatingJetpackSettings: state => state.jetpackSettings.is_updating,
+ isTogglingModule: state => state.jetpackSettings.is_toggling_module,
+ isTogglingInstantSearch: state => state.jetpackSettings.is_toggling_instant_search,
+};
+
+export default jetpackSettingSelectors;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/site-data.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/site-data.js
new file mode 100644
index 00000000..5669e52d
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/site-data.js
@@ -0,0 +1,12 @@
+const siteDataSelectors = {
+ getAPIRootUrl: state => state.siteData?.WP_API_root ?? null,
+ getAPINonce: state => state.siteData?.WP_API_nonce ?? null,
+ getRegistrationNonce: state => state.siteData?.registrationNonce ?? null,
+ getSiteAdminUrl: state => state.siteData?.adminUrl ?? null,
+ isInstantSearchPromotionActive: state => state.siteData?.showPromotions ?? true,
+ getBlogId: state => state.siteData?.blogId ?? 0,
+ getVersion: state => state.siteData?.version ?? 'development',
+ getCalypsoSlug: state => state.siteData?.calypsoSlug,
+};
+
+export default siteDataSelectors;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/site-plan.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/site-plan.js
new file mode 100644
index 00000000..32d24989
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/site-plan.js
@@ -0,0 +1,12 @@
+const sitePlanSelectors = {
+ getSearchPlanInfo: state => state.sitePlan,
+ hasBusinessPlan: state => state.sitePlan.supports_only_classic_search,
+ hasActiveSearchPurchase: state => state.sitePlan.supports_instant_search,
+ supportsInstantSearch: state => state.sitePlan.supports_instant_search,
+ supportsOnlyClassicSearch: state => state.sitePlan.supports_only_classic_search,
+ getUpgradeBillPeriod: state => state.sitePlan?.default_upgrade_bill_period,
+ supportsSearch: state =>
+ state.sitePlan.supports_instant_search || state.sitePlan.supports_only_classic_search,
+};
+
+export default sitePlanSelectors;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/user-data.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/user-data.js
new file mode 100644
index 00000000..6e5ac9d3
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-search/src/dashboard/store/selectors/user-data.js
@@ -0,0 +1,5 @@
+const userDataSelectors = {
+ getWpcomUser: state => state.userData?.currentUser?.wpcomUser,
+};
+
+export default userDataSelectors;