decap-cms-core
Version:
Decap CMS core application, see decap-cms package for the main distribution.
362 lines (359 loc) • 13.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _propTypes = _interopRequireDefault(require("prop-types"));
var _react = _interopRequireWildcard(require("react"));
var _reactImmutableProptypes = _interopRequireDefault(require("react-immutable-proptypes"));
var _immutable = require("immutable");
var _commonTags = require("common-tags");
var _registry = require("../../../lib/registry");
var _validationErrorTypes = _interopRequireDefault(require("../../../constants/validationErrorTypes"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function truthy() {
return {
error: false
};
}
function isEmpty(value) {
return value === null || value === undefined || Object.prototype.hasOwnProperty.call(value, 'length') && value.length === 0 || value.constructor === Object && Object.keys(value).length === 0 || _immutable.List.isList(value) && value.size === 0;
}
class Widget extends _react.Component {
constructor(...args) {
super(...args);
_defineProperty(this, "processInnerControlRef", ref => {
if (!ref) return;
/**
* If the widget is a container that receives state updates from the store,
* we'll need to get the ref of the actual control via the `react-redux`
* `getWrappedInstance` method. Note that connected widgets must pass
* `withRef: true` to `connect` in the options object.
*/
this.innerWrappedControl = ref.getWrappedInstance ? ref.getWrappedInstance() : ref;
this.wrappedControlValid = this.innerWrappedControl.isValid || truthy;
/**
* Get the `shouldComponentUpdate` method from the wrapped control, and
* provide the control instance is the `this` binding.
*/
const {
shouldComponentUpdate: scu
} = this.innerWrappedControl;
this.wrappedControlShouldComponentUpdate = scu && scu.bind(this.innerWrappedControl);
});
_defineProperty(this, "getValidateValue", () => {
var _this$innerWrappedCon, _this$innerWrappedCon2;
let value = ((_this$innerWrappedCon = this.innerWrappedControl) === null || _this$innerWrappedCon === void 0 ? void 0 : (_this$innerWrappedCon2 = _this$innerWrappedCon.getValidateValue) === null || _this$innerWrappedCon2 === void 0 ? void 0 : _this$innerWrappedCon2.call(_this$innerWrappedCon)) || this.props.value;
// Convert list input widget value to string for validation test
_immutable.List.isList(value) && (value = value.join(','));
return value;
});
_defineProperty(this, "validate", (skipWrapped = false) => {
const value = this.getValidateValue();
const field = this.props.field;
const errors = [];
const validations = [this.validatePresence, this.validatePattern];
if (field.get('meta')) {
validations.push(this.props.validateMetaField);
}
validations.forEach(func => {
const response = func(field, value, this.props.t);
if (response.error) errors.push(response.error);
});
if (skipWrapped) {
if (skipWrapped.error) errors.push(skipWrapped.error);
} else {
const wrappedError = this.validateWrappedControl(field);
if (wrappedError.error) errors.push(wrappedError.error);
}
this.props.onValidate(errors);
});
_defineProperty(this, "validatePresence", (field, value) => {
const {
t,
parentIds
} = this.props;
const isRequired = field.get('required', true);
if (isRequired && isEmpty(value)) {
const error = {
type: _validationErrorTypes.default.PRESENCE,
parentIds,
message: t('editor.editorControlPane.widget.required', {
fieldLabel: field.get('label', field.get('name'))
})
};
return {
error
};
}
return {
error: false
};
});
_defineProperty(this, "validatePattern", (field, value) => {
const {
t,
parentIds
} = this.props;
const pattern = field.get('pattern', false);
if (isEmpty(value)) {
return {
error: false
};
}
if (pattern && !RegExp(pattern.first()).test(value)) {
const error = {
type: _validationErrorTypes.default.PATTERN,
parentIds,
message: t('editor.editorControlPane.widget.regexPattern', {
fieldLabel: field.get('label', field.get('name')),
pattern: pattern.last()
})
};
return {
error
};
}
return {
error: false
};
});
_defineProperty(this, "validateWrappedControl", field => {
const {
t,
parentIds
} = this.props;
if (typeof this.wrappedControlValid !== 'function') {
throw new Error((0, _commonTags.oneLine)`
this.wrappedControlValid is not a function. Are you sure widget
"${field.get('widget')}" is registered?
`);
}
const response = this.wrappedControlValid();
if (typeof response === 'boolean') {
const isValid = response;
return {
error: !isValid
};
} else if (Object.prototype.hasOwnProperty.call(response, 'error')) {
return response;
} else if (response instanceof Promise) {
response.then(() => {
this.validate({
error: false
});
}, err => {
const error = {
type: _validationErrorTypes.default.CUSTOM,
message: `${field.get('label', field.get('name'))} - ${err}.`
};
this.validate({
error
});
});
const error = {
type: _validationErrorTypes.default.CUSTOM,
parentIds,
message: t('editor.editorControlPane.widget.processing', {
fieldLabel: field.get('label', field.get('name'))
})
};
return {
error
};
}
return {
error: false
};
});
/**
* In case the `onChangeObject` function is frozen by a child widget implementation,
* e.g. when debounced, always get the latest object value instead of using
* `this.props.value` directly.
*/
_defineProperty(this, "getObjectValue", () => this.props.value || (0, _immutable.Map)());
/**
* Change handler for fields that are nested within another field.
*/
_defineProperty(this, "onChangeObject", (field, newValue, newMetadata) => {
const newObjectValue = this.getObjectValue().set(field.get('name'), newValue);
return this.props.onChange(newObjectValue, newMetadata && {
[this.props.field.get('name')]: newMetadata
});
});
_defineProperty(this, "setInactiveStyle", () => {
this.props.setInactiveStyle();
if (this.props.field.has('pattern') && !isEmpty(this.getValidateValue())) {
this.validate();
}
});
}
shouldComponentUpdate(nextProps) {
/**
* Avoid unnecessary rerenders while loading assets.
*/
if (this.props.isLoadingAsset && nextProps.isLoadingAsset) return false;
/**
* Allow widgets to provide their own `shouldComponentUpdate` method.
*/
if (this.wrappedControlShouldComponentUpdate) {
return this.wrappedControlShouldComponentUpdate(nextProps);
}
return this.props.value !== nextProps.value || this.props.classNameWrapper !== nextProps.classNameWrapper || this.props.hasActiveStyle !== nextProps.hasActiveStyle;
}
render() {
const {
controlComponent,
entry,
collection,
config,
field,
value,
mediaPaths,
metadata,
onChange,
onValidateObject,
onOpenMediaLibrary,
onRemoveMediaControl,
onPersistMedia,
onClearMediaControl,
onAddAsset,
onRemoveInsertedMedia,
getAsset,
classNameWrapper,
classNameWidget,
classNameWidgetActive,
classNameLabel,
classNameLabelActive,
setActiveStyle,
hasActiveStyle,
editorControl,
uniqueFieldId,
resolveWidget,
widget,
getEditorComponents,
query,
queryHits,
clearSearch,
clearFieldErrors,
isFetching,
loadEntry,
fieldsErrors,
controlRef,
isEditorComponent,
isNewEditorComponent,
parentIds,
t,
isDisabled,
isFieldDuplicate,
isFieldHidden,
locale,
isParentListCollapsed
} = this.props;
return /*#__PURE__*/_react.default.createElement(controlComponent, {
entry,
collection,
config,
field,
value,
mediaPaths,
metadata,
onChange,
onChangeObject: this.onChangeObject,
onValidateObject,
onOpenMediaLibrary,
onClearMediaControl,
onRemoveMediaControl,
onPersistMedia,
onAddAsset,
onRemoveInsertedMedia,
getAsset,
forID: uniqueFieldId,
ref: this.processInnerControlRef,
validate: this.validate,
classNameWrapper,
classNameWidget,
classNameWidgetActive,
classNameLabel,
classNameLabelActive,
setActiveStyle,
setInactiveStyle: () => this.setInactiveStyle(),
hasActiveStyle,
editorControl,
resolveWidget,
widget,
getEditorComponents,
getRemarkPlugins: _registry.getRemarkPlugins,
query,
queryHits,
clearSearch,
clearFieldErrors,
isFetching,
loadEntry,
isEditorComponent,
isNewEditorComponent,
fieldsErrors,
controlRef,
parentIds,
t,
isDisabled,
isFieldDuplicate,
isFieldHidden,
locale,
isParentListCollapsed
});
}
}
exports.default = Widget;
_defineProperty(Widget, "propTypes", {
controlComponent: _propTypes.default.func.isRequired,
field: _reactImmutableProptypes.default.map.isRequired,
hasActiveStyle: _propTypes.default.bool,
setActiveStyle: _propTypes.default.func.isRequired,
setInactiveStyle: _propTypes.default.func.isRequired,
classNameWrapper: _propTypes.default.string.isRequired,
classNameWidget: _propTypes.default.string.isRequired,
classNameWidgetActive: _propTypes.default.string.isRequired,
classNameLabel: _propTypes.default.string.isRequired,
classNameLabelActive: _propTypes.default.string.isRequired,
value: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.object, _propTypes.default.string, _propTypes.default.bool]),
mediaPaths: _reactImmutableProptypes.default.map.isRequired,
metadata: _reactImmutableProptypes.default.map,
fieldsErrors: _reactImmutableProptypes.default.map,
onChange: _propTypes.default.func.isRequired,
onValidate: _propTypes.default.func,
onOpenMediaLibrary: _propTypes.default.func.isRequired,
onClearMediaControl: _propTypes.default.func.isRequired,
onRemoveMediaControl: _propTypes.default.func.isRequired,
onPersistMedia: _propTypes.default.func.isRequired,
onAddAsset: _propTypes.default.func.isRequired,
onRemoveInsertedMedia: _propTypes.default.func.isRequired,
getAsset: _propTypes.default.func.isRequired,
resolveWidget: _propTypes.default.func.isRequired,
widget: _propTypes.default.object.isRequired,
getEditorComponents: _propTypes.default.func.isRequired,
isFetching: _propTypes.default.bool,
controlRef: _propTypes.default.func,
query: _propTypes.default.func.isRequired,
clearSearch: _propTypes.default.func.isRequired,
clearFieldErrors: _propTypes.default.func.isRequired,
queryHits: _propTypes.default.oneOfType([_propTypes.default.array, _propTypes.default.object]),
editorControl: _propTypes.default.elementType.isRequired,
uniqueFieldId: _propTypes.default.string.isRequired,
loadEntry: _propTypes.default.func.isRequired,
t: _propTypes.default.func.isRequired,
onValidateObject: _propTypes.default.func,
isEditorComponent: _propTypes.default.bool,
isNewEditorComponent: _propTypes.default.bool,
entry: _reactImmutableProptypes.default.map.isRequired,
isDisabled: _propTypes.default.bool,
isFieldDuplicate: _propTypes.default.func,
isFieldHidden: _propTypes.default.func,
locale: _propTypes.default.string,
isParentListCollapsed: _propTypes.default.bool
});