Skip to content

Commit

Permalink
NEW All unsaved blocks on a page will now save as the page is saved
Browse files Browse the repository at this point in the history
  • Loading branch information
ScopeyNZ committed Oct 16, 2018
1 parent f091a39 commit d254223
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 14 deletions.
17 changes: 12 additions & 5 deletions client/src/components/ElementActions/SaveAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import AbstractAction from 'components/ElementActions/AbstractAction';
import backend from 'lib/Backend';
import i18n from 'i18n';
import { loadElementSchemaValue } from 'state/editor/loadElementSchemaValue';
import { getSerializedFormData } from 'state/editor/getSerializedFormData';

/**
* Using a REST backend, serialize the current form data and post it to the backend endpoint to save
Expand All @@ -16,12 +15,10 @@ const SaveAction = (MenuComponent) => (props) => {
const handleClick = (event) => {
event.stopPropagation();

const { id, title, securityId } = props;
const { id, title, securityId, formData } = props;

const { jQuery: $ } = window;

const formData = getSerializedFormData(`Form_ElementForm_${id}`);

const endpointSpec = {
url: loadElementSchemaValue('saveUrl', id),
method: loadElementSchemaValue('saveMethod'),
Expand Down Expand Up @@ -81,8 +78,18 @@ const SaveAction = (MenuComponent) => (props) => {
);
};

function mapStateToProps(state) {
function mapStateToProps(state, ownProps) {
// TODO Use `loadElementFormStateName` when Raissa's PR is merged
const formNamePattern = ('ElementForm_%s').replace('%s', ownProps.id);

let formData = null;

if (state.form.formState.element && state.form.formState.element[formNamePattern]) {
formData = state.form.formState.element[formNamePattern].values;
}

return {
formData,
securityId: state.config.SecurityID,
};
}
Expand Down
45 changes: 37 additions & 8 deletions client/src/components/ElementEditor/ElementEditor.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,67 @@
import React, { PureComponent, PropTypes } from 'react';
import { inject } from 'lib/Injector';
import { elementTypeType } from 'types/elementTypeType';
import { connect } from 'react-redux';
import { compose } from 'redux';

/**
* The ElementEditor is used in the CMS to manage a list or nested lists of
* elements for a page or other DataObject.
*/
class ElementEditor extends PureComponent {
render() {
const { ToolbarComponent, ListComponent, pageId, elementTypes, baseAddHref } = this.props;
const {
ToolbarComponent, ListComponent,
fieldName, pageId, elementTypes, baseAddHref, formState,
} = this.props;

return (
<div className="element-editor">
<ToolbarComponent elementTypes={elementTypes} baseAddHref={baseAddHref} />
<ListComponent elementTypes={elementTypes} pageId={pageId} baseAddHref={baseAddHref} />
<input name={fieldName} type="hidden" value={JSON.stringify(formState)} />
</div>
);
}
}

ElementEditor.propTypes = {
fieldName: PropTypes.string,
elementTypes: PropTypes.arrayOf(elementTypeType).isRequired,
pageId: PropTypes.number.isRequired,
baseAddHref: PropTypes.string.isRequired,
};

ElementEditor.defaultProps = {};

function mapStateToProps(state) {
// TODO Use `loadElementFormStateName` when Raissa's PR is merged
const formNamePattern = ('ElementForm_%s').replace('%s', '[0-9]+');
const elementFormState = state.form.formState.element;

if (!elementFormState) {
return {};
}

const formState = Object.keys(elementFormState)
.filter(key => key.match(formNamePattern))
.reduce((accumulator, key) => ({
...accumulator,
[key]: elementFormState[key].values
}), {});

return { formState };
}

export { ElementEditor as Component };
export default inject(
['ElementToolbar', 'ElementList'],
(ToolbarComponent, ListComponent) => ({
ToolbarComponent,
ListComponent,
}),
() => 'ElementEditor'
export default compose(
connect(mapStateToProps),
inject(
['ElementToolbar', 'ElementList'],
(ToolbarComponent, ListComponent) => ({
ToolbarComponent,
ListComponent,
}),
() => 'ElementEditor'
)
)(ElementEditor);
14 changes: 13 additions & 1 deletion client/src/legacy/ElementEditor/entwine.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* global window */

import jQuery from 'jquery';
import React from 'react';
import ReactDOM from 'react-dom';
Expand All @@ -15,6 +17,7 @@ jQuery.entwine('ss', ($) => {
const schemaData = this.data('schema');

const props = {
fieldName: this.attr('name'),
pageId: schemaData['page-id'],
elementTypes: schemaData['element-types'],
baseAddHref: schemaData['base-add-href']
Expand All @@ -28,6 +31,15 @@ jQuery.entwine('ss', ($) => {

onunmatch() {
ReactDOM.unmountComponentAtNode(this[0]);
}
},

/**
* Make sure the editor has flushed all it's buffers before the form is submitted.
*/
'from .cms-edit-form': {
onaftersubmitform() {
window.ss.apolloClient.resetStore();
}
},
});
});
47 changes: 47 additions & 0 deletions src/Forms/ElementalAreaField.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@

namespace DNADesign\Elemental\Forms;

use BlocksPage;
use DNADesign\Elemental\Models\BaseElement;
use DNADesign\Elemental\Models\ElementalArea;
use DNADesign\Elemental\Services\ElementTabProvider;
use SilverStripe\Control\Controller;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Forms\CompositeField;
use SilverStripe\Forms\FieldGroup;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\TabSet;
use SilverStripe\ORM\DataObjectInterface;
use Symbiote\GridFieldExtensions\GridFieldAddNewMultiClass;

class ElementalAreaField extends GridField
Expand Down Expand Up @@ -208,4 +211,48 @@ public function performReadonlyTransformation()
->setName($this->getName())
->addExtraClass('elemental-area--read-only');
}

public function setSubmittedValue($value, $data = null)
{
// Content comes through as a JSON encoded list through a hidden field.
$this->setValue(Convert::json2array($value));
}

public function saveInto(DataObjectInterface $dataObject)
{
/** @var BlocksPage $dataObject */
parent::saveInto($dataObject);

$elementData = $this->Value();

foreach ($elementData as $form => $data) {
// Extract the ID
$elementId = (int) substr($form, 12);

/** @var BaseElement $element */
$element = $this->getArea()->Elements()->byID($elementId);

if (!$element) {
// Ignore invalid elements
continue;
}

$fields = [];

$fieldNamePrefix = sprintf(EditFormFactory::FIELD_NAMESPACE_TEMPLATE, $elementId, '');
$prefixLength = strlen($fieldNamePrefix);

foreach($data as $field => $datum) {
// Check that the field starts with a valid name
if (strpos($field, $fieldNamePrefix) !== 0) {
continue;
}

$fields[substr($field, $prefixLength)] = $datum;
}

$element->update($fields);
$element->write();
}
}
}

0 comments on commit d254223

Please sign in to comment.