Move default props to default parameters - simple cases

React throws a deprecation warning for defaultProps.
This commit refactors default props to default values in easy-to-fix cases.

[MAILPOET-6108]
This commit is contained in:
Rostislav Wolny
2024-06-13 16:57:04 +02:00
committed by Jan Lysý
parent b19c30d203
commit a3514377c8
59 changed files with 438 additions and 669 deletions

View File

@ -4,25 +4,31 @@ import ReactDOMServer from 'react-dom/server';
import { MailPoet } from 'mailpoet'; import { MailPoet } from 'mailpoet';
function ConfirmAlert(props) { function ConfirmAlert({
message,
onConfirm,
title = __('Confirm to proceed', 'mailpoet'),
cancelLabel = __('Cancel', 'mailpoet'),
confirmLabel = __('Confirm', 'mailpoet'),
}) {
MailPoet.Modal.popup({ MailPoet.Modal.popup({
title: props.title, title,
template: ReactDOMServer.renderToString( template: ReactDOMServer.renderToString(
<> <>
<p>{props.message}</p> <p>{message}</p>
<button <button
id="mailpoet_alert_cancel" id="mailpoet_alert_cancel"
className="button button-secondary" className="button button-secondary"
type="button" type="button"
> >
{props.cancelLabel} {cancelLabel}
</button> </button>
<button <button
id="mailpoet_alert_confirm" id="mailpoet_alert_confirm"
className="button button-primary" className="button button-primary"
type="submit" type="submit"
> >
{props.confirmLabel} {confirmLabel}
</button> </button>
</>, </>,
), ),
@ -31,7 +37,7 @@ function ConfirmAlert(props) {
.getElementById('mailpoet_alert_confirm') .getElementById('mailpoet_alert_confirm')
.addEventListener('click', () => { .addEventListener('click', () => {
MailPoet.Modal.close(); MailPoet.Modal.close();
props.onConfirm(); onConfirm();
}); });
document document
@ -50,12 +56,6 @@ ConfirmAlert.propTypes = {
onConfirm: PropTypes.func.isRequired, onConfirm: PropTypes.func.isRequired,
}; };
ConfirmAlert.defaultProps = {
title: __('Confirm to proceed', 'mailpoet'),
cancelLabel: __('Cancel', 'mailpoet'),
confirmLabel: __('Confirm', 'mailpoet'),
};
export function confirmAlert(props) { export function confirmAlert(props) {
// the below render is only to invoke proptypes on ConfirmAlert // the below render is only to invoke proptypes on ConfirmAlert
ReactDOMServer.renderToString( ReactDOMServer.renderToString(

View File

@ -1,10 +1,10 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
function KeyValueTable(props) { function KeyValueTable({ rows, max_width: maxWidth = 'auto' }) {
return ( return (
<table className="widefat fixed" style={{ maxWidth: props.max_width }}> <table className="widefat fixed" style={{ maxWidth }}>
<tbody> <tbody>
{props.rows.map((row) => ( {rows.map((row) => (
<tr key={`row_${row.key}`}> <tr key={`row_${row.key}`}>
<td className="row-title">{row.key}</td> <td className="row-title">{row.key}</td>
<td>{row.value}</td> <td>{row.value}</td>
@ -29,8 +29,4 @@ KeyValueTable.propTypes = {
).isRequired, ).isRequired,
}; };
KeyValueTable.defaultProps = {
max_width: 'auto',
};
export { KeyValueTable }; export { KeyValueTable };

View File

@ -18,7 +18,7 @@ function Badge({
tooltipId, tooltipId,
tooltipPlace, tooltipPlace,
type, type,
isInverted, isInverted = true,
}: BadgeProps) { }: BadgeProps) {
return ( return (
<span> <span>
@ -38,8 +38,4 @@ function Badge({
); );
} }
Badge.defaultProps = {
isInverted: true,
};
export { Badge }; export { Badge };

View File

@ -69,6 +69,7 @@ export const getBadgeType = (statName, rate) => {
}; };
function StatsBadge(props: StatsBadgeProps) { function StatsBadge(props: StatsBadgeProps) {
const { isInverted = true } = props;
const badges = { const badges = {
excellent: { excellent: {
name: __('Excellent', 'mailpoet'), name: __('Excellent', 'mailpoet'),
@ -119,7 +120,7 @@ function StatsBadge(props: StatsBadgeProps) {
const content = ( const content = (
<Badge <Badge
isInverted={props.isInverted} isInverted={isInverted}
type={badgeType} type={badgeType}
name={badge.name} name={badge.name}
tooltip={tooltipText} tooltip={tooltipText}
@ -131,8 +132,4 @@ function StatsBadge(props: StatsBadgeProps) {
return content; return content;
} }
StatsBadge.defaultProps = {
isInverted: true,
};
export { StatsBadge }; export { StatsBadge };

View File

@ -20,7 +20,7 @@ function MssActiveMessage({ canUseSuccessClass }: MssActiveMessageProps) {
type NotValidMessageProps = { message?: string }; type NotValidMessageProps = { message?: string };
function NotValidMessage({ message }: NotValidMessageProps) { function NotValidMessage({ message = '' }: NotValidMessageProps) {
return ( return (
<div className="mailpoet_error"> <div className="mailpoet_error">
{message {message
@ -45,10 +45,6 @@ function NotValidMessage({ message }: NotValidMessageProps) {
); );
} }
NotValidMessage.defaultProps = {
message: '',
};
type MssNotActiveMessageProps = { activationCallback?: () => void }; type MssNotActiveMessageProps = { activationCallback?: () => void };
function MssNotActiveMessage({ activationCallback }: MssNotActiveMessageProps) { function MssNotActiveMessage({ activationCallback }: MssNotActiveMessageProps) {
@ -74,19 +70,21 @@ type Props = {
canUseSuccessClass: boolean; canUseSuccessClass: boolean;
}; };
export function MssMessages(props: Props) { export function MssMessages({
activationCallback,
canUseSuccessClass,
keyMessage = '',
}: Props) {
const { mssStatus, mssAccessRestriction } = useSelector( const { mssStatus, mssAccessRestriction } = useSelector(
'getKeyActivationState', 'getKeyActivationState',
)(); )();
switch (mssStatus) { switch (mssStatus) {
case MssStatus.VALID_MSS_ACTIVE: case MssStatus.VALID_MSS_ACTIVE:
return <MssActiveMessage canUseSuccessClass={props.canUseSuccessClass} />; return <MssActiveMessage canUseSuccessClass={canUseSuccessClass} />;
case MssStatus.VALID_MSS_NOT_ACTIVE: case MssStatus.VALID_MSS_NOT_ACTIVE:
return ( return <MssNotActiveMessage activationCallback={activationCallback} />;
<MssNotActiveMessage activationCallback={props.activationCallback} />
);
case MssStatus.INVALID: case MssStatus.INVALID:
return <NotValidMessage message={props.keyMessage} />; return <NotValidMessage message={keyMessage} />;
case MssStatus.VALID_UNDERPRIVILEGED: case MssStatus.VALID_UNDERPRIVILEGED:
if ( if (
@ -101,7 +99,3 @@ export function MssMessages(props: Props) {
return null; return null;
} }
} }
MssMessages.defaultProps = {
keyMessage: '',
};

View File

@ -65,7 +65,7 @@ function PremiumMessageWithModal(props: PremiumMessageProps) {
type NotValidMessageProps = { message?: string }; type NotValidMessageProps = { message?: string };
function NotValidMessage({ message }: NotValidMessageProps) { function NotValidMessage({ message = '' }: NotValidMessageProps) {
return ( return (
<div className="mailpoet_error"> <div className="mailpoet_error">
{message {message
@ -87,21 +87,17 @@ function NotValidMessage({ message }: NotValidMessageProps) {
); );
} }
NotValidMessage.defaultProps = {
message: '',
};
type Props = { type Props = {
keyMessage?: string; keyMessage?: string;
canUseSuccessClass: boolean; canUseSuccessClass: boolean;
}; };
function PremiumMessages(props: Props) { function PremiumMessages({ canUseSuccessClass, keyMessage = '' }: Props) {
const { premiumStatus: status } = useSelector('getKeyActivationState')(); const { premiumStatus: status } = useSelector('getKeyActivationState')();
switch (status) { switch (status) {
case PremiumStatus.VALID_PREMIUM_PLUGIN_ACTIVE: case PremiumStatus.VALID_PREMIUM_PLUGIN_ACTIVE:
return <ActiveMessage canUseSuccessClass={props.canUseSuccessClass} />; return <ActiveMessage canUseSuccessClass={canUseSuccessClass} />;
case PremiumStatus.VALID_PREMIUM_PLUGIN_NOT_INSTALLED: case PremiumStatus.VALID_PREMIUM_PLUGIN_NOT_INSTALLED:
return ( return (
<PremiumMessageWithModal <PremiumMessageWithModal
@ -132,14 +128,10 @@ function PremiumMessages(props: Props) {
/> />
); );
case PremiumStatus.INVALID: case PremiumStatus.INVALID:
return <NotValidMessage message={props.keyMessage} />; return <NotValidMessage message={keyMessage} />;
default: default:
return null; return null;
} }
} }
PremiumMessages.defaultProps = {
keyMessage: '',
};
export { PremiumMessages, PremiumMessageWithModal }; export { PremiumMessages, PremiumMessageWithModal };

View File

@ -5,7 +5,11 @@ import classnames from 'classnames';
import { MobileIcon } from './mobile-icon'; import { MobileIcon } from './mobile-icon';
import { DesktopIcon } from './desktop-icon'; import { DesktopIcon } from './desktop-icon';
function Preview({ children, onDisplayTypeChange, selectedDisplayType }) { function Preview({
children,
onDisplayTypeChange = (type) => type,
selectedDisplayType = 'desktop',
}) {
const [displayType, setDisplayType] = useState(selectedDisplayType); const [displayType, setDisplayType] = useState(selectedDisplayType);
const changeType = (type) => { const changeType = (type) => {
setDisplayType(type); setDisplayType(type);
@ -76,9 +80,5 @@ Preview.propTypes = {
selectedDisplayType: PropTypes.string, selectedDisplayType: PropTypes.string,
}; };
Preview.defaultProps = {
onDisplayTypeChange: () => {},
selectedDisplayType: 'desktop',
};
Preview.displayName = 'FormEditorPreview'; Preview.displayName = 'FormEditorPreview';
export { Preview }; export { Preview };

View File

@ -1,12 +1,17 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
function PrintBoolean(props) { function PrintBoolean({
truthy = __('Yes', 'mailpoet'),
falsy = __('No', 'mailpoet'),
unknown = __('Unknown', 'mailpoet'),
children = null,
}) {
return ( return (
<span> <span>
{(props.children === true && props.truthy) || {(children === true && truthy) ||
(props.children === false && props.falsy) || (children === false && falsy) ||
props.unknown} unknown}
</span> </span>
); );
} }
@ -18,11 +23,4 @@ PrintBoolean.propTypes = {
children: PropTypes.bool, children: PropTypes.bool,
}; };
PrintBoolean.defaultProps = {
truthy: __('Yes', 'mailpoet'),
falsy: __('No', 'mailpoet'),
unknown: __('Unknown', 'mailpoet'),
children: null,
};
export { PrintBoolean }; export { PrintBoolean };

View File

@ -88,7 +88,10 @@ type Props = {
setAuthorizedAddress?: (address: string) => void; setAuthorizedAddress?: (address: string) => void;
}; };
function SetFromAddressModal({ onRequestClose, setAuthorizedAddress }: Props) { function SetFromAddressModal({
onRequestClose,
setAuthorizedAddress = noop,
}: Props) {
const [address, setAddress] = useState<string>(); const [address, setAddress] = useState<string>();
const [showAuthorizedEmailModal, setShowAuthorizedEmailModal] = const [showAuthorizedEmailModal, setShowAuthorizedEmailModal] =
useState(false); useState(false);
@ -230,8 +233,4 @@ function SetFromAddressModal({ onRequestClose, setAuthorizedAddress }: Props) {
); );
} }
SetFromAddressModal.defaultProps = {
setAuthorizedAddress: noop,
};
export { SetFromAddressModal }; export { SetFromAddressModal };

View File

@ -10,7 +10,7 @@ type Props = {
doneCallback?: (step: string) => void; doneCallback?: (step: string) => void;
}; };
function StepsComponent({ count, current, titles, doneCallback }: Props) { function StepsComponent({ count, current, doneCallback, titles = [] }: Props) {
return ( return (
<div className="mailpoet-steps"> <div className="mailpoet-steps">
<ContentWrapperFix /> <ContentWrapperFix />
@ -54,9 +54,6 @@ function StepsComponent({ count, current, titles, doneCallback }: Props) {
); );
} }
StepsComponent.defaultProps = {
titles: [],
};
StepsComponent.displayName = 'StepsComponent'; StepsComponent.displayName = 'StepsComponent';
const Steps = withBoundary(StepsComponent); const Steps = withBoundary(StepsComponent);
export { Steps }; export { Steps };

View File

@ -12,15 +12,15 @@ import { MailPoet } from 'mailpoet';
import { CustomFieldDelete } from '../custom-field-delete.jsx'; import { CustomFieldDelete } from '../custom-field-delete.jsx';
function CustomFieldSettings({ function CustomFieldSettings({
label, label = '',
mandatory, mandatory = false,
isSaving, isSaving = false,
onSave, onSave = null,
isChecked, isChecked = false,
checkboxLabel, checkboxLabel = '',
isDeleting, isDeleting = false,
onCustomFieldDelete, onCustomFieldDelete = null,
onChange, onChange = () => {},
}) { }) {
const [localLabel, setLocalLabel] = useState(label); const [localLabel, setLocalLabel] = useState(label);
const [localMandatory, setLocalMandatory] = useState(mandatory); const [localMandatory, setLocalMandatory] = useState(mandatory);
@ -108,16 +108,4 @@ CustomFieldSettings.propTypes = {
onChange: PropTypes.func, onChange: PropTypes.func,
}; };
CustomFieldSettings.defaultProps = {
label: '',
mandatory: false,
onSave: null,
isSaving: false,
isChecked: false,
checkboxLabel: '',
isDeleting: false,
onCustomFieldDelete: null,
onChange: () => {},
};
export { CustomFieldSettings }; export { CustomFieldSettings };

View File

@ -11,17 +11,17 @@ import { MailPoet } from 'mailpoet';
import { CustomFieldDelete } from '../custom-field-delete.jsx'; import { CustomFieldDelete } from '../custom-field-delete.jsx';
function CustomFieldSettings({ function CustomFieldSettings({
label,
mandatory,
dateType,
dateFormat,
defaultToday,
dateSettings, dateSettings,
isSaving, label = '',
onSave, mandatory = false,
isDeleting, dateType = null,
onCustomFieldDelete, dateFormat = null,
onChange, defaultToday = false,
isSaving = false,
onSave = null,
isDeleting = false,
onCustomFieldDelete = null,
onChange = null,
}) { }) {
const [localLabel, setLocalLabel] = useState(label); const [localLabel, setLocalLabel] = useState(label);
const [localMandatory, setLocalMandatory] = useState(mandatory); const [localMandatory, setLocalMandatory] = useState(mandatory);
@ -161,17 +161,4 @@ CustomFieldSettings.propTypes = {
onChange: PropTypes.func, onChange: PropTypes.func,
}; };
CustomFieldSettings.defaultProps = {
label: '',
mandatory: false,
isSaving: false,
dateType: null,
dateFormat: null,
defaultToday: false,
isDeleting: false,
onCustomFieldDelete: null,
onSave: null,
onChange: null,
};
export { CustomFieldSettings }; export { CustomFieldSettings };

View File

@ -236,12 +236,13 @@ class FormFieldDate extends Component {
} }
render() { render() {
const { field, addDefaultClasses = false } = this.props;
const monthNames = window.mailpoet_month_names || []; const monthNames = window.mailpoet_month_names || [];
const dateFormats = window.mailpoet_date_formats || {}; const dateFormats = window.mailpoet_date_formats || {};
const dateType = this.props.field.params.date_type; const dateType = field.params.date_type;
let dateFormat = dateFormats[dateType][0]; let dateFormat = dateFormats[dateType][0];
if (this.props.field.params.date_format) { if (field.params.date_format) {
dateFormat = this.props.field.params.date_format; dateFormat = field.params.date_format;
} }
const dateSelects = dateFormat.split('/'); const dateSelects = dateFormat.split('/');
@ -252,10 +253,10 @@ class FormFieldDate extends Component {
<FormFieldDateYear <FormFieldDateYear
onValueChange={this.onValueChange} onValueChange={this.onValueChange}
key="year" key="year"
name={this.props.field.name} name={field.name}
addDefaultClasses={this.props.addDefaultClasses} addDefaultClasses={addDefaultClasses}
year={this.state.year} year={this.state.year}
placeholder={this.props.field.year_placeholder} placeholder={field.year_placeholder}
/> />
); );
@ -264,11 +265,11 @@ class FormFieldDate extends Component {
<FormFieldDateMonth <FormFieldDateMonth
onValueChange={this.onValueChange} onValueChange={this.onValueChange}
key="month" key="month"
name={this.props.field.name} name={field.name}
addDefaultClasses={this.props.addDefaultClasses} addDefaultClasses={addDefaultClasses}
month={this.state.month} month={this.state.month}
monthNames={monthNames} monthNames={monthNames}
placeholder={this.props.field.month_placeholder} placeholder={field.month_placeholder}
/> />
); );
@ -277,10 +278,10 @@ class FormFieldDate extends Component {
<FormFieldDateDay <FormFieldDateDay
onValueChange={this.onValueChange} onValueChange={this.onValueChange}
key="day" key="day"
name={this.props.field.name} name={field.name}
addDefaultClasses={this.props.addDefaultClasses} addDefaultClasses={addDefaultClasses}
day={this.state.day} day={this.state.day}
placeholder={this.props.field.day_placeholder} placeholder={field.day_placeholder}
/> />
); );
@ -306,8 +307,4 @@ FormFieldDate.propTypes = {
addDefaultClasses: PropTypes.bool, addDefaultClasses: PropTypes.bool,
}; };
FormFieldDate.defaultProps = {
addDefaultClasses: false,
};
export { FormFieldDate }; export { FormFieldDate };

View File

@ -3,7 +3,7 @@ import { Button } from '@wordpress/components';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { MailPoet } from 'mailpoet'; import { MailPoet } from 'mailpoet';
function CustomFieldDelete({ isBusy, onDelete }) { function CustomFieldDelete({ isBusy = false, onDelete = () => {} }) {
const displayConfirm = useCallback(() => { const displayConfirm = useCallback(() => {
const result = window.confirm(MailPoet.I18n.t('customFieldDeleteConfirm')); // eslint-disable-line no-alert const result = window.confirm(MailPoet.I18n.t('customFieldDeleteConfirm')); // eslint-disable-line no-alert
if (result) { if (result) {
@ -29,9 +29,4 @@ CustomFieldDelete.propTypes = {
onDelete: PropTypes.func, onDelete: PropTypes.func,
}; };
CustomFieldDelete.defaultProps = {
isBusy: false,
onDelete: () => {},
};
export { CustomFieldDelete }; export { CustomFieldDelete };

View File

@ -8,15 +8,15 @@ import { CustomFieldDelete } from '../custom-field-delete.jsx';
import { Preview } from './settings-preview.jsx'; import { Preview } from './settings-preview.jsx';
function CustomFieldSettings({ function CustomFieldSettings({
label, label = '',
mandatory, mandatory = false,
values, values = [],
isSaving, isSaving = false,
onSave, onSave = null,
isDeleting, isDeleting = false,
onCustomFieldDelete, onCustomFieldDelete = null,
onChange, onChange = null,
useDragAndDrop, useDragAndDrop = true,
}) { }) {
const [localLabel, setLocalLabel] = useState(label); const [localLabel, setLocalLabel] = useState(label);
const [localMandatory, setLocalMandatory] = useState(mandatory); const [localMandatory, setLocalMandatory] = useState(mandatory);
@ -149,16 +149,4 @@ CustomFieldSettings.propTypes = {
useDragAndDrop: PropTypes.bool, useDragAndDrop: PropTypes.bool,
}; };
CustomFieldSettings.defaultProps = {
label: '',
mandatory: false,
isSaving: false,
values: [],
isDeleting: false,
onCustomFieldDelete: null,
onSave: null,
onChange: null,
useDragAndDrop: true,
};
export { CustomFieldSettings }; export { CustomFieldSettings };

View File

@ -11,15 +11,15 @@ import { MailPoet } from 'mailpoet';
import { CustomFieldDelete } from '../custom-field-delete.jsx'; import { CustomFieldDelete } from '../custom-field-delete.jsx';
function CustomFieldSettings({ function CustomFieldSettings({
label, label = '',
mandatory, mandatory = false,
validate, validate = '',
isSaving, isSaving = false,
onSave, onSave = null,
isDeleting, isDeleting = false,
onCustomFieldDelete, onCustomFieldDelete = null,
onChange, onChange = null,
fieldType, fieldType = '',
}) { }) {
const [localLabel, setLocalLabel] = useState(label); const [localLabel, setLocalLabel] = useState(label);
const [localMandatory, setLocalMandatory] = useState(mandatory); const [localMandatory, setLocalMandatory] = useState(mandatory);
@ -116,16 +116,4 @@ CustomFieldSettings.propTypes = {
fieldType: PropTypes.string, fieldType: PropTypes.string,
}; };
CustomFieldSettings.defaultProps = {
label: '',
mandatory: false,
fieldType: '',
isSaving: false,
validate: '',
isDeleting: false,
onCustomFieldDelete: null,
onSave: null,
onChange: null,
};
export { CustomFieldSettings }; export { CustomFieldSettings };

View File

@ -1,7 +1,7 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classnames from 'classnames'; import classnames from 'classnames';
function ParagraphEdit({ children, className }) { function ParagraphEdit({ children, className = '' }) {
return ( return (
<div className={classnames('mailpoet_paragraph', className)}> <div className={classnames('mailpoet_paragraph', className)}>
{children} {children}
@ -14,8 +14,4 @@ ParagraphEdit.propTypes = {
className: PropTypes.string, className: PropTypes.string,
}; };
ParagraphEdit.defaultProps = {
className: '',
};
export { ParagraphEdit }; export { ParagraphEdit };

View File

@ -14,7 +14,7 @@ function TextInputEdit({
name, name,
mandatory, mandatory,
styles, styles,
className, className = '',
}) { }) {
const settings = useSelect( const settings = useSelect(
(select) => select(storeName).getFormSettings(), (select) => select(storeName).getFormSettings(),
@ -125,8 +125,4 @@ TextInputEdit.propTypes = {
styles: inputStylesPropTypes.isRequired, styles: inputStylesPropTypes.isRequired,
}; };
TextInputEdit.defaultProps = {
className: '',
};
export { TextInputEdit }; export { TextInputEdit };

View File

@ -3,7 +3,17 @@ import codemirror from 'codemirror';
import 'codemirror/mode/css/css'; // Side effect import 'codemirror/mode/css/css'; // Side effect
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
function CodemirrorWrap({ options, value, onChange }) { function CodemirrorWrap({
value,
onChange,
options = {
lineNumbers: true,
tabMode: 'indent',
matchBrackets: true,
theme: 'neo',
mode: 'css',
},
}) {
const textArea = useRef(null); const textArea = useRef(null);
const editor = useRef(null); const editor = useRef(null);
@ -56,14 +66,4 @@ CodemirrorWrap.propTypes = {
}), }),
}; };
CodemirrorWrap.defaultProps = {
options: {
lineNumbers: true,
tabMode: 'indent',
matchBrackets: true,
theme: 'neo',
mode: 'css',
},
};
export { CodemirrorWrap }; export { CodemirrorWrap };

View File

@ -12,7 +12,7 @@ function FormPlacementOption({
label, label,
icon, icon,
active, active,
canBeActive, canBeActive = true,
onClick, onClick,
}: Props): JSX.Element { }: Props): JSX.Element {
return ( return (
@ -32,8 +32,4 @@ function FormPlacementOption({
); );
} }
FormPlacementOption.defaultProps = {
canBeActive: true,
};
export { FormPlacementOption }; export { FormPlacementOption };

View File

@ -18,12 +18,12 @@ type Props = {
function SelectionItem({ function SelectionItem({
label, label,
active, active,
canBeActive,
onClick, onClick,
children, children,
className, canBeActive = true,
automationId, className = undefined,
displaySettingsIcon, automationId = undefined,
displaySettingsIcon = true,
}: Props): JSX.Element { }: Props): JSX.Element {
const [hover, setHover] = useState(false); const [hover, setHover] = useState(false);
return ( return (
@ -75,11 +75,4 @@ function SelectionItem({
); );
} }
SelectionItem.defaultProps = {
canBeActive: true,
displaySettingsIcon: true,
className: undefined,
automationId: undefined,
};
export { SelectionItem }; export { SelectionItem };

View File

@ -180,6 +180,7 @@ class FormField extends Component {
render() { render() {
let field = false; let field = false;
const { onValueChange = () => {} } = this.props;
if (this.props.field.fields !== undefined) { if (this.props.field.fields !== undefined) {
field = this.props.field.fields.map((subfield, index) => field = this.props.field.fields.map((subfield, index) =>
@ -187,7 +188,7 @@ class FormField extends Component {
index, index,
field: subfield, field: subfield,
item: this.props.item, item: this.props.item,
onValueChange: this.props.onValueChange || false, onValueChange: onValueChange || false,
}), }),
); );
} else { } else {
@ -237,10 +238,4 @@ FormField.propTypes = {
item: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types item: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
}; };
FormField.defaultProps = {
onValueChange: function onValueChange() {
// no-op
},
};
export { FormField }; export { FormField };

View File

@ -9,7 +9,10 @@ class FormFieldRadio extends Component {
this.onValueChange = this.onValueChange.bind(this); this.onValueChange = this.onValueChange.bind(this);
} }
onValueChange = (value, e) => this.props.onValueChange(e); onValueChange = (value, e) => {
const { onValueChange = () => {} } = this.props.onValueChange;
onValueChange(e);
};
render() { render() {
if (this.props.field.values === undefined) { if (this.props.field.values === undefined) {
@ -43,10 +46,4 @@ FormFieldRadio.propTypes = {
item: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types item: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
}; };
FormFieldRadio.defaultProps = {
onValueChange: function onValueChange() {
// no-op
},
};
export { FormFieldRadio }; export { FormFieldRadio };

View File

@ -9,6 +9,8 @@ export class FormFieldSelect extends Component {
return false; return false;
} }
const { automationId = '', onValueChange = () => {} } = this.props;
let filter = false; let filter = false;
let placeholder = false; let placeholder = false;
let sortBy = false; let sortBy = false;
@ -55,8 +57,8 @@ export class FormFieldSelect extends Component {
name={this.props.field.name} name={this.props.field.name}
id={`field_${this.props.field.name}`} id={`field_${this.props.field.name}`}
value={this.props.item[this.props.field.name] || ''} value={this.props.item[this.props.field.name] || ''}
onChange={this.props.onValueChange} onChange={onValueChange}
automationId={this.props.automationId} automationId={automationId}
{...this.props.field.validation} {...this.props.field.validation}
> >
{placeholder} {placeholder}
@ -85,10 +87,3 @@ FormFieldSelect.propTypes = {
item: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types item: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
automationId: PropTypes.string, automationId: PropTypes.string,
}; };
FormFieldSelect.defaultProps = {
automationId: '',
onValueChange: function onValueChange() {
// no-op
},
};

View File

@ -19,10 +19,13 @@ class Selection extends Component {
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
const { item = undefined } = this.props;
const { item: prevItem = undefined } = prevProps;
if ( if (
this.props.item !== undefined && item !== undefined &&
prevProps.item !== undefined && prevItem !== undefined &&
this.props.item.id !== prevProps.item.id item.id !== prevItem.id
) { ) {
jQuery(`#${this.selectRef.current.id}`) jQuery(`#${this.selectRef.current.id}`)
.val(this.getSelectedValues()) .val(this.getSelectedValues())
@ -50,16 +53,17 @@ class Selection extends Component {
}; };
getSelectedValues = () => { getSelectedValues = () => {
if (this.props.field.selected !== undefined) { const { field, item = undefined } = this.props;
return this.props.field.selected(this.props.item); if (field.selected !== undefined) {
return field.selected(item);
} }
if (this.props.item !== undefined && this.props.field.name !== undefined) { if (item !== undefined && field.name !== undefined) {
if (this.allowMultipleValues()) { if (this.allowMultipleValues()) {
if (_.isArray(this.props.item[this.props.field.name])) { if (_.isArray(item[field.name])) {
return this.props.item[this.props.field.name].map((item) => item.id); return item[field.name].map((it) => it.id);
} }
} else { } else {
return this.props.item[this.props.field.name]; return item[field.name];
} }
} }
return null; return null;
@ -85,36 +89,41 @@ class Selection extends Component {
}; };
getLabel = (item) => { getLabel = (item) => {
if (this.props.field.getLabel !== undefined) { const { field, item: propsItem = undefined } = this.props;
return this.props.field.getLabel(item, this.props.item); if (field.getLabel !== undefined) {
return field.getLabel(item, propsItem);
} }
return item.name; return item.name;
}; };
getSearchLabel = (item) => { getSearchLabel = (item) => {
if (this.props.field.getSearchLabel !== undefined) { const { field, item: propsItem = undefined } = this.props;
return this.props.field.getSearchLabel(item, this.props.item); if (field.getSearchLabel !== undefined) {
return field.getSearchLabel(item, propsItem);
} }
return null; return null;
}; };
getValue = (item) => { getValue = (item) => {
if (this.props.field.getValue !== undefined) { const { field, item: propsItem = undefined } = this.props;
return this.props.field.getValue(item, this.props.item); if (field.getValue !== undefined) {
return field.getValue(item, propsItem);
} }
return item.id; return item.id;
}; };
getCount = (item) => { getCount = (item) => {
if (this.props.field.getCount !== undefined) { const { field, item: propsItem = undefined } = this.props;
return this.props.field.getCount(item, this.props.item); if (field.getCount !== undefined) {
return field.getCount(item, propsItem);
} }
return null; return null;
}; };
getTag = (item) => { getTag = (item) => {
if (this.props.field.getTag !== undefined) { const { field, item: propsItem = undefined } = this.props;
return this.props.field.getTag(item, this.props.item); if (field.getTag !== undefined) {
return field.getTag(item, propsItem);
} }
return null; return null;
}; };
@ -135,9 +144,11 @@ class Selection extends Component {
return tpl; return tpl;
}; };
const { width = '', disabled = false } = this.props;
let select2Options = { let select2Options = {
disabled: this.props.disabled || false, disabled: disabled || false,
width: this.props.width || '', width: width || '',
placeholder: { placeholder: {
id: '', // the value of the option id: '', // the value of the option
text: this.props.field.placeholder, text: this.props.field.placeholder,
@ -266,7 +277,7 @@ class Selection extends Component {
this.allowMultipleValues() || this.props.field.forceSelect2; this.allowMultipleValues() || this.props.field.forceSelect2;
handleChange = (e) => { handleChange = (e) => {
if (this.props.onValueChange === undefined) return; const { onValueChange = () => {} } = this.props;
const valueTextPair = jQuery(`#${this.selectRef.current.id}`) const valueTextPair = jQuery(`#${this.selectRef.current.id}`)
.children(':selected') .children(':selected')
@ -278,7 +289,7 @@ class Selection extends Component {
: _.pluck(valueTextPair, 'id').toString(); : _.pluck(valueTextPair, 'id').toString();
const transformedValue = this.transformChangedValue(value, valueTextPair); const transformedValue = this.transformChangedValue(value, valueTextPair);
this.props.onValueChange({ onValueChange({
target: { target: {
value: transformedValue, value: transformedValue,
name: this.props.field.name, name: this.props.field.name,
@ -390,13 +401,4 @@ Selection.propTypes = {
width: PropTypes.string, width: PropTypes.string,
}; };
Selection.defaultProps = {
onValueChange: function onValueChange() {
// no-op
},
disabled: false,
width: '',
item: undefined,
};
export { Selection }; export { Selection };

View File

@ -5,12 +5,13 @@ import { Input } from 'common/form/input/input';
// eslint-disable-next-line react/prefer-stateless-function, max-len // eslint-disable-next-line react/prefer-stateless-function, max-len
class FormFieldText extends Component { class FormFieldText extends Component {
render() { render() {
const { onValueChange = () => {}, onBlurEvent = () => {} } = this.props;
const name = this.props.field.name || null; const name = this.props.field.name || null;
const item = this.props.item || {}; const item = this.props.item || {};
let value; let value;
let defaultValue; let defaultValue;
// value should only be set when onChangeValue is configured // value should only be set when onChangeValue is configured
if (this.props.onValueChange instanceof Function) { if (onValueChange instanceof Function) {
value = item[this.props.field.name]; value = item[this.props.field.name];
// set value to defaultValue if available // set value to defaultValue if available
value = value === undefined ? this.props.field.defaultValue || '' : value; value = value === undefined ? this.props.field.defaultValue || '' : value;
@ -54,8 +55,8 @@ class FormFieldText extends Component {
value={value} value={value}
defaultValue={defaultValue} defaultValue={defaultValue}
placeholder={this.props.field.placeholder} placeholder={this.props.field.placeholder}
onChange={this.props.onValueChange} onChange={onValueChange}
onBlur={this.props.onBlurEvent} onBlur={onBlurEvent}
customLabel={this.props.field.customLabel} customLabel={this.props.field.customLabel}
tooltip={this.props.field.tooltip} tooltip={this.props.field.tooltip}
{...this.props.field.validation} {...this.props.field.validation}
@ -88,13 +89,4 @@ FormFieldText.propTypes = {
item: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types item: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
}; };
FormFieldText.defaultProps = {
onValueChange: function onValueChange() {
// no-op
},
onBlurEvent: function onValueChange() {
// no-op
},
};
export { FormFieldText }; export { FormFieldText };

View File

@ -56,10 +56,4 @@ Tooltip.propTypes = {
className: PropTypes.string, className: PropTypes.string,
}; };
Tooltip.defaultProps = {
tooltipId: undefined,
place: undefined,
className: undefined,
};
export { Tooltip }; export { Tooltip };

View File

@ -2,39 +2,38 @@ import PropTypes from 'prop-types';
import { MailPoet } from 'mailpoet'; import { MailPoet } from 'mailpoet';
import parseDate from 'date-fns/parse'; import parseDate from 'date-fns/parse';
function TasksListDataRow(props) { function TasksListDataRow({
let scheduled = props.task.scheduled_at; task,
show_scheduled_at: showScheduledAt = false,
}) {
let scheduled = task.scheduled_at;
if (scheduled) { if (scheduled) {
scheduled = parseDate(scheduled, 'yyyy-MM-dd HH:mm:ss', new Date()); scheduled = parseDate(scheduled, 'yyyy-MM-dd HH:mm:ss', new Date());
} }
const updated = parseDate( const updated = parseDate(task.updated_at, 'yyyy-MM-dd HH:mm:ss', new Date());
props.task.updated_at,
'yyyy-MM-dd HH:mm:ss',
new Date(),
);
return ( return (
<tr> <tr>
<td className="column column-primary">{props.task.id}</td> <td className="column column-primary">{task.id}</td>
<td className="column">{props.task.type}</td> <td className="column">{task.type}</td>
<td className="column"> <td className="column">
{props.task.newsletter ? ( {task.newsletter ? (
<a <a
href={props.task.newsletter.preview_url} href={task.newsletter.preview_url}
data-newsletter-id={props.task.newsletter.newsletter_id} data-newsletter-id={task.newsletter.newsletter_id}
data-queue-id={props.task.newsletter.queue_id} data-queue-id={task.newsletter.queue_id}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
{props.task.newsletter.subject || MailPoet.I18n.t('preview')} {task.newsletter.subject || MailPoet.I18n.t('preview')}
</a> </a>
) : ( ) : (
MailPoet.I18n.t('none') MailPoet.I18n.t('none')
)} )}
</td> </td>
<td className="column">{props.task.priority}</td> <td className="column">{task.priority}</td>
{props.show_scheduled_at ? ( {showScheduledAt ? (
<td className="column-date"> <td className="column-date">
<abbr>{`${MailPoet.Date.short(scheduled)} ${MailPoet.Date.time( <abbr>{`${MailPoet.Date.short(scheduled)} ${MailPoet.Date.time(
scheduled, scheduled,
@ -68,8 +67,4 @@ TasksListDataRow.propTypes = {
}).isRequired, }).isRequired,
}; };
TasksListDataRow.defaultProps = {
show_scheduled_at: false,
};
export { TasksListDataRow }; export { TasksListDataRow };

View File

@ -1,14 +1,14 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { MailPoet } from 'mailpoet'; import { MailPoet } from 'mailpoet';
function TasksListLabelsRow(props) { function TasksListLabelsRow({ show_scheduled_at: showScheduledAt = false }) {
return ( return (
<tr> <tr>
<th className="row-title">Id</th> <th className="row-title">Id</th>
<th className="row-title">{MailPoet.I18n.t('type')}</th> <th className="row-title">{MailPoet.I18n.t('type')}</th>
<th className="row-title">{MailPoet.I18n.t('email')}</th> <th className="row-title">{MailPoet.I18n.t('email')}</th>
<th className="row-title">{MailPoet.I18n.t('priority')}</th> <th className="row-title">{MailPoet.I18n.t('priority')}</th>
{props.show_scheduled_at ? ( {showScheduledAt ? (
<th className="row-title">{MailPoet.I18n.t('scheduledAt')}</th> <th className="row-title">{MailPoet.I18n.t('scheduledAt')}</th>
) : null} ) : null}
<th className="row-title">{MailPoet.I18n.t('updatedAt')}</th> <th className="row-title">{MailPoet.I18n.t('updatedAt')}</th>
@ -20,8 +20,4 @@ TasksListLabelsRow.propTypes = {
show_scheduled_at: PropTypes.bool, show_scheduled_at: PropTypes.bool,
}; };
TasksListLabelsRow.defaultProps = {
show_scheduled_at: false,
};
export { TasksListLabelsRow }; export { TasksListLabelsRow };

View File

@ -3,21 +3,21 @@ import { MailPoet } from 'mailpoet';
import { TasksListDataRow } from './tasks-list-data-row.jsx'; import { TasksListDataRow } from './tasks-list-data-row.jsx';
import { TasksListLabelsRow } from './tasks-list-labels-row.jsx'; import { TasksListLabelsRow } from './tasks-list-labels-row.jsx';
function TasksList(props) { function TasksList({ tasks, show_scheduled_at: showScheduledAt = false }) {
const colsCount = props.show_scheduled_at ? 6 : 5; const colsCount = showScheduledAt ? 6 : 5;
return ( return (
<table className="widefat fixed striped"> <table className="widefat fixed striped">
<thead> <thead>
<TasksListLabelsRow show_scheduled_at={props.show_scheduled_at} /> <TasksListLabelsRow show_scheduled_at={showScheduledAt} />
</thead> </thead>
<tbody> <tbody>
{props.tasks.length ? ( {tasks.length ? (
props.tasks.map((task) => ( tasks.map((task) => (
<TasksListDataRow <TasksListDataRow
key={task.id} key={task.id}
task={task} task={task}
show_scheduled_at={props.show_scheduled_at} show_scheduled_at={showScheduledAt}
/> />
)) ))
) : ( ) : (
@ -27,7 +27,7 @@ function TasksList(props) {
)} )}
</tbody> </tbody>
<tfoot> <tfoot>
<TasksListLabelsRow show_scheduled_at={props.show_scheduled_at} /> <TasksListLabelsRow show_scheduled_at={showScheduledAt} />
</tfoot> </tfoot>
</table> </table>
); );
@ -38,8 +38,4 @@ TasksList.propTypes = {
tasks: PropTypes.arrayOf(TasksListDataRow.propTypes.task).isRequired, tasks: PropTypes.arrayOf(TasksListDataRow.propTypes.task).isRequired,
}; };
TasksList.defaultProps = {
show_scheduled_at: false,
};
export { TasksList }; export { TasksList };

View File

@ -33,14 +33,15 @@ class ListingFilters extends Component {
handleEmptyTrash = () => this.props.onEmptyTrash(); handleEmptyTrash = () => this.props.onEmptyTrash();
handleFilterAction = () => { handleFilterAction = () => {
const { onSelectFilter, onBeforeSelectFilter = undefined } = this.props;
const filters = {}; const filters = {};
this.getAvailableFilters().forEach((filter, i) => { this.getAvailableFilters().forEach((filter, i) => {
filters[this[`filter-${i}`].name] = this[`filter-${i}`].value; filters[this[`filter-${i}`].name] = this[`filter-${i}`].value;
}); });
if (this.props.onBeforeSelectFilter) { if (onBeforeSelectFilter) {
this.props.onBeforeSelectFilter(filters); onBeforeSelectFilter(filters);
} }
return this.props.onSelectFilter(filters); return onSelectFilter(filters);
}; };
render() { render() {
@ -98,9 +99,6 @@ ListingFilters.propTypes = {
group: PropTypes.string.isRequired, group: PropTypes.string.isRequired,
}; };
ListingFilters.defaultProps = {
onBeforeSelectFilter: undefined,
};
ListingFilters.displayName = 'ListingFilters'; ListingFilters.displayName = 'ListingFilters';
const ListingFiltersWithBoundary = withBoundary(ListingFilters); const ListingFiltersWithBoundary = withBoundary(ListingFilters);
export { ListingFiltersWithBoundary as ListingFilters }; export { ListingFiltersWithBoundary as ListingFilters };

View File

@ -16,15 +16,22 @@ class ListingHeader extends Component {
} }
render() { render() {
const columns = this.props.columns.map((column, index) => { const {
onSort,
sort_by: sortBy,
sort_order: sortOrder,
is_selectable: isSelectable,
selection,
columns: propsColumns = [],
} = this.props;
const columns = propsColumns.map((column, index) => {
const renderColumn = column; const renderColumn = column;
renderColumn.is_primary = index === 0; renderColumn.is_primary = index === 0;
renderColumn.sorted = renderColumn.sorted = sortBy === column.name ? sortOrder : 'desc';
this.props.sort_by === column.name ? this.props.sort_order : 'desc';
return ( return (
<ListingColumn <ListingColumn
onSort={this.props.onSort} onSort={onSort}
sort_by={this.props.sort_by} sort_by={sortBy}
key={`column-${column.name}`} key={`column-${column.name}`}
column={renderColumn} column={renderColumn}
/> />
@ -33,7 +40,7 @@ class ListingHeader extends Component {
let checkbox; let checkbox;
if (this.props.is_selectable === true) { if (isSelectable === true) {
checkbox = ( checkbox = (
<th className="manage-column column-cb mailpoet-listing-check-column"> <th className="manage-column column-cb mailpoet-listing-check-column">
<label className="screen-reader-text" htmlFor="select_all"> <label className="screen-reader-text" htmlFor="select_all">
@ -43,7 +50,7 @@ class ListingHeader extends Component {
name="select_all" name="select_all"
id="select_all" id="select_all"
automationId="select_all" automationId="select_all"
checked={this.props.selection} checked={selection}
onCheck={() => {}} onCheck={() => {}}
onChange={this.handleSelectItems} onChange={this.handleSelectItems}
/> />
@ -70,10 +77,4 @@ ListingHeader.propTypes = {
selection: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]).isRequired, selection: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]).isRequired,
}; };
ListingHeader.defaultProps = {
columns: [],
sort_by: undefined,
sort_order: 'desc',
};
export { ListingHeader }; export { ListingHeader };

View File

@ -10,17 +10,18 @@ class ListingColumn extends Component {
}; };
render() { render() {
const { column, sort_by: sortBy = undefined } = this.props;
const classes = classnames( const classes = classnames(
'manage-column', 'manage-column',
{ 'column-primary': this.props.column.is_primary }, { 'column-primary': column.is_primary },
{ sortable: this.props.column.sortable }, { sortable: column.sortable },
this.props.column.sorted, column.sorted,
{ sorted: this.props.sort_by === this.props.column.name }, { sorted: sortBy === column.name },
this.props.column.className, column.className,
); );
let label; let label;
if (this.props.column.sortable === true) { if (column.sortable === true) {
label = ( label = (
<a <a
onClick={this.handleSort} onClick={this.handleSort}
@ -36,21 +37,21 @@ class ListingColumn extends Component {
} }
}} }}
> >
<span>{this.props.column.label}</span> <span>{column.label}</span>
<span className="mailpoet-listing-sorting-arrow" /> <span className="mailpoet-listing-sorting-arrow" />
</a> </a>
); );
} else { } else {
label = this.props.column.label; label = column.label;
} }
return ( return (
<th <th
role="columnheader" role="columnheader"
className={classes} className={classes}
id={this.props.column.name} id={column.name}
scope="col" scope="col"
width={this.props.column.width || null} width={column.width || null}
data-automation-id={`listing-column-header-${this.props.column.name}`} data-automation-id={`listing-column-header-${column.name}`}
> >
{label} {label}
</th> </th>
@ -72,8 +73,4 @@ ListingColumn.propTypes = {
onSort: PropTypes.func.isRequired, onSort: PropTypes.func.isRequired,
}; };
ListingColumn.defaultProps = {
sort_by: undefined,
};
export { ListingColumn }; export { ListingColumn };

View File

@ -27,7 +27,22 @@ class ListingItem extends Component {
render() { render() {
let checkbox = false; let checkbox = false;
if (this.props.is_selectable === true) { const {
is_selectable: isSelectable,
item,
columns,
group,
selection,
item_actions: propsItemActions,
onRefreshItems,
isItemInactive,
onRenderItem,
location = undefined,
isItemDeletable = () => true,
isItemToggleable = () => false,
} = this.props;
if (isSelectable === true) {
checkbox = ( checkbox = (
<th <th
className="mailpoet-listing-check-column mailpoet-hide-on-mobile" className="mailpoet-listing-check-column mailpoet-hide-on-mobile"
@ -35,24 +50,24 @@ class ListingItem extends Component {
> >
<label <label
className="screen-reader-text" className="screen-reader-text"
htmlFor={`listing-row-checkbox-${this.props.item.id}`} htmlFor={`listing-row-checkbox-${item.id}`}
> >
{`Select ${this.props.item[this.props.columns[0].name]}`} {`Select ${item[columns[0].name]}`}
</label> </label>
<Checkbox <Checkbox
value={this.props.item.id} value={item.id}
checked={this.props.item.selected || this.props.selection === 'all'} checked={item.selected || selection === 'all'}
onCheck={() => {}} onCheck={() => {}}
onChange={this.handleSelectItem} onChange={this.handleSelectItem}
disabled={this.props.selection === 'all'} disabled={selection === 'all'}
id={`listing-row-checkbox-${this.props.item.id}`} id={`listing-row-checkbox-${item.id}`}
automationId={`listing-row-checkbox-${this.props.item.id}`} automationId={`listing-row-checkbox-${item.id}`}
/> />
</th> </th>
); );
} }
const customActions = this.props.item_actions; const customActions = propsItemActions;
let itemActions = false; let itemActions = false;
if (customActions.length > 0) { if (customActions.length > 0) {
@ -75,10 +90,10 @@ class ListingItem extends Component {
href="#" href="#"
onClick={(event) => { onClick={(event) => {
event.preventDefault(); event.preventDefault();
this.handleTrashItem(this.props.item.id); this.handleTrashItem(item.id);
}} }}
> >
{this.props.isItemToggleable(this.props.item) {isItemToggleable(item)
? __('Trash and disable', 'mailpoet') ? __('Trash and disable', 'mailpoet')
: __('Move to trash', 'mailpoet')} : __('Move to trash', 'mailpoet')}
</a> </a>
@ -87,7 +102,7 @@ class ListingItem extends Component {
} else if (action.refresh) { } else if (action.refresh) {
customAction = ( customAction = (
<span <span
onClick={this.props.onRefreshItems} onClick={onRefreshItems}
key={`action-${action.name}`} key={`action-${action.name}`}
className={classnames(action.name, action.className)} className={classnames(action.name, action.className)}
role="button" role="button"
@ -98,11 +113,11 @@ class ListingItem extends Component {
['Enter', ' '].includes(event.key) ['Enter', ' '].includes(event.key)
) { ) {
event.preventDefault(); event.preventDefault();
this.props.onRefreshItems(); onRefreshItems();
} }
}} }}
> >
{action.link(this.props.item)} {action.link(item)}
</span> </span>
); );
} else if (action.link) { } else if (action.link) {
@ -111,7 +126,7 @@ class ListingItem extends Component {
key={`action-${action.name}`} key={`action-${action.name}`}
className={classnames(action.name, action.className)} className={classnames(action.name, action.className)}
> >
{action.link(this.props.item, this.props.location)} {action.link(item, location)}
</span> </span>
); );
} else { } else {
@ -125,10 +140,7 @@ class ListingItem extends Component {
onClick={(event) => { onClick={(event) => {
event.preventDefault(); event.preventDefault();
if (action.onClick !== undefined) { if (action.onClick !== undefined) {
action.onClick( action.onClick(item, onRefreshItems);
this.props.item,
this.props.onRefreshItems,
);
} }
}} }}
> >
@ -144,9 +156,9 @@ class ListingItem extends Component {
<span className="edit mailpoet-hide-on-mobile"> <span className="edit mailpoet-hide-on-mobile">
<Link <Link
to={{ to={{
pathname: `/edit/${this.props.item.id}`, pathname: `/edit/${item.id}`,
state: { state: {
backUrl: this.props.location?.pathname, backUrl: location?.pathname,
}, },
}} }}
> >
@ -158,7 +170,7 @@ class ListingItem extends Component {
let actions; let actions;
if (this.props.group === 'trash') { if (group === 'trash') {
actions = ( actions = (
<div className="mailpoet-listing-actions-holder"> <div className="mailpoet-listing-actions-holder">
<div className="mailpoet-listing-actions"> <div className="mailpoet-listing-actions">
@ -167,22 +179,22 @@ class ListingItem extends Component {
href="#" href="#"
onClick={(event) => { onClick={(event) => {
event.preventDefault(); event.preventDefault();
this.handleRestoreItem(this.props.item.id); this.handleRestoreItem(item.id);
}} }}
> >
{this.props.isItemToggleable(this.props.item) {isItemToggleable(item)
? __('Restore and enable', 'mailpoet') ? __('Restore and enable', 'mailpoet')
: __('Restore', 'mailpoet')} : __('Restore', 'mailpoet')}
</a> </a>
</span> </span>
{this.props.isItemDeletable(this.props.item) && ( {isItemDeletable(item) && (
<span className="delete"> <span className="delete">
<a <a
className="submitdelete" className="submitdelete"
href="#" href="#"
onClick={(event) => { onClick={(event) => {
event.preventDefault(); event.preventDefault();
this.handleDeleteItem(this.props.item.id); this.handleDeleteItem(item.id);
}} }}
> >
{__('Delete permanently', 'mailpoet')} {__('Delete permanently', 'mailpoet')}
@ -201,20 +213,14 @@ class ListingItem extends Component {
} }
const rowClasses = classnames({ const rowClasses = classnames({
'mailpoet-listing-row-selected': 'mailpoet-listing-row-selected': item.selected || selection === 'all',
this.props.item.selected || this.props.selection === 'all', 'mailpoet-listing-row-inactive': isItemInactive(item),
'mailpoet-listing-row-inactive': this.props.isItemInactive(
this.props.item,
),
}); });
return ( return (
<tr <tr className={rowClasses} data-automation-id={`listing_item_${item.id}`}>
className={rowClasses}
data-automation-id={`listing_item_${this.props.item.id}`}
>
{checkbox} {checkbox}
{this.props.onRenderItem(this.props.item, actions)} {onRenderItem(item, actions)}
</tr> </tr>
); );
} }
@ -245,10 +251,4 @@ ListingItem.propTypes = {
isItemToggleable: PropTypes.func, isItemToggleable: PropTypes.func,
}; };
ListingItem.defaultProps = {
location: undefined,
isItemDeletable: () => true,
isItemToggleable: () => false,
};
export { ListingItem }; export { ListingItem };

View File

@ -10,20 +10,43 @@ import { ListingItem } from 'listing/listing-item.jsx';
// eslint-disable-next-line react/prefer-stateless-function, max-len // eslint-disable-next-line react/prefer-stateless-function, max-len
class ListingItems extends Component { class ListingItems extends Component {
render() { render() {
if (this.props.items.length === 0) { const {
bulk_actions: bulkActions,
count,
columns,
group,
items,
is_selectable: isSelectable,
isItemInactive,
item_actions: itemActions,
limit,
loading,
messages,
onBulkAction,
onDeleteItem,
onRefreshItems,
onRenderItem,
onRestoreItem,
onSelectAll,
onSelectItem,
onTrashItem,
selected_ids: selectedIds,
selection,
getListingItemKey = undefined,
search = undefined,
location = undefined,
isItemDeletable = () => true,
isItemToggleable = () => false,
} = this.props;
if (items.length === 0) {
let message; let message;
if (this.props.loading === true) { if (loading === true) {
message = message =
(this.props.messages.onLoadingItems && (messages.onLoadingItems && messages.onLoadingItems(group)) ||
this.props.messages.onLoadingItems(this.props.group)) ||
__('Loading ...', 'mailpoet'); __('Loading ...', 'mailpoet');
} else { } else {
message = message =
(this.props.messages.onNoItemsFound && (messages.onNoItemsFound && messages.onNoItemsFound(group, search)) ||
this.props.messages.onNoItemsFound(
this.props.group,
this.props.search,
)) ||
__('No items found.', 'mailpoet'); __('No items found.', 'mailpoet');
} }
@ -31,9 +54,7 @@ class ListingItems extends Component {
<tbody> <tbody>
<tr className="mailpoet-listing-no-items"> <tr className="mailpoet-listing-no-items">
<td <td
colSpan={ colSpan={columns.length + (isSelectable ? 1 : 0)}
this.props.columns.length + (this.props.is_selectable ? 1 : 0)
}
className="colspanchange" className="colspanchange"
> >
{message} {message}
@ -43,11 +64,8 @@ class ListingItems extends Component {
); );
} }
const isSelectAllHidden = const isSelectAllHidden = selection === false || count <= limit;
this.props.selection === false || this.props.count <= this.props.limit; const areBulkActionsHidden = !(selectedIds.length > 0 || selection);
const areBulkActionsHidden = !(
this.props.selected_ids.length > 0 || this.props.selection
);
const actionAndSelectAllRowClasses = classnames( const actionAndSelectAllRowClasses = classnames(
'mailpoet-listing-actions-and-select-all-row', 'mailpoet-listing-actions-and-select-all-row',
@ -62,39 +80,35 @@ class ListingItems extends Component {
return ( return (
<tbody> <tbody>
<tr className={actionAndSelectAllRowClasses}> <tr className={actionAndSelectAllRowClasses}>
<td <td colSpan={columns.length + (isSelectable ? 1 : 0)}>
colSpan={
this.props.columns.length + (this.props.is_selectable ? 1 : 0)
}
>
<Grid.SpaceBetween verticalAlign="center"> <Grid.SpaceBetween verticalAlign="center">
<div className="mailpoet-listing-bulk-actions-container"> <div className="mailpoet-listing-bulk-actions-container">
{!areBulkActionsHidden && ( {!areBulkActionsHidden && (
<ListingBulkActions <ListingBulkActions
count={this.props.count} count={count}
bulk_actions={this.props.bulk_actions} bulk_actions={bulkActions}
selection={this.props.selection} selection={selection}
selected_ids={this.props.selected_ids} selected_ids={selectedIds}
onBulkAction={this.props.onBulkAction} onBulkAction={onBulkAction}
/> />
)} )}
</div> </div>
<div className={selectAllClasses}> <div className={selectAllClasses}>
{this.props.selection !== 'all' {selection !== 'all'
? __('All items on this page are selected.', 'mailpoet') ? __('All items on this page are selected.', 'mailpoet')
: __('All %d items are selected.', 'mailpoet').replace( : __('All %d items are selected.', 'mailpoet').replace(
'%d', '%d',
this.props.count.toLocaleString(), count.toLocaleString(),
)} )}
&nbsp; &nbsp;
<a <a
href="#" href="#"
onClick={(event) => { onClick={(event) => {
event.preventDefault(); event.preventDefault();
this.props.onSelectAll(event); onSelectAll(event);
}} }}
> >
{this.props.selection !== 'all' {selection !== 'all'
? __('Select all items on all pages', 'mailpoet') ? __('Select all items on all pages', 'mailpoet')
: __('Clear selection', 'mailpoet')} : __('Clear selection', 'mailpoet')}
</a> </a>
@ -104,35 +118,34 @@ class ListingItems extends Component {
</td> </td>
</tr> </tr>
{this.props.items.map((item) => { {items.map((item) => {
const renderItem = item; const renderItem = item;
renderItem.id = parseInt(item.id, 10); renderItem.id = parseInt(item.id, 10);
renderItem.selected = renderItem.selected = selectedIds.indexOf(renderItem.id) !== -1;
this.props.selected_ids.indexOf(renderItem.id) !== -1;
let key = `item-${renderItem.id}-${item.id}`; let key = `item-${renderItem.id}-${item.id}`;
if (typeof this.props.getListingItemKey === 'function') { if (typeof getListingItemKey === 'function') {
key = this.props.getListingItemKey(item); key = getListingItemKey(item);
} }
return ( return (
<ListingItem <ListingItem
columns={this.props.columns} columns={columns}
isItemInactive={this.props.isItemInactive} isItemInactive={isItemInactive}
onSelectItem={this.props.onSelectItem} onSelectItem={onSelectItem}
onRenderItem={this.props.onRenderItem} onRenderItem={onRenderItem}
onDeleteItem={this.props.onDeleteItem} onDeleteItem={onDeleteItem}
onRestoreItem={this.props.onRestoreItem} onRestoreItem={onRestoreItem}
onTrashItem={this.props.onTrashItem} onTrashItem={onTrashItem}
onRefreshItems={this.props.onRefreshItems} onRefreshItems={onRefreshItems}
selection={this.props.selection} selection={selection}
is_selectable={this.props.is_selectable} is_selectable={isSelectable}
item_actions={this.props.item_actions} item_actions={itemActions}
group={this.props.group} group={group}
location={this.props.location} location={location}
key={key} key={key}
item={renderItem} item={renderItem}
isItemDeletable={this.props.isItemDeletable} isItemDeletable={isItemDeletable}
isItemToggleable={this.props.isItemToggleable} isItemToggleable={isItemToggleable}
/> />
); );
})} })}
@ -179,12 +192,4 @@ ListingItems.propTypes = {
isItemToggleable: PropTypes.func, isItemToggleable: PropTypes.func,
}; };
ListingItems.defaultProps = {
getListingItemKey: undefined,
search: undefined,
location: undefined,
isItemDeletable: () => true,
isItemToggleable: () => false,
};
export { ListingItems }; export { ListingItems };

View File

@ -60,7 +60,8 @@ class ListingPages extends Component {
Math.min(Math.max(1, Math.abs(Number(page))), this.getLastPage()); Math.min(Math.max(1, Math.abs(Number(page))), this.getLastPage());
render() { render() {
if (this.props.count === 0) { const { count, limit, page, position = '' } = this.props;
if (count === 0) {
return false; return false;
} }
let pagination = false; let pagination = false;
@ -87,8 +88,8 @@ class ListingPages extends Component {
</span> </span>
); );
if (this.props.limit > 0 && this.props.count > this.props.limit) { if (limit > 0 && count > limit) {
if (this.props.page > 1) { if (page > 1) {
previousPage = ( previousPage = (
<a <a
href="#" href="#"
@ -108,7 +109,7 @@ class ListingPages extends Component {
); );
} }
if (this.props.page > 2) { if (page > 2) {
firstPage = ( firstPage = (
<a <a
href="#" href="#"
@ -129,7 +130,7 @@ class ListingPages extends Component {
); );
} }
if (this.props.page < this.getLastPage()) { if (page < this.getLastPage()) {
nextPage = ( nextPage = (
<a <a
href="#" href="#"
@ -149,7 +150,7 @@ class ListingPages extends Component {
); );
} }
if (this.props.page < this.getLastPage() - 1) { if (page < this.getLastPage() - 1) {
lastPage = ( lastPage = (
<a <a
href="#" href="#"
@ -170,7 +171,7 @@ class ListingPages extends Component {
); );
} }
let pageValue = this.props.page; let pageValue = page;
if (this.state.page !== null) { if (this.state.page !== null) {
pageValue = this.state.page; pageValue = this.state.page;
} }
@ -184,7 +185,7 @@ class ListingPages extends Component {
<span className="mailpoet-listing-paging-input"> <span className="mailpoet-listing-paging-input">
<label <label
className="screen-reader-text" className="screen-reader-text"
htmlFor={`current-page-selector-${this.props.position}`} htmlFor={`current-page-selector-${position}`}
> >
{__('Current page', 'mailpoet')} {__('Current page', 'mailpoet')}
</label> </label>
@ -197,13 +198,13 @@ class ListingPages extends Component {
size="2" size="2"
value={pageValue} value={pageValue}
name="paged" name="paged"
id={`current-page-selector-${this.props.position}`} id={`current-page-selector-${position}`}
className="mailpoet-listing-current-page" className="mailpoet-listing-current-page"
/> />
{__('of', 'mailpoet')} {__('of', 'mailpoet')}
&nbsp; &nbsp;
<span className="mailpoet-listing-total-pages"> <span className="mailpoet-listing-total-pages">
{Math.ceil(this.props.count / this.props.limit).toLocaleString()} {Math.ceil(count / limit).toLocaleString()}
</span> </span>
</span> </span>
&nbsp; &nbsp;
@ -215,16 +216,16 @@ class ListingPages extends Component {
} }
const classes = classnames('mailpoet-listing-pages', { const classes = classnames('mailpoet-listing-pages', {
'one-page': this.props.count <= this.props.limit, 'one-page': count <= limit,
}); });
let numberOfItemsLabel; let numberOfItemsLabel;
if (Number(this.props.count) === 1) { if (Number(count) === 1) {
numberOfItemsLabel = __('1 item', 'mailpoet'); numberOfItemsLabel = __('1 item', 'mailpoet');
} else { } else {
numberOfItemsLabel = __('%1$d items', 'mailpoet').replace( numberOfItemsLabel = __('%1$d items', 'mailpoet').replace(
'%1$d', '%1$d',
parseInt(this.props.count, 10).toLocaleString(), parseInt(count, 10).toLocaleString(),
); );
} }
@ -245,16 +246,12 @@ ListingPages.propTypes = {
limit: PropTypes.number.isRequired, limit: PropTypes.number.isRequired,
}; };
ListingPages.defaultProps = {
position: '',
};
/* type ArrowProps = { /* type ArrowProps = {
direction?: 'right', direction?: 'right',
disabled?: boolean disabled?: boolean
} */ } */
function Arrow({ direction, disabled }) { function Arrow({ direction = 'right', disabled = false }) {
const arrowLeftPath = const arrowLeftPath =
'M8 10V2c0-.552-.448-1-1-1-.216 0-.427.07-.6.2l-5.333 4c-.442.331-.532.958-.2 1.4.057.076.124.143.2.2l5.333 4c.442.331 1.069.242 1.4-.2.13-.173.2-.384.2-.6z'; 'M8 10V2c0-.552-.448-1-1-1-.216 0-.427.07-.6.2l-5.333 4c-.442.331-.532.958-.2 1.4.057.076.124.143.2.2l5.333 4c.442.331 1.069.242 1.4-.2.13-.173.2-.384.2-.6z';
const arrowRightPath = const arrowRightPath =
@ -279,9 +276,4 @@ Arrow.propTypes = {
disabled: PropTypes.bool, disabled: PropTypes.bool,
}; };
Arrow.defaultProps = {
direction: 'right',
disabled: false,
};
export { ListingPages }; export { ListingPages };

View File

@ -95,7 +95,10 @@ class EventScheduling extends Component {
} }
displayAfterTimeNumberField() { displayAfterTimeNumberField() {
const { afterTimeNumberSize, event } = this.props; const {
event,
afterTimeNumberSize = defaultAfterTimeNumberInputFieldSize,
} = this.props;
const { afterTimeType, afterTimeNumber } = this.state; const { afterTimeType, afterTimeNumber } = this.state;
if (afterTimeType === 'immediate') return null; if (afterTimeType === 'immediate') return null;
if ( if (
@ -135,7 +138,7 @@ class EventScheduling extends Component {
} }
propagateChange(data) { propagateChange(data) {
const { onValueChange } = this.props; const { onValueChange = null } = this.props;
if (!onValueChange) return; if (!onValueChange) return;
onValueChange(data); onValueChange(data);
@ -197,9 +200,5 @@ EventScheduling.propTypes = {
}).isRequired, }).isRequired,
}; };
EventScheduling.defaultProps = {
afterTimeNumberSize: defaultAfterTimeNumberInputFieldSize,
onValueChange: null,
};
EventScheduling.displayName = 'EventScheduling'; EventScheduling.displayName = 'EventScheduling';
export { EventScheduling }; export { EventScheduling };

View File

@ -149,7 +149,7 @@ class SendEventConditions extends Component {
segment, segment,
eventOptionValue, eventOptionValue,
} = this.state; } = this.state;
const { onValueChange } = this.props; const { onValueChange = null } = this.props;
if (!onValueChange) return; if (!onValueChange) return;
const options = { const options = {
@ -193,8 +193,5 @@ SendEventConditions.propTypes = {
onValueChange: PropTypes.func, onValueChange: PropTypes.func,
}; };
SendEventConditions.defaultProps = {
onValueChange: null,
};
SendEventConditions.displayName = 'SendEventConditions'; SendEventConditions.displayName = 'SendEventConditions';
export { SendEventConditions }; export { SendEventConditions };

View File

@ -30,7 +30,11 @@ const wrapInLink = (content, params, id, totalSent) => {
); );
}; };
function Statistics({ newsletter, isSent, currentTime }) { function Statistics({
newsletter,
isSent = undefined,
currentTime = undefined,
}) {
let sent = isSent; let sent = isSent;
if (sent === undefined) { if (sent === undefined) {
// condition for standard and post notification listings // condition for standard and post notification listings
@ -199,10 +203,6 @@ Statistics.propTypes = {
currentTime: PropTypes.string, currentTime: PropTypes.string,
}; };
Statistics.defaultProps = {
isSent: undefined,
currentTime: undefined,
};
Statistics.displayName = 'NewsletterStatistics'; Statistics.displayName = 'NewsletterStatistics';
const StatisticsWithBoundary = withBoundary(Statistics); const StatisticsWithBoundary = withBoundary(Statistics);
export { StatisticsWithBoundary as Statistics }; export { StatisticsWithBoundary as Statistics };

View File

@ -39,11 +39,12 @@ class SenderField extends Component {
} }
onChange(event) { onChange(event) {
const { onValueChange = () => {} } = this.props.onValueChange;
const emailAddress = event.target.value.toLowerCase(); const emailAddress = event.target.value.toLowerCase();
this.setState({ this.setState({
emailAddress, emailAddress,
}); });
this.props.onValueChange({ onValueChange({
...event, ...event,
target: { target: {
...event.target, ...event.target,
@ -178,10 +179,5 @@ SenderField.propTypes = {
onValueChange: PropTypes.func, onValueChange: PropTypes.func,
}; };
SenderField.defaultProps = {
onValueChange: function onValueChange() {
// no-op
},
};
SenderField.displayName = 'SenderField'; SenderField.displayName = 'SenderField';
export { SenderField }; export { SenderField };

View File

@ -5,20 +5,28 @@ import { Select } from 'common/form/select/select.tsx';
// eslint-disable-next-line react/prefer-stateless-function // eslint-disable-next-line react/prefer-stateless-function
class TimeSelect extends Component { class TimeSelect extends Component {
render() { render() {
const options = Object.keys(this.props.timeOfDayItems).map((value) => ( const {
<option key={`option-${this.props.timeOfDayItems[value]}`} value={value}> onChange,
{this.props.timeOfDayItems[value]} timeOfDayItems,
value,
disabled = false,
name = 'time',
validation = {},
} = this.props;
const options = Object.keys(timeOfDayItems).map((val) => (
<option key={`option-${timeOfDayItems[value]}`} value={val}>
{timeOfDayItems[val]}
</option> </option>
)); ));
return ( return (
<Select <Select
name={this.props.name || 'time'} name={name || 'time'}
value={this.props.value} value={value}
disabled={this.props.disabled} disabled={disabled}
onChange={this.props.onChange} onChange={onChange}
isMinWidth isMinWidth
{...this.props.validation} {...validation}
> >
{options} {options}
</Select> </Select>
@ -35,10 +43,5 @@ TimeSelect.propTypes = {
validation: PropTypes.object, // eslint-disable-line react/forbid-prop-types validation: PropTypes.object, // eslint-disable-line react/forbid-prop-types
}; };
TimeSelect.defaultProps = {
name: 'time',
disabled: false,
validation: {},
};
TimeSelect.displayName = 'TimeSelect'; TimeSelect.displayName = 'TimeSelect';
export { TimeSelect }; export { TimeSelect };

View File

@ -134,7 +134,13 @@ SendingStatusListing.propTypes = {
}).isRequired, }).isRequired,
}; };
function StatsLink({ newsletter }) { function StatsLink({
newsletter = {
id: null,
subject: null,
sent: false,
},
}) {
if (!newsletter.id || !newsletter.subject || !newsletter.sent) return null; if (!newsletter.id || !newsletter.subject || !newsletter.sent) return null;
return ( return (
<p> <p>
@ -150,16 +156,8 @@ StatsLink.propTypes = {
sent: PropTypes.bool, sent: PropTypes.bool,
}), }),
}; };
StatsLink.defaultProps = {
newsletter: {
id: null,
subject: null,
sent: false,
},
};
function ListingItem({ function ListingItem({
error,
failed, failed,
taskId, taskId,
processed, processed,
@ -167,6 +165,7 @@ function ListingItem({
subscriberId, subscriberId,
lastName, lastName,
firstName, firstName,
error = '',
}) { }) {
const resend = () => { const resend = () => {
MailPoet.Ajax.post({ MailPoet.Ajax.post({
@ -263,9 +262,6 @@ ListingItem.propTypes = {
processed: PropTypes.number.isRequired, processed: PropTypes.number.isRequired,
subscriberId: PropTypes.number.isRequired, subscriberId: PropTypes.number.isRequired,
}; };
ListingItem.defaultProps = {
error: '',
};
ListingItem.displayName = 'ListingItem'; ListingItem.displayName = 'ListingItem';
SendingStatus.displayName = 'SendingStatus'; SendingStatus.displayName = 'SendingStatus';
export { SendingStatus }; export { SendingStatus };

View File

@ -91,7 +91,7 @@ class TemplateBox extends Component {
} }
render() { render() {
const { index, name, thumbnail, readonly } = this.props; const { index, name, readonly, thumbnail = null } = this.props;
let preview = ''; let preview = '';
if (typeof thumbnail === 'string' && thumbnail.length > 0) { if (typeof thumbnail === 'string' && thumbnail.length > 0) {
@ -151,8 +151,5 @@ TemplateBox.propTypes = {
afterSelect: PropTypes.func.isRequired, afterSelect: PropTypes.func.isRequired,
}; };
TemplateBox.defaultProps = {
thumbnail: null,
};
TemplateBox.displayName = 'TemplateBox'; TemplateBox.displayName = 'TemplateBox';
export { TemplateBox }; export { TemplateBox };

View File

@ -29,8 +29,8 @@ const MenuItem = WpMenuItem as React.FC<
>; >;
function NewsletterTypesComponent({ function NewsletterTypesComponent({
filter,
history, history,
filter = null,
hideScreenOptions = true, hideScreenOptions = true,
}: Props): JSX.Element { }: Props): JSX.Element {
const [isCreating, setIsCreating] = useState(false); const [isCreating, setIsCreating] = useState(false);
@ -291,11 +291,6 @@ function NewsletterTypesComponent({
); );
} }
NewsletterTypesComponent.defaultProps = {
filter: null,
hideScreenOptions: true,
};
export const NewsletterTypes = withRouter( export const NewsletterTypes = withRouter(
NewsletterTypesComponent as ComponentType<RouteComponentProps>, NewsletterTypesComponent as ComponentType<RouteComponentProps>,
); );

View File

@ -1,7 +1,7 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Notice } from 'notices/notice.tsx'; import { Notice } from 'notices/notice.tsx';
function MailerStatusNotice({ error }) { function MailerStatusNotice({ error = null }) {
if (!error || error.operation !== 'authorization') return null; if (!error || error.operation !== 'authorization') return null;
return ( return (
<Notice type="error" timeout={false} closable={false}> <Notice type="error" timeout={false} closable={false}>
@ -15,8 +15,5 @@ MailerStatusNotice.propTypes = {
error_message: PropTypes.string, error_message: PropTypes.string,
}), }),
}; };
MailerStatusNotice.defaultProps = {
error: null,
};
export { MailerStatusNotice }; export { MailerStatusNotice };

View File

@ -22,14 +22,14 @@ type Props = {
}; };
function Notice({ function Notice({
onClose,
onDisplay,
renderInPlace,
timeout,
scroll,
children, children,
closable,
type, type,
closable = true,
onClose = undefined,
onDisplay = undefined,
renderInPlace = false,
timeout = 10000,
scroll = false,
}: Props) { }: Props) {
const [hidden, setHidden] = useState(false); const [hidden, setHidden] = useState(false);
const elementRef = useRef(null); const elementRef = useRef(null);
@ -88,14 +88,6 @@ function Notice({
); );
} }
Notice.defaultProps = {
timeout: 10000,
scroll: false,
closable: true,
renderInPlace: false,
onDisplay: undefined,
onClose: undefined,
};
Notice.displayName = 'Notice'; Notice.displayName = 'Notice';
const NoticeWithBoundary = withBoundary(Notice); const NoticeWithBoundary = withBoundary(Notice);
export { NoticeWithBoundary as Notice }; export { NoticeWithBoundary as Notice };

View File

@ -10,7 +10,7 @@ type Props = {
onRequestClose?: () => void; onRequestClose?: () => void;
}; };
function App({ onRequestClose }: Props) { function App({ onRequestClose = noop }: Props) {
const [showModal, setShowModal] = useState(false); const [showModal, setShowModal] = useState(false);
// use jQuery since some of the targeted notices are added to the DOM using the old // use jQuery since some of the targeted notices are added to the DOM using the old
@ -36,10 +36,6 @@ function App({ onRequestClose }: Props) {
); );
} }
App.defaultProps = {
onRequestClose: noop,
};
// nothing is actually rendered to the container because the <Modal> component uses // nothing is actually rendered to the container because the <Modal> component uses
// ReactDOM.createPortal() but we need an element as a React root on all pages // ReactDOM.createPortal() but we need an element as a React root on all pages
const container = document.getElementById('mailpoet_set_from_address_modal'); const container = document.getElementById('mailpoet_set_from_address_modal');

View File

@ -3,11 +3,11 @@ import { MailPoet } from 'mailpoet';
import { Button } from 'common/button/button'; import { Button } from 'common/button/button';
function PreviousNextStepButtons({ function PreviousNextStepButtons({
hidePrevious, hidePrevious = false,
isLastStep, isLastStep = false,
canGoNext, canGoNext = true,
onPreviousAction, onPreviousAction = () => {},
onNextAction, onNextAction = () => {},
}) { }) {
return ( return (
<div className="mailpoet-settings-save"> <div className="mailpoet-settings-save">
@ -40,12 +40,5 @@ PreviousNextStepButtons.propTypes = {
onNextAction: PropTypes.func, onNextAction: PropTypes.func,
}; };
PreviousNextStepButtons.defaultProps = {
hidePrevious: false,
isLastStep: false,
canGoNext: true,
onPreviousAction: () => {},
onNextAction: () => {},
};
PreviousNextStepButtons.displayName = 'PreviousNextStepButtons'; PreviousNextStepButtons.displayName = 'PreviousNextStepButtons';
export { PreviousNextStepButtons }; export { PreviousNextStepButtons };

View File

@ -26,9 +26,9 @@ function getPreviousStepLink(importData, subscribersLimitForValidation) {
function StepDataManipulationComponent({ function StepDataManipulationComponent({
history, history,
stepMethodSelectionData,
subscribersLimitForValidation, subscribersLimitForValidation,
setStepDataManipulationData, setStepDataManipulationData,
stepMethodSelectionData = undefined,
}) { }) {
const [selectedSegments, setSelectedSegments] = useState([]); const [selectedSegments, setSelectedSegments] = useState([]);
const [updateExistingSubscribers, setUpdateExistingSubscribers] = const [updateExistingSubscribers, setUpdateExistingSubscribers] =
@ -132,8 +132,4 @@ StepDataManipulationComponent.propTypes = {
setStepDataManipulationData: PropTypes.func.isRequired, setStepDataManipulationData: PropTypes.func.isRequired,
}; };
StepDataManipulationComponent.defaultProps = {
stepMethodSelectionData: undefined,
};
export const StepDataManipulation = withRouter(StepDataManipulationComponent); export const StepDataManipulation = withRouter(StepDataManipulationComponent);

View File

@ -7,7 +7,7 @@ import { matchColumns } from './match-columns.jsx';
const MAX_SUBSCRIBERS_SHOWN = 10; const MAX_SUBSCRIBERS_SHOWN = 10;
function ColumnDataMatch({ header, subscribers }) { function ColumnDataMatch({ header = [], subscribers }) {
const matchedColumnTypes = matchColumns(subscribers, header); const matchedColumnTypes = matchColumns(subscribers, header);
return ( return (
<tr> <tr>
@ -43,10 +43,6 @@ ColumnDataMatch.propTypes = {
header: PropTypes.arrayOf(PropTypes.string), header: PropTypes.arrayOf(PropTypes.string),
}; };
ColumnDataMatch.defaultProps = {
header: [],
};
function Header({ header }) { function Header({ header }) {
return ( return (
<tr className="mailpoet_header"> <tr className="mailpoet_header">
@ -127,7 +123,7 @@ Subscribers.propTypes = {
).isRequired, ).isRequired,
}; };
function MatchTable({ subscribersCount, subscribers, header }) { function MatchTable({ subscribersCount = 0, subscribers = [], header = [] }) {
useLayoutEffect(() => { useLayoutEffect(() => {
generateColumnSelection(); generateColumnSelection();
}); });
@ -165,10 +161,4 @@ MatchTable.propTypes = {
header: PropTypes.arrayOf(PropTypes.string), header: PropTypes.arrayOf(PropTypes.string),
}; };
MatchTable.defaultProps = {
subscribersCount: 0,
subscribers: [],
header: [],
};
export { MatchTable }; export { MatchTable };

View File

@ -24,7 +24,13 @@ SingleWarning.propTypes = {
subscribers: PropTypes.arrayOf(PropTypes.string).isRequired, subscribers: PropTypes.arrayOf(PropTypes.string).isRequired,
}; };
function Warnings({ stepMethodSelectionData }) { function Warnings({
stepMethodSelectionData = {
invalid: [],
duplicate: [],
role: [],
},
}) {
const { invalid, duplicate, role } = stepMethodSelectionData; const { invalid, duplicate, role } = stepMethodSelectionData;
const [detailsShown, setDetailsShown] = useState(false); const [detailsShown, setDetailsShown] = useState(false);
@ -125,12 +131,4 @@ Warnings.propTypes = {
}), }),
}; };
Warnings.defaultProps = {
stepMethodSelectionData: {
invalid: [],
duplicate: [],
role: [],
},
};
export { Warnings }; export { Warnings };

View File

@ -22,8 +22,8 @@ type Props = {
}; };
function StepInputValidationComponent({ function StepInputValidationComponent({
stepMethodSelectionData,
history, history,
stepMethodSelectionData = undefined,
}: Props): JSX.Element { }: Props): JSX.Element {
const [importSource, setImportSource] = useState(undefined); const [importSource, setImportSource] = useState(undefined);
const [lastSent, setLastSent] = useState(undefined); const [lastSent, setLastSent] = useState(undefined);
@ -69,10 +69,6 @@ function StepInputValidationComponent({
); );
} }
StepInputValidationComponent.defaultProps = {
stepMethodSelectionData: undefined,
};
StepInputValidationComponent.displayName = 'StepInputValidationComponent'; StepInputValidationComponent.displayName = 'StepInputValidationComponent';
export const StepInputValidation = withRouter( export const StepInputValidation = withRouter(

View File

@ -7,7 +7,7 @@ import { Selection } from 'form/fields/selection.jsx';
import ReactStringReplace from 'react-string-replace'; import ReactStringReplace from 'react-string-replace';
import { PreviousNextStepButtons } from '../previous-next-step-buttons.jsx'; import { PreviousNextStepButtons } from '../previous-next-step-buttons.jsx';
function MethodMailChimp({ onFinish, onPrevious }) { function MethodMailChimp({ onFinish = () => {}, onPrevious = () => {} }) {
const [key, setKey] = useState(''); const [key, setKey] = useState('');
const [mailChimpLoadedLists, setMailChimpLoadedLists] = useState(undefined); const [mailChimpLoadedLists, setMailChimpLoadedLists] = useState(undefined);
const [selectedLists, setSelectedLists] = useState([]); const [selectedLists, setSelectedLists] = useState([]);
@ -148,11 +148,6 @@ MethodMailChimp.propTypes = {
onPrevious: PropTypes.func, onPrevious: PropTypes.func,
}; };
MethodMailChimp.defaultProps = {
onFinish: () => {},
onPrevious: () => {},
};
MethodMailChimp.displayName = 'MethodMailChimp'; MethodMailChimp.displayName = 'MethodMailChimp';
export { MethodMailChimp }; export { MethodMailChimp };

View File

@ -10,7 +10,13 @@ const kbLink =
const placeholder = const placeholder =
'Email, First Name, Last Name\njohn@doe.com, John, Doe\nmary@smith.com, Mary, Smith\njohnny@walker.com, Johnny, Walker'; 'Email, First Name, Last Name\njohn@doe.com, John, Doe\nmary@smith.com, Mary, Smith\njohnny@walker.com, Johnny, Walker';
function MethodPaste({ onValueChange, canFinish, onFinish, data, onPrevious }) { function MethodPaste({
canFinish,
onValueChange,
data = '',
onFinish = () => {},
onPrevious = () => {},
}) {
const onChange = (e) => { const onChange = (e) => {
onValueChange(e.target.value); onValueChange(e.target.value);
}; };
@ -64,10 +70,5 @@ MethodPaste.propTypes = {
data: PropTypes.string, data: PropTypes.string,
}; };
MethodPaste.defaultProps = {
onFinish: () => {},
onPrevious: () => {},
data: '',
};
MethodPaste.displayName = 'MethodPaste'; MethodPaste.displayName = 'MethodPaste';
export { MethodPaste }; export { MethodPaste };

View File

@ -7,7 +7,12 @@ import { PreviousNextStepButtons } from '../previous-next-step-buttons.jsx';
const kbLink = const kbLink =
'https://kb.mailpoet.com/article/126-importing-subscribers-with-csv-files'; 'https://kb.mailpoet.com/article/126-importing-subscribers-with-csv-files';
function MethodUpload({ onValueChange, canFinish, onFinish, onPrevious }) { function MethodUpload({
onValueChange,
canFinish,
onFinish = () => {},
onPrevious = () => {},
}) {
const onChange = (e) => { const onChange = (e) => {
const ext = e.target.value.match(/[^.]+$/); const ext = e.target.value.match(/[^.]+$/);
MailPoet.Notice.hide(); MailPoet.Notice.hide();
@ -66,9 +71,5 @@ MethodUpload.propTypes = {
onValueChange: PropTypes.func.isRequired, onValueChange: PropTypes.func.isRequired,
}; };
MethodUpload.defaultProps = {
onFinish: () => {},
onPrevious: () => {},
};
MethodUpload.displayName = 'MethodUpload'; MethodUpload.displayName = 'MethodUpload';
export { MethodUpload }; export { MethodUpload };

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { Radio } from 'common/form/radio/radio'; import { Radio } from 'common/form/radio/radio';
import { Tag } from 'common/tag/tag'; import { Tag } from 'common/tag/tag';
function SelectImportMethod({ activeMethod, onMethodChange }) { function SelectImportMethod({ onMethodChange, activeMethod = undefined }) {
return ( return (
<> <>
<div className="mailpoet-settings-label"> <div className="mailpoet-settings-label">
@ -74,8 +74,5 @@ SelectImportMethod.propTypes = {
onMethodChange: PropTypes.func.isRequired, onMethodChange: PropTypes.func.isRequired,
}; };
SelectImportMethod.defaultProps = {
activeMethod: undefined,
};
SelectImportMethod.displayName = 'SelectImportMethod'; SelectImportMethod.displayName = 'SelectImportMethod';
export { SelectImportMethod }; export { SelectImportMethod };

View File

@ -8,7 +8,11 @@ import ReactStringReplace from 'react-string-replace';
import { Button } from 'common/button/button'; import { Button } from 'common/button/button';
import { ErrorBoundary } from 'common'; import { ErrorBoundary } from 'common';
function ResultMessage({ subscribersCount, segments, initialMessage }) { function ResultMessage({
subscribersCount = 0,
segments = [],
initialMessage = '',
}) {
if (subscribersCount) { if (subscribersCount) {
let message = ReactStringReplace(initialMessage, '%1$s', () => ( let message = ReactStringReplace(initialMessage, '%1$s', () => (
<strong key="%1$s">{subscribersCount.toLocaleString()}</strong> <strong key="%1$s">{subscribersCount.toLocaleString()}</strong>
@ -29,14 +33,9 @@ ResultMessage.propTypes = {
initialMessage: PropTypes.string, initialMessage: PropTypes.string,
}; };
ResultMessage.defaultProps = {
segments: [],
subscribersCount: 0,
initialMessage: '',
};
ResultMessage.displayName = 'ResultMessage'; ResultMessage.displayName = 'ResultMessage';
function NoAction({ createdSubscribers, updatedSubscribers }) { function NoAction({ createdSubscribers = 0, updatedSubscribers = 0 }) {
if (!createdSubscribers && !updatedSubscribers) { if (!createdSubscribers && !updatedSubscribers) {
return <p>{MailPoet.I18n.t('importNoAction')}</p>; return <p>{MailPoet.I18n.t('importNoAction')}</p>;
} }
@ -48,13 +47,12 @@ NoAction.propTypes = {
updatedSubscribers: PropTypes.number, updatedSubscribers: PropTypes.number,
}; };
NoAction.defaultProps = {
createdSubscribers: 0,
updatedSubscribers: 0,
};
NoAction.displayName = 'NoAction'; NoAction.displayName = 'NoAction';
function SuppressionListReminder({ createdSubscribers, updatedSubscribers }) { function SuppressionListReminder({
createdSubscribers = 0,
updatedSubscribers = 0,
}) {
if (createdSubscribers || updatedSubscribers) { if (createdSubscribers || updatedSubscribers) {
return ( return (
<> <>
@ -89,13 +87,9 @@ SuppressionListReminder.propTypes = {
updatedSubscribers: PropTypes.number, updatedSubscribers: PropTypes.number,
}; };
SuppressionListReminder.defaultProps = {
createdSubscribers: 0,
updatedSubscribers: 0,
};
SuppressionListReminder.displayName = 'SuppressionListReminder'; SuppressionListReminder.displayName = 'SuppressionListReminder';
function NoWelcomeEmail({ addedToSegmentWithWelcomeNotification }) { function NoWelcomeEmail({ addedToSegmentWithWelcomeNotification = false }) {
if (addedToSegmentWithWelcomeNotification) { if (addedToSegmentWithWelcomeNotification) {
return <p>{MailPoet.I18n.t('importNoWelcomeEmail')}</p>; return <p>{MailPoet.I18n.t('importNoWelcomeEmail')}</p>;
} }
@ -106,18 +100,15 @@ NoWelcomeEmail.propTypes = {
addedToSegmentWithWelcomeNotification: PropTypes.bool, addedToSegmentWithWelcomeNotification: PropTypes.bool,
}; };
NoWelcomeEmail.defaultProps = {
addedToSegmentWithWelcomeNotification: false,
};
NoWelcomeEmail.diplayName = 'NoWelcomeEmail'; NoWelcomeEmail.diplayName = 'NoWelcomeEmail';
function StepResultsComponent({ function StepResultsComponent({
errors,
createdSubscribers,
updatedSubscribers,
segments,
addedToSegmentWithWelcomeNotification,
history, history,
errors = [],
createdSubscribers = undefined,
updatedSubscribers = undefined,
segments = undefined,
addedToSegmentWithWelcomeNotification = undefined,
}) { }) {
useEffect(() => { useEffect(() => {
if ( if (
@ -204,12 +195,5 @@ StepResultsComponent.propTypes = {
addedToSegmentWithWelcomeNotification: PropTypes.bool, addedToSegmentWithWelcomeNotification: PropTypes.bool,
}; };
StepResultsComponent.defaultProps = {
errors: [],
segments: undefined,
createdSubscribers: undefined,
updatedSubscribers: undefined,
addedToSegmentWithWelcomeNotification: undefined,
};
StepResultsComponent.displayName = 'StepResultsComponent'; StepResultsComponent.displayName = 'StepResultsComponent';
export const StepResults = withRouter(StepResultsComponent); export const StepResults = withRouter(StepResultsComponent);

View File

@ -38,6 +38,7 @@ module.exports = [
'no-underscore-dangle': 0, // Backbone uses underscores, we cannot remove them 'no-underscore-dangle': 0, // Backbone uses underscores, we cannot remove them
'import/no-default-export': 1, // no default exports 'import/no-default-export': 1, // no default exports
'no-only-tests/no-only-tests': 2, 'no-only-tests/no-only-tests': 2,
'react/require-default-props': 0, // deprecated in react 18.3.1
'check-file/filename-naming-convention': [ 'check-file/filename-naming-convention': [
'error', 'error',
{ '**/*.*': 'KEBAB_CASE' }, { '**/*.*': 'KEBAB_CASE' },

View File

@ -47,6 +47,7 @@ module.exports = [
'no-only-tests/no-only-tests': 2, 'no-only-tests/no-only-tests': 2,
'class-methods-use-this': 0, 'class-methods-use-this': 0,
'react/jsx-props-no-spreading': 0, 'react/jsx-props-no-spreading': 0,
'react/require-default-props': 0, // deprecated in react 18.3.1
'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
'import/no-default-export': 1, // no default exports 'import/no-default-export': 1, // no default exports