neo.mjs 2.3.11 → 2.3.15

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.
package/README.md CHANGED
@@ -32,10 +32,9 @@ No need to take care of a workers setup, and the cross channel communication on
32
32
  8. <a href="#online-docs">Online Docs</a>
33
33
  9. <a href="#command-line-interface">Command-Line Interface</a>
34
34
  10. <a href="#get-started">Ready to get started?</a>
35
- 11. <a href="#project-history">Project History</a>
36
- 12. <a href="#story--vision">Story & Vision</a>
37
- 13. <a href="#contributors">neo.mjs is in need of more contributors!</a>
38
- 14. <a href="#sponsors">neo.mjs is in need of more sponsors!</a>
35
+ 11. <a href="#story--vision">Story & Vision</a>
36
+ 12. <a href="#contributors">neo.mjs is in need of more contributors!</a>
37
+ 13. <a href="#sponsors">neo.mjs is in need of more sponsors!</a>
39
38
 
40
39
  </br></br>
41
40
  <h2 id="slack-channel">1. Slack Channel for questions & feedback</h2>
@@ -203,14 +202,7 @@ Please take a look at the <a href=".github/GETTING_STARTED.md">Getting Started G
203
202
  Here is an in depth tutorial on how to build your first neo.mjs app:</br>
204
203
  https://itnext.io/define-a-web-4-0-app-to-be-multi-threaded-9c495c0d0ef9?source=friends_link&sk=4d143ace05f0e9bbe82babd9433cc822
205
204
  </br></br>
206
- <h2 id="project-history">11. Project History</h2>
207
-
208
- neo.mjs got released to the public on November 23, 2019.</br>
209
- Before this point, the project was already at 3720 commits.<br>
210
- Find out more about the start of it inside the <a href=".github/NEOMJS_HISTORY.md">Project History</a> file.
211
-
212
- </br></br>
213
- <h2 id="story--vision">12. Story & Vision</h2>
205
+ <h2 id="story--vision">11. Story & Vision</h2>
214
206
 
215
207
  Although neo.mjs is ready to craft beautiful & blazing fast UIs,</br>
216
208
  the current state is just a fraction of a bigger picture.
@@ -218,7 +210,7 @@ the current state is just a fraction of a bigger picture.
218
210
  Take a look at the <a href=".github/STORY.md">Project Story</a> and <a href=".github/VISION.md">Vision</a>.
219
211
 
220
212
  </br></br>
221
- <h2 id="contributors">13. neo.mjs is in need for more contributors!</h2>
213
+ <h2 id="contributors">12. neo.mjs is in need for more contributors!</h2>
222
214
 
223
215
  Another way to fasten up the neo.mjs development speed is to actively jump in.</br>
224
216
  As the shiny "PRs welcome" badge suggests: open source is intended to be improved by anyone who is up for the challenge.
@@ -228,7 +220,7 @@ You can also write a guide in case you learned something new while using neo.mjs
228
220
  Either way, here are more infos: <a href="./CONTRIBUTING.md">Contributing</a>
229
221
 
230
222
  </br></br>
231
- <h2 id="sponsors">14. neo.mjs is in need for sponsors!</h2>
223
+ <h2 id="sponsors">13. neo.mjs is in need for sponsors!</h2>
232
224
 
233
225
  neo.mjs is an MIT-licensed open source project with an ongoing development.</br>
234
226
  So far the development was made possible with burning my (tobiu's) personal savings.</br>
@@ -132,9 +132,7 @@ class HeaderContainer extends Container {
132
132
  },
133
133
 
134
134
  listeners: {
135
- change: 'onCountryFieldChange',
136
- clear : 'onCountryFieldClear',
137
- select: 'onCountryFieldSelect'
135
+ change: 'onCountryFieldChange'
138
136
  },
139
137
 
140
138
  store: {
@@ -242,7 +242,7 @@ class HelixContainer extends Container {
242
242
  constructor(config) {
243
243
  super(config);
244
244
 
245
- const me = this;
245
+ let me = this;
246
246
 
247
247
  me.helix = Neo.create({
248
248
  module : Helix,
@@ -226,7 +226,6 @@ class MainContainerController extends ComponentController {
226
226
  me.component.on('mounted', me.onMainViewMounted, me);
227
227
  }
228
228
 
229
-
230
229
  /**
231
230
  *
232
231
  * @param {Object} data
@@ -252,21 +251,6 @@ class MainContainerController extends ComponentController {
252
251
  }
253
252
  }
254
253
 
255
- /**
256
- *
257
- */
258
- onCountryFieldClear() {
259
- this.countryRecord = null;
260
- }
261
-
262
- /**
263
- *
264
- * @param {Object} data
265
- */
266
- onCountryFieldSelect(data) {
267
- this.countryRecord = data.record;
268
- }
269
-
270
254
  /**
271
255
  *
272
256
  * @param {Object} value
@@ -277,7 +261,7 @@ class MainContainerController extends ComponentController {
277
261
  activeIndex = me.getTabIndex(value.hash),
278
262
  activeView = me.getView(activeIndex),
279
263
  country = value.hash?.country,
280
- ntype;
264
+ countryRecord, ntype;
281
265
 
282
266
  me.getReference('tab-container').activeIndex = activeIndex;
283
267
  me.activeMainTabIndex = activeIndex;
@@ -312,9 +296,8 @@ class MainContainerController extends ComponentController {
312
296
  me.mapboxglMapHasData = true;
313
297
  }
314
298
 
315
- if (me.countryRecord) {
316
- MainContainerController.selectMapboxGlCountry(activeView, me.countryRecord);
317
- }
299
+ countryRecord = me.getModel().data.countryRecord;
300
+ countryRecord && MainContainerController.selectMapboxGlCountry(activeView, countryRecord);
318
301
 
319
302
  activeView.autoResize();
320
303
  } else if (ntype === 'covid-world-map' && me.data) {
@@ -155,8 +155,8 @@ class TableContainerController extends ComponentController {
155
155
  * @param {String} countryName
156
156
  */
157
157
  loadHistoricalData(countryName) {
158
- const me = this,
159
- apiPath = me.apiBaseUrl + me.apiHistoricalDataEndpoint + countryName + '?lastdays=' + me.apiHistoricalDataTimeRange;
158
+ let me = this,
159
+ apiPath = me.apiBaseUrl + me.apiHistoricalDataEndpoint + countryName + '?lastdays=' + me.apiHistoricalDataTimeRange;
160
160
 
161
161
  fetch(apiPath)
162
162
  .then(response => response.json())
@@ -182,8 +182,8 @@ class TableContainerController extends ComponentController {
182
182
  * {Object} data
183
183
  */
184
184
  onCollapseButtonClick(data) {
185
- const panel = this.getReference('controls-panel'),
186
- expand = panel.width === 40;
185
+ let panel = this.getReference('controls-panel'),
186
+ expand = panel.width === 40;
187
187
 
188
188
  panel.width = expand ? this.component.historyPanelWidth : 40;
189
189
 
@@ -194,7 +194,7 @@ class TableContainerController extends ComponentController {
194
194
  * {Object} record
195
195
  */
196
196
  onCountryChange(record) {
197
- const me = this;
197
+ let me = this;
198
198
 
199
199
  if (record) {
200
200
  me.selectedRecord = {...record};
@@ -212,9 +212,9 @@ class TableContainerController extends ComponentController {
212
212
  * {Object} data
213
213
  */
214
214
  onDailyValuesChange(data) {
215
- const chartId = this.getReference('line-chart').id,
216
- logCheckbox = this.getReference('logarithmic-scale-checkbox'),
217
- value = data.value;
215
+ let chartId = this.getReference('line-chart').id,
216
+ logCheckbox = this.getReference('logarithmic-scale-checkbox'),
217
+ value = data.value;
218
218
 
219
219
  if (value) {
220
220
  logCheckbox.set({
@@ -129,9 +129,7 @@ class Table extends Container {
129
129
  if (!selectionModel.isSelected(id)) {
130
130
  selectionModel.select(id);
131
131
 
132
- if (me.mounted) {
133
- Neo.main.DomAccess.scrollToTableRow({id: id});
134
- }
132
+ me.mounted && Neo.main.DomAccess.scrollToTableRow({id: id});
135
133
  }
136
134
  } else {
137
135
  selectionModel.deselectAll();
@@ -208,7 +208,14 @@ class GalleryContainer extends Container {
208
208
 
209
209
  me.gallery = Neo.create({
210
210
  module : Gallery,
211
+ appName : me.appName,
212
+ parentId : me.id,
211
213
  reference: 'gallery',
214
+
215
+ model: {
216
+ parent: me.getModel()
217
+ },
218
+
212
219
  ...me.galleryConfig
213
220
  });
214
221
 
@@ -135,9 +135,12 @@ class HeaderContainer extends Container {
135
135
  style : {marginTop: '15px'},
136
136
  width : 200,
137
137
 
138
+ bind: {
139
+ value: data => data.country
140
+ },
141
+
138
142
  listeners: {
139
- clear : 'onCountryFieldClear',
140
- select: 'onCountryFieldSelect'
143
+ change: 'onCountryFieldChange'
141
144
  },
142
145
 
143
146
  store: {
@@ -177,4 +180,4 @@ class HeaderContainer extends Container {
177
180
 
178
181
  Neo.applyClassConfig(HeaderContainer);
179
182
 
180
- export {HeaderContainer as default};
183
+ export {HeaderContainer as default};
@@ -250,11 +250,18 @@ class HelixContainer extends Container {
250
250
  constructor(config) {
251
251
  super(config);
252
252
 
253
- const me = this;
253
+ let me = this;
254
254
 
255
255
  me.helix = Neo.create({
256
256
  module : Helix,
257
+ appName : me.appName,
258
+ parentId : me.id,
257
259
  reference: 'helix',
260
+
261
+ model: {
262
+ parent: me.getModel()
263
+ },
264
+
258
265
  ...me.helixConfig
259
266
  });
260
267
 
@@ -1,6 +1,7 @@
1
1
  import FooterContainer from './FooterContainer.mjs';
2
2
  import HeaderContainer from './HeaderContainer.mjs';
3
3
  import MainContainerController from './MainContainerController.mjs';
4
+ import MainContainerModel from './MainContainerModel.mjs';
4
5
  import TabContainer from '../../../src/tab/Container.mjs';
5
6
  import Viewport from '../../../src/container/Viewport.mjs';
6
7
 
@@ -90,10 +91,14 @@ class MainContainer extends Viewport {
90
91
  /**
91
92
  * @member {Object} layout={ntype:'vbox',align:'stretch'}
92
93
  */
93
- layout: {ntype: 'vbox', align: 'stretch'}
94
+ layout: {ntype: 'vbox', align: 'stretch'},
95
+ /**
96
+ * @member {SharedCovid.view.MainContainerModel} model=MainContainerModel
97
+ */
98
+ model: MainContainerModel
94
99
  }}
95
100
  }
96
101
 
97
102
  Neo.applyClassConfig(MainContainer);
98
103
 
99
- export {MainContainer as default};
104
+ export {MainContainer as default};
@@ -34,10 +34,6 @@ class MainContainerController extends ComponentController {
34
34
  * @member {String[]} connectedApps=[]
35
35
  */
36
36
  connectedApps: [],
37
- /**
38
- * @member {Object|null} countryRecord=null
39
- */
40
- countryRecord: null,
41
37
  /**
42
38
  * @member {Object[]|null} data=null
43
39
  */
@@ -80,7 +76,6 @@ class MainContainerController extends ComponentController {
80
76
  }}
81
77
 
82
78
  /**
83
- *
84
79
  * @param {Object[]} data
85
80
  */
86
81
  addStoreItems(data) {
@@ -122,7 +117,6 @@ class MainContainerController extends ComponentController {
122
117
  }
123
118
 
124
119
  /**
125
- *
126
120
  * @param {Object} data
127
121
  * @param {Number} data.active
128
122
  * @param {Number} data.cases
@@ -157,7 +151,6 @@ class MainContainerController extends ComponentController {
157
151
  }
158
152
 
159
153
  /**
160
- *
161
154
  * @param {Object} record
162
155
  */
163
156
  clearCountryField(record) {
@@ -192,7 +185,6 @@ class MainContainerController extends ComponentController {
192
185
  }
193
186
 
194
187
  /**
195
- *
196
188
  * @param {String} [appName]
197
189
  * @returns {Neo.component.Base}
198
190
  */
@@ -205,7 +197,6 @@ class MainContainerController extends ComponentController {
205
197
  }
206
198
 
207
199
  /**
208
- *
209
200
  * @param {Object} hashObject
210
201
  * @param {String} hashObject.mainview
211
202
  * @returns {Number}
@@ -219,7 +210,6 @@ class MainContainerController extends ComponentController {
219
210
  }
220
211
 
221
212
  /**
222
- *
223
213
  * @param {Number} tabIndex
224
214
  * @returns {Neo.component.Base}
225
215
  */
@@ -258,7 +248,6 @@ class MainContainerController extends ComponentController {
258
248
  }
259
249
 
260
250
  /**
261
- *
262
251
  * @param {Object} data
263
252
  * @param {String} data.appName
264
253
  */
@@ -316,7 +305,6 @@ class MainContainerController extends ComponentController {
316
305
  }
317
306
 
318
307
  /**
319
- *
320
308
  * @param {Object} data
321
309
  * @param {String} data.appName
322
310
  */
@@ -412,44 +400,42 @@ class MainContainerController extends ComponentController {
412
400
  me.component.on('mounted', me.onMainViewMounted, me);
413
401
  }
414
402
 
415
- /**
416
- *
417
- */
418
- onCountryFieldClear() {
419
- this.countryRecord = null;
420
-
421
- Neo.Main.editRoute({
422
- country: null
423
- });
424
- }
425
403
 
426
404
  /**
427
- *
428
405
  * @param {Object} data
429
406
  */
430
- onCountryFieldSelect(data) {console.log('onCountryFieldSelect', data);
431
- this.countryRecord = data.record;
407
+ onCountryFieldChange(data) {
408
+ let component = data.component,
409
+ store = component.store,
410
+ value = data.value,
411
+ record;
412
+
413
+ if (store.getCount() > 0) {
414
+ if (Neo.isObject(value)) {
415
+ record = value;
416
+ value = value[component.displayField];
417
+ } else {
418
+ record = value && store.find('country', value)?.[0];
419
+ }
432
420
 
433
- Neo.Main.editRoute({
434
- country: data.value
435
- });
421
+ this.getModel().setData({
422
+ country : value,
423
+ countryRecord: record || null
424
+ });
425
+ }
436
426
  }
437
427
 
438
428
  /**
439
- *
440
429
  * @param {Object} value
441
430
  * @param {Object} oldValue
442
431
  */
443
432
  onHashChange(value, oldValue) {
444
- let me = this,
445
- activeIndex = me.getTabIndex(value.hash),
446
- activeView = me.getView(activeIndex),
447
- country = value.hash?.country,
448
- countryField = me.getReference('country-field'),
449
- tabContainer = me.getReference('tab-container'),
450
- delaySelection = !me.data ? 1000 : tabContainer.activeIndex !== activeIndex ? 100 : 0,
451
- listeners = me.mainTabsListeners,
452
- id, ntype, selectionModel;
433
+ let me = this,
434
+ activeIndex = me.getTabIndex(value.hash),
435
+ activeView = me.getView(activeIndex),
436
+ country = value.hash?.country,
437
+ tabContainer = me.getReference('tab-container'),
438
+ countryRecord, ntype;
453
439
 
454
440
  if (me.firstHashChange || value.appNames) {
455
441
  tabContainer.activeIndex = activeIndex;
@@ -463,112 +449,42 @@ class MainContainerController extends ComponentController {
463
449
  return;
464
450
  }
465
451
 
466
- // todo: this will only load each store once. adjust the logic in case we want to support reloading the API
452
+ me.getModel().setData({
453
+ country: country || null
454
+ });
467
455
 
456
+ // todo: this will only load each store once. adjust the logic in case we want to support reloading the API
468
457
  if (me.data && activeView.store?.getCount() < 1) {
469
458
  activeView.store.data = me.data;
470
- delaySelection = 500;
471
459
  }
472
460
 
473
461
  ntype = activeView.ntype;
474
462
 
475
- // todo: https://github.com/neomjs/neo/issues/483
476
- // quick hack. selectionModels update the vdom of the table.Container.
477
- // if table.View is vdom updating, this can result in a 2x rendering of all rows.
478
- if (delaySelection === 1000 && activeView.ntype === 'table-container') {
479
- delaySelection = 2000;
480
- }
481
-
482
- if (ntype === 'covid-world-map' && me.data) {
483
- if (!me.worldMapHasData) {
484
- activeView.loadData(me.data);
485
- me.worldMapHasData = true;
463
+ if ((ntype === 'mapboxgl' || me.connectedApps.includes('SharedCovidMap')) && me.data) {
464
+ if (!me.mapBoxView) {
465
+ me.mapBoxView = me.getReference('mapboxglmap');
486
466
  }
487
- }
488
-
489
- // todo: instead of a timeout this should add a store load listener (single: true)
490
- setTimeout(() => {
491
- if (me.data) {
492
- selectionModel = activeView.selectionModel;
493
-
494
- if (country) {
495
- countryField.value = country;
496
- } else {
497
- value.country = 'all';
498
- }
499
-
500
- if (ntype === 'gallery' || me.connectedApps.includes('SharedCovidGallery')) {
501
- if (!listeners.includes('gallery')) {
502
- listeners.push('gallery');
503
- me.galleryView = me.getReference('gallery');
504
- me.galleryView.on('select', me.updateCountryField, me);
505
- }
506
-
507
- if (country && !me.galleryView.selectionModel.isSelected(country)) {
508
- me.galleryView.selectionModel.select(country, false);
509
- }
510
- }
511
-
512
- if (ntype === 'helix' || me.connectedApps.includes('SharedCovidHelix')) {
513
- if (!listeners.includes('helix')) {
514
- listeners.push('helix');
515
- me.helixView = me.getReference('helix');
516
- me.helixView.on('select', me.updateCountryField, me);
517
- }
518
-
519
- me.helixView.getOffsetValues();
520
-
521
- if (country && !me.helixView.selectionModel.isSelected(country)) {
522
- me.helixView.selectionModel.select(country, false);
523
- me.helixView.onKeyDownSpace(null);
524
- }
525
- }
526
-
527
- if ((ntype === 'mapboxgl' || me.connectedApps.includes('SharedCovidMap')) && me.data) {
528
- if (!me.mapBoxView) {
529
- me.mapBoxView = me.getReference('mapboxglmap');
530
- }
531
467
 
532
- if (me.mapboxStyle) {
533
- me.mapBoxView.mapboxStyle = me.mapBoxView[me.mapboxStyle];
534
- delete me.mapboxStyle;
535
- }
536
-
537
- if (!me.mapboxglMapHasData) {
538
- me.mapBoxView.chartData = me.data;
539
- me.mapboxglMapHasData = true;
540
- }
541
-
542
- if (me.countryRecord) {
543
- MainContainerController.selectMapboxGlCountry(me.mapBoxView, me.tableView.store.get(country));
544
- }
545
-
546
- me.mapBoxView.autoResize();
547
- }
548
-
549
- if (ntype === 'table-container') {
550
- if (!listeners.includes('table')) {
551
- listeners.push('table');
552
- me.tableView = me.getReference('table')
553
-
554
- me.tableView.on({
555
- deselect: me.clearCountryField,
556
- select : me.updateCountryField,
557
- scope : me
558
- });
559
- }
468
+ if (me.mapboxStyle) {
469
+ me.mapBoxView.mapboxStyle = me.mapBoxView[me.mapboxStyle];
470
+ delete me.mapboxStyle;
471
+ }
560
472
 
561
- id = selectionModel.getRowId(activeView.store.indexOf(country));
473
+ if (!me.mapboxglMapHasData) {
474
+ me.mapBoxView.chartData = me.data;
475
+ me.mapboxglMapHasData = true;
476
+ }
562
477
 
563
- me.getReference('table-container').fire('countrySelect', {record: activeView.store.get(country)});
478
+ countryRecord = me.getModel().data.countryRecord;
479
+ countryRecord && MainContainerController.selectMapboxGlCountry(me.mapBoxView, countryRecord);
564
480
 
565
- if (country && !selectionModel.isSelected(id)) {
566
- selectionModel.select(id);
567
- Neo.main.DomAccess.scrollToTableRow({id: id});
568
- }
569
- }
481
+ me.mapBoxView.autoResize();
482
+ } else if (ntype === 'covid-world-map' && me.data) {
483
+ if (!me.worldMapHasData) {
484
+ activeView.loadData(me.data);
485
+ me.worldMapHasData = true;
570
486
  }
571
- }, delaySelection);
487
+ }
572
488
  }
573
489
 
574
490
  me.firstHashChange = false;
@@ -750,11 +666,10 @@ class MainContainerController extends ComponentController {
750
666
  }
751
667
 
752
668
  /**
753
- *
754
669
  * @param view
755
670
  * @param record
756
671
  */
757
- static selectMapboxGlCountry(view, record) {console.log(record.countryInfo.iso2);
672
+ static selectMapboxGlCountry(view, record) {
758
673
  // https://github.com/neomjs/neo/issues/490
759
674
  // there are missing iso2&3 values on natural earth vector
760
675
  const map = {
@@ -777,7 +692,6 @@ class MainContainerController extends ComponentController {
777
692
  }
778
693
 
779
694
  /**
780
- *
781
695
  * @param {Object} data
782
696
  * @param {Object} data.record
783
697
  */
@@ -0,0 +1,51 @@
1
+ import Component from '../../../src/model/Component.mjs';
2
+
3
+ /**
4
+ * @class SharedCovid.view.MainContainerModel
5
+ * @extends Neo.model.Component
6
+ */
7
+ class MainContainerModel extends Component {
8
+ static getConfig() {return {
9
+ /**
10
+ * @member {String} className='SharedCovid.view.MainContainerModel'
11
+ * @protected
12
+ */
13
+ className: 'SharedCovid.view.MainContainerModel',
14
+ /**
15
+ * @member {Object} data
16
+ */
17
+ data: {
18
+ /**
19
+ * @member {String|null} data.country=null
20
+ */
21
+ country: null,
22
+ /**
23
+ * We are storing the currently selected record of the SharedCovid.view.HeaderContainer SelectField
24
+ * @member {Object} data.countryRecord=null
25
+ */
26
+ countryRecord: null
27
+ }
28
+ }}
29
+
30
+ /**
31
+ *
32
+ * @param {String} key
33
+ * @param {*} value
34
+ * @param {*} oldValue
35
+ */
36
+ onDataPropertyChange(key, value, oldValue) {
37
+ super.onDataPropertyChange(key, value, oldValue);
38
+
39
+ if (oldValue !== undefined) {
40
+ if (key === 'country') {
41
+ Neo.Main.editRoute({
42
+ country: value
43
+ });
44
+ }
45
+ }
46
+ }
47
+ }
48
+
49
+ Neo.applyClassConfig(MainContainerModel);
50
+
51
+ export {MainContainerModel as default};
@@ -22,10 +22,20 @@ class TableContainer extends Container {
22
22
  * @member {Boolean} autoMount=true
23
23
  */
24
24
  autoMount: true,
25
+ /**
26
+ * @member {Object} bind
27
+ */
28
+ bind: {
29
+ countryRecord: data => data.countryRecord
30
+ },
25
31
  /**
26
32
  * @member {Neo.controller.Component|null} controller=TableContainerController
27
33
  */
28
34
  controller: TableContainerController,
35
+ /**
36
+ * @member {Object} countryRecord_=null
37
+ */
38
+ countryRecord_: null,
29
39
  /**
30
40
  * @member {Number} historyPanelWidth=520
31
41
  * @protected
@@ -160,6 +170,8 @@ class TableContainer extends Container {
160
170
 
161
171
  me.table = Neo.create({
162
172
  module : Table,
173
+ appName : me.appName,
174
+ parentId : me.id,
163
175
  reference: 'table',
164
176
  ...me.tableConfig
165
177
  });
@@ -167,6 +179,18 @@ class TableContainer extends Container {
167
179
  me.items[0].items.push(me.table);
168
180
  }
169
181
 
182
+ /**
183
+ * Triggered after the countryRecord config got changed
184
+ * @param {String|null} value
185
+ * @param {String|null} oldValue
186
+ * @protected
187
+ */
188
+ afterSetCountryRecord(value, oldValue) {
189
+ setTimeout(() => {
190
+ this.controller.onCountryChange(value);
191
+ }, this.isConstructed ? 0 : 50);
192
+ }
193
+
170
194
  /**
171
195
  *
172
196
  */