From ce3d61e0ef01914bd9a5660243e677d3ce09871f Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Wed, 27 Dec 2023 10:48:15 +1300 Subject: [PATCH 01/12] . --- .../ElementEditor/AddElementPopover.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/client/src/components/ElementEditor/AddElementPopover.js b/client/src/components/ElementEditor/AddElementPopover.js index 2a1ebff6..c0950a73 100644 --- a/client/src/components/ElementEditor/AddElementPopover.js +++ b/client/src/components/ElementEditor/AddElementPopover.js @@ -19,6 +19,8 @@ class AddElementPopover extends Component { } /** + * #graphql + * * click handler that preserves the details of what was clicked * @param {object} elementType in the shape of types/elmementTypeType * @returns {function} @@ -42,6 +44,16 @@ class AddElementPopover extends Component { }; } + /** + * #rpc + * - call add element to area endpoint (areaID, elementType, insertAfterElementID) + * - then call read blocks from area endpoint (areaID) + * - also then update the preview via jquery/entwine + */ + handleButtonOnClick(elementType) { + // todo + } + /** * Pass toggle to parent and clear the search input */ @@ -66,11 +78,14 @@ class AddElementPopover extends Component { extraClass ); + const globalUseGraphqQL = false; + const buttonOnClickHandler = globalUseGraphqQL ? this.getElementButtonClickHandler : this.handleButtonOnClick; + const buttons = elementTypes.map((elementType) => ({ content: elementType.title, key: elementType.name, className: classNames(elementType.icon, 'btn--icon-xl', 'element-editor-add-element__button'), - onClick: this.getElementButtonClickHandler(elementType), + onClick: buttonOnClickHandler(elementType), })); return ( From ede8f1911f001efce7510cb428c2f33801784248 Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Wed, 27 Dec 2023 14:53:57 +1300 Subject: [PATCH 02/12] . --- .../ElementEditor/AddElementPopover.js | 4 +- .../components/ElementEditor/ElementList.js | 46 +++++++++++++++---- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/client/src/components/ElementEditor/AddElementPopover.js b/client/src/components/ElementEditor/AddElementPopover.js index c0950a73..f9e6a6ef 100644 --- a/client/src/components/ElementEditor/AddElementPopover.js +++ b/client/src/components/ElementEditor/AddElementPopover.js @@ -78,8 +78,8 @@ class AddElementPopover extends Component { extraClass ); - const globalUseGraphqQL = false; - const buttonOnClickHandler = globalUseGraphqQL ? this.getElementButtonClickHandler : this.handleButtonOnClick; + const globalUseGraphQL = false; + const buttonOnClickHandler = globalUseGraphQL ? this.getElementButtonClickHandler : this.handleButtonOnClick; const buttons = elementTypes.map((elementType) => ({ content: elementType.title, diff --git a/client/src/components/ElementEditor/ElementList.js b/client/src/components/ElementEditor/ElementList.js index 51865602..2f481b64 100644 --- a/client/src/components/ElementEditor/ElementList.js +++ b/client/src/components/ElementEditor/ElementList.js @@ -11,6 +11,27 @@ import { getDragIndicatorIndex } from 'lib/dragHelpers'; import { getElementTypeConfig } from 'state/editor/elementConfig'; class ElementList extends Component { + constructor(props) { + super(props); + this.state = { + isLoading: true, + contentBlocks: [], + }; + } + + // #RPC + // it should make an ajax call to the server and do the equivalent of readBlocksForAreaQuery + // it should the call this.setState `contentBlocks` with the result + // this will cause a re-render of the component + // this callback should be passed to other components via context and get called after doing mutations + fetchContentBlocks() { + const globalUseGraphQL = false; + if (globalUseGraphQL) { + return; + } + // TODO: implement + } + getDragIndicatorIndex() { const { dragTargetElementId, draggedItem, blocks, dragSpot } = this.props; return getDragIndicatorIndex( @@ -31,7 +52,7 @@ class ElementList extends Component { ElementComponent, HoverBarComponent, DragIndicatorComponent, - blocks, + blocks, // graphql - comes from readBlocksForAreaQuery allowedElementTypes, elementTypes, areaId, @@ -41,16 +62,19 @@ class ElementList extends Component { isDraggingOver, } = this.props; + const globalUseGraphQL = false; + const contentBlocks = globalUseGraphQL ? blocks : this.state.contentBlocks; + // Blocks can be either null or an empty array - if (!blocks) { + if (!contentBlocks) { return null; } - if (blocks && !blocks.length) { + if (contentBlocks && !contentBlocks.length) { return
{i18n._t('ElementList.ADD_BLOCKS', 'Add blocks to place your content')}
; } - let output = blocks.map((element) => ( + let output = contentBlocks.map((element) => (
; } return null; @@ -106,9 +132,12 @@ class ElementList extends Component { render() { const { blocks } = this.props; + const globalUseGraphQL = false; + const contentBlocks = globalUseGraphQL ? blocks : this.state.contentBlocks; + const listClassNames = classNames( 'elemental-editor-list', - { 'elemental-editor-list--empty': !blocks || !blocks.length } + { 'elemental-editor-list--empty': !contentBlocks || !contentBlocks.length } ); return this.props.connectDropTarget( @@ -121,11 +150,12 @@ class ElementList extends Component { } ElementList.propTypes = { - // @todo support either ElementList or Element children in an array (or both) + // blocks and loading come from readBlocksForAreaQuery blocks: PropTypes.arrayOf(elementType), + loading: PropTypes.bool, + // elementTypes: PropTypes.arrayOf(elementTypeType).isRequired, allowedElementTypes: PropTypes.arrayOf(elementTypeType).isRequired, - loading: PropTypes.bool, areaId: PropTypes.number.isRequired, dragTargetElementId: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), onDragOver: PropTypes.func, From 8ed3b943a329d14c436aecc5d9d556bb20691cb4 Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Sun, 31 Dec 2023 11:51:50 +1300 Subject: [PATCH 03/12] . --- client/dist/js/bundle.js | 4688 ++++++++++++++++- client/dist/styles/bundle.css | 3 +- .../components/ElementEditor/ElementEditor.js | 18 +- client/src/state/editor/sortBlockMutation.js | 1 + 4 files changed, 4704 insertions(+), 6 deletions(-) diff --git a/client/dist/js/bundle.js b/client/dist/js/bundle.js index ebc4e630..4e900982 100644 --- a/client/dist/js/bundle.js +++ b/client/dist/js/bundle.js @@ -1 +1,4687 @@ -!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s="./client/src/bundles/bundle.js")}({"./client/src/boot/index.js":function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}var o=n("./client/src/boot/registerComponents.js"),a=r(o),i=n("./client/src/boot/registerTransforms.js"),l=r(i);window.document.addEventListener("DOMContentLoaded",function(){(0,a.default)(),(0,l.default)()})},"./client/src/boot/registerComponents.js":function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=n(3),a=r(o),i=n("./client/src/components/ElementEditor/Element.js"),l=r(i),u=n("./client/src/components/ElementEditor/ElementActions.js"),c=r(u),s=n("./client/src/components/ElementEditor/ElementEditor.js"),d=r(s),f=n("./client/src/components/ElementEditor/ElementList.js"),p=r(f),m=n("./client/src/components/ElementEditor/Toolbar.js"),b=r(m),y=n("./client/src/components/ElementEditor/AddNewButton.js"),v=r(y),h=n("./client/src/components/ElementEditor/Header.js"),g=r(h),E=n("./client/src/components/ElementEditor/Content.js"),_=r(E),O=n("./client/src/components/ElementEditor/Summary.js"),j=r(O),T=n("./client/src/components/ElementEditor/InlineEditForm.js"),k=r(T),w=n("./client/src/components/ElementEditor/AddElementPopover.js"),I=r(w),S=n("./client/src/components/ElementEditor/HoverBar.js"),A=r(S),P=n("./client/src/components/ElementEditor/DragPositionIndicator.js"),D=r(P),C=n("./client/src/components/TextCheckboxGroupField/TextCheckboxGroupField.js"),N=r(C);t.default=function(){a.default.component.registerMany({ElementEditor:d.default,ElementToolbar:b.default,ElementAddNewButton:v.default,ElementList:p.default,Element:l.default,ElementActions:c.default,ElementHeader:g.default,ElementContent:_.default,ElementSummary:j.default,ElementInlineEditForm:k.default,AddElementPopover:I.default,HoverBar:A.default,DragPositionIndicator:D.default,TextCheckboxGroupField:N.default})}},"./client/src/boot/registerTransforms.js":function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=n(3),a=r(o),i=n("./client/src/state/history/readOneBlockQuery.js"),l=r(i),u=n("./client/src/components/HistoricElementView/HistoricElementView.js"),c=r(u),s=n("./client/src/state/history/revertToBlockVersionMutation.js"),d=r(s),f=n("./client/src/state/editor/readBlocksForAreaQuery.js"),p=r(f),m=n("./client/src/state/editor/addElementMutation.js"),b=r(m),y=n("./client/src/components/ElementActions/ArchiveAction.js"),v=r(y),h=n("./client/src/components/ElementActions/DuplicateAction.js"),g=r(h),E=n("./client/src/components/ElementActions/PublishAction.js"),_=r(E),O=n("./client/src/components/ElementActions/SaveAction.js"),j=r(O),T=n("./client/src/components/ElementActions/UnpublishAction.js"),k=r(T);t.default=function(){a.default.transform("elemental-fieldgroup",function(e){e.component("FieldGroup.HistoryViewer.VersionDetail",c.default,"HistoricElement")},{after:"field-holders"}),a.default.transform("elements-history",function(e){e.component("HistoryViewer.Form_ItemEditForm",l.default,"ElementHistoryViewer")}),a.default.transform("blocks-history-revert",function(e){e.component("HistoryViewerToolbar.VersionedAdmin.HistoryViewer.Element.HistoryViewerVersionDetail",d.default,"BlockRevertMutation")}),a.default.transform("cms-element-editor",function(e){e.component("ElementList",p.default,"PageElements")}),a.default.transform("cms-element-adder",function(e){e.component("AddElementPopover",b.default,"ElementAddButton")}),a.default.transform("element-actions",function(e){e.component("ElementActions",j.default,"ElementActionsWithSave"),e.component("ElementActions",_.default,"ElementActionsWithPublish"),e.component("ElementActions",k.default,"ElementActionsWithUnpublish"),e.component("ElementActions",g.default,"ElementActionsWithDuplicate"),e.component("ElementActions",v.default,"ElementActionsWithArchive")})}},"./client/src/bundles/bundle.js":function(e,t,n){"use strict";n("./client/src/legacy/ElementEditor/entwine.js"),n("./client/src/boot/index.js")},"./client/src/components/ElementActions/AbstractAction.js":function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=Object.assign||function(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=!!e&&e.id;this.setState({dragTargetElementId:n,dragSpot:!1===t?"bottom":"top"})}},{key:"handleDragEnd",value:function(e,t){var n=this.props;(0,n.actions.handleSortBlock)(e,t,n.areaId).then(function(){var e=window.jQuery(".cms-preview");e.entwine("ss.preview")._loadUrl(e.find("iframe").attr("src"))}),this.setState({dragTargetElementId:null,dragSpot:null})}},{key:"render",value:function(){var e=this.props,t=e.fieldName,n=e.formState,r=e.ToolbarComponent,o=e.ListComponent,a=e.areaId,i=e.elementTypes,l=e.isDraggingOver,u=e.connectDropTarget,c=e.allowedElements,s=this.state,d=s.dragTargetElementId,p=s.dragSpot,m=c.map(function(e){return i.find(function(t){return t.class===e})});return u(f.default.createElement("div",{className:"element-editor"},f.default.createElement(r,{elementTypes:m,areaId:a,onDragOver:this.handleDragOver}),f.default.createElement(o,{allowedElementTypes:m,elementTypes:i,areaId:a,onDragOver:this.handleDragOver,onDragStart:this.handleDragStart,onDragEnd:this.handleDragEnd,dragSpot:p,isDraggingOver:l,dragTargetElementId:d}),f.default.createElement(T.default,{elementTypes:i}),f.default.createElement("input",{name:t,type:"hidden",value:JSON.stringify(n)||"",className:"no-change-track"})))}}]),t}(d.PureComponent);I.propTypes={fieldName:m.default.string,elementTypes:m.default.arrayOf(v.elementTypeType).isRequired,allowedElements:m.default.arrayOf(m.default.string).isRequired,areaId:m.default.number.isRequired,actions:m.default.shape({handleSortBlock:m.default.func})},t.Component=I,t.default=(0,y.compose)(w.default,(0,E.DropTarget)("element",{},function(e,t){return{connectDropTarget:e.dropTarget(),isDraggingOver:t.isOver()}}),(0,h.connect)(u),(0,b.inject)(["ElementToolbar","ElementList"],function(e,t){return{ToolbarComponent:e,ListComponent:t}},function(){return"ElementEditor"}),O.default)(I)},"./client/src/components/ElementEditor/ElementList.js":function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0}),t.Component=void 0;var l=Object.assign||function(e){for(var t=1;t]*?>/g,"")).isValid?(e(".cms-edit-form").data("hasValidationErrors",!1),m()):e(".cms-edit-form").data("hasValidationErrors",!0)}}}),e(".js-injector-boot .element-editor__container .element-form-dirty-state").entwine({onmatch:function(){e(".cms-edit-form").trigger("change")},onunmatch:function(){e(".cms-edit-form").trigger("change")}}),e(".cms-edit-form").entwine({getChangeTrackerOptions:function(){var t=void 0===this.entwineData("ChangeTrackerOptions"),n=this._super();return t&&(n=e.extend({},n),n.ignoreFieldSelector+=", .elementalarea :input:not(.element-form-dirty-state)",this.setChangeTrackerOptions(n)),n}})})},"./client/src/lib/dragHelpers.js":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.elementDragSource=t.getDragIndicatorIndex=t.isOverTop=void 0;var r=n(15);t.isOverTop=function(e,t){var n=e.getClientOffset(),o=(0,r.findDOMNode)(t).getBoundingClientRect();return n.y1&&void 0!==arguments[1]?arguments[1]:null,n=e.blockSchema.typeName,r=Array.isArray(t)?t:a().elementTypes,o=r.find(function(e){return e.class===n||e.name===n});return e.obsoleteClassName&&(o=Object.assign({obsoleteClassName:e.obsoleteClassName},o),Object.preventExtensions(o)),o}},"./client/src/state/editor/loadElementFormStateName.js":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.loadElementFormStateName=void 0;var r=n(12),o=function(e){return e&&e.__esModule?e:{default:e}}(r);t.loadElementFormStateName=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=o.default.getSection("DNADesign\\Elemental\\Controllers\\ElementalAreaController"),n=t.form.elementForm.formNameTemplate;return e?n.replace("{id}",e):n}},"./client/src/state/editor/loadElementSchemaValue.js":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.loadElementSchemaValue=void 0;var r=n(12),o=function(e){return e&&e.__esModule?e:{default:e}}(r);t.loadElementSchemaValue=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=o.default.getSection("DNADesign\\Elemental\\Controllers\\ElementalAreaController"),r=n.form.elementForm[e]||"";return t?r+"/"+t:r}},"./client/src/state/editor/publishBlockMutation.js":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.config=t.mutation=void 0;var r=Object.assign||function(e){for(var t=1;t 0 && arguments[0] !== undefined ? arguments[0] : null; + var isOverTop = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + var id = element ? element.id : false; + + this.setState({ + dragTargetElementId: id, + dragSpot: isOverTop === false ? 'bottom' : 'top' + }); + } + }, { + key: 'handleDragEnd', + value: function handleDragEnd(sourceId, afterId) { + var _props = this.props, + handleSortBlock = _props.actions.handleSortBlock, + areaId = _props.areaId; + + + var globalUseGraphqQL = true; + if (globalUseGraphqQL) { + handleSortBlock(sourceId, afterId, areaId).then(function () { + var preview = window.jQuery('.cms-preview'); + preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); + }); + } else {} + + this.setState({ + dragTargetElementId: null, + dragSpot: null + }); + } + }, { + key: 'render', + value: function render() { + var _props2 = this.props, + fieldName = _props2.fieldName, + formState = _props2.formState, + ToolbarComponent = _props2.ToolbarComponent, + ListComponent = _props2.ListComponent, + areaId = _props2.areaId, + elementTypes = _props2.elementTypes, + isDraggingOver = _props2.isDraggingOver, + connectDropTarget = _props2.connectDropTarget, + allowedElements = _props2.allowedElements; + var _state = this.state, + dragTargetElementId = _state.dragTargetElementId, + dragSpot = _state.dragSpot; + + var allowedElementTypes = allowedElements.map(function (className) { + return elementTypes.find(function (type) { + return type.class === className; + }); + }); + + return connectDropTarget(_react2.default.createElement( + 'div', + { className: 'element-editor' }, + _react2.default.createElement(ToolbarComponent, { + elementTypes: allowedElementTypes, + areaId: areaId, + onDragOver: this.handleDragOver + }), + _react2.default.createElement(ListComponent, { + allowedElementTypes: allowedElementTypes, + elementTypes: elementTypes, + areaId: areaId, + onDragOver: this.handleDragOver, + onDragStart: this.handleDragStart, + onDragEnd: this.handleDragEnd, + dragSpot: dragSpot, + isDraggingOver: isDraggingOver, + dragTargetElementId: dragTargetElementId + }), + _react2.default.createElement(_ElementDragPreview2.default, { elementTypes: elementTypes }), + _react2.default.createElement('input', { + name: fieldName, + type: 'hidden', + value: JSON.stringify(formState) || '', + className: 'no-change-track' + }) + )); + } + }]); + + return ElementEditor; +}(_react.PureComponent); + +ElementEditor.propTypes = { + fieldName: _propTypes2.default.string, + elementTypes: _propTypes2.default.arrayOf(_elementTypeType.elementTypeType).isRequired, + allowedElements: _propTypes2.default.arrayOf(_propTypes2.default.string).isRequired, + areaId: _propTypes2.default.number.isRequired, + actions: _propTypes2.default.shape({ + handleSortBlock: _propTypes2.default.func + }) +}; + +function mapStateToProps(state) { + var formNamePattern = (0, _loadElementFormStateName.loadElementFormStateName)('[0-9]+'); + var elementFormState = state.form.formState.element; + + if (!elementFormState) { + return {}; + } + + var formState = Object.keys(elementFormState).filter(function (key) { + return key.match(formNamePattern); + }).reduce(function (accumulator, key) { + return _extends({}, accumulator, _defineProperty({}, key, elementFormState[key].values)); + }, {}); + + return { formState: formState }; +} + +exports.Component = ElementEditor; +exports.default = (0, _redux.compose)(_withDragDropContext2.default, (0, _reactDnd.DropTarget)('element', {}, function (connector, monitor) { + return { + connectDropTarget: connector.dropTarget(), + isDraggingOver: monitor.isOver() }; +}), (0, _reactRedux.connect)(mapStateToProps), (0, _Injector.inject)(['ElementToolbar', 'ElementList'], function (ToolbarComponent, ListComponent) { + return { + ToolbarComponent: ToolbarComponent, + ListComponent: ListComponent + }; +}, function () { + return 'ElementEditor'; +}), _sortBlockMutation2.default)(ElementEditor); + +/***/ }), + +/***/ "./client/src/components/ElementEditor/ElementList.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Component = undefined; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = __webpack_require__(0); + +var _react2 = _interopRequireDefault(_react); + +var _propTypes = __webpack_require__(1); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _elementType = __webpack_require__("./client/src/types/elementType.js"); + +var _elementTypeType = __webpack_require__("./client/src/types/elementTypeType.js"); + +var _redux = __webpack_require__(4); + +var _Injector = __webpack_require__(3); + +var _classnames = __webpack_require__(7); + +var _classnames2 = _interopRequireDefault(_classnames); + +var _i18n = __webpack_require__(2); + +var _i18n2 = _interopRequireDefault(_i18n); + +var _reactDnd = __webpack_require__(9); + +var _dragHelpers = __webpack_require__("./client/src/lib/dragHelpers.js"); + +var _elementConfig = __webpack_require__("./client/src/state/editor/elementConfig.js"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var ElementList = function (_Component) { + _inherits(ElementList, _Component); + + function ElementList(props) { + _classCallCheck(this, ElementList); + + var _this = _possibleConstructorReturn(this, (ElementList.__proto__ || Object.getPrototypeOf(ElementList)).call(this, props)); + + _this.state = { + isLoading: true, + contentBlocks: [] + }; + return _this; + } + + _createClass(ElementList, [{ + key: 'fetchContentBlocks', + value: function fetchContentBlocks() { + var globalUseGraphQL = false; + if (globalUseGraphQL) { + return; + } + } + }, { + key: 'getDragIndicatorIndex', + value: function getDragIndicatorIndex() { + var _props = this.props, + dragTargetElementId = _props.dragTargetElementId, + draggedItem = _props.draggedItem, + blocks = _props.blocks, + dragSpot = _props.dragSpot; + + return (0, _dragHelpers.getDragIndicatorIndex)(blocks.map(function (element) { + return element.id; + }), dragTargetElementId, draggedItem && draggedItem.id, dragSpot); + } + }, { + key: 'renderBlocks', + value: function renderBlocks() { + var _props2 = this.props, + ElementComponent = _props2.ElementComponent, + HoverBarComponent = _props2.HoverBarComponent, + DragIndicatorComponent = _props2.DragIndicatorComponent, + blocks = _props2.blocks, + allowedElementTypes = _props2.allowedElementTypes, + elementTypes = _props2.elementTypes, + areaId = _props2.areaId, + onDragEnd = _props2.onDragEnd, + onDragOver = _props2.onDragOver, + onDragStart = _props2.onDragStart, + isDraggingOver = _props2.isDraggingOver; + + + var globalUseGraphQL = false; + var contentBlocks = globalUseGraphQL ? blocks : this.state.contentBlocks; + + if (!contentBlocks) { + return null; + } + + if (contentBlocks && !contentBlocks.length) { + return _react2.default.createElement( + 'div', + null, + _i18n2.default._t('ElementList.ADD_BLOCKS', 'Add blocks to place your content') + ); + } + + var output = contentBlocks.map(function (element) { + return _react2.default.createElement( + 'div', + { key: element.id }, + _react2.default.createElement(ElementComponent, { + element: element, + areaId: areaId, + type: (0, _elementConfig.getElementTypeConfig)(element, elementTypes), + link: element.blockSchema.actions.edit, + onDragOver: onDragOver, + onDragEnd: onDragEnd, + onDragStart: onDragStart + }), + isDraggingOver || _react2.default.createElement(HoverBarComponent, { + key: 'create-after-' + element.id, + areaId: areaId, + elementId: element.id, + elementTypes: allowedElementTypes + }) + ); + }); + + if (!isDraggingOver) { + output = [_react2.default.createElement(HoverBarComponent, { + key: 0, + areaId: areaId, + elementId: 0, + elementTypes: allowedElementTypes + })].concat(output); + } + + var dragIndicatorIndex = this.getDragIndicatorIndex(); + if (isDraggingOver && dragIndicatorIndex !== null) { + output.splice(dragIndicatorIndex, 0, _react2.default.createElement(DragIndicatorComponent, { key: 'DropIndicator' })); + } + + return output; + } + }, { + key: 'renderLoading', + value: function renderLoading() { + var _props3 = this.props, + loading = _props3.loading, + LoadingComponent = _props3.LoadingComponent; + + var globalUseGraphQL = false; + var isLoading = globalUseGraphQL ? loading : this.state.isLoading; + + if (isLoading) { + return _react2.default.createElement(LoadingComponent, null); + } + return null; + } + }, { + key: 'render', + value: function render() { + var blocks = this.props.blocks; + + var globalUseGraphQL = false; + var contentBlocks = globalUseGraphQL ? blocks : this.state.contentBlocks; + + var listClassNames = (0, _classnames2.default)('elemental-editor-list', { 'elemental-editor-list--empty': !contentBlocks || !contentBlocks.length }); + + return this.props.connectDropTarget(_react2.default.createElement( + 'div', + { className: listClassNames }, + this.renderLoading(), + this.renderBlocks() + )); + } + }]); + + return ElementList; +}(_react.Component); + +ElementList.propTypes = { + blocks: _propTypes2.default.arrayOf(_elementType.elementType), + loading: _propTypes2.default.bool, + + elementTypes: _propTypes2.default.arrayOf(_elementTypeType.elementTypeType).isRequired, + allowedElementTypes: _propTypes2.default.arrayOf(_elementTypeType.elementTypeType).isRequired, + areaId: _propTypes2.default.number.isRequired, + dragTargetElementId: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.bool]), + onDragOver: _propTypes2.default.func, + onDragStart: _propTypes2.default.func, + onDragEnd: _propTypes2.default.func +}; + +ElementList.defaultProps = { + blocks: [], + loading: false +}; + +exports.Component = ElementList; + + +var elementListTarget = { + drop: function drop(props, monitor) { + var blocks = props.blocks; + + var elementTargetDropResult = monitor.getDropResult(); + + if (!elementTargetDropResult) { + return {}; + } + + var dropIndex = (0, _dragHelpers.getDragIndicatorIndex)(blocks.map(function (element) { + return element.id; + }), elementTargetDropResult.target, monitor.getItem(), elementTargetDropResult.dropSpot); + var dropAfterID = blocks[dropIndex - 1] ? blocks[dropIndex - 1].id : '0'; + + return _extends({}, elementTargetDropResult, { + dropAfterID: dropAfterID + }); + } +}; + +exports.default = (0, _redux.compose)((0, _reactDnd.DropTarget)('element', elementListTarget, function (connector, monitor) { + return { + connectDropTarget: connector.dropTarget(), + draggedItem: monitor.getItem() + }; +}), (0, _Injector.inject)(['Element', 'Loading', 'HoverBar', 'DragPositionIndicator'], function (ElementComponent, LoadingComponent, HoverBarComponent, DragIndicatorComponent) { + return { + ElementComponent: ElementComponent, + LoadingComponent: LoadingComponent, + HoverBarComponent: HoverBarComponent, + DragIndicatorComponent: DragIndicatorComponent + }; +}, function () { + return 'ElementEditor.ElementList'; +}))(ElementList); + +/***/ }), + +/***/ "./client/src/components/ElementEditor/Header.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Component = undefined; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = __webpack_require__(0); + +var _react2 = _interopRequireDefault(_react); + +var _propTypes = __webpack_require__(1); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _reactstrap = __webpack_require__(10); + +var _elementType = __webpack_require__("./client/src/types/elementType.js"); + +var _elementTypeType = __webpack_require__("./client/src/types/elementTypeType.js"); + +var _redux = __webpack_require__(4); + +var _reactRedux = __webpack_require__(8); + +var _Injector = __webpack_require__(3); + +var _i18n = __webpack_require__(2); + +var _i18n2 = _interopRequireDefault(_i18n); + +var _classnames = __webpack_require__(7); + +var _classnames2 = _interopRequireDefault(_classnames); + +var _loadElementFormStateName = __webpack_require__("./client/src/state/editor/loadElementFormStateName.js"); + +var _reduxForm = __webpack_require__(11); + +var _reactDnd = __webpack_require__(9); + +var _getFormState = __webpack_require__(16); + +var _getFormState2 = _interopRequireDefault(_getFormState); + +var _dragHelpers = __webpack_require__("./client/src/lib/dragHelpers.js"); + +var _reactDndHtml5Backend = __webpack_require__(14); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var Header = function (_Component) { + _inherits(Header, _Component); + + function Header(props) { + _classCallCheck(this, Header); + + var _this = _possibleConstructorReturn(this, (Header.__proto__ || Object.getPrototypeOf(Header)).call(this, props)); + + _this.toggle = _this.toggle.bind(_this); + + _this.state = { + tooltipOpen: false + }; + return _this; + } + + _createClass(Header, [{ + key: 'componentDidMount', + value: function componentDidMount() { + var connectDragPreview = this.props.connectDragPreview; + + if (connectDragPreview) { + connectDragPreview((0, _reactDndHtml5Backend.getEmptyImage)(), { + captureDraggingState: true + }); + } + } + }, { + key: 'componentDidUpdate', + value: function componentDidUpdate() { + var tooltipOpen = this.state.tooltipOpen; + var disableTooltip = this.props.disableTooltip; + + + if (tooltipOpen && disableTooltip) { + this.setState({ + tooltipOpen: false + }); + } + } + }, { + key: 'getBlockTitle', + value: function getBlockTitle(element, type) { + if (type.broken) { + return _i18n2.default.inject(_i18n2.default._t('ElementHeader.BROKEN', 'This element is of obsolete type {type}.'), { type: type.obsoleteClassName }); + } + if (element.title) { + return element.title; + } + return _i18n2.default.inject(_i18n2.default._t('ElementHeader.NOTITLE', 'Untitled {type} block'), { type: type.title }); + } + }, { + key: 'toggle', + value: function toggle() { + this.setState({ + tooltipOpen: !this.state.tooltipOpen + }); + } + }, { + key: 'renderVersionedStateMessage', + value: function renderVersionedStateMessage() { + var _props = this.props, + _props$element = _props.element, + isLiveVersion = _props$element.isLiveVersion, + isPublished = _props$element.isPublished, + formDirty = _props.formDirty; + + if (!formDirty && isPublished && isLiveVersion) { + return null; + } + + var versionStateButtonTitle = ''; + var stateClassNames = ['element-editor-header__version-state']; + + if (formDirty) { + versionStateButtonTitle = _i18n2.default._t('ElementHeader.STATE_UNSAVED', 'Item has unsaved changes'); + stateClassNames.push('element-editor-header__version-state--unsaved'); + } else if (!isPublished) { + versionStateButtonTitle = _i18n2.default._t('ElementHeader.STATE_DRAFT', 'Item has not been published yet'); + stateClassNames.push('element-editor-header__version-state--draft'); + } else if (!isLiveVersion) { + versionStateButtonTitle = _i18n2.default._t('ElementHeader.STATE_MODIFIED', 'Item has unpublished changes'); + stateClassNames.push('element-editor-header__version-state--modified'); + } + + return _react2.default.createElement('span', { + className: (0, _classnames2.default)(stateClassNames), + title: versionStateButtonTitle + }); + } + }, { + key: 'render', + value: function render() { + var _props2 = this.props, + connectDragSource = _props2.connectDragSource, + element = _props2.element, + type = _props2.type, + areaId = _props2.areaId, + previewExpanded = _props2.previewExpanded, + simple = _props2.simple, + disableTooltip = _props2.disableTooltip, + activeTab = _props2.activeTab, + expandable = _props2.expandable, + ElementActionsComponent = _props2.ElementActionsComponent, + handleEditTabsClick = _props2.handleEditTabsClick; + + + var title = this.getBlockTitle(element, type); + var titleClasses = (0, _classnames2.default)({ + 'element-editor-header__title': true, + 'element-editor-header__title--none': !element.title + }); + var expandTitle = _i18n2.default._t('ElementHeader.EXPAND', 'Show editable fields'); + var containerClasses = (0, _classnames2.default)('element-editor-header', { + 'element-editor-header--simple': simple + }); + var iconContainerClasses = (0, _classnames2.default)('element-editor-header__icon-container', { + 'element-editor-header__icon-container--broken': type.broken + }); + var expandCaretClasses = (0, _classnames2.default)('element-editor-header__expand', { + 'font-icon-right-open-big': !expandable, + 'font-icon-up-open-big': expandable && previewExpanded, + 'font-icon-down-open-big': expandable && !previewExpanded + }); + var blockIconId = 'element-icon-' + element.id; + + var content = _react2.default.createElement( + 'div', + { className: containerClasses }, + _react2.default.createElement( + 'div', + { className: 'element-editor-header__drag-handle' }, + _react2.default.createElement('i', { className: 'font-icon-drag-handle' }) + ), + _react2.default.createElement( + 'div', + { className: 'element-editor-header__info' }, + _react2.default.createElement( + 'div', + { className: iconContainerClasses }, + _react2.default.createElement('i', { className: type.icon, id: blockIconId }), + this.renderVersionedStateMessage(), + !type.broken && !simple && _react2.default.createElement( + _reactstrap.Tooltip, + { + placement: 'top', + isOpen: this.state.tooltipOpen && !disableTooltip, + target: blockIconId, + toggle: this.toggle + }, + type.title + ) + ), + _react2.default.createElement( + 'h3', + { className: titleClasses }, + title + ) + ), + !simple && _react2.default.createElement( + 'div', + { className: 'element-editor-header__actions' }, + _react2.default.createElement( + 'div', + { role: 'none', onClick: function onClick(event) { + return event.stopPropagation(); + } }, + _react2.default.createElement(ElementActionsComponent, { + element: element, + type: type, + areaId: areaId, + activeTab: activeTab, + editTabs: type.editTabs, + handleEditTabsClick: handleEditTabsClick, + expandable: expandable + }) + ), + !type.broken && _react2.default.createElement('i', { className: expandCaretClasses, title: expandTitle }) + ) + ); + + if (previewExpanded) { + return connectDragSource(content); + } + + return content; + } + }]); + + return Header; +}(_react.Component); + +Header.propTypes = { + element: _elementType.elementType.isRequired, + type: _elementTypeType.elementTypeType.isRequired, + areaId: _propTypes2.default.number, + activeTab: _propTypes2.default.string, + simple: _propTypes2.default.bool, + ElementActionsComponent: _propTypes2.default.oneOfType([_propTypes2.default.node, _propTypes2.default.func]), + previewExpanded: _propTypes2.default.bool, + disableTooltip: _propTypes2.default.bool, + formDirty: _propTypes2.default.bool, + connectDragSource: _propTypes2.default.func.isRequired, + connectDragPreview: _propTypes2.default.func.isRequired, + onDragEnd: _propTypes2.default.func }; + +Header.defaultProps = { + expandable: true +}; + +function mapStateToProps(state, ownProps) { + var formName = (0, _loadElementFormStateName.loadElementFormStateName)(ownProps.element.id); + + return { + formDirty: (0, _reduxForm.isDirty)('element.' + formName, _getFormState2.default)(state) + }; +} + +exports.Component = Header; +exports.default = (0, _redux.compose)((0, _reactDnd.DragSource)('element', _dragHelpers.elementDragSource, function (connector) { + return { + connectDragSource: connector.dragSource(), + connectDragPreview: connector.dragPreview() + }; +}), (0, _reactRedux.connect)(mapStateToProps), (0, _Injector.inject)(['ElementActions'], function (ElementActionsComponent) { + return { + ElementActionsComponent: ElementActionsComponent + }; +}, function () { + return 'ElementEditor.ElementList.Element'; +}))(Header); + +/***/ }), + +/***/ "./client/src/components/ElementEditor/HoverBar.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Component = undefined; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = __webpack_require__(0); + +var _react2 = _interopRequireDefault(_react); + +var _propTypes = __webpack_require__(1); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _prefixClassNames = __webpack_require__("./client/src/lib/prefixClassNames.js"); + +var _prefixClassNames2 = _interopRequireDefault(_prefixClassNames); + +var _Injector = __webpack_require__(3); + +var _elementTypeType = __webpack_require__("./client/src/types/elementTypeType.js"); + +var _i18n = __webpack_require__(2); + +var _i18n2 = _interopRequireDefault(_i18n); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var classNames = (0, _prefixClassNames2.default)('element-editor__hover-bar'); + +function StatelessHoverBar(_ref) { + var AddElementPopoverComponent = _ref.AddElementPopoverComponent, + elementTypes = _ref.elementTypes, + elementId = _ref.elementId, + areaId = _ref.areaId, + popoverOpen = _ref.popoverOpen, + onToggle = _ref.onToggle; + + var lineClasses = classNames('-line') + ' font-icon-plus-circled'; + var label = _i18n2.default._t('ElementAddNewButton.ADD_BLOCK', 'Add block'); + var btnProps = { + className: classNames('-area', { '-area--focus': popoverOpen }), + onClick: onToggle, + 'aria-label': label, + title: label, + id: 'AddBlockHoverBarArea_' + areaId + '_' + elementId + }; + + return _react2.default.createElement( + 'div', + { className: classNames(''), id: 'AddBlockHoverBar_' + areaId + '_' + elementId }, + _react2.default.createElement( + 'button', + btnProps, + _react2.default.createElement( + 'span', + { className: classNames('-area-inner') }, + _react2.default.createElement('span', { className: lineClasses }) + ) + ), + _react2.default.createElement(AddElementPopoverComponent, { + placement: 'bottom', + target: 'AddBlockHoverBarArea_' + areaId + '_' + elementId, + isOpen: popoverOpen, + elementTypes: elementTypes, + toggle: onToggle, + container: '#AddBlockHoverBar_' + areaId + '_' + elementId, + areaId: areaId, + insertAfterElement: elementId + }) + ); +} + +var HoverBar = function (_Component) { + _inherits(HoverBar, _Component); + + function HoverBar(props) { + _classCallCheck(this, HoverBar); + + var _this = _possibleConstructorReturn(this, (HoverBar.__proto__ || Object.getPrototypeOf(HoverBar)).call(this, props)); + + _this.toggle = _this.toggle.bind(_this); + _this.state = { + popoverOpen: false + }; + return _this; + } + + _createClass(HoverBar, [{ + key: 'toggle', + value: function toggle() { + this.setState({ + popoverOpen: !this.state.popoverOpen + }); + } + }, { + key: 'render', + value: function render() { + var props = _extends({}, this.state, this.props, { + onToggle: this.toggle + }); + return _react2.default.createElement(StatelessHoverBar, props); + } + }]); + + return HoverBar; +}(_react.Component); + +HoverBar.propTypes = { + elementTypes: _propTypes2.default.arrayOf(_elementTypeType.elementTypeType).isRequired, + elementId: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]).isRequired, + areaId: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.string]).isRequired +}; +exports.Component = HoverBar; +exports.default = (0, _Injector.inject)(['AddElementPopover'], function (AddElementPopoverComponent) { + return { + AddElementPopoverComponent: AddElementPopoverComponent + }; +}, function () { + return 'ElementEditor.ElementList.HoverBar'; +})(HoverBar); + +/***/ }), + +/***/ "./client/src/components/ElementEditor/InlineEditForm.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = __webpack_require__(0); + +var _react2 = _interopRequireDefault(_react); + +var _propTypes = __webpack_require__(1); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _classnames = __webpack_require__(7); + +var _classnames2 = _interopRequireDefault(_classnames); + +var _FormBuilderLoader = __webpack_require__(18); + +var _FormBuilderLoader2 = _interopRequireDefault(_FormBuilderLoader); + +var _loadElementSchemaValue = __webpack_require__("./client/src/state/editor/loadElementSchemaValue.js"); + +var _i18n = __webpack_require__(2); + +var _i18n2 = _interopRequireDefault(_i18n); + +var _loadElementFormStateName = __webpack_require__("./client/src/state/editor/loadElementFormStateName.js"); + +var _reactRedux = __webpack_require__(8); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var InlineEditForm = function (_PureComponent) { + _inherits(InlineEditForm, _PureComponent); + + function InlineEditForm(props) { + _classCallCheck(this, InlineEditForm); + + var _this = _possibleConstructorReturn(this, (InlineEditForm.__proto__ || Object.getPrototypeOf(InlineEditForm)).call(this, props)); + + _this.handleLoadingError = _this.handleLoadingError.bind(_this); + + _this.state = { + loadingError: null + }; + return _this; + } + + _createClass(InlineEditForm, [{ + key: 'handleLoadingError', + value: function handleLoadingError() { + var _window = window, + $ = _window.jQuery; + var handleLoadingError = this.props.handleLoadingError; + + + this.setState({ + loadingError: true + }); + + $.noticeAdd({ + text: _i18n2.default.inject(_i18n2.default._t('ElementEditForm.ERROR_NOTIFICATION', 'Error displaying the edit form for this block')), + stay: true, + type: 'notice' + }); + + handleLoadingError(); + } + }, { + key: 'render', + value: function render() { + var _props = this.props, + elementId = _props.elementId, + extraClass = _props.extraClass, + onClick = _props.onClick, + onFormInit = _props.onFormInit, + formHasState = _props.formHasState; + var loadingError = this.state.loadingError; + + + var classNames = (0, _classnames2.default)('element-editor-editform', extraClass); + var schemaUrl = (0, _loadElementSchemaValue.loadElementSchemaValue)('schemaUrl', elementId); + + var formProps = { + formTag: 'div', + schemaUrl: schemaUrl, + identifier: 'element', + refetchSchemaOnMount: !formHasState, + onLoadingError: this.handleLoadingError + }; + + if (loadingError) { + formProps.loading = false; + } + + if (typeof onFormInit === 'function') { + formProps.onReduxFormInit = onFormInit; + } + + return _react2.default.createElement( + 'div', + { className: classNames, onClick: onClick, role: 'presentation' }, + _react2.default.createElement(_FormBuilderLoader2.default, formProps) + ); + } + }]); + + return InlineEditForm; +}(_react.PureComponent); + +InlineEditForm.propTypes = { + extraClass: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.object]), + onClick: _propTypes2.default.func, + elementId: _propTypes2.default.string, + handleLoadingError: _propTypes2.default.func +}; + +function mapStateToProps(state, ownProps) { + var formName = (0, _loadElementFormStateName.loadElementFormStateName)(ownProps.elementId); + + return { + formHasState: state.form.formState && state.form.formState.element && !!state.form.formState.element[formName] + }; +} + +exports.default = (0, _reactRedux.connect)(mapStateToProps)(InlineEditForm); + +/***/ }), + +/***/ "./client/src/components/ElementEditor/Summary.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = __webpack_require__(0); + +var _react2 = _interopRequireDefault(_react); + +var _propTypes = __webpack_require__(1); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _classnames = __webpack_require__(7); + +var _classnames2 = _interopRequireDefault(_classnames); + +var _i18n = __webpack_require__(2); + +var _i18n2 = _interopRequireDefault(_i18n); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var Summary = function (_PureComponent) { + _inherits(Summary, _PureComponent); + + function Summary() { + _classCallCheck(this, Summary); + + return _possibleConstructorReturn(this, (Summary.__proto__ || Object.getPrototypeOf(Summary)).apply(this, arguments)); + } + + _createClass(Summary, [{ + key: 'render', + value: function render() { + var _props = this.props, + fileUrl = _props.fileUrl, + fileTitle = _props.fileTitle, + content = _props.content, + broken = _props.broken; + + var noContent = _i18n2.default._t('ElementSummary.NO_PREVIEW', 'No preview available'); + + var summaryClassNames = (0, _classnames2.default)('element-editor-summary__content', { + 'element-editor-summary__content--broken': broken + }); + + return _react2.default.createElement( + 'div', + { className: 'element-editor-summary' }, + fileUrl && _react2.default.createElement('img', { + className: 'element-editor-summary__thumbnail-image', + src: fileUrl, + alt: fileTitle + }), + (content || !fileUrl) && _react2.default.createElement( + 'p', + { className: summaryClassNames }, + content || noContent + ) + ); + } + }]); + + return Summary; +}(_react.PureComponent); + +Summary.defaultProps = {}; + +Summary.propTypes = { + content: _propTypes2.default.string, + fileUrl: _propTypes2.default.string, + fileTitle: _propTypes2.default.string, + broken: _propTypes2.default.bool +}; + +exports.default = Summary; + +/***/ }), + +/***/ "./client/src/components/ElementEditor/Toolbar.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = __webpack_require__(0); + +var _react2 = _interopRequireDefault(_react); + +var _propTypes = __webpack_require__(1); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _Injector = __webpack_require__(3); + +var _elementTypeType = __webpack_require__("./client/src/types/elementTypeType.js"); + +var _reactDnd = __webpack_require__(9); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var Toolbar = function (_PureComponent) { + _inherits(Toolbar, _PureComponent); + + function Toolbar() { + _classCallCheck(this, Toolbar); + + return _possibleConstructorReturn(this, (Toolbar.__proto__ || Object.getPrototypeOf(Toolbar)).apply(this, arguments)); + } + + _createClass(Toolbar, [{ + key: 'render', + value: function render() { + var _props = this.props, + AddNewButtonComponent = _props.AddNewButtonComponent, + elementTypes = _props.elementTypes, + areaId = _props.areaId, + connectDropTarget = _props.connectDropTarget; + + return connectDropTarget(_react2.default.createElement( + 'div', + { className: 'element-editor__toolbar' }, + _react2.default.createElement(AddNewButtonComponent, { + elementTypes: elementTypes, + areaId: areaId + }) + )); + } + }]); + + return Toolbar; +}(_react.PureComponent); + +Toolbar.defaultProps = {}; +Toolbar.propTypes = { + elementTypes: _propTypes2.default.arrayOf(_elementTypeType.elementTypeType).isRequired, + areaId: _propTypes2.default.number.isRequired, + AddNewButtonComponent: _propTypes2.default.oneOfType([_propTypes2.default.node, _propTypes2.default.func]).isRequired, + connectDropTarget: _propTypes2.default.func.isRequired, + onDragOver: _propTypes2.default.func, + onDragDrop: _propTypes2.default.func }; + +var toolbarTarget = { + hover: function hover(props) { + var onDragOver = props.onDragOver; + + if (onDragOver) { + onDragOver(); + } + } +}; + +exports.default = (0, _reactDnd.DropTarget)('element', toolbarTarget, function (connect) { + return { + connectDropTarget: connect.dropTarget() + }; +})((0, _Injector.inject)(['ElementAddNewButton'], function (AddNewButtonComponent) { + return { + AddNewButtonComponent: AddNewButtonComponent + }; +}, function () { + return 'ElementEditor.ElementToolbar'; +})(Toolbar)); + +/***/ }), + +/***/ "./client/src/components/HistoricElementView/HistoricElementView.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + +var _react = __webpack_require__(0); + +var _react2 = _interopRequireDefault(_react); + +var _i18n = __webpack_require__(2); + +var _i18n2 = _interopRequireDefault(_i18n); + +var _classnames = __webpack_require__(7); + +var _classnames2 = _interopRequireDefault(_classnames); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var ElementalAreaHistoryFactory = function ElementalAreaHistoryFactory(FieldGroup) { + return function (_FieldGroup) { + _inherits(HistoricElementView, _FieldGroup); + + function HistoricElementView() { + _classCallCheck(this, HistoricElementView); + + return _possibleConstructorReturn(this, (HistoricElementView.__proto__ || Object.getPrototypeOf(HistoricElementView)).apply(this, arguments)); + } + + _createClass(HistoricElementView, [{ + key: 'getClassName', + value: function getClassName() { + var classlist = [_get(HistoricElementView.prototype.__proto__ || Object.getPrototypeOf(HistoricElementView.prototype), 'getClassName', this).call(this)]; + if (this.props.data.ElementID) { + classlist.unshift('elemental-area__element--historic-inner'); + } + return (0, _classnames2.default)(classlist); + } + }, { + key: 'render', + value: function render() { + var legend = this.getLegend(); + var Tag = this.props.data.tag || 'div'; + var classNames = this.getClassName(); + var data = this.props.data; + + + if (!data.ElementID) { + return _get(HistoricElementView.prototype.__proto__ || Object.getPrototypeOf(HistoricElementView.prototype), 'render', this).call(this); + } + + return _react2.default.createElement( + Tag, + { className: classNames }, + legend, + _react2.default.createElement( + 'div', + { className: 'elemental-preview elemental-preview--historic' }, + data.ElementEditLink && _react2.default.createElement( + 'a', + { className: 'elemental-preview__link', href: data.ElementEditLink }, + _react2.default.createElement( + 'span', + { className: 'elemental-preview__link-text' }, + _i18n2.default._t('HistoricElementView.VIEW_BLOCK_HISTORY', 'Block history') + ), + _react2.default.createElement('i', { className: 'font-icon-angle-right btn--icon-lg elemental-preview__link-caret' }) + ), + _react2.default.createElement( + 'div', + { className: 'elemental-preview__icon' }, + _react2.default.createElement('i', { className: data.ElementIcon }) + ), + _react2.default.createElement( + 'div', + { className: 'elemental-preview__detail' }, + _react2.default.createElement( + 'h3', + null, + data.ElementTitle, + ' ', + _react2.default.createElement( + 'small', + null, + data.ElementType + ) + ) + ) + ), + this.props.children + ); + } + }]); + + return HistoricElementView; + }(FieldGroup); +}; + +exports.default = ElementalAreaHistoryFactory; + +/***/ }), + +/***/ "./client/src/components/TextCheckboxGroupField/TextCheckboxGroupField.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = __webpack_require__(0); + +var _react2 = _interopRequireDefault(_react); + +var _reactstrap = __webpack_require__(10); + +var _FieldHolder = __webpack_require__(17); + +var _FieldHolder2 = _interopRequireDefault(_FieldHolder); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var TextCheckboxGroupField = function TextCheckboxGroupField(props) { + var children = props.children; + + var childrenWithProps = _react2.default.Children.toArray(_react2.default.Children.map(children, function (child, index) { + var additionalProps = { noHolder: true }; + + if (index === 0) { + additionalProps.id = props.id; + } + + return _react2.default.cloneElement(child, additionalProps); + })); + + if (props.readOnly) { + return _react2.default.createElement( + 'div', + { className: 'text-checkbox-group-field--read-only' }, + childrenWithProps + ); + } + + if (childrenWithProps.length === 1) { + return childrenWithProps[0]; + } + + return _react2.default.createElement( + _reactstrap.InputGroup, + { className: 'text-checkbox-group-field' }, + childrenWithProps[0], + _react2.default.createElement( + _reactstrap.InputGroupAddon, + { addonType: 'append' }, + _react2.default.createElement( + _reactstrap.InputGroupText, + null, + childrenWithProps[1] + ) + ) + ); +}; + +exports.default = (0, _FieldHolder2.default)(TextCheckboxGroupField); + +/***/ }), + +/***/ "./client/src/legacy/ElementEditor/entwine.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var _jquery = __webpack_require__(20); + +var _jquery2 = _interopRequireDefault(_jquery); + +var _react = __webpack_require__(0); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = __webpack_require__(15); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _Injector = __webpack_require__(3); + +var _elementConfig = __webpack_require__("./client/src/state/editor/elementConfig.js"); + +var _reduxForm = __webpack_require__(11); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +var resetStores = function resetStores() { + window.ss.apolloClient.resetStore(); + + setTimeout(function () { + var store = window.ss.store; + + + if (!store) { + return; + } + + store.dispatch(_reduxForm.destroy.apply(undefined, _toConsumableArray(Object.keys(store.getState().form.formState.element || {}).map(function (name) { + return 'element.' + name; + })))); + }, 0); +}; + +_jquery2.default.entwine('ss', function ($) { + $('.js-injector-boot .element-editor__container').entwine({ + onmatch: function onmatch() { + var context = {}; + var ElementEditorComponent = (0, _Injector.loadComponent)('ElementEditor', context); + var schemaData = this.data('schema'); + var elementTypes = (0, _elementConfig.getConfig)().elementTypes; + + var props = { + fieldName: this.attr('name'), + areaId: schemaData['elemental-area-id'], + allowedElements: schemaData['allowed-elements'], + elementTypes: elementTypes + }; + + _reactDom2.default.render(_react2.default.createElement(ElementEditorComponent, props), this[0]); + }, + onunmatch: function onunmatch() { + if (!$('.cms-edit-form').data('hasValidationErrors')) { + resetStores(); + } + _reactDom2.default.unmountComponentAtNode(this[0]); + }, + + + 'from .cms-edit-form': { + onaftersubmitform: function onaftersubmitform(event, data) { + var validationResultPjax = JSON.parse(data.xhr.responseText).ValidationResult; + var validationResult = JSON.parse(validationResultPjax.replace(/<\/?script[^>]*?>/g, '')); + + if (validationResult.isValid) { + $('.cms-edit-form').data('hasValidationErrors', false); + resetStores(); + } else { + $('.cms-edit-form').data('hasValidationErrors', true); + } + } + } + }); + + $('.js-injector-boot .element-editor__container .element-form-dirty-state').entwine({ + onmatch: function onmatch() { + $('.cms-edit-form').trigger('change'); + }, + onunmatch: function onunmatch() { + $('.cms-edit-form').trigger('change'); + } + }); + + $('.cms-edit-form').entwine({ + getChangeTrackerOptions: function getChangeTrackerOptions() { + var isDefault = this.entwineData('ChangeTrackerOptions') === undefined; + + var opts = this._super(); + + if (isDefault) { + opts = $.extend({}, opts); + + opts.ignoreFieldSelector += ', .elementalarea :input:not(.element-form-dirty-state)'; + + this.setChangeTrackerOptions(opts); + } + + return opts; + } + }); +}); + +/***/ }), + +/***/ "./client/src/lib/dragHelpers.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.elementDragSource = exports.getDragIndicatorIndex = exports.isOverTop = undefined; + +var _reactDom = __webpack_require__(15); + +var isOverTop = exports.isOverTop = function isOverTop(monitor, component) { + var clientOffset = monitor.getClientOffset(); + var componentRect = (0, _reactDom.findDOMNode)(component).getBoundingClientRect(); + + return clientOffset.y < componentRect.y + componentRect.height / 2; +}; + +var getDragIndicatorIndex = exports.getDragIndicatorIndex = function getDragIndicatorIndex(items, dragTarget, draggedItem, dragSpot) { + if (dragTarget === null || !draggedItem) { + return null; + } + + var targetIndex = dragTarget ? items.findIndex(function (element) { + return element === dragTarget; + }) : 0; + var sourceIndex = items.findIndex(function (item) { + return item === draggedItem; + }); + + if (dragSpot === 'bottom') { + targetIndex += 1; + } + + if (sourceIndex === targetIndex || sourceIndex + 1 === targetIndex) { + return null; + } + + return targetIndex; +}; + +var elementDragSource = exports.elementDragSource = { + beginDrag: function beginDrag(props) { + return props.element; + }, + endDrag: function endDrag(props, monitor) { + var onDragEnd = props.onDragEnd; + + var dropResult = monitor.getDropResult(); + + if (!onDragEnd || !dropResult || !dropResult.dropAfterID) { + return; + } + + var itemID = monitor.getItem().id; + var dropAfterID = dropResult.dropAfterID; + + if (itemID !== dropAfterID) { + onDragEnd(itemID, dropAfterID); + } + } +}; + +/***/ }), + +/***/ "./client/src/lib/prefixClassNames.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var _classnames = __webpack_require__(7); + +var _classnames2 = _interopRequireDefault(_classnames); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +var prefixClassNames = function prefixClassNames(cssPrefix) { + return function () { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + var prefix = function prefix(str) { + return '' + cssPrefix + str; + }; + + var prefixArgs = args.map(function (arg) { + if (!arg && arg !== '') { + return false; + } + + if ((typeof arg === 'undefined' ? 'undefined' : _typeof(arg)) === 'object') { + return Array.isArray(arg) ? arg.map(prefix) : Object.entries(arg).reduce(function (accumulator, _ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + value = _ref2[1]; + + return Object.assign({}, accumulator, _defineProperty({}, prefix(key), value)); + }, {}); + } + + return prefix(arg); + }); + + return _classnames2.default.apply(undefined, _toConsumableArray(prefixArgs)); + }; +}; + +exports.default = prefixClassNames; + +/***/ }), + +/***/ "./client/src/state/editor/addElementMutation.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.config = exports.mutation = undefined; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _templateObject = _taggedTemplateLiteral(['\nmutation AddElementToArea($className: String!, $elementalAreaID: ID!, $afterElementID: ID) {\n addElementToArea(\n className: $className,\n elementalAreaID: $elementalAreaID,\n afterElementID: $afterElementID\n ) {\n id\n }\n}\n'], ['\nmutation AddElementToArea($className: String!, $elementalAreaID: ID!, $afterElementID: ID) {\n addElementToArea(\n className: $className,\n elementalAreaID: $elementalAreaID,\n afterElementID: $afterElementID\n ) {\n id\n }\n}\n']); + +var _reactApollo = __webpack_require__(6); + +var _graphqlTag = __webpack_require__(5); + +var _graphqlTag2 = _interopRequireDefault(_graphqlTag); + +var _readBlocksForAreaQuery = __webpack_require__("./client/src/state/editor/readBlocksForAreaQuery.js"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } + +var mutation = (0, _graphqlTag2.default)(_templateObject); + +var config = { + props: function props(_ref) { + var mutate = _ref.mutate, + _ref$ownProps = _ref.ownProps, + actions = _ref$ownProps.actions, + areaId = _ref$ownProps.areaId; + + var handleAddElementToArea = function handleAddElementToArea(className, afterElementID) { + return mutate({ + variables: { className: className, elementalAreaID: areaId, afterElementID: afterElementID } + }); + }; + + return { + actions: _extends({}, actions, { + handleAddElementToArea: handleAddElementToArea + }) + }; + }, + options: function options(_ref2) { + var areaId = _ref2.areaId; + return { + refetchQueries: [{ + query: _readBlocksForAreaQuery.query, + variables: _readBlocksForAreaQuery.config.options({ areaId: areaId }).variables + }] + }; + } +}; + +exports.mutation = mutation; +exports.config = config; +exports.default = (0, _reactApollo.graphql)(mutation, config); + +/***/ }), + +/***/ "./client/src/state/editor/archiveBlockMutation.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.config = exports.mutation = undefined; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _templateObject = _taggedTemplateLiteral(['\nmutation ArchiveBlock($blockId: ID!) {\n deleteBlocks(ids: [$blockId])\n}\n'], ['\nmutation ArchiveBlock($blockId: ID!) {\n deleteBlocks(ids: [$blockId])\n}\n']); + +var _reactApollo = __webpack_require__(6); + +var _graphqlTag = __webpack_require__(5); + +var _graphqlTag2 = _interopRequireDefault(_graphqlTag); + +var _readBlocksForAreaQuery = __webpack_require__("./client/src/state/editor/readBlocksForAreaQuery.js"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } + +var mutation = (0, _graphqlTag2.default)(_templateObject); + +var config = { + props: function props(_ref) { + var mutate = _ref.mutate, + actions = _ref.ownProps.actions; + + var handleArchiveBlock = function handleArchiveBlock(blockId) { + return mutate({ + variables: { blockId: blockId } + }); + }; + + return { + actions: _extends({}, actions, { + handleArchiveBlock: handleArchiveBlock + }) + }; + }, + options: function options(_ref2) { + var areaId = _ref2.areaId; + return { + refetchQueries: [{ + query: _readBlocksForAreaQuery.query, + variables: _readBlocksForAreaQuery.config.options({ areaId: areaId }).variables + }] + }; + } +}; + +exports.mutation = mutation; +exports.config = config; +exports.default = (0, _reactApollo.graphql)(mutation, config); + +/***/ }), + +/***/ "./client/src/state/editor/duplicateBlockMutation.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.config = exports.mutation = undefined; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _templateObject = _taggedTemplateLiteral(['\nmutation DuplicateBlock($blockId: ID!) {\n duplicateBlock(id: $blockId) {\n id\n }\n}\n'], ['\nmutation DuplicateBlock($blockId: ID!) {\n duplicateBlock(id: $blockId) {\n id\n }\n}\n']); + +var _reactApollo = __webpack_require__(6); + +var _graphqlTag = __webpack_require__(5); + +var _graphqlTag2 = _interopRequireDefault(_graphqlTag); + +var _readBlocksForAreaQuery = __webpack_require__("./client/src/state/editor/readBlocksForAreaQuery.js"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } + +var mutation = (0, _graphqlTag2.default)(_templateObject); + +var config = { + props: function props(_ref) { + var mutate = _ref.mutate, + actions = _ref.ownProps.actions; + + var handleDuplicateBlock = function handleDuplicateBlock(blockId) { + return mutate({ + variables: { blockId: blockId } + }); + }; + + return { + actions: _extends({}, actions, { + handleDuplicateBlock: handleDuplicateBlock + }) + }; + }, + options: function options(_ref2) { + var areaId = _ref2.areaId; + return { + refetchQueries: [{ + query: _readBlocksForAreaQuery.query, + variables: _readBlocksForAreaQuery.config.options({ areaId: areaId }).variables + }] + }; + } +}; + +exports.mutation = mutation; +exports.config = config; +exports.default = (0, _reactApollo.graphql)(mutation, config); + +/***/ }), + +/***/ "./client/src/state/editor/elementConfig.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getElementTypeConfig = exports.getConfig = undefined; + +var _Config = __webpack_require__(12); + +var _Config2 = _interopRequireDefault(_Config); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var getConfig = exports.getConfig = function getConfig() { + return _Config2.default.getSection('DNADesign\\Elemental\\Controllers\\ElementalAreaController'); +}; + +var getElementTypeConfig = exports.getElementTypeConfig = function getElementTypeConfig(element) { + var typeConfig = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + var elementType = element.blockSchema.typeName; + var types = Array.isArray(typeConfig) ? typeConfig : getConfig().elementTypes; + + var type = types.find(function (value) { + return value.class === elementType || value.name === elementType; + }); + if (element.obsoleteClassName) { + type = Object.assign({ obsoleteClassName: element.obsoleteClassName }, type); + Object.preventExtensions(type); + } + return type; +}; + +/***/ }), + +/***/ "./client/src/state/editor/loadElementFormStateName.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.loadElementFormStateName = undefined; + +var _Config = __webpack_require__(12); + +var _Config2 = _interopRequireDefault(_Config); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var loadElementFormStateName = exports.loadElementFormStateName = function loadElementFormStateName() { + var elementId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + + var sectionKey = 'DNADesign\\Elemental\\Controllers\\ElementalAreaController'; + var section = _Config2.default.getSection(sectionKey); + var formNameTemplate = section.form.elementForm.formNameTemplate; + + if (elementId) { + return formNameTemplate.replace('{id}', elementId); + } + return formNameTemplate; +}; + +/***/ }), + +/***/ "./client/src/state/editor/loadElementSchemaValue.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.loadElementSchemaValue = undefined; + +var _Config = __webpack_require__(12); + +var _Config2 = _interopRequireDefault(_Config); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var loadElementSchemaValue = exports.loadElementSchemaValue = function loadElementSchemaValue(key) { + var elementId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + var sectionKey = 'DNADesign\\Elemental\\Controllers\\ElementalAreaController'; + var section = _Config2.default.getSection(sectionKey); + var schemaValue = section.form.elementForm[key] || ''; + + if (elementId) { + return schemaValue + '/' + elementId; + } + return schemaValue; +}; + +/***/ }), + +/***/ "./client/src/state/editor/publishBlockMutation.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.config = exports.mutation = undefined; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _templateObject = _taggedTemplateLiteral(['\nmutation PublishBlock($blockId:ID!) {\n publishBlock(id: $blockId) {\n id\n }\n}\n'], ['\nmutation PublishBlock($blockId:ID!) {\n publishBlock(id: $blockId) {\n id\n }\n}\n']); + +var _reactApollo = __webpack_require__(6); + +var _graphqlTag = __webpack_require__(5); + +var _graphqlTag2 = _interopRequireDefault(_graphqlTag); + +var _readBlocksForAreaQuery = __webpack_require__("./client/src/state/editor/readBlocksForAreaQuery.js"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } + +var mutation = (0, _graphqlTag2.default)(_templateObject); + +var config = { + props: function props(_ref) { + var mutate = _ref.mutate, + actions = _ref.ownProps.actions; + + var handlePublishBlock = function handlePublishBlock(blockId) { + return mutate({ + variables: { + blockId: blockId + } + }); + }; + + return { + actions: _extends({}, actions, { + handlePublishBlock: handlePublishBlock + }) + }; + }, + options: function options(_ref2) { + var areaId = _ref2.areaId; + return { + refetchQueries: [{ + query: _readBlocksForAreaQuery.query, + variables: _readBlocksForAreaQuery.config.options({ areaId: areaId }).variables + }] + }; + } +}; + +exports.mutation = mutation; +exports.config = config; +exports.default = (0, _reactApollo.graphql)(mutation, config); + +/***/ }), + +/***/ "./client/src/state/editor/readBlocksForAreaQuery.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.config = exports.query = undefined; + +var _templateObject = _taggedTemplateLiteral(['\nquery ReadBlocksForArea($id:ID!) {\n readOneElementalArea(filter: { id: { eq: $id } }, versioning: {\n mode: DRAFT\n }){\n elements {\n id\n title\n blockSchema\n obsoleteClassName\n isLiveVersion\n isPublished\n version\n canCreate\n canPublish\n canUnpublish\n canDelete\n }\n }\n}\n'], ['\nquery ReadBlocksForArea($id:ID!) {\n readOneElementalArea(filter: { id: { eq: $id } }, versioning: {\n mode: DRAFT\n }){\n elements {\n id\n title\n blockSchema\n obsoleteClassName\n isLiveVersion\n isPublished\n version\n canCreate\n canPublish\n canUnpublish\n canDelete\n }\n }\n}\n']); + +var _reactApollo = __webpack_require__(6); + +var _graphqlTag = __webpack_require__(5); + +var _graphqlTag2 = _interopRequireDefault(_graphqlTag); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } + +var query = (0, _graphqlTag2.default)(_templateObject); + +var config = { + options: function options(_ref) { + var areaId = _ref.areaId; + + return { + variables: { + id: areaId + } + }; + }, + props: function props(_ref2) { + var _ref2$data = _ref2.data, + error = _ref2$data.error, + readOneElementalArea = _ref2$data.readOneElementalArea, + networkLoading = _ref2$data.loading; + + var blocks = null; + if (readOneElementalArea) { + blocks = readOneElementalArea.elements; + } + + var errors = error && error.graphQLErrors && error.graphQLErrors.map(function (graphQLError) { + return graphQLError.message; + }); + + return { + loading: networkLoading || !blocks, + blocks: blocks, + graphQLErrors: errors + }; + } +}; + +exports.query = query; +exports.config = config; +exports.default = (0, _reactApollo.graphql)(query, config); + +/***/ }), + +/***/ "./client/src/state/editor/sortBlockMutation.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.config = exports.mutation = undefined; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +var _templateObject = _taggedTemplateLiteral(['\nmutation SortBlockMutation($blockId:ID!, $afterBlockId:ID!) {\n sortBlock(\n id: $blockId\n afterBlockID: $afterBlockId\n ) {\n id\n isLiveVersion\n isPublished\n }\n}\n'], ['\nmutation SortBlockMutation($blockId:ID!, $afterBlockId:ID!) {\n sortBlock(\n id: $blockId\n afterBlockID: $afterBlockId\n ) {\n id\n isLiveVersion\n isPublished\n }\n}\n']); + +var _reactApollo = __webpack_require__(6); + +var _graphqlTag = __webpack_require__(5); + +var _graphqlTag2 = _interopRequireDefault(_graphqlTag); + +var _readBlocksForAreaQuery = __webpack_require__("./client/src/state/editor/readBlocksForAreaQuery.js"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } + +var mutation = (0, _graphqlTag2.default)(_templateObject); + +var config = { + props: function props(_ref) { + var mutate = _ref.mutate, + actions = _ref.ownProps.actions; + + var handleSortBlock = function handleSortBlock(blockId, afterBlockId, areaId) { + return mutate({ + variables: { + blockId: blockId, + afterBlockId: afterBlockId + }, + optimisticResponse: { + sortBlock: { + id: blockId, + liveVersion: false, + __typename: 'Block' + } + }, + update: function update(store, _ref2) { + var updatedElementData = _ref2.data.sortBlock; + + var variables = _readBlocksForAreaQuery.config.options({ areaId: areaId }).variables; + var cachedData = store.readQuery({ query: _readBlocksForAreaQuery.query, variables: variables }); + + var newData = JSON.parse(JSON.stringify(cachedData)); + var blocks = newData.readOneElementalArea.elements; + + var movedBlockIndex = blocks.findIndex(function (block) { + return block.id === blockId; + }); + + var movedBlock = blocks[movedBlockIndex]; + + Object.entries(updatedElementData).forEach(function (_ref3) { + var _ref4 = _slicedToArray(_ref3, 2), + key = _ref4[0], + value = _ref4[1]; + + if (key === '__typename') { + return; + } + + movedBlock[key] = value; + }); + + blocks.splice(movedBlockIndex, 1); + + if (afterBlockId === '0') { + blocks.unshift(movedBlock); + } else { + var targetBlockIndex = blocks.findIndex(function (block) { + return block.id === afterBlockId; + }); + + if (targetBlockIndex === -1) { + targetBlockIndex = movedBlockIndex - 1; + } + + var end = blocks.slice(targetBlockIndex + 1); + blocks = blocks.slice(0, targetBlockIndex + 1); + blocks.push(movedBlock); + blocks = blocks.concat(end); + } + + newData.readOneElementalArea.elements = blocks; + store.writeQuery({ query: _readBlocksForAreaQuery.query, data: newData, variables: variables }); + } + }); + }; + return { + actions: _extends({}, actions, { + handleSortBlock: handleSortBlock + }) + }; + } +}; + +exports.mutation = mutation; +exports.config = config; +exports.default = (0, _reactApollo.graphql)(mutation, config); + +/***/ }), + +/***/ "./client/src/state/editor/unpublishBlockMutation.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.config = exports.mutation = undefined; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _templateObject = _taggedTemplateLiteral(['\nmutation UnpublishBlock($blockId:ID!) {\n unpublishBlock(\n id: $blockId\n ) {\n id\n }\n}\n'], ['\nmutation UnpublishBlock($blockId:ID!) {\n unpublishBlock(\n id: $blockId\n ) {\n id\n }\n}\n']); + +var _reactApollo = __webpack_require__(6); + +var _graphqlTag = __webpack_require__(5); + +var _graphqlTag2 = _interopRequireDefault(_graphqlTag); + +var _readBlocksForAreaQuery = __webpack_require__("./client/src/state/editor/readBlocksForAreaQuery.js"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } + +var mutation = (0, _graphqlTag2.default)(_templateObject); + +var config = { + props: function props(_ref) { + var mutate = _ref.mutate, + actions = _ref.ownProps.actions; + + var handleUnpublishBlock = function handleUnpublishBlock(blockId, fromStage, toStage, fromVersion) { + return mutate({ + variables: { + blockId: blockId, + fromStage: fromStage, + toStage: toStage, + fromVersion: fromVersion + } + }); + }; + + return { + actions: _extends({}, actions, { + handleUnpublishBlock: handleUnpublishBlock + }) + }; + }, + options: function options(_ref2) { + var areaId = _ref2.areaId; + return { + refetchQueries: [{ + query: _readBlocksForAreaQuery.query, + variables: _readBlocksForAreaQuery.config.options({ areaId: areaId }).variables + }] + }; + } +}; + +exports.mutation = mutation; +exports.config = config; +exports.default = (0, _reactApollo.graphql)(mutation, config); + +/***/ }), + +/***/ "./client/src/state/history/readOneBlockQuery.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.config = exports.query = undefined; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _templateObject = _taggedTemplateLiteral(['\nquery ReadHistoryViewerBlock ($block_id: ID!, $limit: Int!, $offset: Int!) {\n readOneBlock(\n versioning: {\n mode: LATEST\n },\n filter: { id: { eq: $block_id } }\n ) {\n id\n versions (limit: $limit, offset: $offset, sort: { version: DESC }) {\n pageInfo {\n totalCount\n }\n nodes {\n version\n absoluteLink\n author {\n firstName\n surname\n }\n publisher {\n firstName\n surname\n }\n published\n liveVersion\n latestDraftVersion\n lastEdited\n }\n }\n }\n}\n'], ['\nquery ReadHistoryViewerBlock ($block_id: ID!, $limit: Int!, $offset: Int!) {\n readOneBlock(\n versioning: {\n mode: LATEST\n },\n filter: { id: { eq: $block_id } }\n ) {\n id\n versions (limit: $limit, offset: $offset, sort: { version: DESC }) {\n pageInfo {\n totalCount\n }\n nodes {\n version\n absoluteLink\n author {\n firstName\n surname\n }\n publisher {\n firstName\n surname\n }\n published\n liveVersion\n latestDraftVersion\n lastEdited\n }\n }\n }\n}\n']); + +var _reactApollo = __webpack_require__(6); + +var _graphqlTag = __webpack_require__(5); + +var _graphqlTag2 = _interopRequireDefault(_graphqlTag); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } + +var query = (0, _graphqlTag2.default)(_templateObject); + +var config = { + options: function options(_ref) { + var recordId = _ref.recordId, + limit = _ref.limit, + page = _ref.page; + + return { + variables: { + limit: limit, + offset: ((page || 1) - 1) * limit, + block_id: recordId + } + }; + }, + props: function props(_ref2) { + var _ref2$data = _ref2.data, + error = _ref2$data.error, + refetch = _ref2$data.refetch, + readOneBlock = _ref2$data.readOneBlock, + networkLoading = _ref2$data.loading, + _ref2$ownProps = _ref2.ownProps, + _ref2$ownProps$action = _ref2$ownProps.actions, + actions = _ref2$ownProps$action === undefined ? { + versions: {} + } : _ref2$ownProps$action, + limit = _ref2$ownProps.limit, + recordId = _ref2$ownProps.recordId; + + var versions = readOneBlock || null; + + var errors = error && error.graphQLErrors && error.graphQLErrors.map(function (graphQLError) { + return graphQLError.message; + }); + + return { + loading: networkLoading || !versions, + versions: versions, + graphQLErrors: errors, + actions: _extends({}, actions, { + versions: _extends({}, versions, { + goToPage: function goToPage(page) { + refetch({ + offset: ((page || 1) - 1) * limit, + limit: limit, + block_id: recordId + }); + } + }) + }) + }; + } +}; + +exports.query = query; +exports.config = config; +exports.default = (0, _reactApollo.graphql)(query, config); + +/***/ }), + +/***/ "./client/src/state/history/revertToBlockVersionMutation.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.config = exports.mutation = undefined; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _templateObject = _taggedTemplateLiteral(['\nmutation revertBlockToVersion($id:ID!, $fromStage:VersionedStage!, $toStage:VersionedStage!, $fromVersion:Int!) {\n copyBlockToStage(input: {\n id: $id\n fromVersion: $fromVersion\n fromStage: $fromStage\n toStage: $toStage\n }) {\n id\n }\n}\n'], ['\nmutation revertBlockToVersion($id:ID!, $fromStage:VersionedStage!, $toStage:VersionedStage!, $fromVersion:Int!) {\n copyBlockToStage(input: {\n id: $id\n fromVersion: $fromVersion\n fromStage: $fromStage\n toStage: $toStage\n }) {\n id\n }\n}\n']); + +var _reactApollo = __webpack_require__(6); + +var _graphqlTag = __webpack_require__(5); + +var _graphqlTag2 = _interopRequireDefault(_graphqlTag); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } + +var mutation = (0, _graphqlTag2.default)(_templateObject); + +var config = { + props: function props(_ref) { + var mutate = _ref.mutate, + actions = _ref.ownProps.actions; + + var revertToVersion = function revertToVersion(id, fromVersion, fromStage, toStage) { + return mutate({ + variables: { + id: id, + fromVersion: fromVersion, + fromStage: fromStage, + toStage: toStage + } + }); + }; + + return { + actions: _extends({}, actions, { + revertToVersion: revertToVersion + }) + }; + }, + options: { + refetchQueries: ['ReadHistoryViewerBlock'] + } +}; + +exports.mutation = mutation; +exports.config = config; +exports.default = (0, _reactApollo.graphql)(mutation, config); + +/***/ }), + +/***/ "./client/src/types/elementType.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.elementType = undefined; + +var _propTypes = __webpack_require__(1); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var elementType = _propTypes2.default.shape({ + id: _propTypes2.default.string.isRequired, + title: _propTypes2.default.string, + blockSchema: _propTypes2.default.object, + inlineEditable: _propTypes2.default.bool, + published: _propTypes2.default.bool, + liveVersion: _propTypes2.default.bool, + version: _propTypes2.default.number +}); + +exports.elementType = elementType; + +/***/ }), + +/***/ "./client/src/types/elementTypeType.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.elementTypeType = undefined; + +var _propTypes = __webpack_require__(1); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var elementTypeType = _propTypes2.default.shape({ + name: _propTypes2.default.string, + + title: _propTypes2.default.string, + + icon: _propTypes2.default.string, + + inlineEditable: _propTypes2.default.boolean, + + editTabs: _propTypes2.default.arrayOf(_propTypes2.default.shape({ + title: _propTypes2.default.string, + name: _propTypes2.default.string + })), + + config: _propTypes2.default.object +}); + +exports.elementTypeType = elementTypeType; + +/***/ }), + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = React; + +/***/ }), + +/***/ 1: +/***/ (function(module, exports) { + +module.exports = PropTypes; + +/***/ }), + +/***/ 10: +/***/ (function(module, exports) { + +module.exports = Reactstrap; + +/***/ }), + +/***/ 11: +/***/ (function(module, exports) { + +module.exports = ReduxForm; + +/***/ }), + +/***/ 12: +/***/ (function(module, exports) { + +module.exports = Config; + +/***/ }), + +/***/ 13: +/***/ (function(module, exports) { + +module.exports = Backend; + +/***/ }), + +/***/ 14: +/***/ (function(module, exports) { + +module.exports = ReactDNDHtml5Backend; + +/***/ }), + +/***/ 15: +/***/ (function(module, exports) { + +module.exports = ReactDom; + +/***/ }), + +/***/ 16: +/***/ (function(module, exports) { + +module.exports = getFormState; + +/***/ }), + +/***/ 17: +/***/ (function(module, exports) { + +module.exports = FieldHolder; + +/***/ }), + +/***/ 18: +/***/ (function(module, exports) { + +module.exports = FormBuilderLoader; + +/***/ }), + +/***/ 19: +/***/ (function(module, exports) { + +module.exports = TabsActions; + +/***/ }), + +/***/ 2: +/***/ (function(module, exports) { + +module.exports = i18n; + +/***/ }), + +/***/ 20: +/***/ (function(module, exports) { + +module.exports = jQuery; + +/***/ }), + +/***/ 21: +/***/ (function(module, exports) { + +module.exports = withDragDropContext; + +/***/ }), + +/***/ 3: +/***/ (function(module, exports) { + +module.exports = Injector; + +/***/ }), + +/***/ 4: +/***/ (function(module, exports) { + +module.exports = Redux; + +/***/ }), + +/***/ 5: +/***/ (function(module, exports) { + +module.exports = GraphQLTag; + +/***/ }), + +/***/ 6: +/***/ (function(module, exports) { + +module.exports = ReactApollo; + +/***/ }), + +/***/ 7: +/***/ (function(module, exports) { + +module.exports = classnames; + +/***/ }), + +/***/ 8: +/***/ (function(module, exports) { + +module.exports = ReactRedux; + +/***/ }), + +/***/ 9: +/***/ (function(module, exports) { + +module.exports = ReactDND; + +/***/ }) + +/******/ }); +//# sourceMappingURL=bundle.js.map \ No newline at end of file diff --git a/client/dist/styles/bundle.css b/client/dist/styles/bundle.css index c2b39c01..2773765b 100644 --- a/client/dist/styles/bundle.css +++ b/client/dist/styles/bundle.css @@ -1 +1,2 @@ -.elemental-edit{display:-webkit-box;display:-webkit-flex;display:flex;color:inherit}.elemental-edit:focus,.elemental-edit:hover{text-decoration:none;color:inherit}.elemental-editor .col-EditorPreview{padding-left:0}.elemental-preview__detail{display:inline-block;margin-left:.76925rem;margin-top:1px}.elemental-preview__detail h3{font-weight:400;line-height:26px;margin:0;-webkit-font-smoothing:antialiased}.elemental-preview__detail p{-webkit-box-align:center;-webkit-align-items:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:flex;margin-bottom:0;margin-top:6px}.elemental-preview__detail small{color:#566b8d;font-size:13px}.elemental-preview__thumbnail-image{margin-right:.76925rem}.elemental-preview__thumbnail-image img{border-radius:.192rem}.elemental-preview__thumbnail-image--placeholder{border-radius:0;height:36px;margin-left:-4px}.elemental-preview__icon{color:#566b8d;display:inline-block;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;flex-direction:row;font-size:2.3rem;width:28px;vertical-align:top;margin-top:-1px}.ss-gridfield-orderable.elemental-editor .col-reorder .handle{opacity:.5;padding:22px 0 0}.ss-gridfield-orderable.elemental-editor .col-reorder .handle .icon{font-size:1.3em}.elemental-editor .ss-gridfield-item:hover .handle{opacity:1}.elemental-editor .grid-field__table{margin-bottom:12px}@media (max-width:991.98px){.elemental-editor .grid-field__table .col-EditorPreview{display:table-cell}}.elemental-report__grid-field .element-editor-header__version-state{bottom:9px;left:14px}.element-editor .form-group:nth-child(1n){display:block}@media (min-width:992px){.element-editor .form-group:nth-child(1n) .form__field-holder,.element-editor .form-group:nth-child(1n) .form__field-label{-webkit-box-flex:0;-webkit-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%;margin-left:0}}.elemental-block__history-tab{margin-top:-1.5385rem}.cms-edit-form .fieldgroup.elemental-area__element--historic{margin-left:0;margin-right:0}.cms-edit-form .fieldgroup.elemental-area__element--historic.form-group{border-top:1px solid #dbe0e9}.cms-edit-form .fieldgroup.elemental-area__element--historic .form__field-holder{-webkit-box-flex:0;-webkit-flex:0 0 100%;flex:0 0 100%;max-width:100%}.elemental-preview{line-height:20px}.elemental-preview--historic{margin-bottom:1rem}.elemental-preview__link{float:right;margin-top:4px}.elemental-preview__link:hover{text-decoration:none}.elemental-preview__link:hover .elemental-preview__link-text{text-decoration:underline}.elemental-preview__link-caret{display:block;float:right;margin-top:-2px;margin-left:2px}div.elemental-area__element--historic.elemental-area__element--historic-inner{background:transparent;border:0;padding-left:0;padding-right:0;padding-top:1.5385rem}.elemental-area--read-only{border-bottom:1px solid #dbe0e9;margin:2.30775rem -1.5385rem}.history-viewer__version-detail fieldset{overflow:visible}.elemental-report__grid-field .ss-gridfield-item td:first-child{width:1px}.elemental-report__grid-field .col-Icon{font-size:1.5rem}.elemental-report__grid-field .element-item--draft,.elemental-report__grid-field .element-item--modified{bottom:8px;left:14px;height:6px;width:6px}.textcheckboxgroup .input-group-append .form-check-input{margin-left:0;position:relative}.element-editor .action-menu .dropdown-item.disabled{font-style:italic;pointer-events:auto;cursor:not-allowed;color:#6f84a7}.elemental-editor__add-new-block-control{width:20rem}.elemental-editor__add-new-block-control a{line-height:1.85em}.element-editor__element{border-bottom:1px solid #dbe0e9;color:inherit;cursor:pointer;min-height:8rem;padding:.9231rem 1.5385rem 1.8462rem}.element-editor__element:focus,.element-editor__element:hover{-webkit-box-shadow:0 2px 5px 0 rgba(0,0,0,.1),0 2px 10px 0 rgba(0,0,0,.1);box-shadow:0 2px 5px 0 rgba(0,0,0,.1),0 2px 10px 0 rgba(0,0,0,.1);outline-width:0}.element-editor__element:hover .element-editor-header__drag-handle{display:block}.element-editor__element--broken{cursor:default}.element-editor__element--dragging{opacity:.3;cursor:grabbing;cursor:-webkit-grabbing}.elemental-editor-list{background-color:#fff;border-top:1px solid #dbe0e9;margin-left:-1.5385rem;margin-right:-1.5385rem;min-height:calc(8rem + 1px);position:relative;margin-bottom:1.5385rem}.elemental-editor-list--empty{border-bottom:1px solid #dbe0e9;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center}.element-editor-editform{margin-top:.76925rem;cursor:auto;margin-bottom:-1rem}.element-editor-editform .mce-tinymce{-webkit-box-sizing:border-box;box-sizing:border-box}.element-editor-editform__form{width:100%}.element-editor-editform .element-editor-editform__form .form-group .form__field-holder{-webkit-box-flex:1;-webkit-flex:1 0 100%;flex:1 0 100%;max-width:900px}.element-editor-header{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.element-editor-header__title{font-size:15px;font-weight:400;margin:0 0 0 .76925rem;-webkit-font-smoothing:antialiased;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.element-editor-header__title--none{font-style:italic;color:#6f84a7}.element-editor-header__actions,.element-editor-header__info{-webkit-box-align:center;-webkit-align-items:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1}.element-editor-header__info{max-width:calc(100% - 60px)}.element-editor-header__actions{-webkit-box-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.element-editor-header__actions-toggle{padding-top:3px;padding-bottom:3px}.element-editor-header__icon-container{margin-left:-2px;color:#566b8d;font-size:2.154rem;height:28px;line-height:1.5rem}.element-editor-header__icon-container--broken{color:#da273b}.element-editor-header__expand{font-size:1.1rem;margin-left:3px;width:unset}.element-editor-header__version-state{border:1px solid #cf3f00;border-radius:100%;bottom:6px;-webkit-box-shadow:0 0 1px .5px #fff;box-shadow:0 0 1px .5px #fff;display:block;height:8px;left:22px;position:relative;width:8px;z-index:1}.element-editor-header__version-state--unsaved{background-color:#0071c4;border:1px solid #0062ab}.element-editor-header__version-state--draft{background-color:#ff7f22}.element-editor-header__version-state--modified{background-color:#fff7f0}.element-editor-header__drag-handle{display:none;position:absolute;left:5px;cursor:grab;cursor:-webkit-grab}.element-editor-header--simple .element-editor-header__drag-handle{display:block}.element-editor-header--simple .element-editor-header__info{width:460px}.element-editor-header .dropdown-item.active{cursor:default}.element-editor-summary{display:-webkit-box;display:-webkit-flex;display:flex;margin-top:.9231rem;margin-left:36px;-webkit-box-align:center;-webkit-align-items:center;align-items:center;min-height:2em}.element-editor-summary__thumbnail-image{border-radius:.1536rem;height:36px;margin:-.6154rem .9231rem -.6154rem 0}.element-editor-summary__content{color:#566b8d;line-height:1.3;margin-bottom:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.element-editor-summary__content--broken{overflow:visible;white-space:normal}.element-editor__toolbar{margin-bottom:1rem}.element-editor__hover-bar{height:0;display:-webkit-box;display:-webkit-flex;display:flex;width:100%;position:relative;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.element-editor__hover-bar-area{background-color:transparent;min-height:1.8462rem;width:100%;margin:0;padding:0;border:none;outline:none;-webkit-transition:all .2s ease;-o-transition:all ease .2s;transition:all .2s ease;position:relative}.element-editor__hover-bar-area--focus,.element-editor__hover-bar-area:focus,.element-editor__hover-bar-area:hover{outline:none}.element-editor__hover-bar-area--focus .element-editor__hover-bar-area-inner,.element-editor__hover-bar-area:focus .element-editor__hover-bar-area-inner,.element-editor__hover-bar-area:hover .element-editor__hover-bar-area-inner{margin:0 20px}.element-editor__hover-bar-area--focus .element-editor__hover-bar-line,.element-editor__hover-bar-area:focus .element-editor__hover-bar-line,.element-editor__hover-bar-area:hover .element-editor__hover-bar-line{opacity:1;border-radius:5px;max-height:5px}.element-editor__hover-bar-area--focus .element-editor__hover-bar-line:before,.element-editor__hover-bar-area:focus .element-editor__hover-bar-line:before,.element-editor__hover-bar-area:hover .element-editor__hover-bar-line:before{-webkit-transform:translateY(calc(3px + -50%)) scale(1);-o-transform:translateY(calc(3px + -50%)) scale(1);transform:translateY(calc(3px + -50%)) scale(1)}.element-editor__hover-bar-area-inner{margin:0;display:block;position:relative}.element-editor__hover-bar-area-inner,.element-editor__hover-bar-line{-webkit-transition:all .2s ease;-o-transition:all ease .2s;transition:all .2s ease}.element-editor__hover-bar-line{background-color:#005a93;opacity:0;-webkit-align-self:center;align-self:center;width:100%;border:0;position:absolute;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;padding:0;top:50%;-webkit-transform:translateY(-66%);-o-transform:translateY(-66%);transform:translateY(-66%);max-height:0;border-radius:0}.element-editor__hover-bar-line:before{font-size:1.5rem;background-image:-webkit-radial-gradient(#fff 50%,transparent 0);background-image:-o-radial-gradient(#fff 50%,transparent 50%);background-image:radial-gradient(#fff 50%,transparent 0);position:relative;z-index:2;margin-right:50%;right:-.5em;display:block;height:1em;-webkit-transform:translateY(-35%);-o-transform:translateY(-35%);transform:translateY(-35%);-webkit-transform:translateY(calc(-1px + -50%)) scale(0);-o-transform:translateY(calc(-1px + -50%)) scale(0);transform:translateY(calc(-1px + -50%)) scale(0);-webkit-transition:all .2s ease;-o-transition:all ease .2s;transition:all .2s ease;color:#005a93}.elemental-editor-drag-indicator{height:3px;margin:-2px 0 -1px;background-color:#29abe2}.elemental-editor-drag-indicator__ball{position:relative;height:7px;width:7px;top:-2px;left:-3px;border-radius:3.5px;background-color:#29abe2}.element-editor--dragging{cursor:-webkit-grabbing;cursor:grabbing}.element-editor-drag-preview{top:0;left:0;position:fixed;pointer-events:none;z-index:100;background-color:#fff;border:1px solid #ced5e1;padding:.9231rem 1.5385rem;-webkit-box-shadow:0 2px 5px 0 rgba(0,0,0,.1),0 2px 10px 0 rgba(0,0,0,.1);box-shadow:0 2px 5px 0 rgba(0,0,0,.1),0 2px 10px 0 rgba(0,0,0,.1)}.text-checkbox-group-field .form-check{display:inline;padding-left:0;margin-bottom:0}.text-checkbox-group-field--read-only{display:-webkit-box;display:-webkit-flex;display:flex}.text-checkbox-group-field--read-only :first-child{-webkit-box-flex:1;-webkit-flex:1;flex:1}.text-checkbox-group-field--read-only .show-title{font-style:italic} \ No newline at end of file +.elemental-edit{display:-webkit-box;display:-webkit-flex;display:flex;color:inherit}.elemental-edit:focus,.elemental-edit:hover{text-decoration:none;color:inherit}.elemental-editor .col-EditorPreview{padding-left:0}.elemental-preview__detail{display:inline-block;margin-left:.76925rem;margin-top:1px}.elemental-preview__detail h3{font-weight:400;line-height:26px;margin:0;-webkit-font-smoothing:antialiased}.elemental-preview__detail p{-webkit-box-align:center;-webkit-align-items:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:flex;margin-bottom:0;margin-top:6px}.elemental-preview__detail small{color:#566b8d;font-size:13px}.elemental-preview__thumbnail-image{margin-right:.76925rem}.elemental-preview__thumbnail-image img{border-radius:.192rem}.elemental-preview__thumbnail-image--placeholder{border-radius:0;height:36px;margin-left:-4px}.elemental-preview__icon{color:#566b8d;display:inline-block;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;flex-direction:row;font-size:2.3rem;width:28px;vertical-align:top;margin-top:-1px}.ss-gridfield-orderable.elemental-editor .col-reorder .handle{opacity:.5;padding:22px 0 0}.ss-gridfield-orderable.elemental-editor .col-reorder .handle .icon{font-size:1.3em}.elemental-editor .ss-gridfield-item:hover .handle{opacity:1}.elemental-editor .grid-field__table{margin-bottom:12px}@media (max-width:991.98px){.elemental-editor .grid-field__table .col-EditorPreview{display:table-cell}}.elemental-report__grid-field .element-editor-header__version-state{bottom:9px;left:14px}.element-editor .form-group:nth-child(1n){display:block}@media (min-width:992px){.element-editor .form-group:nth-child(1n) .form__field-holder,.element-editor .form-group:nth-child(1n) .form__field-label{-webkit-box-flex:0;-webkit-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%;margin-left:0}}.elemental-block__history-tab{margin-top:-1.5385rem}.cms-edit-form .fieldgroup.elemental-area__element--historic{margin-left:0;margin-right:0}.cms-edit-form .fieldgroup.elemental-area__element--historic.form-group{border-top:1px solid #dbe0e9}.cms-edit-form .fieldgroup.elemental-area__element--historic .form__field-holder{-webkit-box-flex:0;-webkit-flex:0 0 100%;flex:0 0 100%;max-width:100%}.elemental-preview{line-height:20px}.elemental-preview--historic{margin-bottom:1rem}.elemental-preview__link{float:right;margin-top:4px}.elemental-preview__link:hover{text-decoration:none}.elemental-preview__link:hover .elemental-preview__link-text{text-decoration:underline}.elemental-preview__link-caret{display:block;float:right;margin-top:-2px;margin-left:2px}div.elemental-area__element--historic.elemental-area__element--historic-inner{background:transparent;border:0;padding-left:0;padding-right:0;padding-top:1.5385rem}.elemental-area--read-only{border-bottom:1px solid #dbe0e9;margin:2.30775rem -1.5385rem}.history-viewer__version-detail fieldset{overflow:visible}.elemental-report__grid-field .ss-gridfield-item td:first-child{width:1px}.elemental-report__grid-field .col-Icon{font-size:1.5rem}.elemental-report__grid-field .element-item--draft,.elemental-report__grid-field .element-item--modified{bottom:8px;left:14px;height:6px;width:6px}.textcheckboxgroup .input-group-append .form-check-input{margin-left:0;position:relative}.element-editor .action-menu .dropdown-item.disabled{font-style:italic;pointer-events:auto;cursor:not-allowed;color:#6f84a7}.elemental-editor__add-new-block-control{width:20rem}.elemental-editor__add-new-block-control a{line-height:1.85em}.element-editor__element{border-bottom:1px solid #dbe0e9;color:inherit;cursor:pointer;min-height:8rem;padding:.9231rem 1.5385rem 1.8462rem}.element-editor__element:focus,.element-editor__element:hover{-webkit-box-shadow:0 2px 5px 0 rgba(0,0,0,.1),0 2px 10px 0 rgba(0,0,0,.1);box-shadow:0 2px 5px 0 rgba(0,0,0,.1),0 2px 10px 0 rgba(0,0,0,.1);outline-width:0}.element-editor__element:hover .element-editor-header__drag-handle{display:block}.element-editor__element--broken{cursor:default}.element-editor__element--dragging{opacity:.3;cursor:grabbing;cursor:-webkit-grabbing}.elemental-editor-list{background-color:#fff;border-top:1px solid #dbe0e9;margin-left:-1.5385rem;margin-right:-1.5385rem;min-height:calc(8rem + 1px);position:relative;margin-bottom:1.5385rem}.elemental-editor-list--empty{border-bottom:1px solid #dbe0e9;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center}.element-editor-editform{margin-top:.76925rem;cursor:auto;margin-bottom:-1rem}.element-editor-editform .mce-tinymce{-webkit-box-sizing:border-box;box-sizing:border-box}.element-editor-editform__form{width:100%}.element-editor-editform .element-editor-editform__form .form-group .form__field-holder{-webkit-box-flex:1;-webkit-flex:1 0 100%;flex:1 0 100%;max-width:900px}.element-editor-header{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.element-editor-header__title{font-size:15px;font-weight:400;margin:0 0 0 .76925rem;-webkit-font-smoothing:antialiased;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.element-editor-header__title--none{font-style:italic;color:#6f84a7}.element-editor-header__actions,.element-editor-header__info{-webkit-box-align:center;-webkit-align-items:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1}.element-editor-header__info{max-width:calc(100% - 60px)}.element-editor-header__actions{-webkit-box-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.element-editor-header__actions-toggle{padding-top:3px;padding-bottom:3px}.element-editor-header__icon-container{margin-left:-2px;color:#566b8d;font-size:2.154rem;height:28px;line-height:1.5rem}.element-editor-header__icon-container--broken{color:#da273b}.element-editor-header__expand{font-size:1.1rem;margin-left:3px;width:unset}.element-editor-header__version-state{border:1px solid #cf3f00;border-radius:100%;bottom:6px;-webkit-box-shadow:0 0 1px .5px #fff;box-shadow:0 0 1px .5px #fff;display:block;height:8px;left:22px;position:relative;width:8px;z-index:1}.element-editor-header__version-state--unsaved{background-color:#0071c4;border:1px solid #0062ab}.element-editor-header__version-state--draft{background-color:#ff7f22}.element-editor-header__version-state--modified{background-color:#fff7f0}.element-editor-header__drag-handle{display:none;position:absolute;left:5px;cursor:grab;cursor:-webkit-grab}.element-editor-header--simple .element-editor-header__drag-handle{display:block}.element-editor-header--simple .element-editor-header__info{width:460px}.element-editor-header .dropdown-item.active{cursor:default}.element-editor-summary{display:-webkit-box;display:-webkit-flex;display:flex;margin-top:.9231rem;margin-left:36px;-webkit-box-align:center;-webkit-align-items:center;align-items:center;min-height:2em}.element-editor-summary__thumbnail-image{border-radius:.1536rem;height:36px;margin:-.6154rem .9231rem -.6154rem 0}.element-editor-summary__content{color:#566b8d;line-height:1.3;margin-bottom:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.element-editor-summary__content--broken{overflow:visible;white-space:normal}.element-editor__toolbar{margin-bottom:1rem}.element-editor__hover-bar{height:0;display:-webkit-box;display:-webkit-flex;display:flex;width:100%;position:relative;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.element-editor__hover-bar-area{background-color:transparent;min-height:1.8462rem;width:100%;margin:0;padding:0;border:none;outline:none;-webkit-transition:all .2s ease;-o-transition:all ease .2s;transition:all .2s ease;position:relative}.element-editor__hover-bar-area--focus,.element-editor__hover-bar-area:focus,.element-editor__hover-bar-area:hover{outline:none}.element-editor__hover-bar-area--focus .element-editor__hover-bar-area-inner,.element-editor__hover-bar-area:focus .element-editor__hover-bar-area-inner,.element-editor__hover-bar-area:hover .element-editor__hover-bar-area-inner{margin:0 20px}.element-editor__hover-bar-area--focus .element-editor__hover-bar-line,.element-editor__hover-bar-area:focus .element-editor__hover-bar-line,.element-editor__hover-bar-area:hover .element-editor__hover-bar-line{opacity:1;border-radius:5px;max-height:5px}.element-editor__hover-bar-area--focus .element-editor__hover-bar-line:before,.element-editor__hover-bar-area:focus .element-editor__hover-bar-line:before,.element-editor__hover-bar-area:hover .element-editor__hover-bar-line:before{-webkit-transform:translateY(calc(3px + -50%)) scale(1);-o-transform:translateY(calc(3px + -50%)) scale(1);transform:translateY(calc(3px + -50%)) scale(1)}.element-editor__hover-bar-area-inner{margin:0;display:block;position:relative}.element-editor__hover-bar-area-inner,.element-editor__hover-bar-line{-webkit-transition:all .2s ease;-o-transition:all ease .2s;transition:all .2s ease}.element-editor__hover-bar-line{background-color:#005a93;opacity:0;-webkit-align-self:center;align-self:center;width:100%;border:0;position:absolute;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;padding:0;top:50%;-webkit-transform:translateY(-66%);-o-transform:translateY(-66%);transform:translateY(-66%);max-height:0;border-radius:0}.element-editor__hover-bar-line:before{font-size:1.5rem;background-image:-webkit-radial-gradient(#fff 50%,transparent 0);background-image:-o-radial-gradient(#fff 50%,transparent 50%);background-image:radial-gradient(#fff 50%,transparent 0);position:relative;z-index:2;margin-right:50%;right:-.5em;display:block;height:1em;-webkit-transform:translateY(-35%);-o-transform:translateY(-35%);transform:translateY(-35%);-webkit-transform:translateY(calc(-1px + -50%)) scale(0);-o-transform:translateY(calc(-1px + -50%)) scale(0);transform:translateY(calc(-1px + -50%)) scale(0);-webkit-transition:all .2s ease;-o-transition:all ease .2s;transition:all .2s ease;color:#005a93}.elemental-editor-drag-indicator{height:3px;margin:-2px 0 -1px;background-color:#29abe2}.elemental-editor-drag-indicator__ball{position:relative;height:7px;width:7px;top:-2px;left:-3px;border-radius:3.5px;background-color:#29abe2}.element-editor--dragging{cursor:-webkit-grabbing;cursor:grabbing}.element-editor-drag-preview{top:0;left:0;position:fixed;pointer-events:none;z-index:100;background-color:#fff;border:1px solid #ced5e1;padding:.9231rem 1.5385rem;-webkit-box-shadow:0 2px 5px 0 rgba(0,0,0,.1),0 2px 10px 0 rgba(0,0,0,.1);box-shadow:0 2px 5px 0 rgba(0,0,0,.1),0 2px 10px 0 rgba(0,0,0,.1)}.text-checkbox-group-field .form-check{display:inline;padding-left:0;margin-bottom:0}.text-checkbox-group-field--read-only{display:-webkit-box;display:-webkit-flex;display:flex}.text-checkbox-group-field--read-only :first-child{-webkit-box-flex:1;-webkit-flex:1;flex:1}.text-checkbox-group-field--read-only .show-title{font-style:italic} +/*# sourceMappingURL=bundle.css.map*/ \ No newline at end of file diff --git a/client/src/components/ElementEditor/ElementEditor.js b/client/src/components/ElementEditor/ElementEditor.js index 86aac0de..f6e7f550 100644 --- a/client/src/components/ElementEditor/ElementEditor.js +++ b/client/src/components/ElementEditor/ElementEditor.js @@ -57,10 +57,20 @@ class ElementEditor extends PureComponent { handleDragEnd(sourceId, afterId) { const { actions: { handleSortBlock }, areaId } = this.props; - handleSortBlock(sourceId, afterId, areaId).then(() => { - const preview = window.jQuery('.cms-preview'); - preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); - }); + const globalUseGraphqQL = true; + if (globalUseGraphqQL) { + // see sortBlockMutation.js for reference + handleSortBlock(sourceId, afterId, areaId).then(() => { + const preview = window.jQuery('.cms-preview'); + preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); + }); + } else { + // # rpc + // make a call to a sort endpoint with (ID, afterBlocKID) + // after that is done, get ElementList to refetch the list of blocks + // (strange code for sorting is in this component and not ElementList, however do not refator it) + // update the preview via jquery/entwine (see graphql code above) + } this.setState({ dragTargetElementId: null, diff --git a/client/src/state/editor/sortBlockMutation.js b/client/src/state/editor/sortBlockMutation.js index 7ab0eb37..f8300178 100644 --- a/client/src/state/editor/sortBlockMutation.js +++ b/client/src/state/editor/sortBlockMutation.js @@ -34,6 +34,7 @@ const config = { const variables = readBlocksConfig.options({ areaId }).variables; const cachedData = store.readQuery({ query: readBlocksQuery, variables }); + // Query returns a deeply nested object. Explicit reconstruction via spreads is too verbose. // This is an alternative, relatively efficient way to deep clone const newData = JSON.parse(JSON.stringify(cachedData)); From a235e0e6176adadeadcbb9785b3cd69c9b788909 Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Mon, 1 Jan 2024 10:16:27 +1300 Subject: [PATCH 04/12] . --- client/dist/js/bundle.js | 14 +++++++------- .../components/ElementEditor/AddElementPopover.js | 2 +- .../src/components/ElementEditor/ElementEditor.js | 4 ++-- client/src/components/ElementEditor/ElementList.js | 8 ++++---- client/src/state/editor/sortBlockMutation.js | 2 ++ 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/client/dist/js/bundle.js b/client/dist/js/bundle.js index 4e900982..d0e9de2d 100644 --- a/client/dist/js/bundle.js +++ b/client/dist/js/bundle.js @@ -1015,7 +1015,7 @@ var AddElementPopover = function (_Component) { var popoverClassNames = (0, _classnames2.default)('element-editor-add-element', extraClass); - var globalUseGraphQL = false; + var globalUseGraphQL = true; var buttonOnClickHandler = globalUseGraphQL ? this.getElementButtonClickHandler : this.handleButtonOnClick; var buttons = elementTypes.map(function (elementType) { @@ -2144,8 +2144,8 @@ var ElementEditor = function (_PureComponent) { areaId = _props.areaId; - var globalUseGraphqQL = true; - if (globalUseGraphqQL) { + var globalUseGraphQL = true; + if (globalUseGraphQL) { handleSortBlock(sourceId, afterId, areaId).then(function () { var preview = window.jQuery('.cms-preview'); preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); @@ -2327,7 +2327,7 @@ var ElementList = function (_Component) { _createClass(ElementList, [{ key: 'fetchContentBlocks', value: function fetchContentBlocks() { - var globalUseGraphQL = false; + var globalUseGraphQL = true; if (globalUseGraphQL) { return; } @@ -2362,7 +2362,7 @@ var ElementList = function (_Component) { isDraggingOver = _props2.isDraggingOver; - var globalUseGraphQL = false; + var globalUseGraphQL = true; var contentBlocks = globalUseGraphQL ? blocks : this.state.contentBlocks; if (!contentBlocks) { @@ -2422,7 +2422,7 @@ var ElementList = function (_Component) { loading = _props3.loading, LoadingComponent = _props3.LoadingComponent; - var globalUseGraphQL = false; + var globalUseGraphQL = true; var isLoading = globalUseGraphQL ? loading : this.state.isLoading; if (isLoading) { @@ -2435,7 +2435,7 @@ var ElementList = function (_Component) { value: function render() { var blocks = this.props.blocks; - var globalUseGraphQL = false; + var globalUseGraphQL = true; var contentBlocks = globalUseGraphQL ? blocks : this.state.contentBlocks; var listClassNames = (0, _classnames2.default)('elemental-editor-list', { 'elemental-editor-list--empty': !contentBlocks || !contentBlocks.length }); diff --git a/client/src/components/ElementEditor/AddElementPopover.js b/client/src/components/ElementEditor/AddElementPopover.js index f9e6a6ef..358be502 100644 --- a/client/src/components/ElementEditor/AddElementPopover.js +++ b/client/src/components/ElementEditor/AddElementPopover.js @@ -78,7 +78,7 @@ class AddElementPopover extends Component { extraClass ); - const globalUseGraphQL = false; + const globalUseGraphQL = true; const buttonOnClickHandler = globalUseGraphQL ? this.getElementButtonClickHandler : this.handleButtonOnClick; const buttons = elementTypes.map((elementType) => ({ diff --git a/client/src/components/ElementEditor/ElementEditor.js b/client/src/components/ElementEditor/ElementEditor.js index f6e7f550..7cd00aa2 100644 --- a/client/src/components/ElementEditor/ElementEditor.js +++ b/client/src/components/ElementEditor/ElementEditor.js @@ -57,8 +57,8 @@ class ElementEditor extends PureComponent { handleDragEnd(sourceId, afterId) { const { actions: { handleSortBlock }, areaId } = this.props; - const globalUseGraphqQL = true; - if (globalUseGraphqQL) { + const globalUseGraphQL = true; + if (globalUseGraphQL) { // see sortBlockMutation.js for reference handleSortBlock(sourceId, afterId, areaId).then(() => { const preview = window.jQuery('.cms-preview'); diff --git a/client/src/components/ElementEditor/ElementList.js b/client/src/components/ElementEditor/ElementList.js index 2f481b64..9e89e564 100644 --- a/client/src/components/ElementEditor/ElementList.js +++ b/client/src/components/ElementEditor/ElementList.js @@ -25,7 +25,7 @@ class ElementList extends Component { // this will cause a re-render of the component // this callback should be passed to other components via context and get called after doing mutations fetchContentBlocks() { - const globalUseGraphQL = false; + const globalUseGraphQL = true; if (globalUseGraphQL) { return; } @@ -62,7 +62,7 @@ class ElementList extends Component { isDraggingOver, } = this.props; - const globalUseGraphQL = false; + const globalUseGraphQL = true; const contentBlocks = globalUseGraphQL ? blocks : this.state.contentBlocks; // Blocks can be either null or an empty array @@ -121,7 +121,7 @@ class ElementList extends Component { */ renderLoading() { const { loading, LoadingComponent } = this.props; - const globalUseGraphQL = false; + const globalUseGraphQL = true; const isLoading = globalUseGraphQL ? loading : this.state.isLoading; if (isLoading) { @@ -132,7 +132,7 @@ class ElementList extends Component { render() { const { blocks } = this.props; - const globalUseGraphQL = false; + const globalUseGraphQL = true; const contentBlocks = globalUseGraphQL ? blocks : this.state.contentBlocks; const listClassNames = classNames( diff --git a/client/src/state/editor/sortBlockMutation.js b/client/src/state/editor/sortBlockMutation.js index f8300178..07f3dda9 100644 --- a/client/src/state/editor/sortBlockMutation.js +++ b/client/src/state/editor/sortBlockMutation.js @@ -34,6 +34,8 @@ const config = { const variables = readBlocksConfig.options({ areaId }).variables; const cachedData = store.readQuery({ query: readBlocksQuery, variables }); + // store is apollo + // console.log(store); // Query returns a deeply nested object. Explicit reconstruction via spreads is too verbose. // This is an alternative, relatively efficient way to deep clone From c417ab4e75ab2d712a2f4da8a95eaa5c121e22fd Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Mon, 1 Jan 2024 10:35:22 +1300 Subject: [PATCH 05/12] . --- client/dist/js/bundle.js | 13 +++++++------ .../components/ElementEditor/AddElementPopover.js | 9 +++++---- .../src/components/ElementEditor/ElementEditor.js | 3 ++- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/client/dist/js/bundle.js b/client/dist/js/bundle.js index d0e9de2d..44fd5d6a 100644 --- a/client/dist/js/bundle.js +++ b/client/dist/js/bundle.js @@ -970,8 +970,8 @@ var AddElementPopover = function (_Component) { } _createClass(AddElementPopover, [{ - key: 'getElementButtonClickHandler', - value: function getElementButtonClickHandler(elementType) { + key: 'getGraphQLElementButtonClickHandler', + value: function getGraphQLElementButtonClickHandler(elementType) { var _this2 = this; return function (event) { @@ -990,8 +990,8 @@ var AddElementPopover = function (_Component) { }; } }, { - key: 'handleButtonOnClick', - value: function handleButtonOnClick(elementType) {} + key: 'getElementButtonClickHandler', + value: function getElementButtonClickHandler(elementType) {} }, { key: 'handleToggle', value: function handleToggle() { @@ -1003,6 +1003,8 @@ var AddElementPopover = function (_Component) { }, { key: 'render', value: function render() { + var _this3 = this; + var _props2 = this.props, PopoverOptionSetComponent = _props2.PopoverOptionSetComponent, elementTypes = _props2.elementTypes, @@ -1016,14 +1018,13 @@ var AddElementPopover = function (_Component) { var popoverClassNames = (0, _classnames2.default)('element-editor-add-element', extraClass); var globalUseGraphQL = true; - var buttonOnClickHandler = globalUseGraphQL ? this.getElementButtonClickHandler : this.handleButtonOnClick; var buttons = elementTypes.map(function (elementType) { return { content: elementType.title, key: elementType.name, className: (0, _classnames2.default)(elementType.icon, 'btn--icon-xl', 'element-editor-add-element__button'), - onClick: buttonOnClickHandler(elementType) + onClick: globalUseGraphQL ? _this3.getGraphQLElementButtonClickHandler(elementType) : _this3.getElementButtonClickHandler(elementType) }; }); diff --git a/client/src/components/ElementEditor/AddElementPopover.js b/client/src/components/ElementEditor/AddElementPopover.js index 358be502..39e1cdd0 100644 --- a/client/src/components/ElementEditor/AddElementPopover.js +++ b/client/src/components/ElementEditor/AddElementPopover.js @@ -25,7 +25,7 @@ class AddElementPopover extends Component { * @param {object} elementType in the shape of types/elmementTypeType * @returns {function} */ - getElementButtonClickHandler(elementType) { + getGraphQLElementButtonClickHandler(elementType) { return (event) => { const { actions: { handleAddElementToArea }, @@ -50,7 +50,7 @@ class AddElementPopover extends Component { * - then call read blocks from area endpoint (areaID) * - also then update the preview via jquery/entwine */ - handleButtonOnClick(elementType) { + getElementButtonClickHandler(elementType) { // todo } @@ -79,13 +79,14 @@ class AddElementPopover extends Component { ); const globalUseGraphQL = true; - const buttonOnClickHandler = globalUseGraphQL ? this.getElementButtonClickHandler : this.handleButtonOnClick; const buttons = elementTypes.map((elementType) => ({ content: elementType.title, key: elementType.name, className: classNames(elementType.icon, 'btn--icon-xl', 'element-editor-add-element__button'), - onClick: buttonOnClickHandler(elementType), + onClick: globalUseGraphQL + ? this.getGraphQLElementButtonClickHandler(elementType) + : this.getElementButtonClickHandler(elementType), })); return ( diff --git a/client/src/components/ElementEditor/ElementEditor.js b/client/src/components/ElementEditor/ElementEditor.js index 7cd00aa2..f9c9284f 100644 --- a/client/src/components/ElementEditor/ElementEditor.js +++ b/client/src/components/ElementEditor/ElementEditor.js @@ -67,7 +67,8 @@ class ElementEditor extends PureComponent { } else { // # rpc // make a call to a sort endpoint with (ID, afterBlocKID) - // after that is done, get ElementList to refetch the list of blocks + // after sort there is NOT a call to readAll elements, GraphQL will only do a fairly pointless + // call to read the element that was moved // (strange code for sorting is in this component and not ElementList, however do not refator it) // update the preview via jquery/entwine (see graphql code above) } From 7643e54f0d42b0ef05594ccf1becf20fb2a9c938 Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Mon, 1 Jan 2024 13:30:32 +1300 Subject: [PATCH 06/12] . --- client/dist/js/bundle.js | 42 +++++++++---- .../ElementEditor/AddElementPopover.js | 22 ++++++- src/Controllers/ElementalAreaController.php | 61 +++++++++++++++++++ 3 files changed, 110 insertions(+), 15 deletions(-) diff --git a/client/dist/js/bundle.js b/client/dist/js/bundle.js index 44fd5d6a..14770334 100644 --- a/client/dist/js/bundle.js +++ b/client/dist/js/bundle.js @@ -539,7 +539,7 @@ var _i18n = __webpack_require__(2); var _i18n2 = _interopRequireDefault(_i18n); -var _Backend = __webpack_require__(13); +var _Backend = __webpack_require__(12); var _Backend2 = _interopRequireDefault(_Backend); @@ -708,7 +708,7 @@ var _AbstractAction = __webpack_require__("./client/src/components/ElementAction var _AbstractAction2 = _interopRequireDefault(_AbstractAction); -var _Backend = __webpack_require__(13); +var _Backend = __webpack_require__(12); var _Backend2 = _interopRequireDefault(_Backend); @@ -949,6 +949,10 @@ var _i18n = __webpack_require__(2); var _i18n2 = _interopRequireDefault(_i18n); +var _Backend = __webpack_require__(12); + +var _Backend2 = _interopRequireDefault(_Backend); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } @@ -981,7 +985,6 @@ var AddElementPopover = function (_Component) { event.preventDefault(); - handleAddElementToArea(elementType.class, insertAfterElement).then(function () { var preview = window.jQuery('.cms-preview'); preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); @@ -991,7 +994,22 @@ var AddElementPopover = function (_Component) { } }, { key: 'getElementButtonClickHandler', - value: function getElementButtonClickHandler(elementType) {} + value: function getElementButtonClickHandler(elementType) { + var _this3 = this; + + return function (event) { + event.preventDefault(); + _Backend2.default.post('/admin/elemental-area/add/', { + elementClass: elementType.class, + elementalAreaID: _this3.props.areaId, + insertAfterElementID: _this3.props.insertAfterElement + }).then(function () {}).then(function () { + var preview = window.jQuery('.cms-preview'); + preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); + }); + _this3.handleToggle(); + }; + } }, { key: 'handleToggle', value: function handleToggle() { @@ -1003,7 +1021,7 @@ var AddElementPopover = function (_Component) { }, { key: 'render', value: function render() { - var _this3 = this; + var _this4 = this; var _props2 = this.props, PopoverOptionSetComponent = _props2.PopoverOptionSetComponent, @@ -1017,14 +1035,14 @@ var AddElementPopover = function (_Component) { var popoverClassNames = (0, _classnames2.default)('element-editor-add-element', extraClass); - var globalUseGraphQL = true; + var globalUseGraphQL = false; var buttons = elementTypes.map(function (elementType) { return { content: elementType.title, key: elementType.name, className: (0, _classnames2.default)(elementType.icon, 'btn--icon-xl', 'element-editor-add-element__button'), - onClick: globalUseGraphQL ? _this3.getGraphQLElementButtonClickHandler(elementType) : _this3.getElementButtonClickHandler(elementType) + onClick: globalUseGraphQL ? _this4.getGraphQLElementButtonClickHandler(elementType) : _this4.getElementButtonClickHandler(elementType) }; }); @@ -3912,7 +3930,7 @@ Object.defineProperty(exports, "__esModule", { }); exports.getElementTypeConfig = exports.getConfig = undefined; -var _Config = __webpack_require__(12); +var _Config = __webpack_require__(13); var _Config2 = _interopRequireDefault(_Config); @@ -3951,7 +3969,7 @@ Object.defineProperty(exports, "__esModule", { }); exports.loadElementFormStateName = undefined; -var _Config = __webpack_require__(12); +var _Config = __webpack_require__(13); var _Config2 = _interopRequireDefault(_Config); @@ -3983,7 +4001,7 @@ Object.defineProperty(exports, "__esModule", { }); exports.loadElementSchemaValue = undefined; -var _Config = __webpack_require__(12); +var _Config = __webpack_require__(13); var _Config2 = _interopRequireDefault(_Config); @@ -4561,14 +4579,14 @@ module.exports = ReduxForm; /***/ 12: /***/ (function(module, exports) { -module.exports = Config; +module.exports = Backend; /***/ }), /***/ 13: /***/ (function(module, exports) { -module.exports = Backend; +module.exports = Config; /***/ }), diff --git a/client/src/components/ElementEditor/AddElementPopover.js b/client/src/components/ElementEditor/AddElementPopover.js index 39e1cdd0..72121353 100644 --- a/client/src/components/ElementEditor/AddElementPopover.js +++ b/client/src/components/ElementEditor/AddElementPopover.js @@ -6,6 +6,7 @@ import classNames from 'classnames'; import { inject } from 'lib/Injector'; import { elementTypeType } from 'types/elementTypeType'; import i18n from 'i18n'; +import backend from 'lib/Backend'; /** * The AddElementPopover component used in the context of an ElementEditor shows the @@ -27,13 +28,13 @@ class AddElementPopover extends Component { */ getGraphQLElementButtonClickHandler(elementType) { return (event) => { + // handleAddElementToArea comes from addElementMutation.js const { actions: { handleAddElementToArea }, insertAfterElement } = this.props; event.preventDefault(); - // TODO This should probably use the GraphQL element type name (element.__typeName) handleAddElementToArea(elementType.class, insertAfterElement).then( () => { const preview = window.jQuery('.cms-preview'); @@ -51,7 +52,22 @@ class AddElementPopover extends Component { * - also then update the preview via jquery/entwine */ getElementButtonClickHandler(elementType) { - // todo + return (event) => { + event.preventDefault(); + backend.post(`/admin/elemental-area/add/`,{ + elementClass: elementType.class, + elementalAreaID: this.props.areaId, + insertAfterElementID: this.props.insertAfterElement, + }) + .then(() => { + // todo call read blocks from area endpoint (areaID) + }) + .then(() => { + const preview = window.jQuery('.cms-preview'); + preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); + }); + this.handleToggle(); + }; } /** @@ -78,7 +94,7 @@ class AddElementPopover extends Component { extraClass ); - const globalUseGraphQL = true; + const globalUseGraphQL = false; const buttons = elementTypes.map((elementType) => ({ content: elementType.title, diff --git a/src/Controllers/ElementalAreaController.php b/src/Controllers/ElementalAreaController.php index 283b6b89..1e350970 100644 --- a/src/Controllers/ElementalAreaController.php +++ b/src/Controllers/ElementalAreaController.php @@ -15,6 +15,10 @@ use SilverStripe\Core\Injector\Injector; use SilverStripe\Forms\Form; use SilverStripe\Security\SecurityToken; +use InvalidArgumentException; +use DNADesign\Elemental\Models\ElementalArea; +use SilverStripe\GraphQL\QueryHandler\UserContextProvider; +use DNADesign\Elemental\Services\ReorderElements; /** * Controller for "ElementalArea" - handles loading and saving of in-line edit forms in an elemental area in admin @@ -31,6 +35,8 @@ class ElementalAreaController extends CMSMain // API access points with structured data 'POST api/saveForm/$ID' => 'apiSaveForm', '$FormName/field/$FieldName' => 'formAction', + // + 'POST add' => 'add', ]; private static $allowed_actions = [ @@ -38,8 +44,63 @@ class ElementalAreaController extends CMSMain 'schema', 'apiSaveForm', 'formAction', + //a + 'add', ]; + // === + + // Resolver.php resolveAddElementToArea() + public function add() + { + $request = $this->getRequest(); + $postVars = json_decode($request->getBody(), true); + $elementClass = $postVars['elementClass']; + $elementalAreaID = $postVars['elementalAreaID']; + $afterElementID = $postVars['afterElementID'] ?? null; + + // validate post vars + if (!is_subclass_of($elementClass, BaseElement::class)) { + throw new InvalidArgumentException("$elementClass is not a subclass of " . BaseElement::class); + } + $elementalArea = ElementalArea::get()->byID($elementalAreaID); + if (!$elementalArea) { + throw new InvalidArgumentException("Invalid ElementalAreaID: $elementalAreaID"); + } + + // permission checks + if (!$elementalArea->canEdit()) { + throw new InvalidArgumentException("The current user has insufficient permission to edit ElementalAreas"); + } + /** @var BaseElement $newElement */ + $newElement = Injector::inst()->create($elementClass); + if (!$newElement->canEdit()) { + throw new InvalidArgumentException( + 'The current user has insufficient permission to edit Elements' + ); + } + + // Assign the parent ID directly rather than via HasManyList to prevent multiple writes. + // See BaseElement::$has_one for the "Parent" naming. + $newElement->ParentID = $elementalArea->ID; + // Ensure that a sort order is assigned - see BaseElement::onBeforeWrite() + $newElement->onBeforeWrite(); + + if ($afterElementID !== null) { + /** @var ReorderElements $reorderer */ + $reorderer = Injector::inst()->create(ReorderElements::class, $newElement); + $reorderer->reorder($afterElementID); // also writes the element + } else { + $newElement->write(); + } + + $response = $this->getResponse(); + $response->setStatusCode(201); + // return $newElement; + } + + // === + public function getClientConfig() { $clientConfig = parent::getClientConfig(); From ddf3ceffe7b48c60c1e1668c38b2d8393e411289 Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Mon, 1 Jan 2024 14:18:13 +1300 Subject: [PATCH 07/12] . --- client/dist/js/bundle.js | 17 ++++++ .../ElementEditor/AddElementPopover.js | 2 +- .../components/ElementEditor/ElementEditor.js | 16 ++++++ src/Controllers/ElementalAreaController.php | 55 ++++++++++++++++++- 4 files changed, 88 insertions(+), 2 deletions(-) diff --git a/client/dist/js/bundle.js b/client/dist/js/bundle.js index 14770334..1fb4dccd 100644 --- a/client/dist/js/bundle.js +++ b/client/dist/js/bundle.js @@ -2114,6 +2114,10 @@ var _withDragDropContext = __webpack_require__(21); var _withDragDropContext2 = _interopRequireDefault(_withDragDropContext); +var _Backend = __webpack_require__(12); + +var _Backend2 = _interopRequireDefault(_Backend); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } @@ -2176,6 +2180,13 @@ var ElementEditor = function (_PureComponent) { dragSpot: null }); } + }, { + key: 'fetchBlocks', + value: function fetchBlocks() { + _Backend2.default.get('/admin/elemental-area/readBlocks/' + this.props.areaId).then(function (response) { + console.log('readBlocks', response); + }); + } }, { key: 'render', value: function render() { @@ -2193,6 +2204,12 @@ var ElementEditor = function (_PureComponent) { dragTargetElementId = _state.dragTargetElementId, dragSpot = _state.dragSpot; + + var globalUseGraphqQL = true; + if (globalUseGraphqQL) { + this.fetchBlocks(); + } + var allowedElementTypes = allowedElements.map(function (className) { return elementTypes.find(function (type) { return type.class === className; diff --git a/client/src/components/ElementEditor/AddElementPopover.js b/client/src/components/ElementEditor/AddElementPopover.js index 72121353..a3bbf0c5 100644 --- a/client/src/components/ElementEditor/AddElementPopover.js +++ b/client/src/components/ElementEditor/AddElementPopover.js @@ -54,7 +54,7 @@ class AddElementPopover extends Component { getElementButtonClickHandler(elementType) { return (event) => { event.preventDefault(); - backend.post(`/admin/elemental-area/add/`,{ + backend.post(`/admin/elemental-area/add/`, { elementClass: elementType.class, elementalAreaID: this.props.areaId, insertAfterElementID: this.props.insertAfterElement, diff --git a/client/src/components/ElementEditor/ElementEditor.js b/client/src/components/ElementEditor/ElementEditor.js index f9c9284f..fc944ca3 100644 --- a/client/src/components/ElementEditor/ElementEditor.js +++ b/client/src/components/ElementEditor/ElementEditor.js @@ -10,6 +10,7 @@ import { DropTarget } from 'react-dnd'; import sortBlockMutation from 'state/editor/sortBlockMutation'; import ElementDragPreview from 'components/ElementEditor/ElementDragPreview'; import withDragDropContext from 'lib/withDragDropContext'; +import backend from 'lib/Backend'; /** * The ElementEditor is used in the CMS to manage a list or nested lists of @@ -79,6 +80,16 @@ class ElementEditor extends PureComponent { }); } + fetchBlocks() { + // # rpc + // todo + // make a call to readAll elements endpoint (areaID) + backend.get(`/admin/elemental-area/readBlocks/${this.props.areaId}`) + .then((response) => { + console.log('readBlocks', response); + }); + } + render() { const { fieldName, @@ -93,6 +104,11 @@ class ElementEditor extends PureComponent { } = this.props; const { dragTargetElementId, dragSpot } = this.state; + const globalUseGraphqQL = true; + if (globalUseGraphqQL) { + this.fetchBlocks(); + } + // Map the allowed elements because we want to retain the sort order provided by that array. const allowedElementTypes = allowedElements.map(className => elementTypes.find(type => type.class === className) diff --git a/src/Controllers/ElementalAreaController.php b/src/Controllers/ElementalAreaController.php index 1e350970..2d771c4a 100644 --- a/src/Controllers/ElementalAreaController.php +++ b/src/Controllers/ElementalAreaController.php @@ -17,8 +17,8 @@ use SilverStripe\Security\SecurityToken; use InvalidArgumentException; use DNADesign\Elemental\Models\ElementalArea; -use SilverStripe\GraphQL\QueryHandler\UserContextProvider; use DNADesign\Elemental\Services\ReorderElements; +use SilverStripe\Control\Controller; /** * Controller for "ElementalArea" - handles loading and saving of in-line edit forms in an elemental area in admin @@ -36,6 +36,7 @@ class ElementalAreaController extends CMSMain 'POST api/saveForm/$ID' => 'apiSaveForm', '$FormName/field/$FieldName' => 'formAction', // + 'GET readBlocks/$elementalAreaID!' => 'readBlocks', 'POST add' => 'add', ]; @@ -45,11 +46,63 @@ class ElementalAreaController extends CMSMain 'apiSaveForm', 'formAction', //a + 'readBlocks', 'add', ]; // === + public function readBlocks() + { + $request = $this->getRequest(); + $elementalAreaID = $request->param('elementalAreaID'); + + // validate post vars + $elementalArea = ElementalArea::get()->byID($elementalAreaID); + if (!$elementalArea) { + throw new InvalidArgumentException("Invalid ElementalAreaID: $elementalAreaID"); + } + // permission checks + if (!$elementalArea->canView()) { + throw new InvalidArgumentException("The current user has insufficient permission to view ElementalArea"); + } + $json = []; + foreach ($elementalArea->Elements() as $element) { + if (!$element->canView()) { + continue; + } + $typeName = str_replace('//', '_', get_class($element)); // todo obsolete class name + // should probably be able to just red rid of this + $blockSchema = [ + 'typeName' => $typeName, + 'actions' => [ + 'edit' => Controller::join_links(BASE_URL, "/admin/pages/edit/show/4") // todo pageID + ], + 'content' => '', + ]; + $json[] = [ + 'id' => $element->ID, + 'title' => $element->Title, + 'type' => $element->Type, + 'blockSchema' => $blockSchema, + 'obsoleteClassName' => null, // todo + 'version' => 1, // todo + 'isPublished' => false, // todo + 'isLiveVersion' => false, // todo + // 'canEdit' => $element->canEdit(), // not in graphql response + 'canDelete' => $element->canDelete(), + 'canPublish' => $element->canPublish(), + 'canUnpublish' => $element->canUnpublish(), + 'canCreate' => $element->canCreate(), + ]; + } + $response = $this->getResponse(); + $response->setStatusCode(200); + $response->addHeader('Content-Type', 'application/json'); + $response->setBody(json_encode($json)); + return $response; + } + // Resolver.php resolveAddElementToArea() public function add() { From b55ae34fad9d75992abca4b3444e4f8b1e2f40fe Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Mon, 1 Jan 2024 16:06:01 +1300 Subject: [PATCH 08/12] . --- client/dist/js/bundle.js | 148 ++++++++++-------- client/src/boot/registerTransforms.js | 25 +-- .../ElementEditor/AddElementPopover.js | 5 + .../components/ElementEditor/ElementEditor.js | 82 ++++++---- .../components/ElementEditor/ElementList.js | 57 +++---- src/Controllers/ElementalAreaController.php | 13 +- 6 files changed, 190 insertions(+), 140 deletions(-) diff --git a/client/dist/js/bundle.js b/client/dist/js/bundle.js index 1fb4dccd..9c31b470 100644 --- a/client/dist/js/bundle.js +++ b/client/dist/js/bundle.js @@ -255,9 +255,12 @@ exports.default = function () { updater.component('HistoryViewerToolbar.VersionedAdmin.HistoryViewer.Element.HistoryViewerVersionDetail', _revertToBlockVersionMutation2.default, 'BlockRevertMutation'); }); - _Injector2.default.transform('cms-element-editor', function (updater) { - updater.component('ElementList', _readBlocksForAreaQuery2.default, 'PageElements'); - }); + var globalUseGraphqQL = false; + if (globalUseGraphqQL) { + _Injector2.default.transform('cms-element-editor', function (updater) { + updater.component('ElementList', _readBlocksForAreaQuery2.default, 'PageElements'); + }); + } _Injector2.default.transform('cms-element-adder', function (updater) { updater.component('AddElementPopover', _addElementMutation2.default, 'ElementAddButton'); @@ -953,6 +956,8 @@ var _Backend = __webpack_require__(12); var _Backend2 = _interopRequireDefault(_Backend); +var _ElementEditor = __webpack_require__("./client/src/components/ElementEditor/ElementEditor.js"); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } @@ -970,6 +975,7 @@ var AddElementPopover = function (_Component) { var _this = _possibleConstructorReturn(this, (AddElementPopover.__proto__ || Object.getPrototypeOf(AddElementPopover)).call(this, props)); _this.handleToggle = _this.handleToggle.bind(_this); + AddElementPopover.contextType = _ElementEditor.ElementEditorContext; return _this; } @@ -1003,7 +1009,11 @@ var AddElementPopover = function (_Component) { elementClass: elementType.class, elementalAreaID: _this3.props.areaId, insertAfterElementID: _this3.props.insertAfterElement - }).then(function () {}).then(function () { + }).then(function () { + var fetchBlocks = _this3.context.fetchBlocks; + + fetchBlocks(); + }).then(function () { var preview = window.jQuery('.cms-preview'); preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); }); @@ -2076,7 +2086,7 @@ exports.default = (0, _reactDnd.DragLayer)(function (monitor) { Object.defineProperty(exports, "__esModule", { value: true }); -exports.Component = undefined; +exports.Component = exports.ElementEditorContext = undefined; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; @@ -2128,6 +2138,8 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +var ElementEditorContext = exports.ElementEditorContext = (0, _react.createContext)(null); + var ElementEditor = function (_PureComponent) { _inherits(ElementEditor, _PureComponent); @@ -2138,11 +2150,14 @@ var ElementEditor = function (_PureComponent) { _this.state = { dragTargetElementId: null, - dragSpot: null + dragSpot: null, + contentBlocks: null, + isLoading: false }; _this.handleDragOver = _this.handleDragOver.bind(_this); _this.handleDragEnd = _this.handleDragEnd.bind(_this); + _this.fetchBlocks = _this.fetchBlocks.bind(_this); return _this; } @@ -2183,8 +2198,18 @@ var ElementEditor = function (_PureComponent) { }, { key: 'fetchBlocks', value: function fetchBlocks() { + var _this2 = this; + + this.setState(_extends({}, this.state, { + isLoading: true + })); _Backend2.default.get('/admin/elemental-area/readBlocks/' + this.props.areaId).then(function (response) { - console.log('readBlocks', response); + return response.json(); + }).then(function (responseJson) { + _this2.setState(_extends({}, _this2.state, { + contentBlocks: responseJson, + isLoading: false + })); }); } }, { @@ -2202,11 +2227,12 @@ var ElementEditor = function (_PureComponent) { allowedElements = _props2.allowedElements; var _state = this.state, dragTargetElementId = _state.dragTargetElementId, - dragSpot = _state.dragSpot; + dragSpot = _state.dragSpot, + contentBlocks = _state.contentBlocks; - var globalUseGraphqQL = true; - if (globalUseGraphqQL) { + var globalUseGraphqQL = false; + if (!globalUseGraphqQL && contentBlocks === null) { this.fetchBlocks(); } @@ -2219,29 +2245,34 @@ var ElementEditor = function (_PureComponent) { return connectDropTarget(_react2.default.createElement( 'div', { className: 'element-editor' }, - _react2.default.createElement(ToolbarComponent, { - elementTypes: allowedElementTypes, - areaId: areaId, - onDragOver: this.handleDragOver - }), - _react2.default.createElement(ListComponent, { - allowedElementTypes: allowedElementTypes, - elementTypes: elementTypes, - areaId: areaId, - onDragOver: this.handleDragOver, - onDragStart: this.handleDragStart, - onDragEnd: this.handleDragEnd, - dragSpot: dragSpot, - isDraggingOver: isDraggingOver, - dragTargetElementId: dragTargetElementId - }), - _react2.default.createElement(_ElementDragPreview2.default, { elementTypes: elementTypes }), - _react2.default.createElement('input', { - name: fieldName, - type: 'hidden', - value: JSON.stringify(formState) || '', - className: 'no-change-track' - }) + _react2.default.createElement( + ElementEditorContext.Provider, + { value: { fetchBlocks: this.fetchBlocks } }, + _react2.default.createElement(ToolbarComponent, { + elementTypes: allowedElementTypes, + areaId: areaId, + onDragOver: this.handleDragOver + }), + _react2.default.createElement(ListComponent, { + allowedElementTypes: allowedElementTypes, + elementTypes: elementTypes, + areaId: areaId, + onDragOver: this.handleDragOver, + onDragStart: this.handleDragStart, + onDragEnd: this.handleDragEnd, + dragSpot: dragSpot, + isDraggingOver: isDraggingOver, + dragTargetElementId: dragTargetElementId, + contentBlocks: contentBlocks + }), + _react2.default.createElement(_ElementDragPreview2.default, { elementTypes: elementTypes }), + _react2.default.createElement('input', { + name: fieldName, + type: 'hidden', + value: JSON.stringify(formState) || '', + className: 'no-change-track' + }) + ) )); } }]); @@ -2351,33 +2382,22 @@ var ElementList = function (_Component) { function ElementList(props) { _classCallCheck(this, ElementList); - var _this = _possibleConstructorReturn(this, (ElementList.__proto__ || Object.getPrototypeOf(ElementList)).call(this, props)); - - _this.state = { - isLoading: true, - contentBlocks: [] - }; - return _this; + return _possibleConstructorReturn(this, (ElementList.__proto__ || Object.getPrototypeOf(ElementList)).call(this, props)); } _createClass(ElementList, [{ - key: 'fetchContentBlocks', - value: function fetchContentBlocks() { - var globalUseGraphQL = true; - if (globalUseGraphQL) { - return; - } - } - }, { key: 'getDragIndicatorIndex', value: function getDragIndicatorIndex() { var _props = this.props, dragTargetElementId = _props.dragTargetElementId, draggedItem = _props.draggedItem, blocks = _props.blocks, + contentBlocks = _props.contentBlocks, dragSpot = _props.dragSpot; - return (0, _dragHelpers.getDragIndicatorIndex)(blocks.map(function (element) { + var globalUseGraphQL = false; + var elements = globalUseGraphQL ? blocks : contentBlocks; + return (0, _dragHelpers.getDragIndicatorIndex)(elements.map(function (element) { return element.id; }), dragTargetElementId, draggedItem && draggedItem.id, dragSpot); } @@ -2389,6 +2409,7 @@ var ElementList = function (_Component) { HoverBarComponent = _props2.HoverBarComponent, DragIndicatorComponent = _props2.DragIndicatorComponent, blocks = _props2.blocks, + contentBlocks = _props2.contentBlocks, allowedElementTypes = _props2.allowedElementTypes, elementTypes = _props2.elementTypes, areaId = _props2.areaId, @@ -2398,14 +2419,14 @@ var ElementList = function (_Component) { isDraggingOver = _props2.isDraggingOver; - var globalUseGraphQL = true; - var contentBlocks = globalUseGraphQL ? blocks : this.state.contentBlocks; + var globalUseGraphQL = false; + var elements = globalUseGraphQL ? blocks : contentBlocks; - if (!contentBlocks) { + if (!elements) { return null; } - if (contentBlocks && !contentBlocks.length) { + if (elements && !elements.length) { return _react2.default.createElement( 'div', null, @@ -2413,7 +2434,7 @@ var ElementList = function (_Component) { ); } - var output = contentBlocks.map(function (element) { + var output = elements.map(function (element) { return _react2.default.createElement( 'div', { key: element.id }, @@ -2456,12 +2477,13 @@ var ElementList = function (_Component) { value: function renderLoading() { var _props3 = this.props, loading = _props3.loading, + isLoading = _props3.isLoading, LoadingComponent = _props3.LoadingComponent; - var globalUseGraphQL = true; - var isLoading = globalUseGraphQL ? loading : this.state.isLoading; + var globalUseGraphQL = false; + var loadingValue = globalUseGraphQL ? loading : isLoading; - if (isLoading) { + if (loadingValue) { return _react2.default.createElement(LoadingComponent, null); } return null; @@ -2469,12 +2491,14 @@ var ElementList = function (_Component) { }, { key: 'render', value: function render() { - var blocks = this.props.blocks; + var _props4 = this.props, + blocks = _props4.blocks, + contentBlocks = _props4.contentBlocks; - var globalUseGraphQL = true; - var contentBlocks = globalUseGraphQL ? blocks : this.state.contentBlocks; + var globalUseGraphQL = false; + var elements = globalUseGraphQL ? blocks : contentBlocks; - var listClassNames = (0, _classnames2.default)('elemental-editor-list', { 'elemental-editor-list--empty': !contentBlocks || !contentBlocks.length }); + var listClassNames = (0, _classnames2.default)('elemental-editor-list', { 'elemental-editor-list--empty': !elements || !elements.length }); return this.props.connectDropTarget(_react2.default.createElement( 'div', @@ -2492,6 +2516,8 @@ ElementList.propTypes = { blocks: _propTypes2.default.arrayOf(_elementType.elementType), loading: _propTypes2.default.bool, + contentBlocks: _propTypes2.default.arrayOf(_elementType.elementType), + elementTypes: _propTypes2.default.arrayOf(_elementTypeType.elementTypeType).isRequired, allowedElementTypes: _propTypes2.default.arrayOf(_elementTypeType.elementTypeType).isRequired, areaId: _propTypes2.default.number.isRequired, diff --git a/client/src/boot/registerTransforms.js b/client/src/boot/registerTransforms.js index e42c9b4e..78972976 100644 --- a/client/src/boot/registerTransforms.js +++ b/client/src/boot/registerTransforms.js @@ -49,17 +49,20 @@ export default () => { } ); - Injector.transform( - 'cms-element-editor', - (updater) => { - // Add GraphQL query for reading elements on a page for the ElementEditor - updater.component( - 'ElementList', - readBlocksForAreaQuery, - 'PageElements' - ); - } - ); + const globalUseGraphqQL = false; + if (globalUseGraphqQL) { + Injector.transform( + 'cms-element-editor', + (updater) => { + // Add GraphQL query for reading elements on a page for the ElementEditor + updater.component( + 'ElementList', + readBlocksForAreaQuery, + 'PageElements' + ); + } + ); + } Injector.transform( 'cms-element-adder', diff --git a/client/src/components/ElementEditor/AddElementPopover.js b/client/src/components/ElementEditor/AddElementPopover.js index a3bbf0c5..f978a361 100644 --- a/client/src/components/ElementEditor/AddElementPopover.js +++ b/client/src/components/ElementEditor/AddElementPopover.js @@ -7,16 +7,19 @@ import { inject } from 'lib/Injector'; import { elementTypeType } from 'types/elementTypeType'; import i18n from 'i18n'; import backend from 'lib/Backend'; +import { ElementEditorContext } from 'components/ElementEditor/ElementEditor'; /** * The AddElementPopover component used in the context of an ElementEditor shows the * available elements that can be added to an ElementalArea. */ class AddElementPopover extends Component { + constructor(props) { super(props); this.handleToggle = this.handleToggle.bind(this); + AddElementPopover.contextType = ElementEditorContext; } /** @@ -61,6 +64,8 @@ class AddElementPopover extends Component { }) .then(() => { // todo call read blocks from area endpoint (areaID) + const { fetchBlocks } = this.context; + fetchBlocks(); }) .then(() => { const preview = window.jQuery('.cms-preview'); diff --git a/client/src/components/ElementEditor/ElementEditor.js b/client/src/components/ElementEditor/ElementEditor.js index fc944ca3..41a499bf 100644 --- a/client/src/components/ElementEditor/ElementEditor.js +++ b/client/src/components/ElementEditor/ElementEditor.js @@ -1,5 +1,5 @@ /* global window */ -import React, { PureComponent } from 'react'; +import React, { PureComponent, createContext } from 'react'; import PropTypes from 'prop-types'; import { inject } from 'lib/Injector'; import { compose } from 'redux'; @@ -12,6 +12,8 @@ import ElementDragPreview from 'components/ElementEditor/ElementDragPreview'; import withDragDropContext from 'lib/withDragDropContext'; import backend from 'lib/Backend'; +export const ElementEditorContext = createContext(null); + /** * The ElementEditor is used in the CMS to manage a list or nested lists of * elements for a page or other DataObject. @@ -23,10 +25,13 @@ class ElementEditor extends PureComponent { this.state = { dragTargetElementId: null, dragSpot: null, + contentBlocks: null, + isLoading: false, }; this.handleDragOver = this.handleDragOver.bind(this); this.handleDragEnd = this.handleDragEnd.bind(this); + this.fetchBlocks = this.fetchBlocks.bind(this); } /** @@ -80,13 +85,23 @@ class ElementEditor extends PureComponent { }); } + /** + * # rpc + * make a call to readAll elements endpoint (areaID) + */ fetchBlocks() { - // # rpc - // todo - // make a call to readAll elements endpoint (areaID) + this.setState({ + ...this.state, + isLoading: true + }); backend.get(`/admin/elemental-area/readBlocks/${this.props.areaId}`) - .then((response) => { - console.log('readBlocks', response); + .then(response => response.json()) + .then(responseJson => { + this.setState({ + ...this.state, + contentBlocks: responseJson, + isLoading: false, + }) }); } @@ -102,10 +117,10 @@ class ElementEditor extends PureComponent { connectDropTarget, allowedElements, } = this.props; - const { dragTargetElementId, dragSpot } = this.state; + const { dragTargetElementId, dragSpot, contentBlocks } = this.state; - const globalUseGraphqQL = true; - if (globalUseGraphqQL) { + const globalUseGraphqQL = false; + if (!globalUseGraphqQL && contentBlocks === null) { this.fetchBlocks(); } @@ -116,29 +131,32 @@ class ElementEditor extends PureComponent { return connectDropTarget(
- - - - + + + + + +
); } diff --git a/client/src/components/ElementEditor/ElementList.js b/client/src/components/ElementEditor/ElementList.js index 9e89e564..99b27260 100644 --- a/client/src/components/ElementEditor/ElementList.js +++ b/client/src/components/ElementEditor/ElementList.js @@ -13,29 +13,14 @@ import { getElementTypeConfig } from 'state/editor/elementConfig'; class ElementList extends Component { constructor(props) { super(props); - this.state = { - isLoading: true, - contentBlocks: [], - }; - } - - // #RPC - // it should make an ajax call to the server and do the equivalent of readBlocksForAreaQuery - // it should the call this.setState `contentBlocks` with the result - // this will cause a re-render of the component - // this callback should be passed to other components via context and get called after doing mutations - fetchContentBlocks() { - const globalUseGraphQL = true; - if (globalUseGraphQL) { - return; - } - // TODO: implement } getDragIndicatorIndex() { - const { dragTargetElementId, draggedItem, blocks, dragSpot } = this.props; + const { dragTargetElementId, draggedItem, blocks, contentBlocks, dragSpot } = this.props; + const globalUseGraphQL = false; + const elements = globalUseGraphQL ? blocks : contentBlocks; return getDragIndicatorIndex( - blocks.map(element => element.id), + elements.map(element => element.id), dragTargetElementId, draggedItem && draggedItem.id, dragSpot @@ -53,6 +38,7 @@ class ElementList extends Component { HoverBarComponent, DragIndicatorComponent, blocks, // graphql - comes from readBlocksForAreaQuery + contentBlocks, // rpc, passed in as prop from ElementEditor allowedElementTypes, elementTypes, areaId, @@ -62,19 +48,19 @@ class ElementList extends Component { isDraggingOver, } = this.props; - const globalUseGraphQL = true; - const contentBlocks = globalUseGraphQL ? blocks : this.state.contentBlocks; + const globalUseGraphQL = false; + const elements = globalUseGraphQL ? blocks : contentBlocks; // Blocks can be either null or an empty array - if (!contentBlocks) { + if (!elements) { return null; } - if (contentBlocks && !contentBlocks.length) { + if (elements && !elements.length) { return
{i18n._t('ElementList.ADD_BLOCKS', 'Add blocks to place your content')}
; } - let output = contentBlocks.map((element) => ( + let output = elements.map((element) => (
; } return null; } render() { - const { blocks } = this.props; - const globalUseGraphQL = true; - const contentBlocks = globalUseGraphQL ? blocks : this.state.contentBlocks; + const { blocks, contentBlocks } = this.props; + const globalUseGraphQL = false; + const elements = globalUseGraphQL ? blocks : contentBlocks; const listClassNames = classNames( 'elemental-editor-list', - { 'elemental-editor-list--empty': !contentBlocks || !contentBlocks.length } + { 'elemental-editor-list--empty': !elements || !elements.length } ); return this.props.connectDropTarget( @@ -150,9 +140,12 @@ class ElementList extends Component { } ElementList.propTypes = { + // graphql // blocks and loading come from readBlocksForAreaQuery blocks: PropTypes.arrayOf(elementType), loading: PropTypes.bool, + // rpc + contentBlocks: PropTypes.arrayOf(elementType), // elementTypes: PropTypes.arrayOf(elementTypeType).isRequired, allowedElementTypes: PropTypes.arrayOf(elementTypeType).isRequired, diff --git a/src/Controllers/ElementalAreaController.php b/src/Controllers/ElementalAreaController.php index 2d771c4a..2a15c55e 100644 --- a/src/Controllers/ElementalAreaController.php +++ b/src/Controllers/ElementalAreaController.php @@ -19,6 +19,7 @@ use DNADesign\Elemental\Models\ElementalArea; use DNADesign\Elemental\Services\ReorderElements; use SilverStripe\Control\Controller; +use SilverStripe\Control\Director; /** * Controller for "ElementalArea" - handles loading and saving of in-line edit forms in an elemental area in admin @@ -71,19 +72,22 @@ public function readBlocks() if (!$element->canView()) { continue; } - $typeName = str_replace('//', '_', get_class($element)); // todo obsolete class name + $typeName = str_replace('\\', '_', get_class($element)); // todo obsolete class name // should probably be able to just red rid of this $blockSchema = [ 'typeName' => $typeName, 'actions' => [ - 'edit' => Controller::join_links(BASE_URL, "/admin/pages/edit/show/4") // todo pageID + 'edit' => Controller::join_links( + Director::absoluteBaseURL(), + "/admin/pages/edit/show/4" // todo pageID + ) ], 'content' => '', ]; $json[] = [ - 'id' => $element->ID, + 'id' => (string) $element->ID, 'title' => $element->Title, - 'type' => $element->Type, + '__typename' => 'Block', // todo 'blockSchema' => $blockSchema, 'obsoleteClassName' => null, // todo 'version' => 1, // todo @@ -96,6 +100,7 @@ public function readBlocks() 'canCreate' => $element->canCreate(), ]; } + // $json['__typename'] = 'ElementalArea'; // this should get removed $response = $this->getResponse(); $response->setStatusCode(200); $response->addHeader('Content-Type', 'application/json'); From 91db11b4d08a936a8e7a8dc573813d64525dfd6e Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Mon, 1 Jan 2024 19:30:37 +1300 Subject: [PATCH 09/12] . --- client/dist/js/bundle.js | 64 +++++++++++++------ .../components/ElementEditor/ElementEditor.js | 50 +++++++++++---- .../components/ElementEditor/ElementList.js | 9 ++- src/Controllers/ElementalAreaController.php | 42 +++++++++--- 4 files changed, 121 insertions(+), 44 deletions(-) diff --git a/client/dist/js/bundle.js b/client/dist/js/bundle.js index 9c31b470..928c6fbb 100644 --- a/client/dist/js/bundle.js +++ b/client/dist/js/bundle.js @@ -2152,7 +2152,7 @@ var ElementEditor = function (_PureComponent) { dragTargetElementId: null, dragSpot: null, contentBlocks: null, - isLoading: false + isLoading: true }; _this.handleDragOver = _this.handleDragOver.bind(_this); @@ -2177,18 +2177,26 @@ var ElementEditor = function (_PureComponent) { }, { key: 'handleDragEnd', value: function handleDragEnd(sourceId, afterId) { - var _props = this.props, - handleSortBlock = _props.actions.handleSortBlock, - areaId = _props.areaId; - - - var globalUseGraphQL = true; + var globalUseGraphQL = false; if (globalUseGraphQL) { + var _props = this.props, + handleSortBlock = _props.actions.handleSortBlock, + areaId = _props.areaId; + handleSortBlock(sourceId, afterId, areaId).then(function () { var preview = window.jQuery('.cms-preview'); preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); }); - } else {} + } else { + _Backend2.default.post('/admin/elemental-area/sort', { + ID: sourceId, + afterBlockID: afterId + }).then(function (response) { + return response.json(); + }).then(function (responseJson) { + console.log(responseJson); + }); + } this.setState({ dragTargetElementId: null, @@ -2200,9 +2208,13 @@ var ElementEditor = function (_PureComponent) { value: function fetchBlocks() { var _this2 = this; - this.setState(_extends({}, this.state, { - isLoading: true - })); + var doSetLoadingState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + + if (doSetLoadingState) { + this.setState(_extends({}, this.state, { + isLoading: true + })); + } _Backend2.default.get('/admin/elemental-area/readBlocks/' + this.props.areaId).then(function (response) { return response.json(); }).then(function (responseJson) { @@ -2224,7 +2236,8 @@ var ElementEditor = function (_PureComponent) { elementTypes = _props2.elementTypes, isDraggingOver = _props2.isDraggingOver, connectDropTarget = _props2.connectDropTarget, - allowedElements = _props2.allowedElements; + allowedElements = _props2.allowedElements, + isLoading = _props2.isLoading; var _state = this.state, dragTargetElementId = _state.dragTargetElementId, dragSpot = _state.dragSpot, @@ -2233,7 +2246,7 @@ var ElementEditor = function (_PureComponent) { var globalUseGraphqQL = false; if (!globalUseGraphqQL && contentBlocks === null) { - this.fetchBlocks(); + this.fetchBlocks(false); } var allowedElementTypes = allowedElements.map(function (className) { @@ -2263,7 +2276,8 @@ var ElementEditor = function (_PureComponent) { dragSpot: dragSpot, isDraggingOver: isDraggingOver, dragTargetElementId: dragTargetElementId, - contentBlocks: contentBlocks + contentBlocks: contentBlocks, + isLoading: isLoading }), _react2.default.createElement(_ElementDragPreview2.default, { elementTypes: elementTypes }), _react2.default.createElement('input', { @@ -2308,7 +2322,9 @@ function mapStateToProps(state) { } exports.Component = ElementEditor; -exports.default = (0, _redux.compose)(_withDragDropContext2.default, (0, _reactDnd.DropTarget)('element', {}, function (connector, monitor) { + + +var params = [_withDragDropContext2.default, (0, _reactDnd.DropTarget)('element', {}, function (connector, monitor) { return { connectDropTarget: connector.dropTarget(), isDraggingOver: monitor.isOver() }; @@ -2319,7 +2335,13 @@ exports.default = (0, _redux.compose)(_withDragDropContext2.default, (0, _reactD }; }, function () { return 'ElementEditor'; -}), _sortBlockMutation2.default)(ElementEditor); +})]; +var globalUseGraphQL = false; +if (globalUseGraphQL) { + params.push(_sortBlockMutation2.default); +} + +exports.default = _redux.compose.apply(undefined, params)(ElementEditor); /***/ }), @@ -2537,7 +2559,11 @@ exports.Component = ElementList; var elementListTarget = { drop: function drop(props, monitor) { - var blocks = props.blocks; + var blocks = props.blocks, + contentBlocks = props.contentBlocks; + + var globalUseGraphQL = false; + var elements = globalUseGraphQL ? blocks : contentBlocks; var elementTargetDropResult = monitor.getDropResult(); @@ -2545,10 +2571,10 @@ var elementListTarget = { return {}; } - var dropIndex = (0, _dragHelpers.getDragIndicatorIndex)(blocks.map(function (element) { + var dropIndex = (0, _dragHelpers.getDragIndicatorIndex)(elements.map(function (element) { return element.id; }), elementTargetDropResult.target, monitor.getItem(), elementTargetDropResult.dropSpot); - var dropAfterID = blocks[dropIndex - 1] ? blocks[dropIndex - 1].id : '0'; + var dropAfterID = elements[dropIndex - 1] ? elements[dropIndex - 1].id : '0'; return _extends({}, elementTargetDropResult, { dropAfterID: dropAfterID diff --git a/client/src/components/ElementEditor/ElementEditor.js b/client/src/components/ElementEditor/ElementEditor.js index 41a499bf..817f4235 100644 --- a/client/src/components/ElementEditor/ElementEditor.js +++ b/client/src/components/ElementEditor/ElementEditor.js @@ -26,7 +26,7 @@ class ElementEditor extends PureComponent { dragTargetElementId: null, dragSpot: null, contentBlocks: null, - isLoading: false, + isLoading: true, }; this.handleDragOver = this.handleDragOver.bind(this); @@ -61,11 +61,10 @@ class ElementEditor extends PureComponent { * @param afterId */ handleDragEnd(sourceId, afterId) { - const { actions: { handleSortBlock }, areaId } = this.props; - - const globalUseGraphQL = true; + const globalUseGraphQL = false; if (globalUseGraphQL) { // see sortBlockMutation.js for reference + const { actions: { handleSortBlock }, areaId } = this.props; handleSortBlock(sourceId, afterId, areaId).then(() => { const preview = window.jQuery('.cms-preview'); preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); @@ -77,6 +76,19 @@ class ElementEditor extends PureComponent { // call to read the element that was moved // (strange code for sorting is in this component and not ElementList, however do not refator it) // update the preview via jquery/entwine (see graphql code above) + backend.post(`/admin/elemental-area/sort`, { + ID: sourceId, + afterBlockID: afterId, + }) + .then(response => response.json()) + .then(responseJson => { + console.log(responseJson); + // this.setState({ + // ...this.state, + // contentBlocks: responseJson, + // isLoading: false, + // }) + }); } this.setState({ @@ -89,11 +101,13 @@ class ElementEditor extends PureComponent { * # rpc * make a call to readAll elements endpoint (areaID) */ - fetchBlocks() { - this.setState({ - ...this.state, - isLoading: true - }); + fetchBlocks(doSetLoadingState = true) { + if (doSetLoadingState) { + this.setState({ + ...this.state, + isLoading: true, + }); + } backend.get(`/admin/elemental-area/readBlocks/${this.props.areaId}`) .then(response => response.json()) .then(responseJson => { @@ -116,12 +130,13 @@ class ElementEditor extends PureComponent { isDraggingOver, connectDropTarget, allowedElements, + isLoading, } = this.props; const { dragTargetElementId, dragSpot, contentBlocks } = this.state; const globalUseGraphqQL = false; if (!globalUseGraphqQL && contentBlocks === null) { - this.fetchBlocks(); + this.fetchBlocks(false); } // Map the allowed elements because we want to retain the sort order provided by that array. @@ -148,6 +163,7 @@ class ElementEditor extends PureComponent { isDraggingOver={isDraggingOver} dragTargetElementId={dragTargetElementId} contentBlocks={contentBlocks} + isLoading={isLoading} /> ({ connectDropTarget: connector.dropTarget(), @@ -205,7 +222,12 @@ export default compose( ListComponent, }), () => 'ElementEditor' - ), - sortBlockMutation -)(ElementEditor); + ) +]; +const globalUseGraphQL = false; +if (globalUseGraphQL) { + params.push(sortBlockMutation); +} + +export default compose(...params)(ElementEditor); diff --git a/client/src/components/ElementEditor/ElementList.js b/client/src/components/ElementEditor/ElementList.js index 99b27260..5d4f03e0 100644 --- a/client/src/components/ElementEditor/ElementList.js +++ b/client/src/components/ElementEditor/ElementList.js @@ -165,7 +165,10 @@ export { ElementList as Component }; const elementListTarget = { drop(props, monitor) { - const { blocks } = props; + const { blocks, contentBlocks } = props; + const globalUseGraphQL = false; + const elements = globalUseGraphQL ? blocks : contentBlocks; + const elementTargetDropResult = monitor.getDropResult(); if (!elementTargetDropResult) { @@ -173,12 +176,12 @@ const elementListTarget = { } const dropIndex = getDragIndicatorIndex( - blocks.map(element => element.id), + elements.map(element => element.id), elementTargetDropResult.target, monitor.getItem(), elementTargetDropResult.dropSpot, ); - const dropAfterID = blocks[dropIndex - 1] ? blocks[dropIndex - 1].id : '0'; + const dropAfterID = elements[dropIndex - 1] ? elements[dropIndex - 1].id : '0'; return { ...elementTargetDropResult, diff --git a/src/Controllers/ElementalAreaController.php b/src/Controllers/ElementalAreaController.php index 2a15c55e..53cd6a10 100644 --- a/src/Controllers/ElementalAreaController.php +++ b/src/Controllers/ElementalAreaController.php @@ -39,6 +39,7 @@ class ElementalAreaController extends CMSMain // 'GET readBlocks/$elementalAreaID!' => 'readBlocks', 'POST add' => 'add', + 'POST sort' => 'sort', ]; private static $allowed_actions = [ @@ -49,10 +50,40 @@ class ElementalAreaController extends CMSMain //a 'readBlocks', 'add', + 'sort' ]; + private function jsonResponse(?array $data = null) + { + $response = $this->getResponse(); + $response->setStatusCode(200); + $response->addHeader('Content-Type', 'application/json'); + $body = $data ? json_encode($data) : ''; + $response->setBody($body); + return $response; + } + // === + public function sort() + { + $request = $this->getRequest(); + $postVars = json_decode($request->getBody(), true); + $id = $postVars['ID']; + $afterBlockID = $postVars['afterBlockID']; + $element = BaseElement::get()->byID($id); + if (!$element) { + throw new InvalidArgumentException(sprintf('%s#%s not found', BaseElement::class, $id)); + } + if (!$element->canEdit()) { + $message = 'Changing the sort order of blocks is not allowed for the current user'; + throw new InvalidArgumentException($message); + } + $reorderingService = Injector::inst()->create(ReorderElements::class, $element); + $reorderingService->reorder($afterBlockID); + return $this->jsonResponse(null); + } + public function readBlocks() { $request = $this->getRequest(); @@ -67,7 +98,7 @@ public function readBlocks() if (!$elementalArea->canView()) { throw new InvalidArgumentException("The current user has insufficient permission to view ElementalArea"); } - $json = []; + $data = []; foreach ($elementalArea->Elements() as $element) { if (!$element->canView()) { continue; @@ -84,7 +115,7 @@ public function readBlocks() ], 'content' => '', ]; - $json[] = [ + $data[] = [ 'id' => (string) $element->ID, 'title' => $element->Title, '__typename' => 'Block', // todo @@ -100,12 +131,7 @@ public function readBlocks() 'canCreate' => $element->canCreate(), ]; } - // $json['__typename'] = 'ElementalArea'; // this should get removed - $response = $this->getResponse(); - $response->setStatusCode(200); - $response->addHeader('Content-Type', 'application/json'); - $response->setBody(json_encode($json)); - return $response; + return $this->jsonResponse($data); } // Resolver.php resolveAddElementToArea() From d5c9172f8af5946537d3b62adcce3ff0ca812998 Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Mon, 1 Jan 2024 19:35:51 +1300 Subject: [PATCH 10/12] . --- client/dist/js/bundle.js | 12 ++++++------ client/src/components/ElementEditor/ElementEditor.js | 10 +--------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/client/dist/js/bundle.js b/client/dist/js/bundle.js index 928c6fbb..2fe8f5c9 100644 --- a/client/dist/js/bundle.js +++ b/client/dist/js/bundle.js @@ -2177,6 +2177,8 @@ var ElementEditor = function (_PureComponent) { }, { key: 'handleDragEnd', value: function handleDragEnd(sourceId, afterId) { + var _this2 = this; + var globalUseGraphQL = false; if (globalUseGraphQL) { var _props = this.props, @@ -2191,10 +2193,8 @@ var ElementEditor = function (_PureComponent) { _Backend2.default.post('/admin/elemental-area/sort', { ID: sourceId, afterBlockID: afterId - }).then(function (response) { - return response.json(); - }).then(function (responseJson) { - console.log(responseJson); + }).then(function () { + return _this2.fetchBlocks(); }); } @@ -2206,7 +2206,7 @@ var ElementEditor = function (_PureComponent) { }, { key: 'fetchBlocks', value: function fetchBlocks() { - var _this2 = this; + var _this3 = this; var doSetLoadingState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; @@ -2218,7 +2218,7 @@ var ElementEditor = function (_PureComponent) { _Backend2.default.get('/admin/elemental-area/readBlocks/' + this.props.areaId).then(function (response) { return response.json(); }).then(function (responseJson) { - _this2.setState(_extends({}, _this2.state, { + _this3.setState(_extends({}, _this3.state, { contentBlocks: responseJson, isLoading: false })); diff --git a/client/src/components/ElementEditor/ElementEditor.js b/client/src/components/ElementEditor/ElementEditor.js index 817f4235..7eabe07b 100644 --- a/client/src/components/ElementEditor/ElementEditor.js +++ b/client/src/components/ElementEditor/ElementEditor.js @@ -80,15 +80,7 @@ class ElementEditor extends PureComponent { ID: sourceId, afterBlockID: afterId, }) - .then(response => response.json()) - .then(responseJson => { - console.log(responseJson); - // this.setState({ - // ...this.state, - // contentBlocks: responseJson, - // isLoading: false, - // }) - }); + .then(() => this.fetchBlocks()) } this.setState({ From eb7dd8a6c43a9806564cdad0bcb0f8f9e6418c54 Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Mon, 1 Jan 2024 23:33:41 +1300 Subject: [PATCH 11/12] . --- src/Controllers/ElementalAreaController.php | 181 ++++++++++++++++---- 1 file changed, 149 insertions(+), 32 deletions(-) diff --git a/src/Controllers/ElementalAreaController.php b/src/Controllers/ElementalAreaController.php index 53cd6a10..41b1eee6 100644 --- a/src/Controllers/ElementalAreaController.php +++ b/src/Controllers/ElementalAreaController.php @@ -36,10 +36,14 @@ class ElementalAreaController extends CMSMain // API access points with structured data 'POST api/saveForm/$ID' => 'apiSaveForm', '$FormName/field/$FieldName' => 'formAction', - // - 'GET readBlocks/$elementalAreaID!' => 'readBlocks', - 'POST add' => 'add', - 'POST sort' => 'sort', + // new api + 'GET readBlocks/$elementalAreaID!' => 'apiReadBlocks', + 'POST add' => 'apiAdd', + 'POST sort' => 'apiSort', + 'POST duplicate' => 'apiDuplicate', + 'POST archive' => 'apiArchive', + 'POST publish' => 'apiPublish', + 'POST unpublish' => 'apiUnpublish', ]; private static $allowed_actions = [ @@ -47,32 +51,147 @@ class ElementalAreaController extends CMSMain 'schema', 'apiSaveForm', 'formAction', - //a - 'readBlocks', - 'add', - 'sort' + // new api + 'apiReadBlocks', + 'apiAdd', + 'apiSort', + 'apiDuplicate', + 'apiArchive', + 'apiPublish', + 'apiUnpublish', + 'revert', // ???? todo there is a revert mutation, though not sure it's actually used? ]; - private function jsonResponse(?array $data = null) + private function jsonResponse(int $statusCode = 200, ?array $data = null, string $message = ''): HTTPResponse { $response = $this->getResponse(); - $response->setStatusCode(200); + $response->setStatusCode($statusCode); $response->addHeader('Content-Type', 'application/json'); - $body = $data ? json_encode($data) : ''; + $body = ''; + if ($data) { + $body = json_encode($data); + } elseif ($message) { + $body = json_encode(['message' => $message]); + } $response->setBody($body); return $response; } // === - public function sort() + private function getPostData() { $request = $this->getRequest(); - $postVars = json_decode($request->getBody(), true); - $id = $postVars['ID']; - $afterBlockID = $postVars['afterBlockID']; + $postData = json_decode($request->getBody(), true); + return $postData; + } + + public function apiArchive(): HTTPResponse + { + $id = $this->getPostData()['ID'] ?? ''; + $element = BaseElement::get()->byID($id); + if (!$element) { + return $this->jsonResponse(400, null, "Element with ID $id does not exist"); + } + if (!$element->canDelete()) { + return $this->jsonResponse(403, null, "Unable to delete element with ID $id"); + } + $element->doArchive(); + return $this->jsonResponse(204); + } + + public function apiPublish(): HTTPResponse + { + $id = $this->getPostData()['ID'] ?? ''; + $element = BaseElement::get()->byID($id); + if (!$element) { + return $this->jsonResponse(400, null, "Element with ID $id does not exist"); + } + if (!$element->canPublish()) { + return $this->jsonResponse(403, null, "Unable to publish element with ID $id"); + } + $element->publishRecursive(); + return $this->jsonResponse(204); + } + + public function apiUnpublish(): HTTPResponse + { + $id = $this->getPostData()['ID'] ?? ''; + $element = BaseElement::get()->byID($id); + if (!$element) { + return $this->jsonResponse(400, null, "Element with ID $id does not exist"); + } + if (!$element->canUnpublish()) { + return $this->jsonResponse(403, null, "Unable to publish element with ID $id"); + } + $element->doUnpublish(); + return $this->jsonResponse(204); + } + + // Resolver.php resolveDuplicateBlock() + public function apiDuplicate(): HTTPResponse + { + $id = $this->getPostData()['ID'] ?? ''; + $element = BaseElement::get()->byID($id); + if (!$element) { + return $this->jsonResponse(400, null, "Element with ID $id does not exist"); + } + // check can edit the elemental area + $areaID = $element->ParentID; + $area = ElementalArea::get()->byID($areaID); + if (!$area) { + return $this->jsonResponse(400, null, "Invalid ParentID on BaseElement $id"); + } + if (!$area->canEdit()) { + return $this->jsonResponse(403, null, "Unable to edit element with ID $id"); + } + try { + // clone element + $clone = $element->duplicate(false); + $clone->Title = $this->getNewTitle($clone->Title ?? ''); + $clone->Sort = 0; // must be zeroed for reorder to work + $area->Elements()->add($clone); + // reorder + $reorderer = Injector::inst()->create(ReorderElements::class, $clone); + $reorderer->reorder($id); + return $this->jsonResponse(204); + } catch (Exception $e) { + return $this->jsonResponse(500, null, "Something went wrong when duplicating element with ID $id"); + } + } + + // Resolver.php newTitle() + private function getNewTitle(string $title = ''): ?string + { + $hasCopyPattern = '/^.*(\scopy($|\s[0-9]+$))/'; + $hasNumPattern = '/^.*(\s[0-9]+$)/'; + $parts = []; + // does $title end with 'copy' (ignoring numbers for now)? + if (preg_match($hasCopyPattern ?? '', $title ?? '', $parts)) { + $copy = $parts[1]; + // does $title end with numbers? + if (preg_match($hasNumPattern ?? '', $copy ?? '', $parts)) { + $num = trim($parts[1] ?? ''); + $len = strlen($num ?? ''); + $inc = (int)$num + 1; + return substr($title ?? '', 0, -$len) . "$inc"; + } else { + return $title . ' 2'; + } + } else { + return $title . ' copy'; + } + } + + // Resolver.php resolveSortBlock() + public function apiSort(): HTTPResponse + { + $postData = $this->getPostData(); + $id = $postData['ID'] ?? 0; + $afterBlockID = $postData['afterBlockID'] ?? 0; $element = BaseElement::get()->byID($id); if (!$element) { + // todo 404 throw new InvalidArgumentException(sprintf('%s#%s not found', BaseElement::class, $id)); } if (!$element->canEdit()) { @@ -81,20 +200,17 @@ public function sort() } $reorderingService = Injector::inst()->create(ReorderElements::class, $element); $reorderingService->reorder($afterBlockID); - return $this->jsonResponse(null); + return $this->jsonResponse(204); } - public function readBlocks() + public function apiReadBlocks(): HTTPResponse { $request = $this->getRequest(); $elementalAreaID = $request->param('elementalAreaID'); - - // validate post vars $elementalArea = ElementalArea::get()->byID($elementalAreaID); if (!$elementalArea) { throw new InvalidArgumentException("Invalid ElementalAreaID: $elementalAreaID"); } - // permission checks if (!$elementalArea->canView()) { throw new InvalidArgumentException("The current user has insufficient permission to view ElementalArea"); } @@ -118,30 +234,30 @@ public function readBlocks() $data[] = [ 'id' => (string) $element->ID, 'title' => $element->Title, - '__typename' => 'Block', // todo + '__typename' => 'Block', // todo (delete) 'blockSchema' => $blockSchema, - 'obsoleteClassName' => null, // todo - 'version' => 1, // todo - 'isPublished' => false, // todo - 'isLiveVersion' => false, // todo + 'obsoleteClassName' => $element->getObsoleteClassName(), + 'version' => $element->Version, + 'isPublished' => $element->isPublished(), + 'isLiveVersion' => $element->isLiveVersion(), // 'canEdit' => $element->canEdit(), // not in graphql response 'canDelete' => $element->canDelete(), 'canPublish' => $element->canPublish(), 'canUnpublish' => $element->canUnpublish(), - 'canCreate' => $element->canCreate(), + 'canCreate' => $element->canCreate(), // todo shouldn't be in response? ]; } - return $this->jsonResponse($data); + return $this->jsonResponse(200, $data); } // Resolver.php resolveAddElementToArea() - public function add() + public function apiAdd(): HTTPResponse { $request = $this->getRequest(); - $postVars = json_decode($request->getBody(), true); - $elementClass = $postVars['elementClass']; - $elementalAreaID = $postVars['elementalAreaID']; - $afterElementID = $postVars['afterElementID'] ?? null; + $postData = json_decode($request->getBody(), true); + $elementClass = $postData['elementClass']; + $elementalAreaID = $postData['elementalAreaID']; + $afterElementID = $postData['afterElementID'] ?? null; // validate post vars if (!is_subclass_of($elementClass, BaseElement::class)) { @@ -180,6 +296,7 @@ public function add() $response = $this->getResponse(); $response->setStatusCode(201); + return $response; // return $newElement; } From bb9b8b83633aaa79837847ffa2580d9a9fc64917 Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Tue, 2 Jan 2024 12:08:35 +1300 Subject: [PATCH 12/12] . --- client/dist/js/bundle.js | 270 ++++++++++++------ client/src/boot/registerTransforms.js | 28 +- .../ElementActions/ArchiveAction.js | 37 ++- .../ElementActions/DuplicateAction.js | 31 +- .../ElementActions/PublishAction.js | 25 +- .../ElementActions/UnpublishAction.js | 82 +++--- .../components/ElementEditor/ElementEditor.js | 11 +- src/Controllers/ElementalAreaController.php | 11 +- 8 files changed, 311 insertions(+), 184 deletions(-) diff --git a/client/dist/js/bundle.js b/client/dist/js/bundle.js index 2fe8f5c9..cf97af66 100644 --- a/client/dist/js/bundle.js +++ b/client/dist/js/bundle.js @@ -241,6 +241,9 @@ var _UnpublishAction2 = _interopRequireDefault(_UnpublishAction); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } exports.default = function () { + + var globalUseGraphqQL = false; + _Injector2.default.transform('elemental-fieldgroup', function (updater) { updater.component('FieldGroup.HistoryViewer.VersionDetail', _HistoricElementView2.default, 'HistoricElement'); }, { @@ -255,16 +258,17 @@ exports.default = function () { updater.component('HistoryViewerToolbar.VersionedAdmin.HistoryViewer.Element.HistoryViewerVersionDetail', _revertToBlockVersionMutation2.default, 'BlockRevertMutation'); }); - var globalUseGraphqQL = false; if (globalUseGraphqQL) { _Injector2.default.transform('cms-element-editor', function (updater) { updater.component('ElementList', _readBlocksForAreaQuery2.default, 'PageElements'); }); } - _Injector2.default.transform('cms-element-adder', function (updater) { - updater.component('AddElementPopover', _addElementMutation2.default, 'ElementAddButton'); - }); + if (globalUseGraphqQL) { + _Injector2.default.transform('cms-element-adder', function (updater) { + updater.component('AddElementPopover', _addElementMutation2.default, 'ElementAddButton'); + }); + } _Injector2.default.transform('element-actions', function (updater) { updater.component('ElementActions', _SaveAction2.default, 'ElementActionsWithSave'); @@ -312,7 +316,7 @@ var _classnames = __webpack_require__(7); var _classnames2 = _interopRequireDefault(_classnames); -var _reactstrap = __webpack_require__(10); +var _reactstrap = __webpack_require__(11); var _elementTypeType = __webpack_require__("./client/src/types/elementTypeType.js"); @@ -383,28 +387,46 @@ var _i18n = __webpack_require__(2); var _i18n2 = _interopRequireDefault(_i18n); +var _ElementEditor = __webpack_require__("./client/src/components/ElementEditor/ElementEditor.js"); + +var _Backend = __webpack_require__(8); + +var _Backend2 = _interopRequireDefault(_Backend); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var ArchiveAction = function ArchiveAction(MenuComponent) { return function (props) { + var _useContext = (0, _react.useContext)(_ElementEditor.ElementEditorContext), + fetchBlocks = _useContext.fetchBlocks; + var handleClick = function handleClick(event) { event.stopPropagation(); - - var id = props.element.id, - isPublished = props.isPublished, - handleArchiveBlock = props.actions.handleArchiveBlock; - - + var isPublished = props.element.isPublished; var archiveMessage = _i18n2.default._t('ElementArchiveAction.CONFIRM_DELETE', 'Are you sure you want to send this block to the archive?'); - if (isPublished) { archiveMessage = _i18n2.default._t('ElementArchiveAction.CONFIRM_DELETE_AND_UNPUBLISH', 'Warning: This block will be unpublished before being sent to the archive. Are you sure you want to proceed?'); } - - if (handleArchiveBlock && window.confirm(archiveMessage)) { - handleArchiveBlock(id).then(function () { - var preview = window.jQuery('.cms-preview'); - preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); + if (!window.confirm(archiveMessage)) { + return; + } + var globalUseGraphqQL = false; + if (globalUseGraphqQL) { + var id = props.element.id, + handleArchiveBlock = props.actions.handleArchiveBlock; + + if (handleArchiveBlock) { + handleArchiveBlock(id).then(function () { + var preview = window.jQuery('.cms-preview'); + preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); + }); + } + } else { + var _id = props.element.id; + _Backend2.default.post('/admin/elemental-area/archive', { + ID: _id + }).then(function () { + return fetchBlocks(); }); } }; @@ -464,25 +486,42 @@ var _i18n = __webpack_require__(2); var _i18n2 = _interopRequireDefault(_i18n); +var _ElementEditor = __webpack_require__("./client/src/components/ElementEditor/ElementEditor.js"); + +var _Backend = __webpack_require__(8); + +var _Backend2 = _interopRequireDefault(_Backend); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var DuplicateAction = function DuplicateAction(MenuComponent) { return function (props) { + var _useContext = (0, _react.useContext)(_ElementEditor.ElementEditorContext), + fetchBlocks = _useContext.fetchBlocks; + if (props.type.broken) { return _react2.default.createElement(MenuComponent, props); } var handleClick = function handleClick(event) { event.stopPropagation(); - - var id = props.element.id, - handleDuplicateBlock = props.actions.handleDuplicateBlock; - - - if (handleDuplicateBlock) { - handleDuplicateBlock(id).then(function () { - var preview = window.jQuery('.cms-preview'); - preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); + var globalUseGraphqQL = false; + if (globalUseGraphqQL) { + var id = props.element.id, + handleDuplicateBlock = props.actions.handleDuplicateBlock; + + if (handleDuplicateBlock) { + handleDuplicateBlock(id).then(function () { + var preview = window.jQuery('.cms-preview'); + preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); + }); + } + } else { + var _id = props.element.id; + _Backend2.default.post('/admin/elemental-area/duplicate', { + ID: _id + }).then(function () { + return fetchBlocks(); }); } }; @@ -542,17 +581,19 @@ var _i18n = __webpack_require__(2); var _i18n2 = _interopRequireDefault(_i18n); -var _Backend = __webpack_require__(12); +var _Backend = __webpack_require__(8); var _Backend2 = _interopRequireDefault(_Backend); -var _reactRedux = __webpack_require__(8); +var _reactRedux = __webpack_require__(9); var _loadElementSchemaValue = __webpack_require__("./client/src/state/editor/loadElementSchemaValue.js"); var _loadElementFormStateName = __webpack_require__("./client/src/state/editor/loadElementFormStateName.js"); -var _reduxForm = __webpack_require__(11); +var _reduxForm = __webpack_require__(12); + +var _ElementEditor = __webpack_require__("./client/src/components/ElementEditor/ElementEditor.js"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -593,6 +634,9 @@ var performSaveForElementWithFormData = function performSaveForElementWithFormDa var PublishAction = function PublishAction(MenuComponent) { return function (props) { + var _useContext = (0, _react.useContext)(_ElementEditor.ElementEditorContext), + fetchBlocks = _useContext.fetchBlocks; + if (props.type.broken) { return _react2.default.createElement(MenuComponent, props); } @@ -601,6 +645,23 @@ var PublishAction = function PublishAction(MenuComponent) { formDirty = props.formDirty; + var publishElement = function publishElement() { + var globalUseGraphqQL = false; + if (globalUseGraphqQL) { + var id = props.element.id, + handleArchiveBlock = props.actions.handleArchiveBlock; + + return handleArchiveBlock(id); + } else { + var _id = props.element.id; + return _Backend2.default.post('/admin/elemental-area/publish', { + ID: _id + }).then(function () { + return fetchBlocks(); + }); + } + }; + var handleClick = function handleClick(event) { event.stopPropagation(); @@ -610,7 +671,6 @@ var PublishAction = function PublishAction(MenuComponent) { type = props.type, securityId = props.securityId, formData = props.formData, - handlePublishBlock = props.actions.handlePublishBlock, reinitialiseForm = props.reinitialiseForm; @@ -626,7 +686,7 @@ var PublishAction = function PublishAction(MenuComponent) { } actionFlow.then(function () { - return handlePublishBlock(id); + return publishElement(); }).then(function () { return reportPublicationStatus(type.title, title, true); }).catch(function () { @@ -705,13 +765,13 @@ var _react2 = _interopRequireDefault(_react); var _redux = __webpack_require__(4); -var _reactRedux = __webpack_require__(8); +var _reactRedux = __webpack_require__(9); var _AbstractAction = __webpack_require__("./client/src/components/ElementActions/AbstractAction.js"); var _AbstractAction2 = _interopRequireDefault(_AbstractAction); -var _Backend = __webpack_require__(12); +var _Backend = __webpack_require__(8); var _Backend2 = _interopRequireDefault(_Backend); @@ -723,7 +783,7 @@ var _loadElementSchemaValue = __webpack_require__("./client/src/state/editor/loa var _loadElementFormStateName = __webpack_require__("./client/src/state/editor/loadElementFormStateName.js"); -var _reduxForm = __webpack_require__(11); +var _reduxForm = __webpack_require__(12); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -829,7 +889,7 @@ exports.default = (0, _redux.compose)((0, _reactRedux.connect)(mapStateToProps, /***/ (function(module, exports, __webpack_require__) { "use strict"; - +/* WEBPACK VAR INJECTION */(function($) { Object.defineProperty(exports, "__esModule", { value: true @@ -854,46 +914,68 @@ var _i18n = __webpack_require__(2); var _i18n2 = _interopRequireDefault(_i18n); +var _Backend = __webpack_require__(8); + +var _Backend2 = _interopRequireDefault(_Backend); + +var _ElementEditor = __webpack_require__("./client/src/components/ElementEditor/ElementEditor.js"); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var UnpublishAction = function UnpublishAction(MenuComponent) { return function (props) { + var _useContext = (0, _react.useContext)(_ElementEditor.ElementEditorContext), + fetchBlocks = _useContext.fetchBlocks; + + var globalUseGraphqQL = false; + if (props.type.broken) { return _react2.default.createElement(MenuComponent, props); } - var element = props.element, - type = props.type, - handleUnpublishBlock = props.actions.handleUnpublishBlock; - - - var handleClick = function handleClick(event) { - event.stopPropagation(); - var _window = window, - $ = _window.jQuery; + var reportUnpublicationStatus = function reportUnpublicationStatus(type, title, success) { + var noTitle = _i18n2.default.inject(_i18n2.default._t('ElementHeader.NOTITLE', 'Untitled {type} block'), { type: type }); + var successMessage = _i18n2.default.inject(_i18n2.default._t('ElementUnpublishAction.SUCCESS_NOTIFICATION', 'Removed \'{title}\' from the published page'), { title: title || noTitle }); + var errorMessage = _i18n2.default.inject(_i18n2.default._t('ElementUnpublishAction.ERROR_NOTIFICATION', 'Error unpublishing \'{title}\''), { title: title || noTitle }); + window.jQuery.noticeAdd({ + text: success ? successMessage : errorMessage, + stay: false, + type: success ? 'success' : 'error' + }); + }; - var noTitle = _i18n2.default.inject(_i18n2.default._t('ElementHeader.NOTITLE', 'Untitled {type} block'), { type: type.title }); + var unpublishElement = function unpublishElement() { + if (globalUseGraphqQL) { + var id = props.element.id, + handleUnpublishBlock = props.actions.handleUnpublishBlock; - if (handleUnpublishBlock) { - handleUnpublishBlock(element.id).then(function () { + return handleUnpublishBlock(id).then(function () { var preview = $('.cms-preview'); preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); - - $.noticeAdd({ - text: _i18n2.default.inject(_i18n2.default._t('ElementUnpublishAction.SUCCESS_NOTIFICATION', 'Removed \'{title}\' from the published page'), { title: element.title || noTitle }), - stay: false, - type: 'success' - }); - }).catch(function () { - $.noticeAdd({ - text: _i18n2.default.inject(_i18n2.default._t('ElementUnpublishAction.ERROR_NOTIFICATION', 'Error unpublishing \'{title}\''), { title: element.title || noTitle }), - stay: false, - type: 'error' - }); + }); + } else { + var _id = props.element.id; + return _Backend2.default.post('/admin/elemental-area/unpublish', { + ID: _id + }).then(function () { + return fetchBlocks(); }); } }; + var element = props.element, + type = props.type; + + + var handleClick = function handleClick(event) { + event.stopPropagation(); + unpublishElement().then(function () { + return reportUnpublicationStatus(type.title, element.title, true); + }).catch(function () { + return reportUnpublicationStatus(type.title, element.title, false); + }); + }; + var disabled = props.element.canUnpublish !== undefined && !props.element.canUnpublish; var label = _i18n2.default._t('ElementArchiveAction.UNPUBLISH', 'Unpublish'); var title = disabled ? _i18n2.default._t('ElementArchiveAction.UNPUBLISH_PERMISSION_DENY', 'Unpublish, insufficient permissions') : label; @@ -917,6 +999,7 @@ var UnpublishAction = function UnpublishAction(MenuComponent) { exports.Component = UnpublishAction; exports.default = (0, _redux.compose)(_unpublishBlockMutation2.default, UnpublishAction); +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(17))) /***/ }), @@ -952,7 +1035,7 @@ var _i18n = __webpack_require__(2); var _i18n2 = _interopRequireDefault(_i18n); -var _Backend = __webpack_require__(12); +var _Backend = __webpack_require__(8); var _Backend2 = _interopRequireDefault(_Backend); @@ -1116,7 +1199,7 @@ var _propTypes = __webpack_require__(1); var _propTypes2 = _interopRequireDefault(_propTypes); -var _reactstrap = __webpack_require__(10); +var _reactstrap = __webpack_require__(11); var _i18n = __webpack_require__(2); @@ -1238,11 +1321,11 @@ var _Injector = __webpack_require__(3); var _redux = __webpack_require__(4); -var _reactRedux = __webpack_require__(8); +var _reactRedux = __webpack_require__(9); var _loadElementFormStateName = __webpack_require__("./client/src/state/editor/loadElementFormStateName.js"); -var _reduxForm = __webpack_require__(11); +var _reduxForm = __webpack_require__(12); var _getFormState = __webpack_require__(16); @@ -1436,17 +1519,17 @@ var _classnames = __webpack_require__(7); var _classnames2 = _interopRequireDefault(_classnames); -var _reactRedux = __webpack_require__(8); +var _reactRedux = __webpack_require__(9); var _loadElementFormStateName = __webpack_require__("./client/src/state/editor/loadElementFormStateName.js"); var _loadElementSchemaValue = __webpack_require__("./client/src/state/editor/loadElementSchemaValue.js"); -var _TabsActions = __webpack_require__(19); +var _TabsActions = __webpack_require__(20); var TabsActions = _interopRequireWildcard(_TabsActions); -var _reactDnd = __webpack_require__(9); +var _reactDnd = __webpack_require__(10); var _reactDndHtml5Backend = __webpack_require__(14); @@ -1829,7 +1912,7 @@ var _propTypes2 = _interopRequireDefault(_propTypes); var _redux = __webpack_require__(4); -var _reactstrap = __webpack_require__(10); +var _reactstrap = __webpack_require__(11); var _Injector = __webpack_require__(3); @@ -1993,7 +2076,7 @@ var _Header = __webpack_require__("./client/src/components/ElementEditor/Header. var _Header2 = _interopRequireDefault(_Header); -var _reactDnd = __webpack_require__(9); +var _reactDnd = __webpack_require__(10); var _elementType = __webpack_require__("./client/src/types/elementType.js"); @@ -2106,11 +2189,11 @@ var _redux = __webpack_require__(4); var _elementTypeType = __webpack_require__("./client/src/types/elementTypeType.js"); -var _reactRedux = __webpack_require__(8); +var _reactRedux = __webpack_require__(9); var _loadElementFormStateName = __webpack_require__("./client/src/state/editor/loadElementFormStateName.js"); -var _reactDnd = __webpack_require__(9); +var _reactDnd = __webpack_require__(10); var _sortBlockMutation = __webpack_require__("./client/src/state/editor/sortBlockMutation.js"); @@ -2124,7 +2207,7 @@ var _withDragDropContext = __webpack_require__(21); var _withDragDropContext2 = _interopRequireDefault(_withDragDropContext); -var _Backend = __webpack_require__(12); +var _Backend = __webpack_require__(8); var _Backend2 = _interopRequireDefault(_Backend); @@ -2222,6 +2305,9 @@ var ElementEditor = function (_PureComponent) { contentBlocks: responseJson, isLoading: false })); + + var preview = window.jQuery('.cms-preview'); + preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); }); } }, { @@ -2384,7 +2470,7 @@ var _i18n = __webpack_require__(2); var _i18n2 = _interopRequireDefault(_i18n); -var _reactDnd = __webpack_require__(9); +var _reactDnd = __webpack_require__(10); var _dragHelpers = __webpack_require__("./client/src/lib/dragHelpers.js"); @@ -2621,7 +2707,7 @@ var _propTypes = __webpack_require__(1); var _propTypes2 = _interopRequireDefault(_propTypes); -var _reactstrap = __webpack_require__(10); +var _reactstrap = __webpack_require__(11); var _elementType = __webpack_require__("./client/src/types/elementType.js"); @@ -2629,7 +2715,7 @@ var _elementTypeType = __webpack_require__("./client/src/types/elementTypeType.j var _redux = __webpack_require__(4); -var _reactRedux = __webpack_require__(8); +var _reactRedux = __webpack_require__(9); var _Injector = __webpack_require__(3); @@ -2643,9 +2729,9 @@ var _classnames2 = _interopRequireDefault(_classnames); var _loadElementFormStateName = __webpack_require__("./client/src/state/editor/loadElementFormStateName.js"); -var _reduxForm = __webpack_require__(11); +var _reduxForm = __webpack_require__(12); -var _reactDnd = __webpack_require__(9); +var _reactDnd = __webpack_require__(10); var _getFormState = __webpack_require__(16); @@ -3060,7 +3146,7 @@ var _classnames = __webpack_require__(7); var _classnames2 = _interopRequireDefault(_classnames); -var _FormBuilderLoader = __webpack_require__(18); +var _FormBuilderLoader = __webpack_require__(19); var _FormBuilderLoader2 = _interopRequireDefault(_FormBuilderLoader); @@ -3072,7 +3158,7 @@ var _i18n2 = _interopRequireDefault(_i18n); var _loadElementFormStateName = __webpack_require__("./client/src/state/editor/loadElementFormStateName.js"); -var _reactRedux = __webpack_require__(8); +var _reactRedux = __webpack_require__(9); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -3296,7 +3382,7 @@ var _Injector = __webpack_require__(3); var _elementTypeType = __webpack_require__("./client/src/types/elementTypeType.js"); -var _reactDnd = __webpack_require__(9); +var _reactDnd = __webpack_require__(10); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -3502,9 +3588,9 @@ var _react = __webpack_require__(0); var _react2 = _interopRequireDefault(_react); -var _reactstrap = __webpack_require__(10); +var _reactstrap = __webpack_require__(11); -var _FieldHolder = __webpack_require__(17); +var _FieldHolder = __webpack_require__(18); var _FieldHolder2 = _interopRequireDefault(_FieldHolder); @@ -3561,7 +3647,7 @@ exports.default = (0, _FieldHolder2.default)(TextCheckboxGroupField); "use strict"; -var _jquery = __webpack_require__(20); +var _jquery = __webpack_require__(17); var _jquery2 = _interopRequireDefault(_jquery); @@ -3577,7 +3663,7 @@ var _Injector = __webpack_require__(3); var _elementConfig = __webpack_require__("./client/src/state/editor/elementConfig.js"); -var _reduxForm = __webpack_require__(11); +var _reduxForm = __webpack_require__(12); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4634,21 +4720,21 @@ module.exports = PropTypes; /***/ 10: /***/ (function(module, exports) { -module.exports = Reactstrap; +module.exports = ReactDND; /***/ }), /***/ 11: /***/ (function(module, exports) { -module.exports = ReduxForm; +module.exports = Reactstrap; /***/ }), /***/ 12: /***/ (function(module, exports) { -module.exports = Backend; +module.exports = ReduxForm; /***/ }), @@ -4683,21 +4769,21 @@ module.exports = getFormState; /***/ 17: /***/ (function(module, exports) { -module.exports = FieldHolder; +module.exports = jQuery; /***/ }), /***/ 18: /***/ (function(module, exports) { -module.exports = FormBuilderLoader; +module.exports = FieldHolder; /***/ }), /***/ 19: /***/ (function(module, exports) { -module.exports = TabsActions; +module.exports = FormBuilderLoader; /***/ }), @@ -4711,7 +4797,7 @@ module.exports = i18n; /***/ 20: /***/ (function(module, exports) { -module.exports = jQuery; +module.exports = TabsActions; /***/ }), @@ -4760,14 +4846,14 @@ module.exports = classnames; /***/ 8: /***/ (function(module, exports) { -module.exports = ReactRedux; +module.exports = Backend; /***/ }), /***/ 9: /***/ (function(module, exports) { -module.exports = ReactDND; +module.exports = ReactRedux; /***/ }) diff --git a/client/src/boot/registerTransforms.js b/client/src/boot/registerTransforms.js index 78972976..0a8724d4 100644 --- a/client/src/boot/registerTransforms.js +++ b/client/src/boot/registerTransforms.js @@ -11,6 +11,9 @@ import SaveAction from 'components/ElementActions/SaveAction'; import UnpublishAction from 'components/ElementActions/UnpublishAction'; export default () => { + + const globalUseGraphqQL = false; + Injector.transform( 'elemental-fieldgroup', (updater) => { @@ -49,7 +52,6 @@ export default () => { } ); - const globalUseGraphqQL = false; if (globalUseGraphqQL) { Injector.transform( 'cms-element-editor', @@ -64,17 +66,19 @@ export default () => { ); } - Injector.transform( - 'cms-element-adder', - (updater) => { - // Add GraphQL query for adding elements to an ElementEditor (ElementalArea) - updater.component( - 'AddElementPopover', - addElementToArea, - 'ElementAddButton' - ); - } - ); + if (globalUseGraphqQL) { + Injector.transform( + 'cms-element-adder', + (updater) => { + // Add GraphQL query for adding elements to an ElementEditor (ElementalArea) + updater.component( + 'AddElementPopover', + addElementToArea, + 'ElementAddButton' + ); + } + ); + } // Add elemental editor actions Injector.transform('element-actions', (updater) => { diff --git a/client/src/components/ElementActions/ArchiveAction.js b/client/src/components/ElementActions/ArchiveAction.js index 339ab796..2b4b3185 100644 --- a/client/src/components/ElementActions/ArchiveAction.js +++ b/client/src/components/ElementActions/ArchiveAction.js @@ -1,37 +1,50 @@ /* global window */ -import React from 'react'; +import React, { useContext } from 'react'; import { compose } from 'redux'; import AbstractAction from 'components/ElementActions/AbstractAction'; import archiveBlockMutation from 'state/editor/archiveBlockMutation'; import i18n from 'i18n'; +import { ElementEditorContext } from 'components/ElementEditor/ElementEditor'; +import backend from 'lib/Backend'; /** * Adds the elemental menu action to archive a block of any state */ const ArchiveAction = (MenuComponent) => (props) => { + const { fetchBlocks } = useContext(ElementEditorContext); + const handleClick = (event) => { event.stopPropagation(); - - const { element: { id }, isPublished, actions: { handleArchiveBlock } } = props; - + const isPublished = props.element.isPublished; let archiveMessage = i18n._t( 'ElementArchiveAction.CONFIRM_DELETE', 'Are you sure you want to send this block to the archive?' ); - if (isPublished) { archiveMessage = i18n._t( 'ElementArchiveAction.CONFIRM_DELETE_AND_UNPUBLISH', 'Warning: This block will be unpublished before being sent to the archive. Are you sure you want to proceed?' ); } - - // eslint-disable-next-line no-alert - if (handleArchiveBlock && window.confirm(archiveMessage)) { - handleArchiveBlock(id).then(() => { - const preview = window.jQuery('.cms-preview'); - preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); - }); + if (!window.confirm(archiveMessage)) { + return; + } + const globalUseGraphqQL = false; + if (globalUseGraphqQL) { + const { element: { id }, actions: { handleArchiveBlock } } = props; + // eslint-disable-next-line no-alert + if (handleArchiveBlock) { + handleArchiveBlock(id).then(() => { + const preview = window.jQuery('.cms-preview'); + preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); + }); + } + } else { + const id = props.element.id; + backend.post(`/admin/elemental-area/archive`, { + ID: id, + }) + .then(() => fetchBlocks()); } }; diff --git a/client/src/components/ElementActions/DuplicateAction.js b/client/src/components/ElementActions/DuplicateAction.js index f1996aab..91a9bfa8 100644 --- a/client/src/components/ElementActions/DuplicateAction.js +++ b/client/src/components/ElementActions/DuplicateAction.js @@ -1,14 +1,18 @@ /* global window */ -import React from 'react'; +import React, { useContext } from 'react'; import { compose } from 'redux'; import AbstractAction from 'components/ElementActions/AbstractAction'; import duplicateBlockMutation from 'state/editor/duplicateBlockMutation'; import i18n from 'i18n'; +import { ElementEditorContext } from 'components/ElementEditor/ElementEditor'; +import backend from 'lib/Backend'; /** * Adds the elemental menu action to duplicate a block */ const DuplicateAction = (MenuComponent) => (props) => { + const { fetchBlocks } = useContext(ElementEditorContext); + if (props.type.broken) { // Don't allow this action for a broken element. return ( @@ -18,16 +22,23 @@ const DuplicateAction = (MenuComponent) => (props) => { const handleClick = (event) => { event.stopPropagation(); - - const { element: { id }, actions: { handleDuplicateBlock } } = props; - - if (handleDuplicateBlock) { - handleDuplicateBlock(id).then(() => { - const preview = window.jQuery('.cms-preview'); - preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); - }); + const globalUseGraphqQL = false; + if (globalUseGraphqQL) { + const { element: { id }, actions: { handleDuplicateBlock } } = props; + if (handleDuplicateBlock) { + handleDuplicateBlock(id).then(() => { + const preview = window.jQuery('.cms-preview'); + preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); + }); + } + } else { + const id = props.element.id; + backend.post('/admin/elemental-area/duplicate', { + ID: id, + }) + .then(() => fetchBlocks()); } - }; + } const disabled = props.element.canCreate !== undefined && !props.element.canCreate; const label = i18n._t('ElementArchiveAction.DUPLICATE', 'Duplicate'); diff --git a/client/src/components/ElementActions/PublishAction.js b/client/src/components/ElementActions/PublishAction.js index 60cdf4d7..4ea2c152 100644 --- a/client/src/components/ElementActions/PublishAction.js +++ b/client/src/components/ElementActions/PublishAction.js @@ -1,5 +1,5 @@ /* global window */ -import React from 'react'; +import React, { useContext } from 'react'; import { compose } from 'redux'; import AbstractAction from 'components/ElementActions/AbstractAction'; import publishBlockMutation from 'state/editor/publishBlockMutation'; @@ -9,6 +9,7 @@ import { connect } from 'react-redux'; import { loadElementSchemaValue } from 'state/editor/loadElementSchemaValue'; import { loadElementFormStateName } from 'state/editor/loadElementFormStateName'; import { initialize } from 'redux-form'; +import { ElementEditorContext } from 'components/ElementEditor/ElementEditor'; /** * Show a toast message reporting whether publication of Element was successful @@ -76,6 +77,8 @@ const performSaveForElementWithFormData = (id, formData, securityId) => { * Adds the elemental menu action to publish a draft/modified block */ const PublishAction = (MenuComponent) => (props) => { + const { fetchBlocks } = useContext(ElementEditorContext); + if (props.type.broken) { // Don't allow this action for a broken element. return ( @@ -85,6 +88,20 @@ const PublishAction = (MenuComponent) => (props) => { const { element, formDirty } = props; + const publishElement = () => { + const globalUseGraphqQL = false; + if (globalUseGraphqQL) { + const { element: { id }, actions: { handleArchiveBlock } } = props; + return handleArchiveBlock(id); + } else { + const id = props.element.id; + return backend.post('/admin/elemental-area/publish', { + ID: id, + }) + .then(() => fetchBlocks()); + } + } + const handleClick = (event) => { event.stopPropagation(); @@ -96,7 +113,6 @@ const PublishAction = (MenuComponent) => (props) => { type, securityId, formData, - actions: { handlePublishBlock }, reinitialiseForm, } = props; @@ -113,7 +129,8 @@ const PublishAction = (MenuComponent) => (props) => { // Perform publish. Data is assumed to be up to date actionFlow - .then(() => handlePublishBlock(id)) + // .then(() => handlePublishBlock(id)) + .then(() => publishElement()) .then(() => reportPublicationStatus(type.title, title, true)) .catch(() => reportPublicationStatus(type.title, title, false)); }; @@ -169,7 +186,7 @@ function mapDispatchToProps(dispatch, ownProps) { export { PublishAction as Component }; export default compose( - publishBlockMutation, + publishBlockMutation, // todo connect(mapStateToProps, mapDispatchToProps), PublishAction ); diff --git a/client/src/components/ElementActions/UnpublishAction.js b/client/src/components/ElementActions/UnpublishAction.js index a8bc506d..1a060045 100644 --- a/client/src/components/ElementActions/UnpublishAction.js +++ b/client/src/components/ElementActions/UnpublishAction.js @@ -1,14 +1,19 @@ /* global window */ -import React from 'react'; +import React, { useContext } from 'react'; import { compose } from 'redux'; import AbstractAction from 'components/ElementActions/AbstractAction'; import unpublishBlockMutation from 'state/editor/unpublishBlockMutation'; import i18n from 'i18n'; +import backend from 'lib/Backend'; +import { ElementEditorContext } from 'components/ElementEditor/ElementEditor'; /** * Adds the elemental menu action to unpublish a published block */ const UnpublishAction = (MenuComponent) => (props) => { + const { fetchBlocks } = useContext(ElementEditorContext); + const globalUseGraphqQL = false; + if (props.type.broken) { // Don't allow this action for a broken element. return ( @@ -16,52 +21,51 @@ const UnpublishAction = (MenuComponent) => (props) => { ); } - const { element, type, actions: { handleUnpublishBlock } } = props; - - const handleClick = (event) => { - event.stopPropagation(); - const { jQuery: $ } = window; + const reportUnpublicationStatus = (type, title, success) => { const noTitle = i18n.inject( - i18n._t( - 'ElementHeader.NOTITLE', - 'Untitled {type} block' - ), - { type: type.title } + i18n._t('ElementHeader.NOTITLE', 'Untitled {type} block'), + { type } ); + const successMessage = i18n.inject( + i18n._t('ElementUnpublishAction.SUCCESS_NOTIFICATION', 'Removed \'{title}\' from the published page'), + { title: title || noTitle } + ); + const errorMessage = i18n.inject( + i18n._t('ElementUnpublishAction.ERROR_NOTIFICATION', 'Error unpublishing \'{title}\''), + { title: title || noTitle } + ); + window.jQuery.noticeAdd({ + text: success ? successMessage : errorMessage, + stay: false, + type: success ? 'success' : 'error', + }); + } - if (handleUnpublishBlock) { - handleUnpublishBlock(element.id) + const unpublishElement = () => { + if (globalUseGraphqQL) { + const { element: { id }, actions: { handleUnpublishBlock } } = props; + return handleUnpublishBlock(id) .then(() => { const preview = $('.cms-preview'); preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); - - $.noticeAdd({ - text: i18n.inject( - i18n._t( - 'ElementUnpublishAction.SUCCESS_NOTIFICATION', - 'Removed \'{title}\' from the published page' - ), - { title: element.title || noTitle } - ), - stay: false, - type: 'success' - }); - }) - .catch(() => { - $.noticeAdd({ - text: i18n.inject( - i18n._t( - 'ElementUnpublishAction.ERROR_NOTIFICATION', - 'Error unpublishing \'{title}\'' - ), - { title: element.title || noTitle } - ), - stay: false, - type: 'error' - }); }); + } else { + const id = props.element.id; + return backend.post('/admin/elemental-area/unpublish', { + ID: id, + }) + .then(() => fetchBlocks()); } - }; + } + + const { element, type } = props; + + const handleClick = (event) => { + event.stopPropagation(); + unpublishElement() + .then(() => reportUnpublicationStatus(type.title, element.title, true)) + .catch(() => reportUnpublicationStatus(type.title, element.title, false)); + } const disabled = props.element.canUnpublish !== undefined && !props.element.canUnpublish; const label = i18n._t('ElementArchiveAction.UNPUBLISH', 'Unpublish'); diff --git a/client/src/components/ElementEditor/ElementEditor.js b/client/src/components/ElementEditor/ElementEditor.js index 7eabe07b..4372e799 100644 --- a/client/src/components/ElementEditor/ElementEditor.js +++ b/client/src/components/ElementEditor/ElementEditor.js @@ -70,17 +70,11 @@ class ElementEditor extends PureComponent { preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); }); } else { - // # rpc - // make a call to a sort endpoint with (ID, afterBlocKID) - // after sort there is NOT a call to readAll elements, GraphQL will only do a fairly pointless - // call to read the element that was moved - // (strange code for sorting is in this component and not ElementList, however do not refator it) - // update the preview via jquery/entwine (see graphql code above) backend.post(`/admin/elemental-area/sort`, { ID: sourceId, afterBlockID: afterId, }) - .then(() => this.fetchBlocks()) + .then(() => this.fetchBlocks()); } this.setState({ @@ -108,6 +102,9 @@ class ElementEditor extends PureComponent { contentBlocks: responseJson, isLoading: false, }) + // refresh preview + const preview = window.jQuery('.cms-preview'); + preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src')); }); } diff --git a/src/Controllers/ElementalAreaController.php b/src/Controllers/ElementalAreaController.php index 41b1eee6..0a851cb8 100644 --- a/src/Controllers/ElementalAreaController.php +++ b/src/Controllers/ElementalAreaController.php @@ -59,7 +59,7 @@ class ElementalAreaController extends CMSMain 'apiArchive', 'apiPublish', 'apiUnpublish', - 'revert', // ???? todo there is a revert mutation, though not sure it's actually used? + 'revert', // todo - revert mutation is used in history viewer (versioned-admin) ]; private function jsonResponse(int $statusCode = 200, ?array $data = null, string $message = ''): HTTPResponse @@ -132,7 +132,7 @@ public function apiUnpublish(): HTTPResponse public function apiDuplicate(): HTTPResponse { $id = $this->getPostData()['ID'] ?? ''; - $element = BaseElement::get()->byID($id); + $element = BaseElement::get()->byID($id); if (!$element) { return $this->jsonResponse(400, null, "Element with ID $id does not exist"); } @@ -257,8 +257,7 @@ public function apiAdd(): HTTPResponse $postData = json_decode($request->getBody(), true); $elementClass = $postData['elementClass']; $elementalAreaID = $postData['elementalAreaID']; - $afterElementID = $postData['afterElementID'] ?? null; - + $afterElementID = $postData['insertAfterElementID'] ?? null; // validate post vars if (!is_subclass_of($elementClass, BaseElement::class)) { throw new InvalidArgumentException("$elementClass is not a subclass of " . BaseElement::class); @@ -267,7 +266,6 @@ public function apiAdd(): HTTPResponse if (!$elementalArea) { throw new InvalidArgumentException("Invalid ElementalAreaID: $elementalAreaID"); } - // permission checks if (!$elementalArea->canEdit()) { throw new InvalidArgumentException("The current user has insufficient permission to edit ElementalAreas"); @@ -279,13 +277,11 @@ public function apiAdd(): HTTPResponse 'The current user has insufficient permission to edit Elements' ); } - // Assign the parent ID directly rather than via HasManyList to prevent multiple writes. // See BaseElement::$has_one for the "Parent" naming. $newElement->ParentID = $elementalArea->ID; // Ensure that a sort order is assigned - see BaseElement::onBeforeWrite() $newElement->onBeforeWrite(); - if ($afterElementID !== null) { /** @var ReorderElements $reorderer */ $reorderer = Injector::inst()->create(ReorderElements::class, $newElement); @@ -293,7 +289,6 @@ public function apiAdd(): HTTPResponse } else { $newElement->write(); } - $response = $this->getResponse(); $response->setStatusCode(201); return $response;