Skip to content

Commit

Permalink
CRM: Create Automations UI root (#31853)
Browse files Browse the repository at this point in the history
* [not verified] Initial admin root

* [not verified] changelog

* [not verified] Add header

* [not verified] Add feature flag

* [not verified] Add tests

* [not verified] Update TODO

* [not verified] Add newline

* [not verified] Fix menu by using Core.Menus

* [not verified] Revert extraneous changes

* Rename automations component to automations-admin

* Create admin-page-init.php

* Use ThemeProvider

* Update changelog

* Add feature flags to menus

* Adhere to monorepo expectations

* Automation: move admin init file into admin dir

* Prevent direct file access to automations main page

* Correct load admin page hook

* Rename core automations slug

We currently have a paid extension using the same slug, so if that has been enabled, we're having issues with overrides.
E.g.: the CRM system will not recognize the new page as an admin page.

* Refactor admin page to use a CRM generic admin page wrapper

* Remove unused style file

---------

Co-authored-by: André Kallehauge <[email protected]>
  • Loading branch information
robertf4 and kallehauge authored Jul 18, 2023
1 parent b319ee3 commit d7fb216
Show file tree
Hide file tree
Showing 16 changed files with 300 additions and 50 deletions.
28 changes: 28 additions & 0 deletions projects/plugins/crm/admin/automations/main.page.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
/**
* Jetpack CRM
* https://jetpackcrm.com
*
* Automation UI main page
*
* @package automattic/jetpack-crm
*/

namespace Automattic\Jetpack_CRM\Automations;

defined( 'ZEROBSCRM_PATH' ) || exit;

if ( ! apply_filters( 'jetpack_crm_feature_flag_automations', false ) ) {
return;
}

/**
* Render the Automations page, which is simply a mounting point for React.
*
* @return void
*/
function render_page() {
echo '<div id="jetpack-crm-automations-root"></div>';
}

render_page();
3 changes: 3 additions & 0 deletions projects/plugins/crm/changelog/add-crm-automations-admin-root
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Significance: patch
Type: added
Comment: This PR is establishing the base of a React app. The changelog should only announce when the app is released.
9 changes: 9 additions & 0 deletions projects/plugins/crm/includes/ZeroBSCRM.AdminPages.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,15 @@ function zeroBSCRM_pages_admin_view_page_company( $id = -1 ) {
jpcrm_render_company_view_page( $id );
}

/**
* Load the Automations admin page
*
* @return void
*/
function jpcrm_pages_automations() {
jpcrm_load_admin_page( 'automations/main' );
}

/*
======================================================
/ Page loading
Expand Down
22 changes: 22 additions & 0 deletions projects/plugins/crm/includes/ZeroBSCRM.Core.Menus.WP.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,17 @@ function zeroBSCRM_menu_buildMenu() {
'stylefuncs' => array( 'zeroBSCRM_global_admin_styles', 'zeroBSCRM_admin_styles_chartjs', 'zeroBSCRM_admin_styles_homedash' ),
);

if ( apply_filters( 'jetpack_crm_feature_flag_automations', false ) ) {
$menu['jpcrm']['subitems']['core-automations'] = array(
'title' => __( 'Automations', 'zero-bs-crm' ),
'url' => $zbs->slugs['core-automations'],
'perms' => 'manage_options',
'order' => 2,
'wpposition' => 2,
'callback' => 'jpcrm_pages_automations',
);
}

// Contacts (sub)
$menu['jpcrm']['subitems']['contacts'] = array(
'title' => __( 'Contacts', 'zero-bs-crm' ),
Expand Down Expand Up @@ -347,6 +358,17 @@ function zeroBSCRM_menu_buildMenu() {
'stylefuncs' => array( 'zeroBSCRM_global_admin_styles', 'zeroBSCRM_admin_styles_chartjs', 'zeroBSCRM_admin_styles_homedash' ),
);

if ( apply_filters( 'jetpack_crm_feature_flag_automations', false ) ) {
$menu['jpcrm']['subitems']['core-automations'] = array(
'title' => __( 'Automations', 'zero-bs-crm' ),
'url' => $zbs->slugs['core-automations'],
'perms' => 'manage_options',
'order' => 2,
'wpposition' => 2,
'callback' => 'jpcrm_pages_automations',
);
}

// Core modules (sub)
$menu['jpcrm']['subitems']['modules'] = array(
'title' => '<span>' . __( 'Core Modules', 'zero-bs-crm' ) . '</span>',
Expand Down
25 changes: 13 additions & 12 deletions projects/plugins/crm/includes/ZeroBSCRM.Core.php
Original file line number Diff line number Diff line change
Expand Up @@ -1013,18 +1013,19 @@ private function setupUrlsSlugsEtc() {
##WLREMOVE
$this->slugs['home'] = 'zerobscrm-plugin';
##/WLREMOVE
$this->slugs['dash'] = 'zerobscrm-dash';
$this->slugs['settings'] = 'zerobscrm-plugin-settings';
$this->slugs['logout'] = 'zerobscrm-logout';
$this->slugs['datatools'] = 'zerobscrm-datatools';
$this->slugs['welcome'] = 'zerobscrm-welcome';
$this->slugs['crmresources'] = 'jpcrm-resources';
$this->slugs['support'] = 'jpcrm-support';
$this->slugs['extensions'] = 'zerobscrm-extensions';
$this->slugs['modules'] = 'zerobscrm-modules';
$this->slugs['export'] = 'zerobscrm-export';
$this->slugs['systemstatus'] = 'zerobscrm-systemstatus';
$this->slugs['sync'] = 'zerobscrm-sync';
$this->slugs['dash'] = 'zerobscrm-dash';
$this->slugs['settings'] = 'zerobscrm-plugin-settings';
$this->slugs['logout'] = 'zerobscrm-logout';
$this->slugs['datatools'] = 'zerobscrm-datatools';
$this->slugs['welcome'] = 'zerobscrm-welcome';
$this->slugs['crmresources'] = 'jpcrm-resources';
$this->slugs['support'] = 'jpcrm-support';
$this->slugs['extensions'] = 'zerobscrm-extensions';
$this->slugs['modules'] = 'zerobscrm-modules';
$this->slugs['export'] = 'zerobscrm-export';
$this->slugs['systemstatus'] = 'zerobscrm-systemstatus';
$this->slugs['sync'] = 'zerobscrm-sync';
$this->slugs['core-automations'] = 'jpcrm-automations';

// CSV importer Lite
$this->slugs['csvlite'] = 'zerobscrm-csvimporterlite-app';
Expand Down
80 changes: 80 additions & 0 deletions projects/plugins/crm/modules/automations/admin/admin-page-init.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php
/**
* Jetpack CRM
* https://jetpackcrm.com
*
* Automation admin page initialization
*
* @package automattic/jetpack-crm
*/

namespace Automattic\Jetpack_CRM\Automations;

use Automattic\Jetpack\Assets;

/**
* The main initializing function.
*
* @return void
*/
function initialize_admin_page() {
add_action( 'load-jetpack-crm_page_jpcrm-automations', 'Automattic\Jetpack_CRM\Automations\admin_init' );
}

/**
* Actions to run on admin init
*
* @return void
*/
function admin_init() {
add_action( 'admin_enqueue_scripts', 'Automattic\Jetpack_CRM\Automations\enqueue_admin_scripts' );
}

/**
* Enqueues the React app bundle.
*
* @return void
*/
function enqueue_admin_scripts() {
Assets::register_script(
'jetpack-crm-automations',
'build/automations-admin/index.js',
ZBS_ROOTFILE,
array(
'in_footer' => true,
'textdomain' => 'zero-bs-crm',
)
);
Assets::enqueue_script( 'jetpack-crm-automations' );

wp_add_inline_script( 'jetpack-crm-automations', render_initial_state(), 'before' );
}

/**
* Initial state to be served with the React app.
*
* @return string
*/
function render_initial_state() {
/**
* Allow external plugins to modify Automations UI hydration data.
*
* @since $$next-version$$
*
* @param array {
* Array of default data we need to render our React UI.
*
* @type string $apiRoot The base URL for the sites REST API.
* @type string $apiNonce Nonce value to communicate with the sites REST API.
* }
*/
$initial_state = apply_filters(
'jetpack_crm_automations_initial_state',
array(
'apiRoot' => esc_url_raw( rest_url() ),
'apiNonce' => wp_create_nonce( 'wp_rest' ),
)
);

return 'var jpcrmAutomationsInitialState=JSON.parse(decodeURIComponent( "' . rawurlencode( wp_json_encode( $initial_state ) ) . '" ) );';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
/**
* Jetpack CRM
* https://jetpackcrm.com
*
* Automation Module initialization
*
* @package automattic/jetpack-crm
*/

namespace Automattic\Jetpack_CRM\Automations;

if ( ! defined( 'ZEROBSCRM_PATH' ) ) {
exit;
}

if ( ! apply_filters( 'jetpack_crm_feature_flag_automations', false ) ) {
return;
}

/**
* The main initializing function.
*
* @return void
*/
function init() {
require_once JPCRM_MODULES_PATH . 'automations/admin/admin-page-init.php';
initialize_admin_page();
}

init();
51 changes: 34 additions & 17 deletions projects/plugins/crm/src/js/components/admin-page/index.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,52 @@
import { AdminPage as JetpackAdminPage, JetpackLogo } from '@automattic/jetpack-components';
import { __ } from '@wordpress/i18n';
import {
AdminPage as JetpackAdminPage,
AdminSectionHero,
Col,
Container,
Text,
} from '@automattic/jetpack-components';
import styles from './styles.module.scss';
import type { AdminPageProps } from '@automattic/jetpack-components/components/admin-page/types';
import type { AdminPageProps } from './types';
import type React from 'react';

/**
* This is the base structure for any Jetpack CRM admin page. It comes with Header and Footer.
* This is the base structure for any Jetpack CRM admin page.
*
* All content must be passed as children wrapped in as many <AdminSection> elements as needed.
*
* @param {AdminPageProps} props - Component properties.
* @returns {React.ReactNode} AdminPage component.
*/
const AdminPage: React.FC< AdminPageProps > = props => {
const { children } = props;
const { children, headline, subHeadline } = props;

return <JetpackAdminPage { ...props }>{ children }</JetpackAdminPage>;
return (
<JetpackAdminPage { ...props }>
<AdminSectionHero>
{ ( headline || subHeadline ) && (
<Container horizontalSpacing={ 2 }>
<Col>
{ headline && <Text variant="headline-small">{ headline }</Text> }
{ subHeadline && (
<Text className={ styles[ 'sub-headline' ] } variant="body-small">
{ subHeadline }
</Text>
) }
</Col>
</Container>
) }
</AdminSectionHero>
{ children }
</JetpackAdminPage>
);
};

/* @todo Replace this when we have a JetpackSearchLogo in the Components library. */
const crmLogo = (
<div className={ styles[ 'custom-header' ] }>
<JetpackLogo height={ 40 } />
<div className={ styles[ 'logo-title' ] }>CRM</div>
</div>
);

AdminPage.defaultProps = {
moduleName: __( 'Jetpack CRM', 'zero-bs-crm' ),
moduleNameHref: 'https://jetpackcrm.com/',
header: crmLogo,
/*
* Hide footer and header since we output them with PHP.
*/
showHeader: false,
showFooter: false,
};

export default AdminPage;
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
.custom-header {
display: flex;
}

.logo-title {
flex: 1;
line-height: 30px;
font-size: 30px;
margin-top: 2px;
margin-left: 4px;
font-weight: 300;
letter-spacing: 0.0625em;
.sub-headline {
letter-spacing: 0.15px;
color: var(--jp-gray-50);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@ import AdminPage from '../index';
describe( 'AdminPage', () => {
test( 'Renders the component', () => {
render(
<AdminPage>
<AdminPage headline={ 'Headline is present' } subHeadline={ 'Sub-headline is present' }>
<p>This is a child element.</p>
</AdminPage>
);

expect( screen.getByText( 'This is a child element.' ) ).toBeInTheDocument();
expect( screen.getByRole( 'link', { name: 'Jetpack CRM' } ) ).toHaveAttribute(
'href',
'https://jetpackcrm.com/'
);
expect( screen.getByText( 'Headline is present' ) ).toBeInTheDocument();
expect( screen.getByText( 'Sub-headline is present' ) ).toBeInTheDocument();
} );
} );
16 changes: 16 additions & 0 deletions projects/plugins/crm/src/js/components/admin-page/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { AdminPageProps as JetpackAdminPageProps } from '@automattic/jetpack-components/components/admin-page/types';

export type AdminPageProps = JetpackAdminPageProps & {
/**
* Page Headline.
*
* This headline will be shown at the top of the page, below the navigation menu.
*/
headline?: string;
/**
* Sub headline
*
* This sub headline will be shown below the page headline.
*/
subHeadline?: string;
};
14 changes: 14 additions & 0 deletions projects/plugins/crm/src/js/components/automations-admin/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { AdminSection } from '@automattic/jetpack-components';
import { __ } from '@wordpress/i18n';
import React from 'react';
import AdminPage from '../admin-page';

export const AutomationsAdmin = () => {
return (
<AdminPage
headline={ __( 'Automations', 'zero-bs-crm' ) }
subHeadline={ __( 'Streamline your workflows with CRM Automations', 'zero-bs-crm' ) }
children={ <AdminSection>{ /* Page content goes here in the future. */ }</AdminSection> }
/>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { render, screen } from '@testing-library/react';
import React from 'react';
import { AutomationsAdmin } from '../index';

describe( 'AutomationsAdmin', () => {
test( 'Renders the component', () => {
render( <AutomationsAdmin /> );

expect( screen.getByRole( 'heading', { name: 'Automations' } ) ).toBeInTheDocument();
} );
} );
Loading

0 comments on commit d7fb216

Please sign in to comment.