Skip to content
Merged
4 changes: 4 additions & 0 deletions projects/packages/forms/changelog/update-use-config-forms
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: changed

Forms: add new useConfigValue hook and start using it on the dashboard
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import useFormsConfig from '../../../../../hooks/use-forms-config';
import useConfigValue from '../../../../../hooks/use-config-value';
import { usePluginInstallation } from '../hooks/use-plugin-installation';

type PluginActionButtonProps = {
Expand All @@ -34,9 +34,9 @@ const PluginActionButton = ( {
trackEventName
);

const config = useFormsConfig();
const canUserInstallPlugins = Boolean( config?.canInstallPlugins );
const canUserActivatePlugins = Boolean( config?.canActivatePlugins );
// Permissions from consolidated Forms config (shared across editor and dashboard)
const canUserInstallPlugins = useConfigValue( 'canInstallPlugins' );
const canUserActivatePlugins = useConfigValue( 'canActivatePlugins' );

const canPerformAction = isInstalled ? canUserActivatePlugins : canUserInstallPlugins;
const [ isReconcilingStatus, setIsReconcilingStatus ] = useState( false );
Expand Down
5 changes: 2 additions & 3 deletions projects/packages/forms/src/blocks/contact-form/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import clsx from 'clsx';
/*
* Internal dependencies
*/
import useFormsConfig from '../../hooks/use-forms-config';
import useConfigValue from '../../hooks/use-config-value';
import { store as singleStepStore } from '../../store/form-step-preview';
import {
PREVIOUS_BUTTON_TEMPLATE,
Expand Down Expand Up @@ -168,8 +168,7 @@ function JetpackContactFormEdit( {
disableSummary,
notificationRecipients,
} = attributes;
const formsConfig = useFormsConfig();
const showFormIntegrations = Boolean( formsConfig?.isIntegrationsEnabled );
const showFormIntegrations = useConfigValue( 'isIntegrationsEnabled' );
const instanceId = useInstanceId( JetpackContactFormEdit );

// Backward compatibility for the deprecated customThankyou attribute.
Expand Down
4 changes: 2 additions & 2 deletions projects/packages/forms/src/dashboard/about/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import useConfigValue from '../../hooks/use-config-value';
import AkismetIcon from '../../icons/akismet';
import CreativeMailIcon from '../../icons/creative-mail';
import GoogleSheetsIcon from '../../icons/google-sheets';
import SalesforceIcon from '../../icons/salesforce';
import CreateFormButton from '../components/create-form-button';
import Details from '../components/details';
import { config } from '../index';
import PatternCard from './pattern-card';
import CheckSVG from './svg/check-svg';
import CloseSVG from './svg/close-svg';
Expand All @@ -32,7 +32,7 @@ import './style.scss';
import type { Pattern } from '../../types';

const About = () => {
const ASSETS_URL = useMemo( () => config( 'pluginAssetsURL' ), [] );
const ASSETS_URL = useConfigValue( 'pluginAssetsURL' ); // Ensure config is loaded.

const patterns: Pattern[] = useMemo(
() => [
Expand Down
26 changes: 1 addition & 25 deletions projects/packages/forms/src/dashboard/class-dashboard.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
use Automattic\Jetpack\Assets;
use Automattic\Jetpack\Connection\Initial_State as Connection_Initial_State;
use Automattic\Jetpack\Forms\ContactForm\Contact_Form_Plugin;
use Automattic\Jetpack\Forms\Jetpack_Forms;
use Automattic\Jetpack\Redirect;
use Automattic\Jetpack\Status;
use Automattic\Jetpack\Tracking;

if ( ! defined( 'ABSPATH' ) ) {
Expand Down Expand Up @@ -151,29 +148,8 @@ public function add_new_admin_submenu() {
* Render the dashboard.
*/
public function render_dashboard() {
if ( ! class_exists( 'Jetpack_AI_Helper' ) ) {
require_once JETPACK__PLUGIN_DIR . '_inc/lib/class-jetpack-ai-helper.php';
}

$ai_feature = \Jetpack_AI_Helper::get_ai_assistance_feature();
$has_ai = ! is_wp_error( $ai_feature ) ? $ai_feature['has-feature'] : false;

$config = array(
'blogId' => get_current_blog_id(),
'exportNonce' => wp_create_nonce( 'feedback_export' ),
'newFormNonce' => wp_create_nonce( 'create_new_form' ),
'gdriveConnectSupportURL' => esc_url( Redirect::get_url( 'jetpack-support-contact-form-export' ) ),
'checkForSpamNonce' => wp_create_nonce( 'grunion_recheck_queue' ),
'pluginAssetsURL' => Jetpack_Forms::assets_url(),
'siteURL' => ( new Status() )->get_site_suffix(),
'hasFeedback' => $this->has_feedback(),
'hasAI' => $has_ai,
'dashboardURL' => self::get_forms_admin_url(),
'isMailpoetEnabled' => Jetpack_Forms::is_mailpoet_enabled(),
);

?>
<div id="jp-forms-dashboard" data-config="<?php echo esc_attr( wp_json_encode( $config, JSON_FORCE_OBJECT ) ); ?>"></div>
<div id="jp-forms-dashboard"></div>
<?php
}

Expand Down
36 changes: 19 additions & 17 deletions projects/packages/forms/src/dashboard/components/layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ import { Outlet, useLocation, useNavigate } from 'react-router';
/**
* Internal dependencies
*/
import useFormsConfig from '../../../hooks/use-forms-config';
import useConfigValue from '../../../hooks/use-config-value';
import EmptySpamButton from '../../components/empty-spam-button';
import EmptyTrashButton from '../../components/empty-trash-button';
import ExportResponsesButton from '../../inbox/export-responses';
import { config } from '../../index';
import { store as dashboardStore } from '../../store';
import ActionsDropdownMenu from '../actions-dropdown-menu';
import CreateFormButton from '../create-form-button';
Expand All @@ -27,9 +26,10 @@ const Layout = () => {
const location = useLocation();
const navigate = useNavigate();
const [ isSm ] = useBreakpointMatch( 'sm' );
const formsConfig = useFormsConfig();

const enableIntegrationsTab = Boolean( formsConfig?.isIntegrationsEnabled );
const enableIntegrationsTab = useConfigValue( 'isIntegrationsEnabled' );
const hasFeedback = useConfigValue( 'hasFeedback' );
const isLoadingConfig = enableIntegrationsTab === undefined;

const { currentStatus } = useSelect(
select => ( {
Expand Down Expand Up @@ -72,15 +72,15 @@ const Layout = () => {
return path;
}

return config( 'hasFeedback' ) ? 'responses' : 'about';
}, [ location.pathname, tabs ] );
return hasFeedback ? 'responses' : 'about';
}, [ location.pathname, tabs, hasFeedback ] );

const isResponsesTab = getCurrentTab() === 'responses';

const handleTabSelect = useCallback(
( tabName: string ) => {
if ( ! tabName ) {
tabName = config( 'hasFeedback' ) ? 'responses' : 'about';
tabName = hasFeedback ? 'responses' : 'about';
}

const currentTab = getCurrentTab();
Expand All @@ -98,7 +98,7 @@ const Layout = () => {
search: tabName === 'responses' ? location.search : '',
} );
},
[ navigate, location.search, isSm, getCurrentTab ]
[ navigate, location.search, isSm, getCurrentTab, hasFeedback ]
);

return (
Expand All @@ -124,15 +124,17 @@ const Layout = () => {
</div>
) }
</div>
<TabPanel
className="jp-forms__dashboard-tabs"
tabs={ tabs }
initialTabName={ getCurrentTab() }
onSelect={ handleTabSelect }
key={ getCurrentTab() }
>
{ () => <Outlet /> }
</TabPanel>
{ ! isLoadingConfig && (
<TabPanel
className="jp-forms__dashboard-tabs"
tabs={ tabs }
initialTabName={ getCurrentTab() }
onSelect={ handleTabSelect }
key={ getCurrentTab() }
>
{ () => <Outlet /> }
</TabPanel>
) }
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ import clsx from 'clsx';
/**
* Internal dependencies
*/
import useFormsConfig from '../../../hooks/use-forms-config';
import useConfigValue from '../../../hooks/use-config-value';
import CopyClipboardButton from '../../components/copy-clipboard-button';
import Gravatar from '../../components/gravatar';
import { useMarkAsSpam } from '../../hooks/use-mark-as-spam';
import { getPath, updateMenuCounter, updateMenuCounterOptimistically } from '../../inbox/utils';
import CopyClipboardButton from '../copy-clipboard-button';
import Gravatar from '../gravatar';
import type { FormResponse } from '../../../types';

const getDisplayName = response => {
Expand Down Expand Up @@ -203,8 +203,7 @@ const ResponseViewBody = ( {

const { editEntityRecord } = useDispatch( 'core' );

const formsConfig = useFormsConfig();
const emptyTrashDays = formsConfig?.emptyTrashDays ?? 0;
const emptyTrashDays = useConfigValue( 'emptyTrashDays' ) ?? 0;

// When opening a "Mark as spam" link from the email, the ResponseViewBody component is rendered, so we use a hook here to handle it.
const { isConfirmDialogOpen, onConfirmMarkAsSpam, onCancelMarkAsSpam } = useMarkAsSpam(
Expand Down
42 changes: 23 additions & 19 deletions projects/packages/forms/src/dashboard/hooks/use-create-form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useCallback } from '@wordpress/element';
/**
* Internal dependencies
*/
import { config } from '../index';
import useConfigValue from '../../hooks/use-config-value';

type ClickHandlerProps = {
formPattern?: string;
Expand All @@ -24,30 +24,34 @@ type CreateFormReturn = {
* @return {CreateFormReturn} The createForm and openNewForm functions.
*/
export default function useCreateForm(): CreateFormReturn {
const createForm = useCallback( async ( formPattern: string ) => {
const data = new FormData();
const newFormNonce = useConfigValue( 'newFormNonce' );
const createForm = useCallback(
async ( formPattern: string ) => {
const data = new FormData();

data.append( 'action', 'create_new_form' );
data.append( 'newFormNonce', config( 'newFormNonce' ) );
data.append( 'action', 'create_new_form' );
data.append( 'newFormNonce', newFormNonce );

if ( formPattern ) {
data.append( 'pattern', formPattern );
}
if ( formPattern ) {
data.append( 'pattern', formPattern );
}

const response = await fetch( window.ajaxurl, { method: 'POST', body: data } );
const response = await fetch( window.ajaxurl, { method: 'POST', body: data } );

const {
success,
post_url: postUrl,
data: message,
}: { success?: boolean; data?: string; post_url?: string } = await response.json();
const {
success,
post_url: postUrl,
data: message,
}: { success?: boolean; data?: string; post_url?: string } = await response.json();

if ( success === false ) {
throw new Error( message );
}
if ( success === false ) {
throw new Error( message );
}

return postUrl;
}, [] );
return postUrl;
},
[ newFormNonce ]
);

const openNewForm = useCallback(
async ( { formPattern, showPatterns, analyticsEvent }: ClickHandlerProps ) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import { config } from '..';
import useConfigValue from '../../hooks/use-config-value';
import { store as dashboardStore } from '../store';

type ExportHookReturn = {
Expand Down Expand Up @@ -78,11 +78,13 @@ export default function useExportResponses(): ExportHookReturn {
return { selected: getSelectedResponsesFromCurrentDataset(), currentQuery: getCurrentQuery() };
}, [] );

const exportNonce = useConfigValue( 'exportNonce' );

const onExport = useCallback(
( action: string, nonceName: string ) => {
const data = new FormData();
data.append( 'action', action );
data.append( nonceName, config( 'exportNonce' ) );
data.append( nonceName, exportNonce );
selected.forEach( ( id: string ) => data.append( 'selected[]', id ) );
data.append( 'post', currentQuery.parent || 'all' );
data.append( 'search', currentQuery.search || '' );
Expand All @@ -95,7 +97,7 @@ export default function useExportResponses(): ExportHookReturn {

return fetch( window.ajaxurl, { method: 'POST', body: data } );
},
[ currentQuery, selected ]
[ currentQuery, selected, exportNonce ]
);

useEffect( () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
__experimentalVStack as VStack, // eslint-disable-line @wordpress/no-unsafe-wp-apis
} from '@wordpress/components';
import { __, _n, sprintf } from '@wordpress/i18n';
import useFormsConfig from '../../hooks/use-forms-config';
import useConfigValue from '../../hooks/use-config-value';

const EmptyWrapper = ( { heading = '', body = '' } ) => (
<VStack alignment="center" spacing="2">
Expand All @@ -22,8 +22,7 @@ type EmptyResponsesProps = {
};

const EmptyResponses = ( { status, isSearch }: EmptyResponsesProps ) => {
const formsConfig = useFormsConfig();
const emptyTrashDays = formsConfig?.emptyTrashDays ?? 0;
const emptyTrashDays = useConfigValue( 'emptyTrashDays' ) ?? 0;

const searchHeading = __( 'No results found', 'jetpack-forms' );
const searchMessage = __(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import clsx from 'clsx';
/**
* Internal dependencies
*/
import { config } from '../..';
import useConfigValue from '../../../hooks/use-config-value';
import { INTEGRATIONS_STORE } from '../../../store/integrations';
import { PARTIAL_RESPONSES_PATH } from '../../../util/get-preferred-responses-view';
/**
Expand All @@ -31,6 +31,7 @@ const GoogleDriveExport = ( { onExport, autoConnect = false } ) => {
}, [] ) as { integration?: Integration };
const { refreshIntegrations } = useDispatch( INTEGRATIONS_STORE ) as IntegrationsDispatch;
const isConnectedToGoogleDrive = !! integration?.isConnected;
const gdriveConnectSupportURL = useConfigValue( 'gdriveConnectSupportURL' );
const { tracks } = useAnalytics();
const autoConnectOpened = useRef( false );
const [ isTogglingConnection, setIsTogglingConnection ] = useState( false );
Expand Down Expand Up @@ -110,7 +111,7 @@ const GoogleDriveExport = ( { onExport, autoConnect = false } ) => {
<>
&nbsp;
<a
href={ config( 'gdriveConnectSupportURL' ) }
href={ gdriveConnectSupportURL }
title={ __( 'Connect to Google Drive', 'jetpack-forms' ) }
target="_blank"
rel="noopener noreferrer"
Expand Down
14 changes: 10 additions & 4 deletions projects/packages/forms/src/dashboard/inbox/index.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import { useEffect } from '@wordpress/element';
import { useNavigate } from 'react-router';
import { config } from '../';
import useConfigValue from '../../hooks/use-config-value';
import InboxView from './dataviews';
import './style.scss';

const Inbox = () => {
const navigate = useNavigate();

const hasFeedback = useConfigValue( 'hasFeedback' );

// If a user has no responses yet, redirect them to the landing page.
useEffect( () => {
if ( config( 'hasFeedback' ) ) {
if ( hasFeedback !== false ) {
return;
}
navigate( '/landing' );
}, [ navigate ] );
navigate( '/about' );
}, [ navigate, hasFeedback ] );

if ( hasFeedback === undefined ) {
return null; // or a loading spinner, if you prefer
}

return <InboxView />;
};
Expand Down
Loading
Loading