plugin updates

This commit is contained in:
Tony Volpe
2024-09-25 09:45:47 -04:00
parent cc870f301f
commit f6021c7c22
245 changed files with 4835 additions and 4671 deletions

View File

@@ -49,7 +49,7 @@ export interface LeadinConfig {
wpVersion: string;
contentEmbed: ContentEmbedDetails;
requiresContentEmbedScope?: boolean;
refreshTokenError?: string;
decryptError?: string;
}
const {
@@ -91,7 +91,7 @@ const {
wpVersion,
contentEmbed,
requiresContentEmbedScope,
refreshTokenError,
decryptError,
}: //@ts-expect-error global
LeadinConfig = window.leadinConfig;
@@ -134,5 +134,5 @@ export {
wpVersion,
contentEmbed,
requiresContentEmbedScope,
refreshTokenError,
decryptError,
};

View File

@@ -7,9 +7,10 @@ import {
getOrCreateBackgroundApp,
initBackgroundApp,
} from '../utils/backgroundAppUtils';
import { refreshToken } from '../constants/leadinConfig';
import { ProxyMessages } from '../iframe/integratedMessages';
let embedder: any;
function deactivatePlugin() {
const href = $(domElements.deactivatePluginButton).attr('href');
if (href) {
@@ -30,8 +31,7 @@ function submitAndDeactivate(e: Event) {
submitFeedbackForm(domElements.deactivateFeedbackForm)
.then(() => {
if (feedback && refreshToken) {
const embedder = getOrCreateBackgroundApp(refreshToken);
if (feedback) {
embedder.postMessage({
key: ProxyMessages.TrackPluginDeactivation,
payload: {
@@ -49,6 +49,7 @@ function submitAndDeactivate(e: Event) {
}
function init() {
embedder = getOrCreateBackgroundApp();
// eslint-disable-next-line no-new
new ThickBoxModal(
domElements.deactivatePluginButton,

View File

@@ -0,0 +1,23 @@
import React from 'react';
import { leadinPluginVersion, pluginPath } from '../../constants/leadinConfig';
import { useRefEffect } from '@wordpress/compose';
function StylesheetErrorBondary({ children }: React.PropsWithChildren) {
const ref = useRefEffect(element => {
const { ownerDocument } = element;
if (
ownerDocument &&
!ownerDocument.getElementById('leadin-gutenberg-css')
) {
const link = ownerDocument.createElement('link');
link.id = 'leadin-gutenberg-css';
link.rel = 'stylesheet';
link.href = `${pluginPath}/build/gutenberg.css?ver=${leadinPluginVersion}`;
ownerDocument.head.appendChild(link);
}
}, []);
return <div ref={ref}>{children}</div>;
}
export default StylesheetErrorBondary;

View File

@@ -1,6 +1,7 @@
import React from 'react';
import * as WpBlocksApi from '@wordpress/blocks';
import SprocketIcon from '../Common/SprocketIcon';
import StylesheetErrorBondary from '../Common/StylesheetErrorBondary';
import FormBlockSave from './FormBlockSave';
import { connectionStatus } from '../../constants/leadinConfig';
import FormGutenbergPreview from './FormGutenbergPreview';
@@ -27,17 +28,28 @@ export interface IFormBlockProps extends IFormBlockAttributes {
export default function registerFormBlock() {
const editComponent = (props: IFormBlockProps) => {
if (props.attributes.preview) {
return <FormGutenbergPreview />;
} else if (connectionStatus === ConnectionStatus.Connected) {
return <FormEdit {...props} origin="gutenberg" preview={true} />;
} else {
return <ErrorHandler status={401} />;
}
const isPreview = props.attributes.preview;
const isConnected = connectionStatus === ConnectionStatus.Connected;
return (
<StylesheetErrorBondary>
{isPreview ? (
<FormGutenbergPreview />
) : isConnected ? (
<FormEdit
{...props}
origin="gutenberg"
preview={true}
fullSiteEditor={isFullSiteEditor()}
/>
) : (
<ErrorHandler status={401} />
)}
</StylesheetErrorBondary>
);
};
// We do not support the full site editor: https://issues.hubspotcentral.com/browse/WP-1033
if (!WpBlocksApi || isFullSiteEditor()) {
if (!WpBlocksApi) {
return null;
}

View File

@@ -8,6 +8,7 @@ import MeetingEdit from '../../shared/Meeting/MeetingEdit';
import ErrorHandler from '../../shared/Common/ErrorHandler';
import { __ } from '@wordpress/i18n';
import { isFullSiteEditor } from '../../utils/withMetaData';
import StylesheetErrorBondary from '../Common/StylesheetErrorBondary';
const ConnectionStatus = {
Connected: 'Connected',
@@ -28,17 +29,28 @@ export interface IMeetingBlockProps extends IMeetingBlockAttributes {
export default function registerMeetingBlock() {
const editComponent = (props: IMeetingBlockProps) => {
if (props.attributes.preview) {
return <MeetingGutenbergPreview />;
} else if (connectionStatus === ConnectionStatus.Connected) {
return <MeetingEdit {...props} preview={true} origin="gutenberg" />;
} else {
return <ErrorHandler status={401} />;
}
const isPreview = props.attributes.preview;
const isConnected = connectionStatus === ConnectionStatus.Connected;
return (
<StylesheetErrorBondary>
{isPreview ? (
<MeetingGutenbergPreview />
) : isConnected ? (
<MeetingEdit
{...props}
preview={true}
origin="gutenberg"
fullSiteEditor={isFullSiteEditor()}
/>
) : (
<ErrorHandler status={401} />
)}
</StylesheetErrorBondary>
);
};
// We do not support the full site editor: https://issues.hubspotcentral.com/browse/WP-1033
if (!WpBlocksApi || isFullSiteEditor()) {
if (!WpBlocksApi) {
return null;
}

View File

@@ -10,6 +10,7 @@ import { __ } from '@wordpress/i18n';
import { BackgroudAppContext } from '../../iframe/useBackgroundApp';
import { refreshToken } from '../../constants/leadinConfig';
import { getOrCreateBackgroundApp } from '../../utils/backgroundAppUtils';
import { isFullSiteEditor } from '../../utils/withMetaData';
export function registerHubspotSidebar() {
const ContentTypeLabelStyle = styled.div`
@@ -27,7 +28,7 @@ export function registerHubspotSidebar() {
);
const LeadinPluginSidebar = ({ postType }: { postType: string }) =>
postType ? (
postType && !isFullSiteEditor() ? (
<PluginSidebar
name="leadin"
title="HubSpot"

View File

@@ -5,6 +5,7 @@ export const CoreMessages = {
RedirectParentFrame: 'INTEGRATED_APP_EMBEDDER_REDIRECT_PARENT_FRAME',
SendLocale: 'INTEGRATED_APP_EMBEDDER_SEND_LOCALE',
SendDeviceId: 'INTEGRATED_APP_EMBEDDER_SEND_DEVICE_ID',
SendIntegratedAppConfig: 'INTEGRATED_APP_EMBEDDER_CONFIG',
} as const;
export type CoreMessageType = typeof CoreMessages[keyof typeof CoreMessages];

View File

@@ -1,4 +1,4 @@
import { MessageType, PluginMessages } from '../iframe/integratedMessages';
import { MessageType, PluginMessages } from './integratedMessages';
import {
fetchDisableInternalTracking,
trackConsent,

View File

@@ -25,7 +25,7 @@ import {
wpVersion,
contentEmbed,
requiresContentEmbedScope,
refreshTokenError,
decryptError,
LeadinConfig,
} from '../constants/leadinConfig';
import { App, AppIframe } from './constants';
@@ -55,9 +55,17 @@ type PartialLeadinConfig = Pick<
| 'wpVersion'
| 'contentEmbed'
| 'requiresContentEmbedScope'
| 'refreshTokenError'
| 'decryptError'
>;
type AppIntegrationConfig = Pick<LeadinConfig, 'adminUrl'>;
const getIntegrationConfig = (): AppIntegrationConfig => {
return {
adminUrl: leadinQueryParams.adminUrl,
};
};
/**
* A modified version of the original leadinConfig that is passed to some integrated apps.
*
@@ -120,7 +128,7 @@ const getLeadinConfig = (): AppLeadinConfig => {
wpVersion,
contentEmbed,
requiresContentEmbedScope,
refreshTokenError,
decryptError,
...utm_query_params,
};
};
@@ -135,15 +143,15 @@ const getAppOptions = (app: App, createRoute = false) => {
let options;
switch (app) {
case App.Plugin:
options = new PluginAppOptions().setLeadinConfig(getLeadinConfig());
options = new PluginAppOptions();
break;
case App.PluginSettings:
options = new PluginAppOptions()
.setLeadinConfig(getLeadinConfig())
.setPluginSettingsInit();
options = new PluginAppOptions().setPluginSettingsInit();
break;
case App.Forms:
options = new FormsAppOptions();
options = new FormsAppOptions().setIntegratedAppConfig(
getIntegrationConfig()
);
if (createRoute) {
options = options.setCreateFormAppInit();
}
@@ -180,7 +188,8 @@ export default function useAppEmbedder(
const options = getAppOptions(app, createRoute)
.setLocale(locale)
.setDeviceId(deviceId)
.setRefreshToken(refreshToken);
.setRefreshToken(refreshToken)
.setLeadinConfig(getLeadinConfig());
const embedder = new IntegratedAppEmbedder(
AppIframe[app],

View File

@@ -19,6 +19,11 @@ export function configureRaven() {
instrument: {
tryCatch: false,
},
shouldSendCallback(data) {
return (
!!data && !!data.culprit && /plugins\/leadin\//.test(data.culprit)
);
},
release: leadinPluginVersion,
}
).install();

View File

@@ -0,0 +1,24 @@
import React from 'react';
import UIContainer from '../UIComponents/UIContainer';
import HubspotWrapper from './HubspotWrapper';
import { pluginPath } from '../../constants/leadinConfig';
import { __ } from '@wordpress/i18n';
export default function PreviewDisabled() {
const errorHeader = __('Preview Unavailable', 'leadin');
const errorMessage = `${__(
'This block cannot be previewed within the Full Site Editor',
'leadin'
)} ${__('Switch to the Block Editor to view the content', 'leadin')}`;
return (
<HubspotWrapper pluginPath={pluginPath}>
<UIContainer textAlign="center">
<h4>{errorHeader}</h4>
<p>
<b>{errorMessage}</b>
</p>
</UIContainer>
</HubspotWrapper>
);
}

View File

@@ -16,6 +16,7 @@ import { getOrCreateBackgroundApp } from '../../utils/backgroundAppUtils';
interface IFormEditProps extends IFormBlockProps {
preview: boolean;
origin: 'gutenberg' | 'elementor';
fullSiteEditor?: boolean;
}
function FormEdit({
@@ -24,6 +25,7 @@ function FormEdit({
setAttributes,
preview = true,
origin = 'gutenberg',
fullSiteEditor,
}: IFormEditProps) {
const { formId, formName } = attributes;
const formSelected = portalId && formId;
@@ -63,7 +65,13 @@ function FormEdit({
{formSelected && (
<Fragment>
{isSelected && <UISpacer />}
{preview && <PreviewForm portalId={portalId} formId={formId} />}
{preview && (
<PreviewForm
portalId={portalId}
formId={formId}
fullSiteEditor={fullSiteEditor}
/>
)}
</Fragment>
)}
</Fragment>

View File

@@ -1,29 +1,43 @@
import React, { useEffect, useRef } from 'react';
import UIOverlay from '../UIComponents/UIOverlay';
import { formsScriptPayload, hublet } from '../../constants/leadinConfig';
import useFormScript from './hooks/useFormsScript';
import {
formsScriptPayload,
hublet as region,
} from '../../constants/leadinConfig';
import PreviewDisabled from '../Common/PreviewDisabled';
export default function PreviewForm({
portalId,
formId,
fullSiteEditor,
}: {
portalId: number;
formId: string;
fullSiteEditor?: boolean;
}) {
const inputEl = useRef<HTMLDivElement>(null);
const ready = useFormScript();
useEffect(() => {
if (!ready) {
return;
}
if (inputEl.current) {
inputEl.current.innerHTML = '';
const embedScript = document.createElement('script');
embedScript.innerHTML = `hbspt.forms.create({ portalId: '${portalId}', formId: '${formId}', region: '${hublet}', ${formsScriptPayload} });`;
inputEl.current.appendChild(embedScript);
}
}, [formId, portalId, ready, inputEl]);
//@ts-expect-error Hubspot global
const hbspt = window.parent.hbspt || window.hbspt;
return <UIOverlay ref={inputEl} />;
const additionalParams = formsScriptPayload.includes('qa')
? { env: 'qa' }
: {};
hbspt.forms.create({
portalId,
formId,
region,
target: `#${inputEl.current.id}`,
...additionalParams,
});
}
}, [formId, portalId, inputEl]);
if (fullSiteEditor) {
return <PreviewDisabled />;
}
return <UIOverlay ref={inputEl} id={`hbspt-previewform-${formId}`} />;
}

View File

@@ -15,6 +15,7 @@ import { getOrCreateBackgroundApp } from '../../utils/backgroundAppUtils';
interface IMeetingEditProps extends IMeetingBlockProps {
preview?: boolean;
origin?: 'gutenberg' | 'elementor';
fullSiteEditor?: boolean;
}
function MeetingEdit({
@@ -23,6 +24,7 @@ function MeetingEdit({
setAttributes,
preview = true,
origin = 'gutenberg',
fullSiteEditor,
}: IMeetingEditProps) {
const isBackgroundAppReady = useBackgroundAppContext();
const monitorFormPreviewRender = usePostBackgroundMessage();
@@ -49,7 +51,9 @@ function MeetingEdit({
{(isSelected || !url) && (
<MeetingController url={url} handleChange={handleChange} />
)}
{preview && url && <PreviewMeeting url={url} />}
{preview && url && (
<PreviewMeeting url={url} fullSiteEditor={fullSiteEditor} />
)}
</Fragment>
);
}

View File

@@ -1,31 +1,36 @@
import React, { Fragment, useEffect, useRef } from 'react';
import UIOverlay from '../UIComponents/UIOverlay';
import useMeetingsScript from './hooks/useMeetingsScript';
import PreviewDisabled from '../Common/PreviewDisabled';
interface IPreviewForm {
url: string;
fullSiteEditor?: boolean;
}
export default function PreviewForm({ url }: IPreviewForm) {
const ready = useMeetingsScript();
export default function PreviewForm({ url, fullSiteEditor }: IPreviewForm) {
const inputEl = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!ready) {
return;
}
if (inputEl.current) {
inputEl.current.innerHTML = '';
const container = document.createElement('div');
container.dataset.src = `${url}?embed=true`;
container.classList.add('meetings-iframe-container');
inputEl.current.appendChild(container);
const embedScript = document.createElement('script');
embedScript.innerHTML =
'hbspt.meetings.create(".meetings-iframe-container");';
inputEl.current.appendChild(embedScript);
//@ts-expect-error Hubspot global
const hbspt = window.parent.hbspt || window.hbspt;
hbspt.meetings.create('.meetings-iframe-container');
}
}, [url, ready, inputEl]);
}, [url, inputEl]);
return <Fragment>{url && <UIOverlay ref={inputEl}></UIOverlay>}</Fragment>;
if (fullSiteEditor) {
return <PreviewDisabled />;
}
return (
<Fragment>
{url && (
<UIOverlay
ref={inputEl}
className="meetings-iframe-container"
data-src={`${url}?embed=true`}
></UIOverlay>
)}
</Fragment>
);
}

View File

@@ -19,7 +19,7 @@ export function initBackgroundApp(initFn: CallbackFn | CallbackFn[]) {
initApp(main);
}
export const getOrCreateBackgroundApp = (refreshToken: string) => {
export const getOrCreateBackgroundApp = (refreshToken = '') => {
if ((window as any).LeadinBackgroundApp) {
return (window as any).LeadinBackgroundApp;
}

View File

@@ -5,7 +5,7 @@ export const isFullSiteEditor = () => {
return select && !!select('core/edit-site');
};
const applyWithSelect = withSelect((select: Function, props: any): any => {
const applyWithSelect: any = withSelect((select: Function, props: any): any => {
return {
metaValue: select('core/editor').getEditedPostAttribute('meta')[
props.metaKey
@@ -13,7 +13,7 @@ const applyWithSelect = withSelect((select: Function, props: any): any => {
};
});
const applyWithDispatch = withDispatch(
const applyWithDispatch: any = withDispatch(
(dispatch: Function, props: any): any => {
return {
setMetaValue(value: string) {