Fix code style by updated eslint

[MAILPOET-3511]
This commit is contained in:
Jan Lysý
2021-03-26 14:41:04 +01:00
committed by Veljko V
parent 26f6dfa25d
commit 410c25482a
54 changed files with 325 additions and 319 deletions

View File

@ -31,6 +31,7 @@
// PropTypes
"react/prop-types": 0,
"react/jsx-props-no-spreading": 0,
"react/require-default-props": 0,
// Hooks
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
@ -255,4 +256,3 @@
}
]
}

View File

@ -1,6 +1,7 @@
import React from 'react';
import classnames from 'classnames';
/* eslint-disable react/no-unused-prop-types */
interface Props extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
dimension?: 'extra-small' | 'small' | 'large';

View File

@ -1,6 +1,6 @@
import MailPoet from 'mailpoet';
export default async function ({ endpoint, action, data }) {
export default async function callApi({ endpoint, action, data }) {
try {
const res = await MailPoet.Ajax.post({
api_version: MailPoet.apiVersion,

View File

@ -2,7 +2,7 @@ import MailPoet from 'mailpoet';
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export default async function ({ name, data, timeout = 0 }) {
export default async function trackEvent({ name, data, timeout = 0 }) {
MailPoet.trackEvent(name, data);
return sleep(timeout);
}

View File

@ -1,5 +1,6 @@
import React from 'react';
/* eslint-disable react/no-unused-prop-types */
type Props = {
title?: string;
iconStart?: JSX.Element;

View File

@ -5,5 +5,6 @@ export default function useSegmentsContext(data) {
all: data.mailpoetSegments,
// eslint-disable-next-line no-param-reassign
updateAll: (segments) => { data.mailpoetSegments = segments; },
/* eslint-disable-next-line react-hooks/exhaustive-deps */
}), [data.mailpoetSegments]);
}

View File

@ -48,7 +48,7 @@ FormFieldCheckbox.propTypes = {
onValueChange: PropTypes.func.isRequired,
field: PropTypes.shape({
name: PropTypes.string.isRequired,
values: PropTypes.object.isRequired,
values: PropTypes.objectOf(PropTypes.string),
}).isRequired,
item: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
};

View File

@ -191,13 +191,13 @@ FormField.propTypes = {
onValueChange: PropTypes.func,
field: PropTypes.shape({
name: PropTypes.string.isRequired,
values: PropTypes.object,
values: PropTypes.objectOf(PropTypes.string),
tip: PropTypes.oneOfType([
PropTypes.array,
PropTypes.string,
]),
label: PropTypes.string,
fields: PropTypes.array,
fields: PropTypes.arrayOf(PropTypes.object),
description: PropTypes.string,
}).isRequired,
item: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types

View File

@ -43,7 +43,7 @@ FormFieldRadio.propTypes = {
onValueChange: PropTypes.func,
field: PropTypes.shape({
name: PropTypes.string.isRequired,
values: PropTypes.object,
values: PropTypes.objectOf(PropTypes.string),
}).isRequired,
item: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
};
@ -54,5 +54,4 @@ FormFieldRadio.defaultProps = {
},
};
export default FormFieldRadio;

View File

@ -78,11 +78,17 @@ FormFieldSelect.propTypes = {
onValueChange: PropTypes.func,
field: PropTypes.shape({
name: PropTypes.string.isRequired,
values: PropTypes.object,
values: PropTypes.objectOf(PropTypes.string),
placeholder: PropTypes.string,
filter: PropTypes.func,
sortBy: PropTypes.func,
validation: PropTypes.object,
validation: PropTypes.shape({
'data-parsley-required': PropTypes.bool,
'data-parsley-required-message': PropTypes.string,
'data-parsley-type': PropTypes.string,
'data-parsley-errors-container': PropTypes.string,
maxLength: PropTypes.number,
}),
}).isRequired,
item: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
automationId: PropTypes.string,
@ -95,5 +101,4 @@ FormFieldSelect.defaultProps = {
},
};
export default FormFieldSelect;

View File

@ -346,13 +346,19 @@ Selection.propTypes = {
getCount: PropTypes.func,
getTag: PropTypes.func,
placeholder: PropTypes.string,
remoteQuery: PropTypes.object,
extendSelect2Options: PropTypes.object,
remoteQuery: PropTypes.object, // eslint-disable-line react/forbid-prop-types
extendSelect2Options: PropTypes.object, // eslint-disable-line react/forbid-prop-types
multiple: PropTypes.bool,
forceSelect2: PropTypes.bool,
transformChangedValue: PropTypes.func,
disabled: PropTypes.bool,
validation: PropTypes.object,
validation: PropTypes.shape({
'data-parsley-required': PropTypes.bool,
'data-parsley-required-message': PropTypes.string,
'data-parsley-type': PropTypes.string,
'data-parsley-errors-container': PropTypes.string,
maxLength: PropTypes.number,
}),
}).isRequired,
item: PropTypes.object, // eslint-disable-line react/forbid-prop-types
disabled: PropTypes.bool,
@ -368,5 +374,4 @@ Selection.defaultProps = {
item: undefined,
};
export default Selection;

View File

@ -71,7 +71,13 @@ FormFieldText.propTypes = {
]),
disabled: PropTypes.func,
placeholder: PropTypes.string,
validation: PropTypes.object,
validation: PropTypes.shape({
'data-parsley-required': PropTypes.bool,
'data-parsley-required-message': PropTypes.string,
'data-parsley-type': PropTypes.string,
'data-parsley-errors-container': PropTypes.string,
maxLength: PropTypes.number,
}),
customLabel: PropTypes.string,
tooltip: PropTypes.string,
}).isRequired,

View File

@ -24,7 +24,13 @@ FormFieldTextarea.propTypes = {
name: PropTypes.string,
placeholder: PropTypes.string,
defaultValue: PropTypes.string,
validation: PropTypes.object, // eslint-disable-line react/forbid-prop-types
validation: PropTypes.shape({
'data-parsley-required': PropTypes.bool,
'data-parsley-required-message': PropTypes.string,
'data-parsley-type': PropTypes.string,
'data-parsley-errors-container': PropTypes.string,
maxLength: PropTypes.number,
}),
className: PropTypes.string,
customLabel: PropTypes.string,
tooltip: PropTypes.string,

View File

@ -11,7 +11,6 @@ import MailPoet from 'mailpoet';
import icon from './icon.jsx';
import AddCustomFieldForm from './add_custom_field_form.jsx';
const AddCustomField = ({ clientId }) => {
const { createCustomField } = useDispatch('mailpoet-form-editor');

View File

@ -105,7 +105,6 @@ const CustomCheckboxEdit = ({ attributes, setAttributes, clientId }) => {
return attributes.label;
};
let checkboxLabel = getCheckboxLabel();
if (attributes.mandatory) {
checkboxLabel += ' *';

View File

@ -46,6 +46,7 @@ const CustomHtmlEdit = ({ attributes, setAttributes, clientId }) => {
[]
);
const [renderedContent, setRenderedContent] = useState(attributes.content);
/* eslint-disable-next-line react-hooks/exhaustive-deps -- because we use external function */
const setRenderedContentDebounced = useCallback(debounce((content) => {
setRenderedContent(content);
}, 300), []);

View File

@ -63,7 +63,6 @@ const Preview = ({
updateSegment(segment);
};
const onDragEnd = (result) => {
const from = result.source.index;
const to = result.destination.index;

View File

@ -33,7 +33,6 @@ export const Settings: React.FunctionComponent = () => (
</>
);
export const SettingsInSidebar: React.FunctionComponent = () => (
<div className="edit-post-sidebar mailpoet_form_editor_sidebar">
<SizeSettings

View File

@ -25,7 +25,6 @@ const CustomCssPanel = ({ onToggle, isOpened }) => {
);
};
CustomCssPanel.propTypes = {
onToggle: PropTypes.func.isRequired,
isOpened: PropTypes.bool.isRequired,

View File

@ -321,13 +321,19 @@ Selection.propTypes = {
getSearchLabel: PropTypes.func,
getValue: PropTypes.func,
placeholder: PropTypes.string,
remoteQuery: PropTypes.object,
extendSelect2Options: PropTypes.object,
remoteQuery: PropTypes.object, // eslint-disable-line react/forbid-prop-types
extendSelect2Options: PropTypes.object, // eslint-disable-line react/forbid-prop-types
multiple: PropTypes.bool,
forceSelect2: PropTypes.bool,
transformChangedValue: PropTypes.func,
disabled: PropTypes.bool,
validation: PropTypes.object,
validation: PropTypes.shape({
'data-parsley-required': PropTypes.bool,
'data-parsley-required-message': PropTypes.string,
'data-parsley-type': PropTypes.string,
'data-parsley-errors-container': PropTypes.string,
maxLength: PropTypes.number,
}),
}).isRequired,
item: PropTypes.object, // eslint-disable-line react/forbid-prop-types
disabled: PropTypes.bool,
@ -345,5 +351,4 @@ Selection.defaultProps = {
dropDownParent: undefined,
};
export default Selection;

View File

@ -11,7 +11,6 @@ import Preview from 'common/preview/preview.jsx';
import Modal from 'common/modal/modal';
import PlacementSettingsPanel from 'form_editor/components/form_settings/form_placement_options/settings_panel';
const FormPreview: React.FunctionComponent = () => {
const iframeElement = useRef(null);
const [iframeLoaded, setIframeLoaded] = useState(false);

View File

@ -2,6 +2,6 @@ import '@wordpress/format-library'; // load default formats (bold, italic, ...)
import { registerFormatType } from '@wordpress/rich-text';
import * as FontSelectionFormat from './font_selection_format';
export default function (): void {
export default function Init(): void {
registerFormatType(FontSelectionFormat.name, FontSelectionFormat.settings);
}

View File

@ -109,7 +109,6 @@ const historyMove = (state, increment: number) => {
};
};
export const historyUndo = (state) => (historyMove(state, 1));
export const historyRedo = (state) => (historyMove(state, -1));

View File

@ -1,4 +1,3 @@
function asNum(num?: string): number | undefined {
const numI = parseInt(num, 10);
if (Number.isNaN(numI)) {

View File

@ -93,7 +93,6 @@ Handlebars.registerHelper('lookup', function lookupHelper(obj, field) {
return obj && obj[field];
});
Handlebars.registerHelper('rsa_key', function rsaKeyHelper(value) {
var lines;
// extract all lines into an array

View File

@ -11,18 +11,6 @@ class ListingBulkActions extends React.Component {
this.handleApplyAction = this.handleApplyAction.bind(this);
}
getSelectedAction(actionName) {
const selectedAction = actionName;
if (selectedAction.length > 0) {
const action = this.props.bulk_actions.filter((act) => (act.name === selectedAction));
if (action.length > 0) {
return action[0];
}
}
return null;
}
handleApplyAction(actionName) {
const action = this.getSelectedAction(actionName);
@ -67,6 +55,18 @@ class ListingBulkActions extends React.Component {
});
}
getSelectedAction(actionName) {
const selectedAction = actionName;
if (selectedAction.length > 0) {
const action = this.props.bulk_actions.filter((act) => (act.name === selectedAction));
if (action.length > 0) {
return action[0];
}
}
return null;
}
render() {
if (this.props.bulk_actions.length === 0) {
return null;

View File

@ -42,17 +42,17 @@ class ListingSearch extends React.Component {
}
}
onChange(e) {
this.setState({ search: e.target.value });
this.debouncedHandleSearch();
}
handleSearch() {
this.props.onSearch(
this.state.search.trim()
);
}
onChange(e) {
this.setState({ search: e.target.value });
this.debouncedHandleSearch();
}
render() {
if (this.props.search === false) {
return false;

View File

@ -59,7 +59,6 @@ const Log: React.FunctionComponent<LogProps> = ({ log }: LogProps) => {
);
};
export type FilterType = {
from?: string;
to?: string;

View File

@ -81,7 +81,6 @@ BL.DraggableBehavior = Marionette.Behavior.extend({
event.interaction.element = clone;
if (that.options.hideOriginal === true) {
that.view.$el.addClass('mailpoet_hidden');
}

View File

@ -105,5 +105,4 @@ App.on('before:start', function beforeAppStart(BeforeStartApp) {
});
});
export default Module;

View File

@ -113,5 +113,4 @@ App.on('start', function appOnStart(Application, options) {
}, this);
});
export default Module;

View File

@ -95,10 +95,4 @@ export const EventOptions = ({
);
};
EventOptions.defaultProps = {
eventOptions: null,
selected: [],
onValueChange: null,
};
export default EventOptions;

View File

@ -33,34 +33,25 @@ class EventScheduling extends React.Component {
}
}
displayAfterTimeNumberField() {
const { afterTimeNumberSize, event } = this.props;
const { afterTimeType, afterTimeNumber } = this.state;
if (afterTimeType === 'immediate') return null;
if (
event.timeDelayValues
&& event.timeDelayValues[afterTimeType]
&& !event.timeDelayValues[afterTimeType].displayAfterTimeNumberField
) return null;
handleChange(e, property) {
let { value } = e.target;
if (property === 'afterTimeNumber') {
value = parseInt(e.target.value, 10);
value = Number.isNaN(value) ? null : value;
}
const data = { [property]: value };
const props = {
field: {
id: 'scheduling_time_duration',
name: 'scheduling_time_duration',
defaultValue: afterTimeNumber ? afterTimeNumber.toString() : '',
size: afterTimeNumberSize,
},
item: {},
onValueChange: _.partial(this.handleChange, _, 'afterTimeNumber'),
};
return (
<Text
field={props.field}
item={props.item}
onValueChange={props.onValueChange}
/>
);
// Reset afterTimeNumber to default when switching between minutes and other types
const { afterTimeType } = this.state;
if (property === 'afterTimeType' && afterTimeType !== value) {
if (afterTimeType === 'minutes') {
data.afterTimeNumber = defaultAfterTimeNumber;
}
if (value === 'minutes') {
data.afterTimeNumber = defaultAfterTimeNumberForMinutes;
}
}
this.setState(data, this.propagateChange(data));
}
displayAfterTimeTypeOptions() {
@ -97,25 +88,34 @@ class EventScheduling extends React.Component {
);
}
handleChange(e, property) {
let { value } = e.target;
if (property === 'afterTimeNumber') {
value = parseInt(e.target.value, 10);
value = Number.isNaN(value) ? null : value;
}
const data = { [property]: value };
displayAfterTimeNumberField() {
const { afterTimeNumberSize, event } = this.props;
const { afterTimeType, afterTimeNumber } = this.state;
if (afterTimeType === 'immediate') return null;
if (
event.timeDelayValues
&& event.timeDelayValues[afterTimeType]
&& !event.timeDelayValues[afterTimeType].displayAfterTimeNumberField
) return null;
// Reset afterTimeNumber to default when switching between minutes and other types
const { afterTimeType } = this.state;
if (property === 'afterTimeType' && afterTimeType !== value) {
if (afterTimeType === 'minutes') {
data.afterTimeNumber = defaultAfterTimeNumber;
}
if (value === 'minutes') {
data.afterTimeNumber = defaultAfterTimeNumberForMinutes;
}
}
this.setState(data, this.propagateChange(data));
const props = {
field: {
id: 'scheduling_time_duration',
name: 'scheduling_time_duration',
defaultValue: afterTimeNumber ? afterTimeNumber.toString() : '',
size: afterTimeNumberSize,
},
item: {},
onValueChange: _.partial(this.handleChange, _, 'afterTimeNumber'),
};
return (
<Text
field={props.field}
item={props.item}
onValueChange={props.onValueChange}
/>
);
}
propagateChange(data) {

View File

@ -50,6 +50,78 @@ class EventsConditions extends React.Component {
};
}
handleChange(data) {
const { segment, afterTimeNumber } = this.state;
const newState = data;
if (newState.eventSlug) {
newState.event = this.getEvent(newState.eventSlug);
// keep the existing segment (if set) or set it to the first segment in the list
newState.segment = (newState.event.sendToLists)
? segment || this.constructor.getFirstSegment() : null;
// if the new event doesn't have options, reset the currently selected option value
const eventOptions = this.constructor.getEventOptions(newState.event);
newState.eventOptionValue = (eventOptions)
? this.constructor.getEventOptionsFirstValue(eventOptions) : null;
}
if (newState.afterTimeType && newState.afterTimeType === 'immediate') {
newState.afterTimeNumber = null;
} else if (newState.afterTimeType && !newState.afterTimeNumber && !afterTimeNumber) {
newState.afterTimeNumber = defaultAfterTimeNumber;
}
this.setState(newState);
}
handleNextStep() {
const { history } = this.props;
const {
eventSlug, afterTimeType, afterTimeNumber, event, segment, eventOptionValue,
} = this.state;
const options = {
group: this.email.slug,
event: eventSlug,
afterTimeType,
};
if (afterTimeNumber) options.afterTimeNumber = afterTimeNumber;
options.sendTo = (event.sendToLists) ? 'segment' : 'user';
if (segment) options.segment = segment;
if (eventOptionValue) {
options.meta = JSON.stringify({ option: eventOptionValue });
}
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'newsletters',
action: 'create',
data: {
type: 'automatic',
subject: MailPoet.I18n.t('draftNewsletterTitle'),
options,
},
}).done((response) => {
MailPoet.trackEvent('Emails > New Automatic Email Created', {
'MailPoet Premium version': window.mailpoet_premium_version,
'MailPoet Free version': window.mailpoet_version,
'Event type': options.event,
'Schedule type': options.afterTimeType,
'Schedule value': options.afterTimeNumber,
});
history.push(`/template/${response.data.id}`);
}).fail((response) => {
if (response.errors.length > 0) {
this.context.notices.error(
response.errors.map((error) => <p key={error.message}>{error.message}</p>),
{ scroll: true }
);
}
});
}
getEvent(eventSlug) {
return this.emailEvents[eventSlug];
}
@ -140,78 +212,6 @@ class EventsConditions extends React.Component {
) : null;
}
handleChange(data) {
const { segment, afterTimeNumber } = this.state;
const newState = data;
if (newState.eventSlug) {
newState.event = this.getEvent(newState.eventSlug);
// keep the existing segment (if set) or set it to the first segment in the list
newState.segment = (newState.event.sendToLists)
? segment || this.constructor.getFirstSegment() : null;
// if the new event doesn't have options, reset the currently selected option value
const eventOptions = this.constructor.getEventOptions(newState.event);
newState.eventOptionValue = (eventOptions)
? this.constructor.getEventOptionsFirstValue(eventOptions) : null;
}
if (newState.afterTimeType && newState.afterTimeType === 'immediate') {
newState.afterTimeNumber = null;
} else if (newState.afterTimeType && !newState.afterTimeNumber && !afterTimeNumber) {
newState.afterTimeNumber = defaultAfterTimeNumber;
}
this.setState(newState);
}
handleNextStep() {
const { history } = this.props;
const {
eventSlug, afterTimeType, afterTimeNumber, event, segment, eventOptionValue,
} = this.state;
const options = {
group: this.email.slug,
event: eventSlug,
afterTimeType,
};
if (afterTimeNumber) options.afterTimeNumber = afterTimeNumber;
options.sendTo = (event.sendToLists) ? 'segment' : 'user';
if (segment) options.segment = segment;
if (eventOptionValue) {
options.meta = JSON.stringify({ option: eventOptionValue });
}
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'newsletters',
action: 'create',
data: {
type: 'automatic',
subject: MailPoet.I18n.t('draftNewsletterTitle'),
options,
},
}).done((response) => {
MailPoet.trackEvent('Emails > New Automatic Email Created', {
'MailPoet Premium version': window.mailpoet_premium_version,
'MailPoet Free version': window.mailpoet_version,
'Event type': options.event,
'Schedule type': options.afterTimeType,
'Schedule value': options.afterTimeNumber,
});
history.push(`/template/${response.data.id}`);
}).fail((response) => {
if (response.errors.length > 0) {
this.context.notices.error(
response.errors.map((error) => <p key={error.message}>{error.message}</p>),
{ scroll: true }
);
}
});
}
render() {
return (
<div>

View File

@ -34,9 +34,64 @@ class SendEventConditions extends React.Component {
};
}
displayHeader() {
const { event } = this.state;
return event.title;
handleChange(data) {
const { afterTimeNumber } = this.state;
const newState = data;
if (newState.afterTimeType && newState.afterTimeType === 'immediate') {
newState.afterTimeNumber = null;
} else if (newState.afterTimeType && !newState.afterTimeNumber && !afterTimeNumber) {
newState.afterTimeNumber = defaultAfterTimeNumber;
}
this.setState(data, this.propagateChange);
}
displayScheduling() {
const { afterTimeNumber, afterTimeType, event } = this.state;
const props = {
item: {
afterTimeNumber,
afterTimeType,
},
event,
onValueChange: this.handleChange,
};
return (
<EventScheduling
item={props.item}
event={props.event}
onValueChange={props.onValueChange}
/>
);
}
displaySegments() {
const { segment } = this.state;
if (this.emailOptions.sendTo === 'user') return null;
const props = {
field: {
id: 'segments',
forceSelect2: true,
values: this.segments,
extendSelect2Options: {
minimumResultsForSearch: Infinity,
},
selected: () => segment,
},
onValueChange: (e) => this.handleChange({ segment: e.target.value }),
};
return (
<div className="event-segment-selection">
<Selection
field={props.field}
onValueChange={props.onValueChange}
/>
</div>
);
}
displayEventOptions() {
@ -75,64 +130,9 @@ class SendEventConditions extends React.Component {
);
}
displaySegments() {
const { segment } = this.state;
if (this.emailOptions.sendTo === 'user') return null;
const props = {
field: {
id: 'segments',
forceSelect2: true,
values: this.segments,
extendSelect2Options: {
minimumResultsForSearch: Infinity,
},
selected: () => segment,
},
onValueChange: (e) => this.handleChange({ segment: e.target.value }),
};
return (
<div className="event-segment-selection">
<Selection
field={props.field}
onValueChange={props.onValueChange}
/>
</div>
);
}
displayScheduling() {
const { afterTimeNumber, afterTimeType, event } = this.state;
const props = {
item: {
afterTimeNumber,
afterTimeType,
},
event,
onValueChange: this.handleChange,
};
return (
<EventScheduling
item={props.item}
event={props.event}
onValueChange={props.onValueChange}
/>
);
}
handleChange(data) {
const { afterTimeNumber } = this.state;
const newState = data;
if (newState.afterTimeType && newState.afterTimeType === 'immediate') {
newState.afterTimeNumber = null;
} else if (newState.afterTimeType && !newState.afterTimeNumber && !afterTimeNumber) {
newState.afterTimeNumber = defaultAfterTimeNumber;
}
this.setState(data, this.propagateChange);
displayHeader() {
const { event } = this.state;
return event.title;
}
propagateChange() {

View File

@ -274,7 +274,6 @@ class NewsletterListNotification extends React.Component {
break;
}
return (
<span>
{ sendingToSegments }

View File

@ -201,7 +201,9 @@ NewsletterListNotificationHistory.propTypes = {
pathname: PropTypes.string,
}).isRequired,
match: PropTypes.shape({
params: PropTypes.object,
params: PropTypes.shape({
id: PropTypes.node,
}).isRequired,
}).isRequired,
};

View File

@ -16,6 +16,8 @@ const QueuePropType = PropTypes.shape({
const NewsletterPropType = PropTypes.shape({
id: PropTypes.number.isRequired,
sent_at: PropTypes.string,
status: PropTypes.string.isRequired,
queue: PropTypes.oneOfType([
QueuePropType,
PropTypes.bool,

View File

@ -138,7 +138,13 @@ DateText.propTypes = {
storageFormat: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
disabled: PropTypes.bool.isRequired,
validation: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
validation: PropTypes.shape({
'data-parsley-required': PropTypes.bool,
'data-parsley-required-message': PropTypes.string,
'data-parsley-type': PropTypes.string,
'data-parsley-errors-container': PropTypes.string,
maxLength: PropTypes.number,
}).isRequired,
};
DateText.defaultProps = {

View File

@ -12,6 +12,31 @@ class ImportTemplate extends React.Component {
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e) {
e.preventDefault();
if (_.size(this.fileRef.current.files) <= 0) {
return false;
}
const file = _.first(this.fileRef.current.files);
const reader = new FileReader();
reader.onload = (evt) => {
try {
this.saveTemplate(JSON.parse(evt.target.result));
MailPoet.trackEvent('Emails > Template imported', {
'MailPoet Free version': window.mailpoet_version,
});
} catch (err) {
this.context.notices.error(<p>{MailPoet.I18n.t('templateFileMalformedError')}</p>);
}
};
reader.readAsText(file);
return true;
}
saveTemplate(saveTemplate) {
const template = saveTemplate;
const { beforeImport, afterImport } = this.props;
@ -41,7 +66,6 @@ class ImportTemplate extends React.Component {
template.categories = JSON.stringify(template.categories);
beforeImport();
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
@ -61,31 +85,6 @@ class ImportTemplate extends React.Component {
});
}
handleSubmit(e) {
e.preventDefault();
if (_.size(this.fileRef.current.files) <= 0) {
return false;
}
const file = _.first(this.fileRef.current.files);
const reader = new FileReader();
reader.onload = (evt) => {
try {
this.saveTemplate(JSON.parse(evt.target.result));
MailPoet.trackEvent('Emails > Template imported', {
'MailPoet Free version': window.mailpoet_version,
});
} catch (err) {
this.context.notices.error(<p>{MailPoet.I18n.t('templateFileMalformedError')}</p>);
}
};
reader.readAsText(file);
return true;
}
render() {
return (
<div>

View File

@ -77,7 +77,6 @@ const NewsletterTypes: React.FunctionComponent<Props> = ({
return null;
};
const renderType = (type): JSX.Element => {
const badgeClassName = (window.mailpoet_is_new_user === true) ? 'mailpoet_badge mailpoet_badge_video' : 'mailpoet_badge mailpoet_badge_video mailpoet_badge_video_grey';

View File

@ -27,7 +27,6 @@ jQuery(($) => {
setTimeout(renderCaptcha, 400, element, 1);
});
/**
* @param form jQuery object of form form.mailpoet_form
*/

View File

@ -59,6 +59,45 @@ class DynamicSegmentForm extends React.Component {
this.onItemLoad = this.onItemLoad.bind(this);
}
handleValueChange(e) {
const { item } = this.state;
const field = e.target.name;
item[field] = e.target.value;
this.setState({
item,
});
this.loadFields();
return true;
}
handleSave(e) {
const { item } = this.state;
const { history, match } = this.props;
e.preventDefault();
this.setState({ errors: undefined });
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'dynamic_segments',
action: 'save',
data: item,
}).done(() => {
history.push('/segments');
if (match.params.id !== undefined) {
messages.onUpdate();
} else {
messages.onCreate(item);
}
}).fail((response) => {
if (response.errors.length > 0) {
this.setState({ errors: response.errors });
}
});
}
onItemLoad(loadedData) {
const item = _.mapObject(loadedData, (val) => (_.isNull(val) ? '' : val));
this.setState({ item }, this.loadFields);
@ -165,45 +204,6 @@ class DynamicSegmentForm extends React.Component {
});
}
handleValueChange(e) {
const { item } = this.state;
const field = e.target.name;
item[field] = e.target.value;
this.setState({
item,
});
this.loadFields();
return true;
}
handleSave(e) {
const { item } = this.state;
const { history, match } = this.props;
e.preventDefault();
this.setState({ errors: undefined });
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'dynamic_segments',
action: 'save',
data: item,
}).done(() => {
history.push('/segments');
if (match.params.id !== undefined) {
messages.onUpdate();
} else {
messages.onCreate(item);
}
}).fail((response) => {
if (response.errors.length > 0) {
this.setState({ errors: response.errors });
}
});
}
render() {
const fields = this.getFields();
const { match } = this.props;

View File

@ -30,7 +30,6 @@ const MssNotActiveMessage = ({ activationCallback }: MssNotActiveMessageProps) =
</div>
);
type Props = {
keyMessage?: string;
activationCallback: () => void;

View File

@ -33,7 +33,7 @@ const NotValidMessage = ({ message }: NotValidMessageProps) => (
</div>
);
NotValidMessage.defaultProps = {
keyMessage: '',
message: '',
};
type Props = {

View File

@ -15,5 +15,4 @@ export type Tail<T extends any[]> =
export type ExcludeFirstParam<F extends ((...args: any[]) => any)> =
(...args: Tail<Parameters<F>>) => ReturnType<F>
export type ValueAndSetter<T> = [T, (value: T) => any]

View File

@ -1,7 +1,6 @@
import jQuery from 'jquery';
import MailPoet from 'mailpoet';
export default (onCreateSegment) => {
MailPoet.Modal.popup({
title: MailPoet.I18n.t('addNewList'),

View File

@ -1,4 +1,3 @@
export default (subscribers, header) => {
const displayedColumns = [];
const displayedColumnsIds = [];

View File

@ -53,5 +53,4 @@ LastSentQuestion.propTypes = {
onSubmit: PropTypes.func.isRequired,
};
export default LastSentQuestion;

View File

@ -1,4 +1,3 @@
const notFreeAddress = ({ name, address }) => ({
sender: { name, address },
reply_to: { name, address },

View File

@ -24,7 +24,6 @@ export const Controls = (props) => (
href={props.mailpoetAccountUrl}
target="_blank"
rel="noopener noreferrer"
onClick={(event) => {
event.preventDefault();
window.open(props.mailpoetAccountUrl);

View File

@ -33,7 +33,6 @@ const data = {
deleted_at: null,
};
describe('Form Data Load Mapper', () => {
it('Returns ID', () => {
expect(map(data)).to.have.property('id', '1');

View File

@ -33,7 +33,6 @@ const data = {
deleted_at: null,
};
describe('Form Data Save Mapper', () => {
it('Returns ID', () => {
expect(map(data)).to.have.property('id', '1');
@ -50,7 +49,7 @@ describe('Form Data Save Mapper', () => {
it('Returns dates', () => {
expect(map(data)).to.have.property('created_at', '2020-01-15 07:39:15');
expect(map(data)).to.have.property('updated_at', '2020-01-28 10:28:02');
expect(map(data)).to.have.property('deleted_at').that.is.null;
expect(map(data)).to.have.property('deleted_at').that.is.null;// eslint-disable-line no-unused-expressions
});
describe('Settings', () => {

View File

@ -33,7 +33,6 @@ global.$ = jQuery;
global.jQuery = jQuery;
global.window.jQuery = jQuery;
testHelpers.loadScript('tests/javascript_newsletter_editor/testBundles/vendor.js', global.window);
const Handlebars = global.window.Handlebars;
global.Handlebars = global.window.Handlebars;
@ -186,7 +185,6 @@ testHelpers.loadTemplate('components/sidebar/layout.hbs', window, { id: 'newslet
testHelpers.loadTemplate('components/sidebar/preview.hbs', window, { id: 'newsletter_editor_template_sidebar_preview' });
testHelpers.loadTemplate('components/sidebar/styles.hbs', window, { id: 'newsletter_editor_template_sidebar_styles' });
global.templates = {
styles: Handlebars.compile(jQuery('#newsletter_editor_template_styles').html()),
save: Handlebars.compile(jQuery('#newsletter_editor_template_save').html()),