Skip to content

Commit

Permalink
Merge pull request silverstripe#277 from creative-commoners/pulls/4.0…
Browse files Browse the repository at this point in the history
…/attach-graphql

NEW Query for reading blocks is now bound to ElementEditor component
  • Loading branch information
ScopeyNZ authored Jul 30, 2018
2 parents f9efe01 + 885a4ea commit 037cc07
Show file tree
Hide file tree
Showing 14 changed files with 151 additions and 1,533 deletions.
1,504 changes: 1 addition & 1,503 deletions client/dist/js/bundle.js

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions client/dist/styles/bundle.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions client/src/boot/registerComponents.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import Injector from 'lib/Injector';
import ElementEditor from 'components/ElementEditor/containers/ElementEditor';
import Element from 'components/ElementEditor/Element';
import ElementEditor from 'components/ElementEditor/ElementEditor';
import ElementList from 'components/ElementEditor/ElementList';
import Toolbar from 'components/ElementEditor/Toolbar';

export default () => {
Injector.component.registerMany({
ElementEditor
ElementEditor,
ElementToolbar: Toolbar,
ElementList,
Element,
});
};
19 changes: 16 additions & 3 deletions client/src/boot/registerTransforms.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import Injector from 'lib/Injector';
import readOneBlockQuery from '../state/history/readOneBlockQuery';
import HistoricElementViewFactory from '../components/HistoricElementView/HistoricElementView';
import revertToBlockVersionMutation from '../state/history/revertToBlockVersionMutation';
import readOneBlockQuery from 'state/history/readOneBlockQuery';
import HistoricElementViewFactory from 'components/HistoricElementView/HistoricElementView';
import revertToBlockVersionMutation from 'state/history/revertToBlockVersionMutation';
import readBlocksForPageQuery from 'state/editor/readBlocksForPageQuery';

export default () => {
Injector.transform(
Expand Down Expand Up @@ -41,4 +42,16 @@ export default () => {
);
}
);

Injector.transform(
'cms-element-editor',
(updater) => {
// Add GraphQL query for reading elements on a page for the ElementEditor
updater.component(
'ElementList',
readBlocksForPageQuery,
'PageElements'
);
}
);
};
29 changes: 24 additions & 5 deletions client/src/components/ElementEditor/Element.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,33 @@
import React, { Component, PropTypes } from 'react';
import React, { PureComponent } from 'react';
import { elementType } from 'types/elementType';

class Element extends Component {
/**
* The Element component used in the context of an ElementEditor shows the summary
* of an element's details when used in the CMS, including ID, Title and Summary.
*/
class Element extends PureComponent {
render() {
const { element: { ID, Title, Summary } } = this.props;

if (!ID) {
return null;
}

return (
<div />
<div className="element-editor__element">
<p>#{ID}: {Title}</p>
<p>{Summary}</p>
</div>
);
}
}

Element.defaultProps = {};
Element.propTypes = {};
Element.propTypes = {
element: elementType,
};

Element.defaultProps = {
element: null,
};

export default Element;
30 changes: 25 additions & 5 deletions client/src/components/ElementEditor/ElementEditor.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
import React, { Component, PropTypes } from 'react';
import React, { PureComponent, PropTypes } from 'react';
import { inject } from 'lib/Injector';

class ElementEditor extends Component {
/**
* 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 } = this.props;

return (
<div />
<div className="element-editor">
<ToolbarComponent />
<ListComponent pageId={pageId} />
</div>
);
}
}

ElementEditor.propTypes = {
pageId: PropTypes.number.isRequired,
};

ElementEditor.defaultProps = {};
ElementEditor.propTypes = {};

export default ElementEditor;
export default inject(
['ElementToolbar', 'ElementList'],
(ToolbarComponent, ListComponent) => ({
ToolbarComponent,
ListComponent,
}),
() => 'ElementEditor'
)(ElementEditor);
44 changes: 40 additions & 4 deletions client/src/components/ElementEditor/ElementList.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,50 @@
import React, { Component, PropTypes } from 'react';
import { elementType } from 'types/elementType';
import { inject } from 'lib/Injector';

class ElementList extends Component {
/**
* Renders a list of Element components, each with an elementType object
* of data mapped into it. The data is provided by a GraphQL HOC registered
* in registerTransforms.js.
*/
renderBlocks() {
const { ElementComponent, blocks } = this.props;

if (!blocks) {
return null;
}

return blocks.map((element) => (
<ElementComponent
key={element.ID}
element={element}
/>
));
}

render() {
return (
<div />
<div className="elemental-editor__list">
{this.renderBlocks()}
</div>
);
}
}

ElementList.defaultProps = {};
ElementList.propTypes = {};
ElementList.propTypes = {
// @todo support either ElementList or Element children in an array (or both)
blocks: PropTypes.arrayOf(elementType),
};

ElementList.defaultProps = {
blocks: [],
};

export default ElementList;
export default inject(
['Element'],
(ElementComponent) => ({
ElementComponent,
}),
() => 'ElementEditor.ElementList'
)(ElementList);
5 changes: 3 additions & 2 deletions client/src/components/ElementEditor/Toolbar.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { Component, PropTypes } from 'react';
import React, { PureComponent } from 'react';

class Toolbar extends Component {
// eslint-disable-next-line react/prefer-stateless-function
class Toolbar extends PureComponent {
render() {
return (
<div />
Expand Down
7 changes: 6 additions & 1 deletion client/src/legacy/ElementEditor/entwine.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ jQuery.entwine('ss', ($) => {
onmatch() {
const context = {};
const ElementEditorComponent = loadComponent('ElementEditor', context);
const schemaData = this.data('schema');

const props = {
pageId: schemaData['page-id'],
};

ReactDOM.render(
<ElementEditorComponent />,
<ElementEditorComponent {...props} />,
this[0]
);
},
Expand Down
10 changes: 7 additions & 3 deletions client/src/state/editor/readBlocksForPageQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import gql from 'graphql-tag';
// ElementalArea. The results of the query must be set to the "blocks" prop on
// the component that this HOC is applied to for binding implementation.
const query = gql`
query readBlocksForPage($id:ID!) {
query ReadBlocksForPage($id:ID!) {
readOnePage(ID: $id, Versioning: {
Mode: LATEST
}){
Expand Down Expand Up @@ -40,12 +40,16 @@ const config = {
{
data: {
error,
readBlocksForPage,
readOnePage,
loading: networkLoading,
},
}
) {
const blocks = readBlocksForPage || null;
let blocks = null;
if (readOnePage) {
// Remove the GraphQL pagination keys
blocks = readOnePage.ElementalArea.Elements.edges.map((element) => element.node);
}

const errors = error && error.graphQLErrors &&
error.graphQLErrors.map((graphQLError) => graphQLError.message);
Expand Down
10 changes: 10 additions & 0 deletions client/src/types/elementType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { PropTypes } from 'react';

// Describes the structure of an element coming in via GraphQL
const elementType = {
ID: PropTypes.number.isRequired,
Title: PropTypes.string,
Summary: PropTypes.string,
};

export { elementType };
7 changes: 7 additions & 0 deletions src/ElementalEditor.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,11 @@ public function getArea()
{
return $this->area;
}

public function getSchemaDataDefaults()
{
$schemaData = parent::getSchemaDataDefaults();
$schemaData['page-id'] = $this->getArea()->getOwnerPage()->ID;
return $schemaData;
}
}
3 changes: 0 additions & 3 deletions templates/DNADesign/Elemental/ElementalEditor.ss

This file was deleted.

3 changes: 3 additions & 0 deletions templates/DNADesign/Elemental/ElementalEditor_holder.ss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div $AttributesHTML data-schema="$SchemaData.JSON">
<%-- Field is rendered by React components --%>
</div>

0 comments on commit 037cc07

Please sign in to comment.