nutella_framework 0.6.6 → 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/framework_components/roomcast-main-app/.gitignore +2 -0
  4. data/framework_components/roomcast-main-app/README.md +9 -0
  5. data/framework_components/roomcast-main-app/dist/LICENSE +21 -0
  6. data/framework_components/roomcast-main-app/dist/app.js +54280 -0
  7. data/framework_components/roomcast-main-app/dist/assets/Logo.png +0 -0
  8. data/framework_components/roomcast-main-app/dist/assets/Logo_alpha.png +0 -0
  9. data/framework_components/roomcast-main-app/dist/assets/Logo_grid.svg +216 -0
  10. data/framework_components/roomcast-main-app/dist/css/ionicons.min.css +11 -0
  11. data/framework_components/roomcast-main-app/dist/fonts/ionicons.eot +0 -0
  12. data/framework_components/roomcast-main-app/dist/fonts/ionicons.svg +2230 -0
  13. data/framework_components/roomcast-main-app/dist/fonts/ionicons.ttf +0 -0
  14. data/framework_components/roomcast-main-app/dist/fonts/ionicons.woff +0 -0
  15. data/framework_components/roomcast-main-app/dist/main.css +3227 -0
  16. data/framework_components/roomcast-main-app/gulp/config.js +47 -0
  17. data/framework_components/roomcast-main-app/gulp/tasks/browserify.js +77 -0
  18. data/framework_components/roomcast-main-app/gulp/tasks/build.js +3 -0
  19. data/framework_components/roomcast-main-app/gulp/tasks/css.js +7 -0
  20. data/framework_components/roomcast-main-app/gulp/tasks/default.js +3 -0
  21. data/framework_components/roomcast-main-app/gulp/tasks/fonts.js +7 -0
  22. data/framework_components/roomcast-main-app/gulp/tasks/less.js +16 -0
  23. data/framework_components/roomcast-main-app/gulp/tasks/markup.js +7 -0
  24. data/framework_components/roomcast-main-app/gulp/tasks/setWatch.js +5 -0
  25. data/framework_components/roomcast-main-app/gulp/tasks/svgs.js +7 -0
  26. data/framework_components/roomcast-main-app/gulp/tasks/watch.js +12 -0
  27. data/framework_components/roomcast-main-app/gulp/util/bundleLogger.js +21 -0
  28. data/framework_components/roomcast-main-app/gulp/util/handleErrors.js +15 -0
  29. data/framework_components/roomcast-main-app/gulpfile.js +16 -0
  30. data/framework_components/roomcast-main-app/index.html +38 -0
  31. data/framework_components/roomcast-main-app/nutella.json +6 -0
  32. data/framework_components/roomcast-main-app/package.json +47 -0
  33. data/framework_components/roomcast-main-app/src/app/app.js +15 -0
  34. data/framework_components/roomcast-main-app/src/app/components/app/Channel.js +72 -0
  35. data/framework_components/roomcast-main-app/src/app/components/app/NutellaMixin.js +23 -0
  36. data/framework_components/roomcast-main-app/src/app/components/app/Player.js +129 -0
  37. data/framework_components/roomcast-main-app/src/app/components/app/iOSMixin.js +22 -0
  38. data/framework_components/roomcast-main-app/src/app/components/app/main.js +519 -0
  39. data/framework_components/roomcast-main-app/src/app/components/app/material-ui/menu-item.jsx +79 -0
  40. data/framework_components/roomcast-main-app/src/app/components/app/material-ui/menu.jsx +177 -0
  41. data/framework_components/roomcast-main-app/src/app/components/app/material-ui/overlay.jsx +21 -0
  42. data/framework_components/roomcast-main-app/src/app/components/app/material-ui/right-nav.jsx +108 -0
  43. data/framework_components/roomcast-main-app/src/app/components/identity-selector/IdentitiesGrid.js +91 -0
  44. data/framework_components/roomcast-main-app/src/app/components/identity-selector/IdentityCard.js +86 -0
  45. data/framework_components/roomcast-main-app/src/app/components/identity-selector/iOSMixin.js +19 -0
  46. data/framework_components/roomcast-main-app/src/app/components/identity-selector/main.js +105 -0
  47. data/framework_components/roomcast-main-app/src/app/components/login/AppIdPage.js +97 -0
  48. data/framework_components/roomcast-main-app/src/app/components/login/BrokerPage.js +139 -0
  49. data/framework_components/roomcast-main-app/src/app/components/login/IdentitiesGrid.js +93 -0
  50. data/framework_components/roomcast-main-app/src/app/components/login/IdentityCard.js +99 -0
  51. data/framework_components/roomcast-main-app/src/app/components/login/RunIdPage.js +78 -0
  52. data/framework_components/roomcast-main-app/src/app/components/login/iOSMixin.js +23 -0
  53. data/framework_components/roomcast-main-app/src/app/components/login/main.js +121 -0
  54. data/framework_components/roomcast-main-app/src/app/components/main.js +64 -0
  55. data/framework_components/roomcast-main-app/src/less/main.less +364 -0
  56. data/framework_components/roomcast-main-app/src/less/my_overrides.less +39 -0
  57. data/framework_components/roomcast-main-app/src/less/right-nav.less +31 -0
  58. data/framework_components/roomcast-package-creator/dist/app.js +17830 -3473
  59. data/framework_components/roomcast-package-creator/dist/fonts/material-ui-icons.eot +0 -0
  60. data/framework_components/roomcast-package-creator/dist/fonts/material-ui-icons.svg +0 -0
  61. data/framework_components/roomcast-package-creator/dist/fonts/material-ui-icons.ttf +0 -0
  62. data/framework_components/roomcast-package-creator/dist/fonts/material-ui-icons.woff +0 -0
  63. data/framework_components/roomcast-package-creator/dist/main.css +2 -1
  64. data/framework_components/roomcast-package-creator/dist/nutella_lib.js +4110 -4050
  65. data/framework_components/roomcast-package-creator/index.html +0 -13
  66. data/framework_components/roomcast-package-creator/package.json +33 -32
  67. data/framework_components/roomcast-package-creator/src/app/app.js +14 -4
  68. data/framework_components/roomcast-package-creator/src/app/components/ChannelCard.js +14 -1
  69. data/framework_components/roomcast-package-creator/src/app/components/main.js +0 -4
  70. data/framework_components/roomcast-package-creator/src/less/main.less +1 -0
  71. metadata +57 -2
@@ -0,0 +1,519 @@
1
+
2
+ var React = require('react');
3
+ var Channel = require('./Channel');
4
+ var Mui = require('material-ui');
5
+ var FloatingActionButton = Mui.FloatingActionButton;
6
+ var RightNav = require('./material-ui/right-nav.jsx');
7
+ var NUTELLA = require('nutella_lib');
8
+ var IdentitySelector = require('../identity-selector/main');
9
+ var Player = require('./Player');
10
+
11
+ var $ = require('jquery');
12
+ require('jquery-ui/draggable');
13
+
14
+ var Main = React.createClass({
15
+
16
+ componentDidMount: function() {
17
+ var self = this;
18
+
19
+ window.nutella = NUTELLA.init(self.props.params.broker, self.props.params.app_id, self.props.params.run_id, 'app', function(connected) {
20
+ if(connected) {
21
+
22
+ // Get current channels catalogue
23
+ nutella.net.request('channels/retrieve', 'all', function (response) {
24
+ self.handleUpdatedChannelsCatalogue(response);
25
+
26
+ // TODO check that rid is within current available rids: if rids changed, catch error and ask for new one
27
+ // If at startup info on id is already in state
28
+ if(self.state.rid) {
29
+ // Get current assigned channels (mapping)
30
+ nutella.net.request('mapping/retrieve', 'all', function (response) {
31
+ self.updateChannelsForRid(response, self.state.rid);
32
+ });
33
+ }
34
+
35
+ // Subscribe for future changes
36
+ nutella.net.subscribe('mapping/updated', function (message, from) {
37
+ self.updateChannelsForRid(message, self.state.rid);
38
+ });
39
+ nutella.net.subscribe('currentConfig/switched', function (message, from) {
40
+ self.handleActivitySwitch(message);
41
+ });
42
+ nutella.net.subscribe('channels/updated', function (message, from) {
43
+ nutella.net.request('mapping/retrieve', 'all', function (response) {
44
+ self.handleUpdatedChannelsCatalogue(message, function() {
45
+ self.updateChannelsForRid(response, self.state.rid);
46
+ });
47
+ });
48
+ });
49
+
50
+ // Subscribe to teacher forced logout
51
+ nutella.net.subscribe('logout/all', function (message, from) {
52
+ self.handleLogout();
53
+ });
54
+ });
55
+
56
+ }
57
+ });
58
+
59
+
60
+ },
61
+
62
+ /**
63
+ * Manages the modal sidebar right after state change
64
+ */
65
+ componentWillReceiveProps: function(nextProps) {
66
+ var self = this;
67
+ if(!this.state.rid) {
68
+ this.refs.rightNav.open();
69
+ this.refs.rightNav.setState({
70
+ modal: true
71
+ });
72
+ // Force update menu with resources
73
+ nutella.net.request('mapping/retrieve', 'all', function (response) {
74
+ self.handleUpdatedMapping(response);
75
+ });
76
+ } else {
77
+ this.refs.rightNav.setState({
78
+ modal: false
79
+ });
80
+ }
81
+ },
82
+
83
+ /**
84
+ * Updates current available channels.
85
+ * @param message list of channels
86
+ * @param rid current identity
87
+ */
88
+ updateChannelsForRid: function(message, rid) {
89
+
90
+ var self = this;
91
+ var myChannelsId = [];
92
+ var myChannels = [];
93
+ message.forEach(function (f) {
94
+ for (var i in f.items) {
95
+ var item = f.items[i];
96
+ if (item.name === rid) {
97
+ myChannelsId = item.channels;
98
+ break;
99
+ }
100
+ }
101
+ });
102
+ for(var i=0; i<myChannelsId.length; i++) {
103
+ var id = myChannelsId[i];
104
+ if(self.state.channelsCatalogue[+id] !== undefined) {
105
+ // Add info on id of the channel
106
+ var ch = self.state.channelsCatalogue[+id];
107
+ ch['id'] = id;
108
+ myChannels.push(ch);
109
+ }
110
+ }
111
+ if (myChannels.length === 0) {
112
+ self.handleUpdatedBackgroundMessageTabs('No available channels');
113
+ if(!self.state.rid) {
114
+ //self.handleUpdatedBackgroundMessage('No identity set');
115
+ }
116
+ } else {
117
+ self.handleUpdatedBackgroundMessageTabs(null);
118
+ }
119
+ // update channels list
120
+ this.handleUpdatedChannels(myChannels);
121
+ // logout from current channel (i.e. hide it) if not allowed anymore (for now)
122
+ if(myChannelsId.indexOf(this.state.playing) === -1) {
123
+ this.setState({playing: null});
124
+ }
125
+ },
126
+
127
+ getInitialState: function() {
128
+ return {
129
+ rid: null,
130
+ channels: [],
131
+ mapping: [],
132
+ channelsCatalogue: {},
133
+ backgroundMessage: 'Select a channel',
134
+ backgroundMessageTabs: null,
135
+ modal: null,
136
+ playing: null, // id of the current displayed channel
137
+ players: [], // list of ids of the current played channels
138
+ tabs: true
139
+ };
140
+ },
141
+
142
+ handleUpdatedRid: function(rid) {
143
+ this.setState({
144
+ rid: rid
145
+ });
146
+ },
147
+
148
+ handleUpdatedChannels: function(channels) {
149
+ this.setState({
150
+ channels: channels
151
+ });
152
+ },
153
+
154
+ handleUpdatedMapping: function(mapping) {
155
+ this.setState({
156
+ mapping: mapping
157
+ });
158
+ },
159
+
160
+ handleUpdatedChannelsCatalogue: function(cat, callback) {
161
+ if(callback) {
162
+ this.setState({
163
+ channelsCatalogue: cat
164
+ }, callback);
165
+ } else {
166
+ this.setState({
167
+ channelsCatalogue: cat
168
+ });
169
+ }
170
+ },
171
+
172
+ handleUpdatedBackgroundMessage: function(m) {
173
+ this.setState({
174
+ backgroundMessage: m
175
+ });
176
+ },
177
+
178
+ handleUpdatedBackgroundMessageTabs: function(m) {
179
+ this.setState({
180
+ backgroundMessageTabs: m
181
+ });
182
+ },
183
+
184
+ handleSetPlaying: function(id) {
185
+ var self = this;
186
+ var players = this.state.players;
187
+ if(players.indexOf(id) === -1) {
188
+ players.push(id);
189
+ }
190
+ var callback = function() {
191
+ if(self.state.players.length === 0) {
192
+ self.setState({backgroundMessage: 'Select a channel'});
193
+ } else {
194
+ self.setState({backgroundMessage: null});
195
+ }
196
+ };
197
+
198
+ this.setState({playing: id, players: players, tabs: false}, callback);
199
+ },
200
+
201
+ handleBacktoMenu: function() {
202
+ var self = this;
203
+ this.setState({playing: null});
204
+
205
+ // Hide all players
206
+ var ids = this.state.players;
207
+ ids.forEach(function(id) {
208
+ self.refs['player_' + id].setState({playing: false});
209
+ });
210
+
211
+ },
212
+
213
+ handleControlButton: function() {
214
+ var self = this;
215
+ this.refs.rightNav.toggle();
216
+ if(this.refs.rightNav.state.open === false) {
217
+ nutella.net.request('mapping/retrieve', 'all', function (response) {
218
+ self.handleUpdatedMapping(response);
219
+ });
220
+ }
221
+ },
222
+
223
+ handleSelectedResource: function(rid) {
224
+ var self = this;
225
+ this.handleUpdatedRid(rid);
226
+ nutella.net.request('mapping/retrieve', 'all', function (response) {
227
+ self.updateChannelsForRid(response, rid);
228
+ });
229
+ },
230
+
231
+ handleItemTap: function(menuItem) {
232
+ this.handleSelectedResource(menuItem.id);
233
+ },
234
+
235
+ handleSetRid: function(rid) {
236
+ this.handleSelectedResource(rid);
237
+ },
238
+
239
+ handleLogout: function() {
240
+ //this.handleSelectedResource(null);
241
+ this.props.onSwitchPage(1);
242
+ },
243
+
244
+ promptIdentitySelector: function(mode) {
245
+ return (
246
+ <IdentitySelector
247
+ params = {this.props.params}
248
+ onSetRid = {this.handleSetRid}
249
+ mode = {mode}/>);
250
+ },
251
+
252
+ componentWillUnmount: function() {
253
+ },
254
+
255
+ /**
256
+ * Enables the tabs.
257
+ */
258
+ handleTabsButton: function() {
259
+ this.setState({tabs: true});
260
+ },
261
+
262
+ /**
263
+ * Disables the tabs.
264
+ */
265
+ handleOverlayTabs: function() {
266
+ this.setState({tabs: false});
267
+ },
268
+
269
+ componentDidUpdate: function() {
270
+ this.setupTabsButton();
271
+ },
272
+
273
+ setupTabsButton: function() {
274
+
275
+ var fix = function() {
276
+ $("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>")
277
+ .css({
278
+ top: 0,
279
+ left: 0,
280
+ width: window.innerWidth, height: window.innerHeight,
281
+ position: "absolute", opacity: "0.001", zIndex: 1000
282
+ })
283
+ .appendTo("body");
284
+
285
+ };
286
+ var unfix = function() {
287
+ $( ".ui-draggable-iframeFix" ).remove();
288
+ };
289
+
290
+ $(".tabs-button")
291
+ .draggable({
292
+ containment: ".outer-div",
293
+ start: function(event, ui) {
294
+ fix();
295
+ },
296
+ stop: function(event, ui) {
297
+ unfix();
298
+ }
299
+ })
300
+
301
+ },
302
+
303
+ /**
304
+ * Manages the transition between activities.
305
+ * If old identity is still within the new available ones, then keeps it.
306
+ * If not, it shows the identity-selector to pick the new one.
307
+ */
308
+ handleActivitySwitch: function(mapping) {
309
+ var ids = this.extractIdentitiesFromMapping(mapping);
310
+ var id = this.state.rid;
311
+ if(id) {
312
+ if(ids.indexOf(id) !== -1) {
313
+ this.updateChannelsForRid(mapping, this.state.rid);
314
+ } else {
315
+ this.setState({rid: null, modal: 'activity'});
316
+ }
317
+ } else {
318
+ this.setState({rid: null, modal: 'activity'});
319
+ }
320
+ },
321
+
322
+ /**
323
+ * Helper to extract identities from current mapping.
324
+ * @param mapping
325
+ * @returns {Array}
326
+ */
327
+ extractIdentitiesFromMapping: function(mapping) {
328
+ var ids = [];
329
+ mapping.forEach(function (f) {
330
+ for (var i in f.items) {
331
+ if(f.items.hasOwnProperty(i) && f.items[i].name !== '') {
332
+ ids.push(f.items[i].name);
333
+ }
334
+ }
335
+ });
336
+ return ids;
337
+ },
338
+
339
+ render: function() {
340
+
341
+ if(!this.state.rid) {
342
+ if(this.state.modal === 'activity') {
343
+ return this.promptIdentitySelector('activity');
344
+ }
345
+ return this.promptIdentitySelector('id');
346
+ }
347
+
348
+ var self = this;
349
+ var channels = [];
350
+ for (var ch in this.state.channels) {
351
+ if (this.state.channels.hasOwnProperty(ch)) {
352
+ channels.push(
353
+ <Channel
354
+ key={ch}
355
+ chId={this.state.channels[ch].id}
356
+ channel={this.state.channels[ch]}
357
+ playing={this.state.playing === this.state.channels[ch].id}
358
+ onSetPlaying={this.handleSetPlaying} />
359
+ );
360
+ }
361
+ }
362
+
363
+ var menuItems = [];
364
+ this.state.mapping.forEach(function (f) {
365
+ for (var i in f.items) {
366
+ if(f.items.hasOwnProperty(i) && f.items[i].name !== '') {
367
+ menuItems.push({
368
+ id: f.items[i].name,
369
+ text: f.items[i].name,
370
+ currentSelected: f.items[i].name === self.state.rid
371
+ });
372
+ }
373
+ }
374
+
375
+ });
376
+
377
+ var backgroundMessageStyle = {
378
+ position: 'fixed',
379
+ left: '0',
380
+ bottom: '50%',
381
+ width: '100%',
382
+ fontSize: '2.5vw',
383
+ textAlign: 'center',
384
+ color: '#9197a3',
385
+ fontWeight: '300'
386
+ };
387
+ var backgroundMessage = null;
388
+ if(this.state.backgroundMessage) {
389
+ backgroundMessage = <p style={backgroundMessageStyle} >{this.state.backgroundMessage}</p>;
390
+ }
391
+ if(this.state.playing === null) {
392
+ backgroundMessage = <p style={backgroundMessageStyle} >{'Select a channel'}</p>;
393
+ }
394
+
395
+ var gridHeight = $('.grid').css('height');
396
+ var backgroundMessageTabsStyle = {
397
+ position: 'fixed',
398
+ left: '0',
399
+ top: (parseInt(gridHeight) / 2) - 10,
400
+ width: '100%',
401
+ fontSize: '2.5vw',
402
+ textAlign: 'center',
403
+ color: 'rgba(255,255,255,0.8)',
404
+ fontWeight: '300'
405
+ };
406
+ var backgroundMessageTabs = null;
407
+ if(this.state.backgroundMessageTabs) {
408
+ backgroundMessageTabs = <p style={backgroundMessageTabsStyle} >{this.state.backgroundMessageTabs}</p>;
409
+ }
410
+
411
+ var canLogout = true;
412
+ if(!this.state.rid) {
413
+ canLogout = false;
414
+ }
415
+
416
+ var touchDivStyle = {
417
+ width: '80px',
418
+ height: '60px',
419
+ position: 'fixed',
420
+ bottom: 0,
421
+ right: 0,
422
+ zIndex: 250
423
+ };
424
+
425
+ var players = [];
426
+ var ids = this.state.players;
427
+ ids.forEach(function(id) {
428
+ var p_id = self.state.playing;
429
+ var playing = p_id === id;
430
+ var player =
431
+ <Player
432
+ key={id}
433
+ chId={id}
434
+ ref={'player_' + id}
435
+ playing={playing}
436
+ url={self.state.channelsCatalogue[+id].url}
437
+ name={self.state.channelsCatalogue[+id].name}
438
+ nutellaParams={self.props.params}
439
+ onBackButton={self.handleBacktoMenu} />;
440
+ players.push(player);
441
+ });
442
+
443
+ var outerDivStyle = null;
444
+ if(this.state.playing) {
445
+ // prevent the scrolling only when there's a channel playing
446
+ outerDivStyle = {
447
+ position: 'relative',
448
+ height: '100vh',
449
+ overflow: 'hidden'
450
+ };
451
+ }
452
+
453
+ var buttonStyle = {
454
+ zIndex: 110
455
+ };
456
+
457
+ var tabsButton = <div className='tabs-button' style={buttonStyle} onTouchTap={this.handleTabsButton} >
458
+ <FloatingActionButton
459
+ primary={true}
460
+ mini={true} >
461
+ <i className="icon ion-ios-arrow-down" ></i>
462
+ </FloatingActionButton>
463
+ </div>;
464
+
465
+ var overlayTabs = null;
466
+ var tabsClass = '';
467
+ var overlayTabsStyle = {
468
+ position: 'absolute',
469
+ top: 0,
470
+ left: 0,
471
+ width: '100vw',
472
+ height: '100vh',
473
+ zIndex: 110
474
+ };
475
+
476
+ if(this.state.tabs) {
477
+
478
+ overlayTabs = <div style={overlayTabsStyle} onTouchTap={this.handleOverlayTabs} ></div>;
479
+ buttonStyle['opacity'] = 0;
480
+ buttonStyle['pointerEvents'] = 'none';
481
+
482
+ } else {
483
+ tabsClass = ' hidden-tabs';
484
+ }
485
+
486
+ return (
487
+
488
+ <div className='outerDiv' style={outerDivStyle} >
489
+
490
+ <div className={"grid" + tabsClass}>{backgroundMessageTabs},{channels}</div>
491
+
492
+ {tabsButton}
493
+
494
+ {overlayTabs}
495
+
496
+ {players}
497
+
498
+ {backgroundMessage}
499
+
500
+ <div style={touchDivStyle} onTouchTap={this.handleControlButton} >
501
+ <i className="controlButton icon ion-android-lock" ></i>
502
+ </div>
503
+
504
+ <RightNav ref='rightNav'
505
+ docked={false}
506
+ modal={false}
507
+ menuItems={menuItems}
508
+ onItemTap={this.handleItemTap}
509
+ canLogout={canLogout}
510
+ onLogout={this.handleLogout} />
511
+ </div>
512
+
513
+ );
514
+ }
515
+
516
+
517
+ });
518
+
519
+ module.exports = Main;
@@ -0,0 +1,79 @@
1
+ var React = require('react');
2
+ //var FontIcon = require('./font-icon');
3
+
4
+ var MenuItem = React.createClass({
5
+
6
+ propTypes: {
7
+ index: React.PropTypes.number.isRequired,
8
+ iconClassName: React.PropTypes.string,
9
+ iconRightClassName: React.PropTypes.string,
10
+ attribute: React.PropTypes.string,
11
+ number: React.PropTypes.string,
12
+ data: React.PropTypes.string,
13
+ toggle: React.PropTypes.bool,
14
+ onTouchTap: React.PropTypes.func,
15
+ onClick: React.PropTypes.func,
16
+ onToggle: React.PropTypes.func,
17
+ selected: React.PropTypes.bool
18
+ },
19
+
20
+ getDefaultProps: function() {
21
+ return {
22
+ toggle: false
23
+ };
24
+ },
25
+
26
+ render: function() {
27
+ var classes = 'mui-menu-item';
28
+ if(this.props.selected) {
29
+ classes += ' mui-is-selected';
30
+ }
31
+ if(this.props.currentSelected) {
32
+ classes += ' mui-is-current-selected';
33
+ }
34
+
35
+ var icon;
36
+ var data;
37
+ var iconRight;
38
+ var attribute;
39
+ var number;
40
+
41
+ if (this.props.iconClassName) icon = <FontIcon className={'mui-menu-item-icon ' + this.props.iconClassName} />;
42
+ if (this.props.iconRightClassName) iconRight = <FontIcon className={'mui-menu-item-icon-right ' + this.props.iconRightClassName} />;
43
+ if (this.props.data) data = <span className="mui-menu-item-data">{this.props.data}</span>;
44
+ if (this.props.number !== undefined) number = <span className="mui-menu-item-number">{this.props.number}</span>;
45
+ if (this.props.attribute !== undefined) attribute = <span className="mui-menu-item-attribute">{this.props.attribute}</span>;
46
+
47
+ return (
48
+ <div
49
+ key={this.props.index}
50
+ className={classes}
51
+ onTouchTap={this._handleTouchTap}
52
+ onClick={this._handleOnClick}>
53
+
54
+ {icon}
55
+ {this.props.children}
56
+ {data}
57
+ {attribute}
58
+ {number}
59
+ {iconRight}
60
+
61
+ </div>
62
+ );
63
+ },
64
+
65
+ _handleTouchTap: function(e) {
66
+ if (this.props.onTouchTap) this.props.onTouchTap(e, this.props.index);
67
+ },
68
+
69
+ _handleOnClick: function(e) {
70
+ if (this.props.onClick) this.props.onClick(e, this.props.index);
71
+ },
72
+
73
+ _handleToggle: function(e, toggled) {
74
+ if (this.props.onToggle) this.props.onToggle(e, this.props.index, toggled);
75
+ }
76
+
77
+ });
78
+
79
+ module.exports = MenuItem;