@prisma-cms/front-editor
Version:
1,225 lines • 83.2 kB
JavaScript
"use strict";
/* eslint-disable @typescript-eslint/ban-ts-ignore */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-lone-blocks */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EditorComponent = void 0;
/**
* ToDo
* 1. Сейчас не оптимально структура компонентов выстроена, из-за чего нарушается
* отзывчивость компонентов на изменения. В частности renderHeader() выполняется
* из активного элемента, а не текущего, и после сохранения объекта не
* прекращается индикатор загрузки. Пришлось хакнуть принудительным обновлением через 2 сек.
*
* 2. Вынести методы в контекст.
createTemplate,
updateTemplate,
deleteTemplate,
*/
const react_1 = __importStar(require("react"));
const react_dom_1 = __importDefault(require("react-dom"));
// import PropTypes from 'prop-types'
const Button_1 = __importDefault(require("material-ui/Button"));
const IconButton_1 = __importDefault(require("material-ui/IconButton"));
const TextField_1 = __importDefault(require("material-ui/TextField"));
const Delete_1 = __importDefault(require("material-ui-icons/Delete"));
const Close_1 = __importDefault(require("material-ui-icons/Close"));
const ContentCopy_1 = __importDefault(require("material-ui-icons/ContentCopy"));
const DragHandle_1 = __importDefault(require("material-ui-icons/DragHandle"));
const ArrowUpward_1 = __importDefault(require("material-ui-icons/ArrowUpward"));
const ArrowDownward_1 = __importDefault(require("material-ui-icons/ArrowDownward"));
const HelpOutline_1 = __importDefault(require("material-ui-icons/HelpOutline"));
const FormControlLabel_1 = __importDefault(require("material-ui/Form/FormControlLabel"));
const Switch_1 = __importDefault(require("material-ui/Switch"));
// ComponentContext = createContext();
const apollo_cms_1 = require("apollo-cms");
// import gql from 'graphql-tag'
const context_1 = require("../context");
// import SingleUploader from "@prisma-cms/uploader/lib/components/SingleUploader";
const uploader_1 = __importDefault(require("@prisma-cms/uploader"));
const Typography_1 = __importDefault(require("material-ui/Typography"));
const Grid_1 = __importDefault(require("../common/Grid"));
__exportStar(require("./interfaces"), exports);
// eslint-disable-next-line @typescript-eslint/no-empty-function
const emptyMutate = () => __awaiter(void 0, void 0, void 0, function* () { });
const defaultProps = Object.assign(Object.assign({}, apollo_cms_1.EditableObject.defaultProps), { deletable: true, mutate: emptyMutate,
// data: {},
object: {
props: {},
components: [],
}, style: {
position: undefined,
display: undefined,
marginTop: undefined,
marginBottom: undefined,
marginLeft: undefined,
marginRight: undefined,
paddingTop: undefined,
paddingBottom: undefined,
paddingLeft: undefined,
paddingRight: undefined,
color: undefined,
fontFamily: undefined,
fontSize: undefined,
fontWeight: undefined,
textAlign: undefined,
textTransform: undefined,
verticalAlign: undefined,
minHeight: undefined,
height: undefined,
width: undefined,
maxWidth: undefined,
border: undefined,
borderRadius: undefined,
background: undefined,
backgroundImage: undefined,
backgroundColor: undefined,
backgroundPosition: undefined,
backgroundClip: undefined,
backgroundSize: undefined,
backgroundRepeat: undefined,
backgroundAttachment: undefined,
opacity: undefined,
visibility: undefined,
zIndex: undefined,
}, id: undefined, src: undefined, name: undefined, page_title: undefined, contentEditable: false, className: undefined, lang: undefined, tag: undefined, hide_wrapper_in_default_mode: false, render_badge: true, can_be_edited: true, render_add_button: true });
class EditorComponent extends apollo_cms_1.EditableObject {
constructor(props) {
super(props);
/**
* Пока что имеются коллизии с обновляемыми объектами, взятыми из кеша,
* так что пока кеш отключаем
*/
// getCacheKey() {
// return null;
// }
// container: Element | Text | null = null;
// container: EditorComponent | Node | null = null
this.container = null;
this.reactComponent = null;
// onDragStart = (event: React.DragEvent, item: EditorComponent | null) => {
this.onDragStart = (event) => {
const { onDragStart } = this.getEditorContext();
onDragStart && onDragStart(event, this.prepareDragItem());
};
this.onDragEnd = () => {
const { onDragEnd } = this.getEditorContext();
onDragEnd && onDragEnd();
};
/**
* Удаление элемента.
* Если это корневой элемент, удаляем его.
* Если нет, то удаляем из родительского
*/
// TODO Fix delete from list
this.delete = (event) => {
if (event) {
event.preventDefault();
event.stopPropagation();
}
const { setActiveItem } = this.getEditorContext();
// const activeItem = this.getActiveItem();
const { parent, delete_component, index } = this.props;
if (!parent) {
console.error('Can not get parent');
return false;
}
if (delete_component) {
delete_component(index);
// return;
}
else {
const parentObject = parent.getObjectWithMutations();
if (parentObject) {
const { components } = parentObject;
const object = this.getObjectWithMutations();
const index = object ? components.indexOf(object) : -1;
if (index === -1) {
console.error('Can not find component in parent');
return false;
}
const newComponents = components.slice(0);
newComponents.splice(index, 1);
parent.updateObject({
components: newComponents,
});
}
}
// if (activeItem === activeParent && !activeItem.props.parent) {
// this.addError("Can not delete root item");
// return;
// }
// else {
// let {
// data: {
// object,
// },
// parent: {
// props: {
// data: {
// object: {
// components,
// },
// },
// },
// },
// } = activeItem.props;
// const index = components.indexOf(object);
// components.splice(index, 1);
// // if (components) {
// // components.push(newItem);
// // }
// activeItem.props.parent.updateParentComponents();
// }
// return;
setActiveItem && setActiveItem(null);
};
this.setActiveItem = (component) => {
const { setActiveItem } = this.getEditorContext();
setActiveItem && setActiveItem(component);
};
this.inMainMode = () => {
const { mode } = this.props;
return mode === 'main';
};
this.onAddButtonClick = (event) => {
event.preventDefault();
event.stopPropagation();
const { parent } = this.props;
if (parent) {
const newItem = parent.prepareNewItem(this.prepareDragItem());
if (newItem) {
parent.addComponent(newItem);
}
}
};
this.unsetActiveItem = (event) => {
event.preventDefault();
event.stopPropagation();
const { setActiveItem } = this.getEditorContext();
setActiveItem && setActiveItem(null);
};
this.onInputSettings = (event) => {
const { innerText } = event.target;
let data;
if (innerText) {
try {
data = JSON.parse(innerText);
}
catch (error) {
console.warn(error);
}
}
if (data) {
const { name, props,
// component,
components, } = data;
// if (component && components && props) {
if (components && props) {
this.updateObject({
name,
props,
// component,
components,
});
}
}
};
this.expandStructure = (event) => {
event.preventDefault();
event.stopPropagation();
const structureViewLength = event.currentTarget.value;
this.setState({
maxStructureLengthView: parseInt(structureViewLength),
});
};
this.isActive = () => {
const { active } = this.state;
return active ? true : false;
};
// isActive() {
// const activeItem = this.getActiveItem()
// return activeItem && activeItem instanceof this.constructor ? true : false
// }
this.stopPropagation = (event) => {
event.preventDefault();
event.stopPropagation();
};
this.deleteComponentByIndex = (index) => {
var _a;
const components = (_a = this.getObjectWithMutations()) === null || _a === void 0 ? void 0 : _a.components;
if (index === -1) {
return;
}
else if (components && components.length) {
const newComponents = components.slice(0);
newComponents.splice(index, 1);
this.updateObject({
components: newComponents,
});
}
};
this.getEditorContext = () => {
return this.editorContext;
};
const { maxStructureLengthView = 3000 } = props;
this.updateComponentProperty = this.updateComponentProperty.bind(this);
this.updateObject = this.updateObject.bind(this);
this.onChangeProps = this.onChangeProps.bind(this);
this.updateProps = this.updateProps.bind(this);
this.getActiveParent = this.getActiveParent.bind(this);
this.renderHeader = this.renderHeader.bind(this);
this.renderComponentHeader = this.renderComponentHeader.bind(this);
this.save = this.save.bind(this);
this.moveBlockUp = this.moveBlockUp.bind(this);
this.moveBlockDown = this.moveBlockDown.bind(this);
this.onDrop = this.onDrop.bind(this);
this.onDragEnter = this.onDragEnter.bind(this);
this.onDragOver = this.onDragOver.bind(this);
this.onClick = this.onClick.bind(this);
this.onMouseOver = this.onMouseOver.bind(this);
this.onMouseLeave = this.onMouseLeave.bind(this);
this.state = Object.assign(Object.assign({}, this.state), { maxStructureLengthView, hovered: false, active: false });
}
componentDidMount() {
const { registerMountedComponent } = this.getEditorContext();
// if (!this.container) {
// // eslint-disable-next-line react/no-find-dom-node
// const container = ReactDOM.findDOMNode(this)
// if (container instanceof EditorComponent) {
// this.container = container
// }
// }
// // TODO check instanceof extended components
// // if (this.container && this.container instanceof EditorComponent) {
// if (this.container) {
// // @ts-ignore
// this.container.reactComponent = this
// }
if (!this.container) {
// eslint-disable-next-line react/no-find-dom-node
this.container = react_dom_1.default.findDOMNode(this);
}
// console.log('this.container instanceof Element', this.container instanceof Element);
// if (this.container) {
if (this.container && this.container instanceof Element) {
this.container.reactComponent = this;
}
// console.log('this.container.reactComponent', this.container?.reactComponent);
registerMountedComponent && registerMountedComponent(this);
const { mode } = this.props;
if (mode === 'main') {
this.addEventListeners();
}
super.componentDidMount && super.componentDidMount();
}
addEventListeners() {
return;
}
componentWillUnmount() {
const { activeItem, setActiveItem } = this.getEditorContext();
if (activeItem && activeItem === this) {
setActiveItem && setActiveItem(null);
}
const { unregisterMountedComponent } = this.getEditorContext();
unregisterMountedComponent && unregisterMountedComponent(this);
super.componentWillUnmount && super.componentWillUnmount();
}
// componentDidUpdate(prevProps, prevState) {
// super.componentDidUpdate && super.componentDidUpdate(prevProps, prevState)
// }
/**
* @deprecated
*/
processMeta(_meta = {}) {
// const { inEditMode, setPageMeta } = this.getEditorContext()
// const { page_title, page_status } = this.getComponentProps(this)
// if (!inEditMode && this.inMainMode()) {
// if (page_title) {
// meta = {
// ...meta,
// title: page_title,
// }
// }
// if (page_status) {
// meta = {
// ...meta,
// status: page_status,
// }
// }
// meta && setPageMeta(meta)
// }
}
/**
* Редактировать можно в следующих случаях:
* 1. Если нет родителя и нет id
* 2. Если есть ID и пользователь является владельцем
*/
// canEdit__() {
// const { id: objectId, CreatedBy } = this.getObjectWithMutations()
// const { parent } = this.props
// const { id: currentUserId, sudo } = this.getCurrentUser() || {}
// const { id: createdById } = CreatedBy || {}
// if (objectId) {
// // return true;
// if ((createdById && createdById === currentUserId) || sudo) {
// return true
// }
// } else {
// if (!parent) {
// return true
// }
// }
// return false
// }
prepareDirty(data) {
const newData = super.prepareDirty(data);
if (this.props.onChangeState) {
this.props.onChangeState(newData);
return;
}
return newData;
}
/**
* Обновление данных объекта.
* Так как компоненты рендерятся на основании передаваемых свойств,
* надо обновить данные абсолютного родителя, а не просто текущего элемента
*/
updateObject(data) {
const object = this.getObjectWithMutations();
const activeParent = this.getActiveParent();
/**
* Если это текущий компонент, обновляем его
*/
if (activeParent === this) {
return super.updateObject(data);
}
else {
/**
* Иначе находим свои данные в родительском компоненте и обновляем их
*/
const { parent } = this.props;
if (!parent) {
console.error('Can not get parent');
return;
}
const parentData = parent === null || parent === void 0 ? void 0 : parent.getObjectWithMutations();
const components = parentData === null || parentData === void 0 ? void 0 : parentData.components;
const current = components === null || components === void 0 ? void 0 : components.find((n) => n === object);
if (current && components) {
const index = components.indexOf(current);
const newComponents = components.slice(0);
newComponents[index] = Object.assign(Object.assign({}, current), data);
parent.updateObject({
components: newComponents,
});
}
else {
console.error('Can not get current element data in parent');
}
}
}
/**
* Создаем новый элемент, который будет добавлен в схему при перетаскивании
*/
prepareDragItem() {
return {
component: this,
name: this.constructor.Name,
props: this.prepareDragItemProps(),
components: this.prepareDragItemComponents(),
};
}
prepareDragItemProps() {
return {};
}
prepareDragItemComponents() {
return [];
}
onDrop(event) {
const { dragItem, dragTarget,
// setActiveItem,
onDragEnd, } = this.getEditorContext();
if (dragItem && dragTarget && dragTarget === this) {
event.preventDefault();
event.stopPropagation();
/**
* Здесь надо учитывать добавление или перетаскивание элемента.
* Если вбрасываемый объект - готовый инстанс, то перемещаем его.
* Иначе создаем новый.
*/
// TODO Restore block logic
if (dragItem instanceof EditorComponent) {
// let { parent: dragItemParent, index } = dragItem.props
// /**
// * Нельзя переносить элементы, у которых нет родителя
// */
// if (!dragItemParent) {
// // return false;
// } else if (dragItemParent === this) {
// /**
// * Нет смысла закидывать в себя же
// */
// // return false;
// } else {
// /**
// * Если все ОК, переносим элемент в другой блок.
// * Для этого надо найти переносимый элемент в родительском массиве элементов и перенести в новый.
// */
// const dragItemActiveParent = dragItem.getActiveParent()
// const dragTargetActiveParent = dragTarget.getActiveParent()
// const {
// // components,
// // data: {
// // object: {
// // components,
// // },
// // },
// components,
// } = dragItemParent.getObjectWithMutations()
// if (index === undefined) {
// const object = dragItem.getObject()
// index = components.indexOf(object)
// }
// /**
// * Если компонент найден, то исключаем его из массива
// */
// if (index !== -1) {
// let newComponents = components
// /**
// * Если абсолютный родители у обоих элементов одни,
// * то нельзя дважды обновить массив компонентов, иначе
// * второй элемент не найдет родителя.
// * По этой причине нам надо менять массив напрямую.
// * Здесь проблема возникает в том, что при отмене редактирования исключенный элемент
// * не будет восстановлен, так как редактирование происходит в исходной массиве
// */
// if (dragItemActiveParent !== dragTargetActiveParent) {
// newComponents = newComponents.slice(0)
// }
// const movingComponent = newComponents.splice(index, 1)[0]
// if (dragItemActiveParent !== dragTargetActiveParent) {
// dragItemParent.updateObject({
// components: newComponents,
// })
// }
// this.addComponent(movingComponent)
// }
// }
}
else {
const { dragItem } = this.getEditorContext();
if (dragItem && !(dragItem instanceof EditorComponent)) {
const newItem = this.prepareNewItem(dragItem);
if (newItem) {
this.addComponent(newItem);
// return;
}
}
}
// setActiveItem(null);
onDragEnd && onDragEnd();
return true;
}
}
// prepareNewItem(item: NonNullable<EditorContextValue['dragItem']>) {
prepareNewItem(item) {
if (!item) {
return;
}
// TODO: Check logic
// if (item instanceof EditorComponent) {
// return
// }
const { component: componentProto } = item, newItem = __rest(item
/**
* Return only typeof P["object"]
*/
, ["component"]);
/**
* Return only typeof P["object"]
*/
return Object.assign(Object.assign({}, newItem), { component: componentProto.constructor.Name });
}
/**
* Двигаем блок вверх
*/
moveBlockUp(event) {
var _a;
event === null || event === void 0 ? void 0 : event.preventDefault();
event === null || event === void 0 ? void 0 : event.stopPropagation();
const { parent } = this.props;
if (!parent) {
console.error('Can not get parent');
return;
}
const component = this.getComponentInParent();
if (component) {
// let {
// // components,
// data: {
// object: {
// components,
// },
// },
// } = this.props.parent.props;
const components = (_a = parent.getObjectWithMutations()) === null || _a === void 0 ? void 0 : _a.components;
if (!components) {
console.error('Can not get components');
return;
}
const index = components.indexOf(component);
/**
* Если элемент не на первом месте, двигаем его
*/
if (index === -1) {
console.error('Can not find component in parent');
}
else if (index > 0) {
const newComponents = components.slice(0);
newComponents.splice(index - 1, 0, newComponents.splice(index, 1)[0]);
parent.updateObject({
components: newComponents,
});
// this.updateParentComponents();
}
}
}
/**
* Двигаем блок вниз
*/
moveBlockDown(event) {
var _a;
event === null || event === void 0 ? void 0 : event.preventDefault();
event === null || event === void 0 ? void 0 : event.stopPropagation();
const { parent } = this.props;
if (!parent) {
console.error('Can not get parent');
return;
}
const component = this.getComponentInParent();
if (component) {
// let {
// // components,
// data: {
// object: {
// components,
// },
// },
// } = this.props.parent.props;
const components = (_a = parent === null || parent === void 0 ? void 0 : parent.getObjectWithMutations()) === null || _a === void 0 ? void 0 : _a.components;
const index = components ? components.indexOf(component) : -1;
/**
* Если элемент не на первом месте, двигаем его
*/
if (components && index !== -1 && components.length > index + 1) {
// components.splice(index + 1, 0, components.splice(index, 1)[0]);
// this.updateParentComponents();
const newComponents = components.slice(0);
newComponents.splice(index + 1, 0, newComponents.splice(index, 1)[0]);
parent.updateObject({
components: newComponents,
});
}
}
}
/**
* Обновить мы должны текущий элемент или предка
*/
addComponent(newItem) {
var _a;
const components = (_a = this.getObjectWithMutations()) === null || _a === void 0 ? void 0 : _a.components;
const { name, component } = newItem;
if (!component) {
Object.assign(newItem, {
component: name,
});
}
const newComponents = (components || []).slice(0);
newComponents.push(newItem);
this.updateObject({
components: newComponents,
});
}
/**
* Перетираем компоненты текущего объекта
*/
setComponents(components) {
// let {
// data: {
// object,
// },
// } = this.props;
// Object.assign(object, {
// components,
// });
// this.updateParentComponents();
this.updateObject({
components,
});
}
isDeletable() {
const { deletable } = this.props;
// const activeItem = this.getActiveItem();
// if (!activeItem) {
// return false;
// }
// const activeParent = activeItem.getActiveParent();
// return deletable && activeItem !== activeParent ? true : false;
// return deletable && activeItem.props.parent ? true : false;
return deletable && this.props.parent ? true : false;
}
// isDeletable = () => {
// const {
// deletable,
// } = this.props;
// // const activeItem = this.getActiveItem();
// // if(!activeItem) {
// // return false;
// // }
// // const activeParent = this.getActiveParent();
// return deletable ? true : false;
// }
/**
* Надо обновить components, чтобы в объекте было актуальное свойство
// */
// updateParentComponents() {
// const {
// forceUpdate,
// } = this.getEditorContext();
// const activeParent = this.getActiveParent();
// if (!activeParent) {
// // throw new Error("Can not get absParent");
// console.error("Can not get absParent");
// return;
// }
// activeParent.updateObject({
// components: activeParent.props.data.object.components.slice(0),
// });
// // forceUpdate();
// return;
// }
/**
* Проходимся вверх до тех пор, пока не найдем родителя с id
*/
getActiveParent() {
const { parent,
// data: {
// object,
// },
} = this.props;
const object = this.getObjectWithMutations();
if (object && object.id) {
return this;
}
else if (parent) {
return parent.getActiveParent();
}
else {
return this;
}
}
/**
* При клике по активному элементу в документе,
* отмечаем его, чтобы можно было редактировать его свойства
*/
onClick(event) {
// if (event.target === event.currentTarget) {
event.preventDefault();
event.stopPropagation();
// const {
// setActiveItem,
// } = this.getEditorContext();
// setActiveItem(this);
// }
this.setActiveItem(this);
}
onMouseOver(event) {
if (event.target === event.currentTarget) {
event.preventDefault();
event.stopPropagation();
const { setHoveredItem } = this.getEditorContext();
setHoveredItem && setHoveredItem(this);
}
}
// onMouseOver(event) {
// if (event.target === event.currentTarget) {
// event.preventDefault();
// event.stopPropagation();
// this.setState({
// hovered: true,
// });
// }
// }
onMouseLeave(event) {
if (event.target === event.currentTarget) {
event.preventDefault();
event.stopPropagation();
const { setHoveredItem,
// hoveredItem,
} = this.getEditorContext();
// if (hoveredItem && hoveredItem === this) {
// setHoveredItem(null);
// }
if (this.isHovered()) {
setHoveredItem && setHoveredItem(null);
// this.setState({
// hovered: false,
// });
}
}
}
// onMouseLeave(event) {
// if (event.target === event.currentTarget) {
// event.preventDefault();
// event.stopPropagation();
// if (this.isHovered()) {
// this.setState({
// hovered: false,
// });
// }
// }
// }
isHovered() {
return this.state.hovered;
}
// onDragEnter(event) {
// const {
// setDragTarget,
// dragItem,
// } = this.getEditorContext();
// if (dragItem && this.canBeChild(dragItem)) {
// event.preventDefault();
// event.stopPropagation();
// setDragTarget(this);
// return true;
// }
// }
// onDragEnter(event) {
// const {
// setDragTarget,
// dragItem,
// } = this.getEditorContext();
// if (dragItem && dragItem.component && this.canBeChild(dragItem) && dragItem.component.canBeParent(this)) {
// event.preventDefault();
// event.stopPropagation();
// setDragTarget(this);
// return true;
// }
// }
// onDragEnter(event) {
// const {
// setDragTarget,
// dragItem,
// } = this.getEditorContext();
// // if (dragItem && dragItem.component && this.canBeChild(dragItem) && dragItem.component.canBeParent(this)) {
// if (dragItem && this.canBeChild(dragItem)) {
// event.preventDefault();
// event.stopPropagation();
// setDragTarget(this);
// return true;
// }
// }
onDragEnter(event) {
const { setDragTarget, dragItem } = this.getEditorContext();
if (dragItem && this.canBeDropped(dragItem)) {
event.preventDefault();
event.stopPropagation();
setDragTarget && setDragTarget(this);
return true;
}
}
/**
* Учитывается при наведении.
* Определяет может ли быть брошен сюда перетаскиваемый элемент
*/
// canBeDropped(dragItem) {
// return this.canBeChild(dragItem);
// }
/**
* Возможно этот метод будет оставлен (или переименован).
* Получается следующая логика:
* При перетаскивании, дочерний элемент смотрим, хочет ли он стать дочерним
* через метод canBeChild(), в котором смотрит
*
*/
canBeDropped(child) {
if (!child || child === this) {
return false;
}
let item;
/**
* Если это перетаскивается готовый элемент на странице, проверяем, чтобы это не был родитель
*/
if (child instanceof EditorComponent) {
item = child;
const { parent: dragItemParent } = child.props;
/**
* Если у перетаскиваемого элемента нет родителя, то нельзя вкидывать
*/
if (!dragItemParent) {
return false;
}
let Parent = this.props.parent;
while (Parent && (Parent = Parent.props.parent)) {
if (Parent === dragItemParent) {
return false;
}
// Parent = Parent.props.parent;
}
// return false;
}
else {
/**
* Иначе это новый компонент, перетаскиваемый из панели компонентов
*/
if (child && child.component) {
item = child.component;
}
}
if (item && item instanceof EditorComponent) {
return item.canBeParent(this);
}
return false;
}
/**
* В новом компоненте проверяет может ли компонент на странице стать родительским для него.
*/
canBeParent(parent) {
/**
* Может, если этот компонент может быть дочерним для целевого.
*/
var _a;
return (_a = parent === null || parent === void 0 ? void 0 : parent.canBeChild(this)) !== null && _a !== void 0 ? _a : false;
}
/**
* В родительском компоненте проверяет может ли новый компонент стать дочерним.
*/
canBeChild(child) {
return child ? true : false;
}
/**
* Note: If using in canBeParent, should pass parent instead this
*/
findInParent(parent, condition) {
if (!parent) {
return null;
}
if (condition(parent)) {
return parent;
}
// else
return parent.props.parent
? this.findInParent(parent.props.parent, condition)
: null;
}
/**
* Поиск реакт-объекта в дочерних
* this.findReactChild(editableObject._reactInternalFiber.child, stateNode => stateNode instanceof Editable);
*/
// findReactChild(child: EditorComponent, condition: (child: EditorComponent) => EditorComponent | null) : EditorComponent | null {
// if (!child) {
// return null
// }
// if (condition(child.stateNode)) {
// return child.stateNode
// }
// // else
// return this.findReactChild(child.child, condition)
// }
onDragOver(event) {
const { dragTarget } = this.getEditorContext();
if (dragTarget === this) {
event.preventDefault();
event.stopPropagation();
return true;
}
}
// getComponentProps(component: EditorComponent):
// P['object']['props']
// // & Omit<P, "mode" | "deletable" | "parent" | "style" | "createTemplate" | "updateTemplate" | "deleteTemplate" | "errorDelay" | "SaveIcon" | "ResetIcon" | "EditIcon" | "cacheKeyPrefix" | "mutate" | "props" | "object">
// & Pick<P, "mode" >
// {
getComponentProps(component) {
var _a;
const _b = component.props, { mode, deletable, parent, style: defaultStyle, createTemplate, updateTemplate, deleteTemplate, errorDelay, SaveIcon, ResetIcon, EditIcon, cacheKeyPrefix, mutate } = _b, other = __rest(_b, ["mode", "deletable", "parent", "style", "createTemplate", "updateTemplate", "deleteTemplate", "errorDelay", "SaveIcon", "ResetIcon", "EditIcon", "cacheKeyPrefix", "mutate"]);
const _c = ((_a = component.getObjectWithMutations()) === null || _a === void 0 ? void 0 : _a.props) || {}, { style } = _c, componentProps = __rest(_c, ["style"]);
const result = Object.assign(Object.assign(Object.assign({}, other), componentProps), { style: Object.assign(Object.assign({}, defaultStyle), style) });
return result;
}
getRenderProps(componentProps = {}) {
var _a;
const inEditMode = this.inEditorMode();
const _b = this.props, { className: defaultClassName, mode, deletable, component, mutate,
// data,
// data: {
// object,
// },
object: objectNull, errorDelay, SaveIcon, ResetIcon, EditIcon, cacheKeyPrefix, hide_wrapper_in_default_mode } = _b,
// style,
other = __rest(_b, ["className", "mode", "deletable", "component", "mutate", "object", "errorDelay", "SaveIcon", "ResetIcon", "EditIcon", "cacheKeyPrefix", "hide_wrapper_in_default_mode"]);
const object = this.getObjectWithMutations();
// const {
// props: { className, ...objectProps },
// } = object
const _c = (_a = object === null || object === void 0 ? void 0 : object.props) !== null && _a !== void 0 ? _a : {}, { className } = _c, objectProps = __rest(_c, ["className"]);
let classNames = [
defaultClassName,
className,
// propsClassName,
];
Object.assign(componentProps, Object.assign(Object.assign(Object.assign(Object.assign({}, other), object), objectProps), this.getComponentProps(this)));
if (inEditMode) {
const { dragItem, dragTarget,
// activeItem,
// hoveredItem,
} = this.getEditorContext();
// if (dragItem && (dragItem.component && !dragItem.component.canBeParent(this))) {
// }
const isRoot = this.isRoot();
classNames = classNames.concat([
'item',
inEditMode ? 'itemEditable' : '',
isRoot ? 'root' : '',
]);
/**
* Если есть перетаскиваемый элемент, проверяем, может ли компонент стать родительским для него.
* Если нет, то убираем бордеры и события.
*/
if (dragItem &&
dragItem instanceof EditorComponent &&
dragItem.component &&
!dragItem.component.canBeParent(this)) {
classNames = classNames.concat(['disabled']);
}
else {
// if (!dragItem || (!dragItem.component || dragItem.component.canBeParent(this))) {
const isDragOvered = dragTarget === this ? true : false;
// const isActive = activeItem === this ? true : false;
const isActive = this.isActive();
// const isHovered = hoveredItem === this ? true : false;
const isHovered = this.isHovered();
const isDirty = this.isDirty();
classNames = classNames.concat([
isDragOvered ? 'dragOvered' : '',
isActive ? 'active' : '',
isHovered ? 'hovered' : '',
isDirty ? 'dirty' : '',
]);
Object.assign(componentProps, {
onDrop: this.onDrop,
onDragEnter: this.onDragEnter,
onDragOver: this.onDragOver,
onClick: this.onClick,
onMouseOver: this.onMouseOver,
onMouseLeave: this.onMouseLeave,
});
}
}
Object.assign(componentProps, {
className: classNames.filter((n) => n).join(' '),
});
return componentProps;
}
renderPanelView(content) {
const { hoveredItem, dragTarget } = this.getEditorContext();
const isActive = this.isActive();
const isHovered = hoveredItem instanceof this.constructor && !isActive ? true : false;
const isDragOvered = dragTarget && dragTarget instanceof this.constructor ? true : false;
const { help_url } = this.constructor;
return (react_1.default.createElement(Grid_1.default, { item: true, className: [
'panelItem',
isHovered ? 'hovered' : '',
isDragOvered ? 'dragOvered' : '',
].join(' '), draggable: true, onDragStart: this.onDragStart, onDragEnd: this.onDragEnd },
content || this.constructor.Name,
' ',
help_url ? (react_1.default.createElement("a", { href: help_url, target: "_blank", rel: "noopener noreferrer", className: "helpLink" },
react_1.default.createElement(HelpOutline_1.default, null))) : null));
}
renderAddButton(content) {
const help_url = this.constructor.help_url;
const { className, style, render_add_button,
// ...other
} = this.props;
if (!render_add_button) {
return null;
}
return (react_1.default.createElement(Grid_1.default, { item: true },
react_1.default.createElement("div", { className: ['panelItem', className].join(' '), onClick: this.onAddButtonClick, style: style },
content || this.constructor.Name,
' ',
help_url ? (react_1.default.createElement("a", { href: help_url, target: "_blank", rel: "noopener noreferrer", className: "helpLink" },
react_1.default.createElement(HelpOutline_1.default, null))) : null)));
}
renderSettingsView(content) {
var _a, _b;
const canEdit = this.canEdit();
const object = this.getObjectWithMutations();
if (!object) {
return null;
}
const { id: objectId, name, description } = object;
const { maxStructureLengthView } = this.state;
const header = this.renderComponentHeader();
// let {
// props: {
// props,
// ...other
// },
// } = this;
const saveable = this.constructor.saveable;
const activeParent = this.getActiveParent();
const parentId = (_a = activeParent.getObjectWithMutations()) === null || _a === void 0 ? void 0 : _a.id;
const deletable = this.isDeletable();
const _c = this.getComponentProps(this), { style: allStyles } = _c, componentProps = __rest(_c, ["style"]);
const isRoot = this.isRoot();
const structure = this.getStructure(this);
let structureView;
if (structure) {
try {
structureView = JSON.stringify(structure, undefined, 2);
// if (structureView) {
// }
}
catch (error) {
console.error(error);
}
}
const structureViewLength = structureView ? structureView.length : 0;
if (maxStructureLengthView &&
structureViewLength > maxStructureLengthView) {
structureView = (react_1.default.createElement(Button_1.default, { onClick: this.expandStructure, value: structureViewLength },
"Show ",
structureViewLength,
" chars"));
}
else {
structureView = (react_1.default.createElement("div", { contentEditable: canEdit ? true : false, suppressContentEditableWarning: true, style: canEdit
? {
border: '1px dashed #ddd',
padding: 3,
}
: undefined, onInput: this.onInputSettings }, structureView));
}
const style = (_b = this.props.props) === null || _b === void 0 ? void 0 : _b.style;
const editableStyles = Object.assign(Object.assign({}, allStyles), style);
const settings = [];
if (componentProps) {
const names = Object.keys(componentProps);
names.map((name) => {
const value = componentProps[name];
const type = typeof value;
const field = this.getEditorField({
key: name,
type,
name,
label: name,
value,
// deletable: this.props.data.object.props && this.props.data.object.props[name] !== undefined ? true : false,
deletable: this.isDeletable(),
});
if (field) {
settings.push(field);
}
return null;
});
}
if (editableStyles) {
const names = Object.keys(editableStyles);
names.map((name) => {
const value = editableStyles[name];
const type = typeof value;
const field = this.getEditorField({
key: name,
type,
name,
label: name,
value,
deletable: style && style[name] !== undefined ? true : false,
style: editableStyles || {},
});
if (field) {
settings.push(field);
}
return null;
});
}
const isDirty = this.isDirty();
const buttons = (react_1.default.createElement(Grid_1.default, { container: true, spacing: 8, alignItems: "center" },
react_1.default.createElement(Grid_1.default, { item: true, xs: true }),
isDirty ? this.renderResetButton() : null,
!isRoot && !objectId && activeParent && saveable ? (react_1.default.createElement(Grid_1.default, { item: true },
react_1.default.createElement(IconButton_1.default, { title: "\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u0432 \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u044B\u0439 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442",
/**
* При сохранении, мы должны текущий элемент заменить новым
*/
// eslint-disable-next-line react/jsx-no-bind
onClick: (event) => __awaiter(this, void 0, void 0, function* () {
event.preventDefault();
event.stopPropagation();
this.saveSeparatedComponent(parentId);
}) },
react_1.default.createElement(ContentCopy_1.default, null)))) : null,
deletable ? (react_1.default.createElement(Grid_1.default, { item: true },
react_1.default.createElement(IconButton_1.default, { title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u044D\u043B\u0435\u043C\u0435\u043D\u0442", onClick: this.delete },
react_1.default.createElement(Delete_1.default, null)))) : null,
react_1.default.createElement(Grid_1.default, { item: true },
react_1.default.createElement(IconButton_1.default, { title: "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u0430", onClick: this.unsetActiveItem },
react_1.default.createElement(Close_1.default, null)))));
const output = (react_1.default.createElement(Grid_1.default, { container: true, spacing: 8, onMouseOver: this.stopPropagation, onMouseLeave: this.stopPropagation,
/**
Важно! Хотя этот блок отрендерен через портал в другую часть HTML-документа, на него распростроняются ивенты
из родительского компонента. https://prisma-cms.com/chat-messages/cjv791tug5qg50989k3v2tdaa
Из-за этого при клике событие уходит в ближайший верхний элемент основной области (и устанавливает активный компонент).
Для предотвращения вызываем event.stopPropagation().
Если установить и event.preventDefault(), то тогда не срабатывают клики на компонентах типа @prisma-cms/uploader
event.target === event.currentTarget вроде помогает
*/
onClick: this.stopPropagation },
react_1.d