Skip to content

Instantly share code, notes, and snippets.

@davidgljay
Last active September 21, 2016 20:22
Show Gist options
  • Save davidgljay/1d1223c819456c36df1a90543eaa5dc9 to your computer and use it in GitHub Desktop.
Save davidgljay/1d1223c819456c36df1a90543eaa5dc9 to your computer and use it in GitHub Desktop.
Coral Dynamic Config Proposal
let config = {
/*
* Unique identifier used to find this config file's view
*/
uuid: 'abcd12345',
/*
* Item that serves as the root of the view and that
* is passed to children of RootContainer.
*/
root:{
type:'stream'
},
/*
* A list of queries that will be called on the backend view.
* These can be accessed via some action.
*/
queries:{
init:'a_query_string', //Query to initialize
getItems: 'another_query_string' //Query to get an array of items
},
/*
* A list of components that will be placed in the application's containers.
* They can appear in any order.
*/
components: [
/*
* This is an example of a simple config object.
* It's container recieves an id, it uses that id to look up
* a comment object, and it passes the 'pubdate' prop of that object
* to component PubDate.
*
* Renders component 'Pubdate' in container 'Comment' with props:
* this.props === {
* pubdate: somedate
* }
*/
{
container:'Comment', //The container in which to instantiate this component
component:'PubDate', //The component to instantiate
order:-10, //The order that this component should appear within the container
graphQL: '(type='comment'){{pubdate}}' //GraphQL for retreiving data for the component from the appropriate item
},
/*
* An example of a config object that traverses a path. The container is passed a comment id
* and retrieves that comment's author. All such pathing must be handled in this configuration file
* so that it is transparent to both the front and back end.
*
* Renders component 'DefaultAuthor in container 'Author' with props:
* this.props === {
* name: 'Suzan'
* }
*/
{
container: 'Author',
component: 'DefaultAuthor',
order: 10,
graphQL: '(type='comment'){{author(type='user'){name}}}' //Get the name of the author for this comment
},
/*
* This is an example of a config item which references its children and employs iteration.
* In this case, the container gets an array called "comments" from an item of type "Stream"
* and iterates over those items, passing each comment id as prop 'id' to each of its children.
*
* Renders the children of the Stream container with props:
* this.props === {
* comments: [
* commentId1,
* commentId2,
* etc
* ]
* }
*/
{
container:'Stream',
mapChildren: true, //Rather than loading a component, this config item
//passes its props to the container's children.
order:0,
graphQL: '(type='stream'){{comments(type='comment'){id}}}' //Gets an array of comments and returns their ids
},
{
/*
* This is an example of a component with a one to many relationship: a list of users
* who like a comment.
* The ItemPath encounters a one-to-many relationship between comments and likes. When this
* happens it splits the remainder of the path into an array. Multidimensional arrays could be
* created this way.
*
* Renders component 'UsersWhoLike' in container 'UsersWhoLikeContainer' with props:
* this.props === {
* users:[
* {
* name: 'Joe'
* },
* {
* name: 'Sue'
* }
* ]
* }
*/
container: 'UsersWhoLikeContainer',
component: 'UsersWhoLike',
order:10,
graphQL:'(type='comment'){{likes(type='like'){user(type='user'){name}}}}'
},
/*
* This is an example of a component which which pulls information from multiple item types.
* This is expessed through multiple item types, and some specification in propTypes.
* In this example, we're a going to show a graph of likes on the user's comments since
* they've joined.
*
* Renders component 'UserLikesGraph' in container 'Stats' with props:
*
* this.props === {
* created_at: somedate,
* likes: [
* {
* created_at: anotherdate
* },
* {
* created_at: yetanotherdate
* }
* ]
* }
*
*/
{
container: 'Stats',
component: 'UserLikesGraph',
order: 5,
graphQL: '(type='user'){{created_at, likes(type='like'){created_at}}}'
}
]
};
export default config;
import React from 'react';
import { connect } from 'react-redux';
import Radium from 'radium';
import {RootContainer, Container, MapContainer} from 'react-dynamic-containers';
@connect(state => state.playground)
@Radium
class Preview extends React.Component {
render() {
return (
<div>
{
/*
* RootContainer takes an ID of a root component used to kick off a query
* for the view.
*/
}
<RootContainer type="stream" id={this.props.params.streamId}>
{
/*
* These components are then each passed the id of the stream object.
* That id is used as a starting place for graphQL queries for that container.
*/
}
<Container name='Guidelines' />
<Container name='CommentBox' />
{
/*
* This component has children, which can be rendered in config along with
* other components.
*/
}
<Container name='Stream'>
{
/*
* MapContainer looks for an array in props (in this case "comments")
* and maps its children to that array.
*
* If MapContainer is passed props like so:
*
* this.props === {
* comments:[
* {
* id:1
* },
* {
* id:2
* }
* ]
* }
* Then it will render an Author and Comment container with id=1, then with id=2, etc.
*/
}
<MapContainer array="comments">
{
/*
* These containers will be passed an ID for a item of type comment.
*/
}
<Container name='Author'/>
<Container name='Comment' />
</MapContainer>
</Container>
</RootContainer>
</div>
);
}
}
export default Preview;
@davidgljay
Copy link
Author

Proposal for Coral Configuration

Above is a proposal for how an application like Talk could be structured around dynamic components.

  • A hierarchy of containers, defined in Talk.js, lays out the structure of the application.
  • A series of configuration objects, defined in config.js, determine what components are rendered in each container and what data is delivered to those components.
  • The config file should also be sufficient for the backend to render a view of everything the frontend will need.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment