Add module entry files and expose mailpoet module

- Expose mailpoet and dependencies for premium plugin to use
- Update type definitions for window
- Fix typings
- Get rid of side-effects in mailpoet.js(ts)

[MAILPOET-3140]
This commit is contained in:
Sam Najian
2022-02-10 16:24:33 +01:00
committed by Veljko V
parent 573cec0fda
commit 6b470981ae
30 changed files with 130 additions and 87 deletions

View File

@ -67,9 +67,9 @@
"no-only-tests/no-only-tests": 2, "no-only-tests/no-only-tests": 2,
"no-script-url": 0, "no-script-url": 0,
"@typescript-eslint/no-unsafe-return": 0, // we need to disable it for wordpress select :( "@typescript-eslint/no-unsafe-return": 0, // we need to disable it for wordpress select :(
"@typescript-eslint/no-unsafe-member-access": 0, // this needs to be off until mailpoet.js is converted to typescript "@typescript-eslint/no-unsafe-member-access": 0, // this needs to be off until we have typed assignments :(
"@typescript-eslint/no-unsafe-call": 0, // this needs to be off until mailpoet.js is converted to typescript "@typescript-eslint/no-unsafe-call": 0, // this needs to be off until we have typed assignments :(
"@typescript-eslint/no-unsafe-assignment": 0, // this needs to be off until mailpoet.js is converted to typescript "@typescript-eslint/no-unsafe-assignment": 0, // this needs to be off until we have typed assignments :(
"import/extensions": 0, // we wouldn't be able to import jQuery without this line "import/extensions": 0, // we wouldn't be able to import jQuery without this line
"import/prefer-default-export": 0, // we want to stop using default exports and start using named exports "import/prefer-default-export": 0, // we want to stop using default exports and start using named exports
"react/destructuring-assignment": 0, // that would be too many changes to fix this one "react/destructuring-assignment": 0, // that would be too many changes to fix this one

View File

@ -1,4 +1,4 @@
import MailPoet from 'mailpoet'; import { MailPoetI18n } from './i18n';
import jQuery from 'jquery'; import jQuery from 'jquery';
import _ from 'underscore'; import _ from 'underscore';
@ -27,7 +27,7 @@ jQuery(document).on('heartbeat-tick.mailpoet-ajax', (event, data) => {
} }
}); });
MailPoet.Ajax = { export const MailPoetAjax = {
version: 0.5, version: 0.5,
options: {}, options: {},
defaults: { defaults: {
@ -104,9 +104,9 @@ MailPoet.Ajax = {
}).then(deferred.resolve, (failedXhr, textStatus) => { }).then(deferred.resolve, (failedXhr, textStatus) => {
let errorData; let errorData;
if (textStatus === 'timeout') { if (textStatus === 'timeout') {
errorData = buildErrorResponse(MailPoet.I18n.t('ajaxTimeoutErrorMessage').replace('%d', timeout.toString())); errorData = buildErrorResponse(MailPoetI18n.t('ajaxTimeoutErrorMessage').replace('%d', timeout.toString()));
} else { } else {
errorData = requestFailed(MailPoet.I18n.t('ajaxFailedErrorMessage'), failedXhr); errorData = requestFailed(MailPoetI18n.t('ajaxFailedErrorMessage'), failedXhr);
} }
deferred.reject(errorData); deferred.reject(errorData);
}); });

View File

@ -7,7 +7,6 @@
* even if it has been disabled. * even if it has been disabled.
* *
*/ */
import MailPoet from 'mailpoet';
import _ from 'underscore'; import _ from 'underscore';
/** /**
@ -38,12 +37,12 @@ function track(name, data = []) {
} }
function exportMixpanel() { function exportMixpanel() {
MailPoet.forceTrackEvent = track; window.MailPoet.forceTrackEvent = track;
if (window.mailpoet_analytics_enabled && MailPoet.libs3rdPartyEnabled) { if (window.mailpoet_analytics_enabled && window.MailPoet.libs3rdPartyEnabled) {
MailPoet.trackEvent = track; window.MailPoet.trackEvent = track;
} else { } else {
MailPoet.trackEvent = function emptyFunction() {}; window.MailPoet.trackEvent = function emptyFunction() {};
} }
} }
@ -72,7 +71,7 @@ function initializeMixpanelWhenLoaded() {
} }
} }
MailPoet.trackEvent = _.partial(cacheEvent, false); export const MailPoetTrackEvent = _.partial(cacheEvent, false);
MailPoet.forceTrackEvent = _.partial(cacheEvent, true); export const MailPoetForceTrackEvent = _.partial(cacheEvent, true);
initializeMixpanelWhenLoaded(); initializeMixpanelWhenLoaded();

View File

@ -0,0 +1,2 @@
export * from './select/select';
export * from './input/input';

View File

@ -2,3 +2,8 @@ export { default as Button } from './button/button';
export { default as Loader } from './loader/loader'; export { default as Loader } from './loader/loader';
export { default as Tab } from './tabs/tab'; export { default as Tab } from './tabs/tab';
export { default as Tag } from './tag/tag'; export { default as Tag } from './tag/tag';
export { default as TypographyHeading } from './typography/heading/heading';
export { default as PremiumRequired } from './premium_required/premium_required';
export { default as Loading } from './loading';
export { default as Badge } from './listings/newsletter_stats/badge';
export * from './form';

View File

@ -0,0 +1,2 @@
export * from './newsletter_stats';
export * from './newsletter_status';

View File

@ -0,0 +1,2 @@
export * from './badge';
export * from './stats';

View File

@ -6,14 +6,12 @@ import Modal from 'common/modal/modal';
import { GlobalContext } from 'context'; import { GlobalContext } from 'context';
import { noop } from 'lodash'; import { noop } from 'lodash';
const mailPoetApiVersion = MailPoet.apiVersion as string;
/** /**
* @param {string|null} address * @param {string|null} address
* @returns {Promise} * @returns {Promise}
*/ */
const handleSave = (address: string | null) => MailPoet.Ajax.post({ const handleSave = (address: string | null) => MailPoet.Ajax.post({
api_version: mailPoetApiVersion, api_version: MailPoet.apiVersion,
endpoint: 'settings', endpoint: 'settings',
action: 'setAuthorizedFromAddress', action: 'setAuthorizedFromAddress',
data: { data: {

View File

@ -0,0 +1 @@
export * from './tag';

View File

@ -165,4 +165,4 @@ export const MailPoetDate = {
return convertedFormat.join(''); return convertedFormat.join('');
}, },
isInFuture: (dateString: string): boolean => new Date(dateString).getTime() > Date.now(), isInFuture: (dateString: string): boolean => new Date(dateString).getTime() > Date.now(),
}; } as const;

View File

@ -59,7 +59,7 @@ const FixedBarSettings: React.FunctionComponent = () => {
onChange={compose([changeFormSettings, assocPath('formPlacement.fixedBar.delay', __, formSettings)])} onChange={compose([changeFormSettings, assocPath('formPlacement.fixedBar.delay', __, formSettings)])}
options={delayValues.map((delayValue) => ({ options={delayValues.map((delayValue) => ({
value: delayValue, value: delayValue,
label: MailPoet.I18n.t('formPlacementDelaySeconds').replace('%1s', delayValue), label: MailPoet.I18n.t('formPlacementDelaySeconds').replace('%1s', `${delayValue}`),
}))} }))}
/> />
</> </>

View File

@ -51,7 +51,7 @@ const PopUpSettings: React.FunctionComponent = () => {
onChange={compose([changeFormSettings, assocPath('formPlacement.popup.delay', __, formSettings)])} onChange={compose([changeFormSettings, assocPath('formPlacement.popup.delay', __, formSettings)])}
options={delayValues.map((delayValue) => ({ options={delayValues.map((delayValue) => ({
value: delayValue, value: delayValue,
label: MailPoet.I18n.t('formPlacementDelaySeconds').replace('%1s', delayValue), label: MailPoet.I18n.t('formPlacementDelaySeconds').replace('%1s', `${delayValue}`),
}))} }))}
/> />
<div> <div>

View File

@ -59,7 +59,7 @@ const SlideInSettings: React.FunctionComponent = () => {
onChange={compose([changeFormSettings, assocPath('formPlacement.slideIn.delay', __, formSettings)])} onChange={compose([changeFormSettings, assocPath('formPlacement.slideIn.delay', __, formSettings)])}
options={delayValues.map((delayValue) => ({ options={delayValues.map((delayValue) => ({
value: delayValue, value: delayValue,
label: MailPoet.I18n.t('formPlacementDelaySeconds').replace('%1s', delayValue), label: MailPoet.I18n.t('formPlacementDelaySeconds').replace('%1s', `${delayValue}`),
}))} }))}
/> />
</> </>

View File

@ -47,8 +47,38 @@ declare module '@woocommerce/blocks-checkout' {
} }
interface Window { interface Window {
mailpoet_date_offset?: string; mailpoet_feature_flags: string;
mailpoet_datetime_format?: string; mailpoet_referral_id: string;
mailpoet_date_format?: string; mailpoet_version: string;
mailpoet_time_format?: string; mailpoet_premium_version: string;
mailpoet_premium_link: string;
mailpoet_woocommerce_active: boolean;
mailpoet_premium_active: boolean;
mailpoet_subscribers_limit: number;
mailpoet_subscribers_limit_reached: boolean;
mailpoet_subscribers_count: number;
mailpoet_has_premium_support: boolean;
mailpoet_has_valid_api_key: boolean;
mailpoet_has_valid_premium_key: string;
mailpoet_mss_key_invalid: boolean;
mailpoet_mta_method: string;
mailpoet_date_offset: string;
mailpoet_time_format: string;
mailpoet_date_format: string;
mailpoet_listing_per_page: string;
mailpoet_3rd_party_libs_enabled: string;
mailpoet_datetime_format: string;
mailpoet_api_version: string;
mailpoet_email_regex: RegExp;
mailpoet_wp_segment_state: string;
mailpoet_wp_week_starts_on: number;
mailpoet_subscribers_counts_cache_created_at: string;
mailpoet_shortcode_links: string[];
mailpoet_settings: any;
mailpoet_tracking_config: string;
mailpoet_display_detailed_stats?: string;
mailpoet_premium_plugin_installed: boolean;
mailpoet_premium_plugin_download_url: string;
mailpoet_premium_plugin_activation_url: string;
mailpoet_plugin_partial_key: string;
} }

View File

@ -1,9 +1,8 @@
import TooltipComponent from 'help-tooltip.jsx'; import TooltipComponent from 'help-tooltip.jsx';
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import MailPoet from 'mailpoet';
MailPoet.helpTooltip = { export const MailPoetHelpTooltip = {
show: function show(domContainerNode, opts) { show: function show(domContainerNode, opts) {
ReactDOM.render(React.createElement( ReactDOM.render(React.createElement(
TooltipComponent, { TooltipComponent, {

View File

@ -1,17 +0,0 @@
import mp from 'mailpoet';
var MailPoet = mp;
var translations = {};
MailPoet.I18n = {
add: function add(key, value) {
translations[key] = value;
},
t: function t(key) {
return translations[key] || 'TRANSLATION "%1$s" NOT FOUND'.replace('%1$s', key);
},
all: function all() {
return translations;
},
};

View File

@ -0,0 +1,13 @@
const translations: Record<string, string> = {};
export const MailPoetI18n = {
add: function add(key: string, value: string): void {
translations[key] = value;
},
t: function t(key: string): string {
return translations[key] || 'TRANSLATION "%1$s" NOT FOUND'.replace('%1$s', key);
},
all: function all(): Record<string, string> {
return translations;
},
} as const;

View File

@ -1,7 +1,4 @@
import mp from 'mailpoet'; export const MailPoetIframe = {
var MailPoet = mp;
MailPoet.Iframe = {
marginY: 20, marginY: 20,
autoSize: function autoSize(iframe) { autoSize: function autoSize(iframe) {
if (!iframe) return; if (!iframe) return;
@ -20,5 +17,3 @@ MailPoet.Iframe = {
) + 'px'; ) + 'px';
}, },
}; };
export default MailPoet;

View File

@ -0,0 +1,4 @@
import './global.d.ts';
import { MailPoet } from './mailpoet';
export default MailPoet;

View File

@ -0,0 +1 @@
export { default as Listing } from './listing';

View File

@ -1,8 +1,18 @@
import FeaturesController from 'features_controller'; import FeaturesController from './features_controller';
import MailPoetComUrlFactory from 'mailpoet_com_url_factory'; import MailPoetComUrlFactory from './mailpoet_com_url_factory';
import { MailPoetDate as Date } from 'date'; import { MailPoetI18n } from './i18n';
import { MailPoetDate } from './date';
import { MailPoetAjax } from './ajax';
import { MailPoetModal } from './modal';
import { MailPoetNotice } from './notice';
// side effect - extends MailPoet object in initializeMixpanelWhenLoaded
import { MailPoetForceTrackEvent, MailPoetTrackEvent } from './analytics_event';
import { MailPoetNum } from './num';
import { MailPoetHelpTooltip } from './help-tooltip';
import { MailPoetIframe } from './iframe';
// A placeholder for MailPoet object // A placeholder for MailPoet object
var MailPoet = { export const MailPoet = {
FeaturesController: FeaturesController(window.mailpoet_feature_flags), FeaturesController: FeaturesController(window.mailpoet_feature_flags),
MailPoetComUrlFactory: MailPoetComUrlFactory(window.mailpoet_referral_id), MailPoetComUrlFactory: MailPoetComUrlFactory(window.mailpoet_referral_id),
version: window.mailpoet_version, version: window.mailpoet_version,
@ -25,25 +35,35 @@ var MailPoet = {
wpSegmentState: window.mailpoet_wp_segment_state, wpSegmentState: window.mailpoet_wp_segment_state,
wpWeekStartsOn: window.mailpoet_wp_week_starts_on, wpWeekStartsOn: window.mailpoet_wp_week_starts_on,
subscribersCountsCacheCreatedAt: window.mailpoet_subscribers_counts_cache_created_at, subscribersCountsCacheCreatedAt: window.mailpoet_subscribers_counts_cache_created_at,
getShortcodeLinks: () => (window.mailpoet_shortcode_links ? window.mailpoet_shortcode_links : []), getShortcodeLinks: (): string[] => (window.mailpoet_shortcode_links
? window.mailpoet_shortcode_links
: []
),
settings: window.mailpoet_settings, settings: window.mailpoet_settings,
trackingConfig: window.mailpoet_tracking_config || {}, trackingConfig: window.mailpoet_tracking_config || {},
Date, I18n: MailPoetI18n,
Date: MailPoetDate,
Ajax: MailPoetAjax,
Modal: MailPoetModal,
Notice: MailPoetNotice,
trackEvent: MailPoetTrackEvent,
forceTrackEvent: MailPoetForceTrackEvent,
Num: MailPoetNum,
helpTooltip: MailPoetHelpTooltip,
Iframe: MailPoetIframe,
isPremiumPluginInstalled: window.mailpoet_premium_plugin_installed, isPremiumPluginInstalled: window.mailpoet_premium_plugin_installed,
premiumPluginDownloadUrl: window.mailpoet_premium_plugin_download_url, premiumPluginDownloadUrl: window.mailpoet_premium_plugin_download_url,
premiumPluginActivationUrl: window.mailpoet_premium_plugin_activation_url, premiumPluginActivationUrl: window.mailpoet_premium_plugin_activation_url,
pluginPartialKey: window.mailpoet_plugin_partial_key, pluginPartialKey: window.mailpoet_plugin_partial_key,
}; } as const;
declare global {
interface Window {
MailPoet: typeof MailPoet;
}
}
// Expose MailPoet globally // Expose MailPoet globally
window.MailPoet = MailPoet; window.MailPoet = MailPoet;
export default MailPoet; export default MailPoet;
require('ajax'); // side effect - extends MailPoet object
require('i18n'); // side effect - extends MailPoet object
require('modal'); // side effect - extends MailPoet object
require('notice'); // side effect - extends MailPoet object
require('num'); // side effect - extends MailPoet object
require('analytics_event'); // side effect - extends MailPoet object
require('help-tooltip'); // side effect - extends MailPoet object

View File

@ -1,8 +1,6 @@
/* eslint-disable func-names */ /* eslint-disable func-names */
import mp from 'mailpoet';
import jQuery from 'jquery'; import jQuery from 'jquery';
var MailPoet = mp;
var closeModalImage = '<svg viewBox="0 0 23 23" xmlns="http://www.w3.org/2000/svg">' var closeModalImage = '<svg viewBox="0 0 23 23" xmlns="http://www.w3.org/2000/svg">'
+ '<path d="M21.454 1.546L1.546 21.454M1.546 1.546L21.454 21.454" stroke-width="3" stroke-linecap="round" />' + '<path d="M21.454 1.546L1.546 21.454M1.546 1.546L21.454 21.454" stroke-width="3" stroke-linecap="round" />'
+ '</svg>'; + '</svg>';
@ -26,7 +24,7 @@ var closeModalImage = '<svg viewBox="0 0 23 23" xmlns="http://www.w3.org/2000/sv
MailPoet.Modal.loading(bool); MailPoet.Modal.loading(bool);
************************************************************************** */ ************************************************************************** */
MailPoet.Modal = { export const MailPoetModal = {
version: 0.9, version: 0.9,
// flags // flags

View File

@ -33,14 +33,6 @@ type State = {
loading: boolean; loading: boolean;
} }
interface PageWindow extends Window {
mailpoet_display_detailed_stats: boolean;
mailpoet_mss_key_invalid: boolean;
mailpoet_subscribers_count: number;
}
declare let window: PageWindow;
const CampaignStatsPage = ({ match, history, location }: Props) => { const CampaignStatsPage = ({ match, history, location }: Props) => {
const [state, setState] = useState<State>({ const [state, setState] = useState<State>({
item: undefined, item: undefined,

View File

@ -60,7 +60,7 @@ export function Scheduling({
{ {
ReactStringReplace( ReactStringReplace(
MailPoet.I18n.t('reEngagementEmailWarning') MailPoet.I18n.t('reEngagementEmailWarning')
.replace('{$months}', Math.floor(inactiveSubscribersPeriod / 30)), .replace('{$months}', `${Math.floor(inactiveSubscribersPeriod / 30)}`),
/\[link\](.*?)\[\/link\]/g, /\[link\](.*?)\[\/link\]/g,
(match) => ( (match) => (
<a <a

View File

@ -1,4 +1,4 @@
import mp from 'mailpoet'; import { MailPoetI18n as I18n } from './i18n';
import jQuery from 'jquery'; // eslint-disable-line func-names import jQuery from 'jquery'; // eslint-disable-line func-names
/*= ========================================================================================== /*= ==========================================================================================
@ -23,8 +23,7 @@ import jQuery from 'jquery'; // eslint-disable-line func-names
MailPoet.Notice.system('You need to updated ASAP!'); MailPoet.Notice.system('You need to updated ASAP!');
=========================================================================================== */ =========================================================================================== */
var MailPoet = mp; export const MailPoetNotice = {
MailPoet.Notice = {
version: 1.0, version: 1.0,
// default options // default options
defaults: { defaults: {
@ -216,7 +215,7 @@ MailPoet.Notice = {
}, options)); }, options));
}, },
showApiErrorNotice: function showApiErrorNotice(response, options) { showApiErrorNotice: function showApiErrorNotice(response, options) {
var errorMessage = MailPoet.I18n.t('ajaxFailedErrorMessage'); var errorMessage = I18n.t('ajaxFailedErrorMessage');
if (response && response.errors && response.errors.length > 0) { if (response && response.errors && response.errors.length > 0) {
errorMessage = response.errors.map(error => error.message); errorMessage = response.errors.map(error => error.message);
} }

View File

@ -1,7 +1,4 @@
import mp from 'mailpoet'; export const MailPoetNum = {
var MailPoet = mp;
MailPoet.Num = {
toLocaleFixed: function (num, precisionOpts) { // eslint-disable-line func-names toLocaleFixed: function (num, precisionOpts) { // eslint-disable-line func-names
var precision = precisionOpts || 0; var precision = precisionOpts || 0;
var factor = Math.pow(10, precision); var factor = Math.pow(10, precision);

View File

@ -0,0 +1 @@
export * from './dynamic/types';

View File

@ -0,0 +1 @@
export * from './location_state';

View File

@ -0,0 +1 @@
export * from '../segments/dynamic/types';

View File

@ -138,7 +138,7 @@ const baseConfig = {
}, },
}, },
{ {
test: /listing.jsx/i, include: path.resolve(__dirname, 'assets/js/src/listing/index.ts'),
use: [ use: [
{ {
loader: 'expose-loader', loader: 'expose-loader',
@ -265,7 +265,7 @@ const adminConfig = {
'classnames', 'classnames',
'lodash', 'lodash',
'help-tooltip.jsx', 'help-tooltip.jsx',
'listing/listing.jsx', 'listing/index.ts',
'common/index.ts', 'common/index.ts',
'wp-data-hooks.js', 'wp-data-hooks.js',
'segments/dynamic/types.ts', 'segments/dynamic/types.ts',