UNPKG

@prisma-cms/front-editor

Version:
1,225 lines 83.2 kB
"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