UNPKG

3.49 kBJavaScriptView Raw
1var React = require('react');
2var createElement = React.createElement;
3var types = React.PropTypes;
4var URL = require('url');
5var Emitter = require('events');
6
7var Application = module.exports = React.createClass({
8 displayName: 'Application',
9
10 componentWillMount: function() {
11 var self = this;
12 var props = self.props;
13 self.streams = new Emitter();
14 self.client = props.createClient(props.src, props.props, self);
15 if (process.env.NODE_ENV == 'development') {
16 this.history = [];
17 this.tt = function tt(i) {
18 if (i >= this.history.length) throw Error('History out of bounds');
19 this.setState({tree: this.history[i]});
20 };
21 }
22 },
23
24 componentWillReceiveProps: function(newProps) {
25 var props = this.props;
26 if (props.src !== newProps.src ||
27 JSON.stringify(props.props) !== JSON.stringify(newProps.props)) {
28 this.client.mount(newProps.src, newProps.props);
29 }
30 },
31
32 componentWillUnmount: function() {
33 this.client.unmount();
34 },
35
36 childContextTypes: {
37 action: types.func,
38 authenticate: types.func,
39 tree: types.object,
40 transclude: types.func,
41 appSrc: types.string,
42 streams: types.object
43 },
44
45 getChildContext: function() {
46 var client = this.client;
47 var props = this.props;
48 return {
49 action: client.action,
50 authenticate: client.authenticate,
51 tree: this.state.tree,
52 transclude: this.transclude,
53 appSrc: props.src,
54 streams: this.streams
55 };
56 },
57
58 transclude: function(src, appProps) {
59 var props = this.props;
60
61 if (src && src.charAt(0) == '/') {
62 var url = URL.parse(src);
63 url.pathname = url.path = src;
64 src = URL.format(url);
65 }
66
67 return createElement(Application, Object.assign({}, props, {
68 src: src,
69 props: appProps
70 }));
71 },
72
73 getInitialState: function() {
74 return {
75 tree: {
76 components: {
77 $root: null
78 },
79 schemas: {}
80 },
81 error: null
82 };
83 },
84
85 render: function() {
86 var state = this.state;
87 var error = state.error;
88 return error ?
89 createElement('pre', {
90 style: {
91 color: 'red',
92 'font-family': 'monospace'
93 }
94 }, error) :
95 state.tree.components.$root;
96 },
97
98 // client callbacks
99 mount: function(message) {
100 var init = process.env.NODE_ENV == 'development' ?
101 this.history[0] :
102 this.state.tree;
103
104 var tree = message.body.reduce(function(acc, fun) {
105 return fun(acc, init);
106 }, init);
107
108 if (process.env.NODE_ENV == 'development') this.history.unshift(tree);
109
110 this.setState({tree: tree, error: null});
111 },
112
113 unmount: function() {
114
115 },
116
117 notFound: function(message) {
118 this.setState({error: 'Not found: ' + message.path});
119 },
120
121 authenticationRequired: function() {
122
123 },
124
125 unauthorized: function() {
126
127 },
128
129 info: function(message) {
130 var self = this;
131 var props = self.props;
132 var name = message.name;
133 var data = message.data || {};
134 var obj = {};
135 if (name === '_emit') {
136 var streams = self.streams;
137 return Object.keys(data).forEach(function(id) {
138 data[id].forEach(function(event) {
139 streams.emit(id, event);
140 });
141 });
142 }
143 if (name === 'event') obj = props.events || {};
144 var call = obj[data.type];
145 if (call) call(data.props);
146 },
147
148 call: function(message, cb) {
149
150 },
151
152 error: function(message) {
153 this.setState({error: message.info});
154 }
155});