Skip to content

Commit

Permalink
fetch data on elements
Browse files Browse the repository at this point in the history
  • Loading branch information
bruno12mota committed Nov 15, 2015
1 parent c1f6f5a commit f6054b8
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 83 deletions.
16 changes: 16 additions & 0 deletions lib/client/actions/elements.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import actionTypes from './types';
import request from '../helpers/request';

export function getElementData (elementId, {query, variables}) {
return (dispatch) => {
return request({
dispatch,
type: actionTypes.getElementData,
query,
variables,
params: {
elementId
}
});
};
}
2 changes: 2 additions & 0 deletions lib/client/actions/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ export default {
pbRedoAction: 'PB_REDO_ACTION',
pbLinkDataMode: 'PB_LINK_DATA_MODE',
pbCloseLinkDataMode: 'PB_CLOSE_LINK_DATA_MODE',
// Elements
getElementData: 'GET_ELEMENT_DATA',
// Revisions
getRevisions: 'GET_REVISIONS',
// Draft
Expand Down
144 changes: 61 additions & 83 deletions lib/components/elements/dynamic-list/index.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
import cx from 'classnames';
import * as elementsActions from '../../../client/actions/elements';

import React, {PropTypes} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {buildQueryAndVariables} from 'relax-framework';

import classes from './classes';
import propsSchema from './props-schema';
import settings from './settings';
import Component from '../../component';
import Element from '../../element';
import {Droppable} from '../../dnd';
import List from './list';

@connect(
(state) => ({
elements: state.elements
}),
(dispatch) => bindActionCreators(elementsActions, dispatch)
)
export default class Schema extends Component {
static propTypes = {
children: PropTypes.node,
schemaId: PropTypes.string,
dataLinking: PropTypes.object,
limit: PropTypes.number,
columns: PropTypes.number,
pageBuilder: PropTypes.object,
Expand All @@ -22,7 +32,8 @@ export default class Schema extends Component {
elementId: PropTypes.string.isRequired,
renderChildren: PropTypes.func.isRequired,
verticalGutter: PropTypes.number.isRequired,
horizontalGutter: PropTypes.number.isRequired
horizontalGutter: PropTypes.number.isRequired,
getElementData: PropTypes.func.isRequired
}
static defaultProps = {
limit: 10,
Expand All @@ -32,96 +43,63 @@ export default class Schema extends Component {
}
static propsSchema = propsSchema
static settings = settings

render () {
const props = {
htmlTag: 'div',
info: this.props,
settings: settings
};

return (
<Element {...props}>
{this.renderItems()}
</Element>
);
static fragments = {
schemaList: {
_id: 1,
title: 1,
slug: 1,
date: 1,
state: 1,
properties: 1
}
}

renderItems () {
const items = [];
for (let i = 0; i < this.props.limit; i) {
if (this.props.columns > 1) {
const columnItems = [];
for (let a = 0; a < this.props.columns && i < this.props.limit; a++) {
columnItems.push(this.renderItem(i, a === 0, a === this.props.columns - 1));
i++;
}
items.push(this.renderRow(columnItems, i >= this.props.limit));
} else {
items.push(this.renderItem(i));
i++;
}
}
return items;
getInitialState () {
this.fetchData(this.props);
return {};
}

renderRow (items, isLast) {
const style = {};
if (!isLast) {
style.marginBottom = this.props.verticalGutter + 'px';
componentWillReceiveProps (nextProps) {
if (nextProps.schemaId !== this.props.schemaId ||
nextProps.dataLinking !== this.props.dataLinking ||
nextProps.limit > this.props.limit) {
this.fetchData(nextProps);
}

return (
<div className={cx(classes.row)} style={style}>{items}</div>
);
}

renderItem (key, isFirst, isLast) {
let result;
const editing = this.props.pageBuilder && this.props.pageBuilder.editing;
const content = this.props.children && this.props.renderChildren(this.props.element.children, {});
const spaceThird = Math.round(this.props.horizontalGutter / 3 * 100) / 100;
const spaceSides = spaceThird * 2;

if (editing) {
result = (
<Droppable
key={key}
type={this.props.element.tag}
dropInfo={{id: this.props.elementId}}
{...settings.drop}
placeholder
pageBuilder={this.props.pageBuilder}
pageBuilderActions={this.props.pageBuilderActions}
dnd={this.props.dnd}
dndActions={this.props.dndActions}
style={{position: 'relative'}}
>
{content}
</Droppable>
);
} else {
result = content;
fetchData (props) {
if (props.schemaId) {
props.getElementData(props.elementId, buildQueryAndVariables(
this.constructor.fragments,
{
schemaList: {
schemaId: {
value: props.schemaId,
type: 'ID!'
},
limit: {
value: props.limit,
type: 'Int'
}
}
}
));
}
}

const style = {};
if (this.props.columns > 1) {
style.width = (100 / this.props.columns) + '%';

if (isFirst) {
style.paddingRight = spaceSides;
} else if (isLast) {
style.paddingLeft = spaceSides;
} else {
style.paddingRight = spaceThird;
style.paddingLeft = spaceThird;
}
}
render () {
const props = {
htmlTag: 'div',
info: this.props,
settings: settings
};

return (
<div className={cx(this.props.columns > 1 && classes.column)} style={style}>
{result}
</div>
<Element {...props}>
<List {...this.props}>
{this.props.children}
</List>
</Element>
);
}
}
106 changes: 106 additions & 0 deletions lib/components/elements/dynamic-list/list.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import cx from 'classnames';
import React, {PropTypes} from 'react';
import {Component} from 'relax-framework';

import classes from './classes';
import settings from './settings';
import {Droppable} from '../../dnd';

export default class List extends Component {
static propTypes = {
children: PropTypes.node,
limit: PropTypes.number,
columns: PropTypes.number,
renderChildren: PropTypes.func.isRequired,
verticalGutter: PropTypes.number.isRequired,
horizontalGutter: PropTypes.number.isRequired,
pageBuilder: PropTypes.object,
pageBuilderActions: PropTypes.object,
dnd: PropTypes.object,
dndActions: PropTypes.object,
element: PropTypes.object.isRequired,
elementId: PropTypes.string.isRequired
}

render () {
const items = [];
for (let i = 0; i < this.props.limit; i) {
if (this.props.columns > 1) {
const columnItems = [];
for (let a = 0; a < this.props.columns && i < this.props.limit; a++) {
columnItems.push(this.renderItem(i, a === 0, a === this.props.columns - 1));
i++;
}
items.push(this.renderRow(columnItems, i >= this.props.limit));
} else {
items.push(this.renderItem(i));
i++;
}
}
return (
<div>
{items}
</div>
);
}

renderRow (items, isLast) {
const style = {};
if (!isLast) {
style.marginBottom = this.props.verticalGutter + 'px';
}

return (
<div className={cx(classes.row)} style={style}>{items}</div>
);
}

renderItem (key, isFirst, isLast) {
let result;
const editing = this.props.pageBuilder && this.props.pageBuilder.editing;
const content = this.props.children && this.props.renderChildren(this.props.element.children, {});
const spaceThird = Math.round(this.props.horizontalGutter / 3 * 100) / 100;
const spaceSides = spaceThird * 2;

if (editing) {
result = (
<Droppable
key={key}
type={this.props.element.tag}
dropInfo={{id: this.props.elementId}}
{...settings.drop}
placeholder
pageBuilder={this.props.pageBuilder}
pageBuilderActions={this.props.pageBuilderActions}
dnd={this.props.dnd}
dndActions={this.props.dndActions}
style={{position: 'relative'}}
>
{content}
</Droppable>
);
} else {
result = content;
}

const style = {};
if (this.props.columns > 1) {
style.width = (100 / this.props.columns) + '%';

if (isFirst) {
style.paddingRight = spaceSides;
} else if (isLast) {
style.paddingLeft = spaceSides;
} else {
style.paddingRight = spaceThird;
style.paddingLeft = spaceThird;
}
}

return (
<div className={cx(this.props.columns > 1 && classes.column)} style={style}>
{result}
</div>
);
}
}
25 changes: 25 additions & 0 deletions lib/reducers/elements.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import forEach from 'lodash.foreach';

import actionTypes from '../client/actions/types';
import parseFields from '../helpers/parse-fields';

const defaultState = {};
const schemaEntryParsableFields = ['properties'];

export default function elementsReducer (state = defaultState, action = {}) {
switch (action.type) {
case actionTypes.getElementData:
if (action.data.schemaList) {
let newSchemaList = [];
forEach(action.data.schemaList, (schemaEntry) => {
newSchemaList.push(parseFields(schemaEntry, schemaEntryParsableFields));
});
action.data.schemaList = newSchemaList;
}
return Object.assign({}, state, {
[action.params.elementId]: action.data
});
default:
return state;
}
}
2 changes: 2 additions & 0 deletions lib/reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import colors from './colors';
import display from './display';
import dnd from './dnd';
import draft from './draft';
import elements from './elements';
import fonts from './fonts';
import media from './media';
import menu from './menu';
Expand All @@ -29,6 +30,7 @@ import users from './users';
const rootReducer = combineReducers({
admin,
overlays,
elements,
fonts,
settings,
page,
Expand Down

0 comments on commit f6054b8

Please sign in to comment.