neo.mjs 8.29.0 → 8.31.0
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/BACKERS.md +15 -15
- package/CONTRIBUTING.md +9 -9
- package/apps/ServiceWorker.mjs +2 -2
- package/apps/portal/index.html +1 -1
- package/apps/portal/view/home/FooterContainer.mjs +1 -1
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/grid/animatedRowSorting/MainModel.mjs +40 -0
- package/examples/grid/animatedRowSorting/MainStore.mjs +36 -0
- package/examples/grid/animatedRowSorting/Viewport.mjs +87 -0
- package/examples/grid/animatedRowSorting/app.mjs +6 -0
- package/examples/grid/animatedRowSorting/index.html +11 -0
- package/examples/grid/animatedRowSorting/neo-config.json +8 -0
- package/examples/grid/bigData/GridContainer.mjs +3 -2
- package/examples/grid/bigData/MainModel.mjs +3 -2
- package/examples/grid/bigData/MainStore.mjs +3 -2
- package/package.json +3 -3
- package/resources/scss/src/component/Progress.scss +1 -1
- package/resources/scss/src/grid/column/Progress.scss +34 -0
- package/resources/scss/theme-dark/grid/column/Progress.scss +6 -0
- package/resources/scss/theme-light/grid/column/Progress.scss +6 -0
- package/resources/scss/theme-neo-light/grid/column/Progress.scss +6 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/collection/Base.mjs +2 -1
- package/src/component/Base.mjs +1 -1
- package/src/component/Progress.mjs +26 -5
- package/src/data/Store.mjs +12 -9
- package/src/grid/Container.mjs +45 -68
- package/src/grid/ScrollManager.mjs +1 -1
- package/src/grid/View.mjs +81 -1
- package/src/grid/column/Component.mjs +50 -8
- package/src/grid/column/Progress.mjs +42 -0
- package/src/grid/column/_export.mjs +2 -1
- package/src/grid/header/Button.mjs +1 -2
- package/src/grid/plugin/AnimateRows.mjs +234 -0
- package/src/list/plugin/Animate.mjs +16 -7
- package/src/vdom/Helper.mjs +1 -1
- package/src/worker/Manager.mjs +6 -8
package/src/data/Store.mjs
CHANGED
@@ -400,7 +400,7 @@ class Store extends Base {
|
|
400
400
|
onCollectionMutate(opts) {
|
401
401
|
let me = this;
|
402
402
|
|
403
|
-
if (me.
|
403
|
+
if (me.isConstructed && !me.isLoading) {
|
404
404
|
me.fire('load', me.items)
|
405
405
|
}
|
406
406
|
}
|
@@ -411,9 +411,8 @@ class Store extends Base {
|
|
411
411
|
onCollectionSort() {
|
412
412
|
let me = this;
|
413
413
|
|
414
|
-
if (me.
|
415
|
-
//
|
416
|
-
// me.fire('load', me.items);
|
414
|
+
if (me.isConstructed) {
|
415
|
+
//me.fire('load', me.items)
|
417
416
|
}
|
418
417
|
}
|
419
418
|
|
@@ -426,14 +425,18 @@ class Store extends Base {
|
|
426
425
|
let me = this;
|
427
426
|
|
428
427
|
if (me.data) {
|
429
|
-
me.afterSetData(me.data)
|
428
|
+
me.afterSetData(me.data)
|
430
429
|
}
|
431
430
|
|
432
|
-
|
433
|
-
|
431
|
+
// Being constructed does not mean that related afterSetStore() methods got executed
|
432
|
+
// => break the sync flow to ensure potential listeners got applied
|
433
|
+
Promise.resolve().then(() => {
|
434
|
+
if (me.getCount() > 0) {
|
435
|
+
me.fire('load', me.items)
|
436
|
+
} else if (me.autoLoad) {
|
434
437
|
me.load()
|
435
|
-
}
|
436
|
-
}
|
438
|
+
}
|
439
|
+
})
|
437
440
|
}
|
438
441
|
|
439
442
|
/**
|
package/src/grid/Container.mjs
CHANGED
@@ -22,7 +22,8 @@ class GridContainer extends BaseContainer {
|
|
22
22
|
animatedChange: column.AnimatedChange,
|
23
23
|
column : column.Base,
|
24
24
|
component : column.Component,
|
25
|
-
index : column.Index
|
25
|
+
index : column.Index,
|
26
|
+
progress : column.Progress
|
26
27
|
}
|
27
28
|
/**
|
28
29
|
* @member {Object} delayable
|
@@ -321,6 +322,29 @@ class GridContainer extends BaseContainer {
|
|
321
322
|
}
|
322
323
|
}
|
323
324
|
|
325
|
+
/**
|
326
|
+
* Triggered after the store config got changed
|
327
|
+
* @param {Number} value
|
328
|
+
* @param {Number} oldValue
|
329
|
+
* @protected
|
330
|
+
*/
|
331
|
+
afterSetStore(value, oldValue) {
|
332
|
+
let me = this,
|
333
|
+
listeners = {
|
334
|
+
filter: me.onStoreFilter,
|
335
|
+
load : me.onStoreLoad,
|
336
|
+
scope : me
|
337
|
+
};
|
338
|
+
|
339
|
+
value ?.on(listeners);
|
340
|
+
oldValue?.un(listeners);
|
341
|
+
|
342
|
+
// in case we dynamically change the store, the view needs to get the new reference
|
343
|
+
if (me.view) {
|
344
|
+
me.view.store = value
|
345
|
+
}
|
346
|
+
}
|
347
|
+
|
324
348
|
/**
|
325
349
|
* Triggered before the columns config gets changed.
|
326
350
|
* @param {Object[]} value
|
@@ -347,36 +371,13 @@ class GridContainer extends BaseContainer {
|
|
347
371
|
|
348
372
|
/**
|
349
373
|
* Triggered before the store config gets changed.
|
350
|
-
* @param {Neo.data.Store} value
|
351
|
-
* @param {Neo.data.Store}
|
374
|
+
* @param {Object|Neo.data.Store|null} value
|
375
|
+
* @param {Neo.data.Store} oldValue
|
352
376
|
* @protected
|
353
377
|
*/
|
354
378
|
beforeSetStore(value, oldValue) {
|
355
|
-
oldValue?.destroy();
|
356
|
-
|
357
379
|
if (value) {
|
358
|
-
|
359
|
-
|
360
|
-
listeners = {
|
361
|
-
filter : me.onStoreFilter,
|
362
|
-
load : me.onStoreLoad,
|
363
|
-
recordChange: me.onStoreRecordChange,
|
364
|
-
scope : me
|
365
|
-
};
|
366
|
-
|
367
|
-
if (value instanceof Store) {
|
368
|
-
value.on(listeners);
|
369
|
-
value.getCount() > 0 && me.onStoreLoad(value.items)
|
370
|
-
} else {
|
371
|
-
value = ClassSystemUtil.beforeSetInstance(value, Store, {
|
372
|
-
listeners
|
373
|
-
})
|
374
|
-
}
|
375
|
-
|
376
|
-
// in case we dynamically change the store, the view needs to get the new reference
|
377
|
-
if (me.view) {
|
378
|
-
me.view.store = value
|
379
|
-
}
|
380
|
+
value = ClassSystemUtil.beforeSetInstance(value, Store)
|
380
381
|
}
|
381
382
|
|
382
383
|
return value
|
@@ -475,24 +476,14 @@ class GridContainer extends BaseContainer {
|
|
475
476
|
})
|
476
477
|
}
|
477
478
|
|
478
|
-
/**
|
479
|
-
* @param {Array} inputData
|
480
|
-
*/
|
481
|
-
createViewData(inputData) {
|
482
|
-
let me = this;
|
483
|
-
|
484
|
-
me.getVdomRoot()['aria-rowcount'] = inputData.length + 2; // 1 based & the header row counts as well
|
485
|
-
me.update();
|
486
|
-
|
487
|
-
me.view.createViewData()
|
488
|
-
}
|
489
|
-
|
490
479
|
/**
|
491
480
|
* @param args
|
492
481
|
*/
|
493
482
|
destroy(...args) {
|
494
483
|
let me = this;
|
495
484
|
|
485
|
+
me.store = null; // remove the listeners
|
486
|
+
|
496
487
|
me.scrollManager.destroy();
|
497
488
|
|
498
489
|
me.mounted && Neo.main.addon.ResizeObserver.unregister({
|
@@ -569,14 +560,14 @@ class GridContainer extends BaseContainer {
|
|
569
560
|
|
570
561
|
me.store.sort(opts);
|
571
562
|
me.removeSortingCss(opts.property);
|
572
|
-
me.onStoreLoad(
|
563
|
+
me.view.onStoreLoad()
|
573
564
|
}
|
574
565
|
|
575
566
|
/**
|
576
567
|
*
|
577
568
|
*/
|
578
569
|
onStoreFilter() {
|
579
|
-
this.
|
570
|
+
this.updateRowCount()
|
580
571
|
}
|
581
572
|
|
582
573
|
/**
|
@@ -586,37 +577,13 @@ class GridContainer extends BaseContainer {
|
|
586
577
|
onStoreLoad(data) {
|
587
578
|
let me = this;
|
588
579
|
|
589
|
-
|
590
|
-
me.createViewData(data);
|
591
|
-
|
592
|
-
me.timeout(50).then(() => {
|
593
|
-
Neo.main.DomAccess.scrollTo({
|
594
|
-
direction: 'top',
|
595
|
-
id : me.view.vdom.id,
|
596
|
-
value : 0
|
597
|
-
})
|
598
|
-
})
|
580
|
+
me.updateRowCount();
|
599
581
|
|
600
|
-
|
601
|
-
|
602
|
-
}
|
582
|
+
if (me.store.sorters?.length < 1) {
|
583
|
+
me.removeSortingCss()
|
603
584
|
}
|
604
585
|
}
|
605
586
|
|
606
|
-
/**
|
607
|
-
* Gets triggered after changing the value of a record field.
|
608
|
-
* E.g. myRecord.foo = 'bar';
|
609
|
-
* @param {Object} opts
|
610
|
-
* @param {String} opts.field The name of the field which got changed
|
611
|
-
* @param {Neo.data.Model} opts.model The model instance of the changed record
|
612
|
-
* @param {*} opts.oldValue
|
613
|
-
* @param {Object} opts.record
|
614
|
-
* @param {*} opts.value
|
615
|
-
*/
|
616
|
-
onStoreRecordChange(opts) {
|
617
|
-
this.view.onStoreRecordChange(opts)
|
618
|
-
}
|
619
|
-
|
620
587
|
/**
|
621
588
|
* @param {Boolean} silent=false
|
622
589
|
* @returns {Promise<void>}
|
@@ -700,6 +667,16 @@ class GridContainer extends BaseContainer {
|
|
700
667
|
})
|
701
668
|
}
|
702
669
|
}
|
670
|
+
|
671
|
+
/**
|
672
|
+
* @param {Boolean} silent=false
|
673
|
+
*/
|
674
|
+
updateRowCount(silent=false) {
|
675
|
+
let me = this;
|
676
|
+
|
677
|
+
this.getVdomRoot()['aria-rowcount'] = me.store.getCount() + 2; // 1 based & the header row counts as well
|
678
|
+
!silent && this.update()
|
679
|
+
}
|
703
680
|
}
|
704
681
|
|
705
682
|
export default Neo.setupClass(GridContainer);
|
package/src/grid/View.mjs
CHANGED
@@ -21,6 +21,10 @@ class GridView extends Component {
|
|
21
21
|
* @protected
|
22
22
|
*/
|
23
23
|
ntype: 'grid-view',
|
24
|
+
/**
|
25
|
+
* @member {Boolean} animatedRowSorting_=false
|
26
|
+
*/
|
27
|
+
animatedRowSorting_: false,
|
24
28
|
/**
|
25
29
|
* Internal flag. Gets calculated when mounting the grid.Container
|
26
30
|
* @member {Number} availableHeight_=0
|
@@ -93,6 +97,11 @@ class GridView extends Component {
|
|
93
97
|
* @protected
|
94
98
|
*/
|
95
99
|
mountedRows: [0, 0],
|
100
|
+
/**
|
101
|
+
* Optional config values for Neo.grid.plugin.AnimateRows
|
102
|
+
* @member {Object} pluginAnimateRowsConfig=null
|
103
|
+
*/
|
104
|
+
pluginAnimateRowsConfig: null,
|
96
105
|
/**
|
97
106
|
* @member {String} role='rowgroup'
|
98
107
|
*/
|
@@ -204,6 +213,30 @@ class GridView extends Component {
|
|
204
213
|
}])
|
205
214
|
}
|
206
215
|
|
216
|
+
/**
|
217
|
+
* Triggered after the animatedRowSorting config got changed
|
218
|
+
* @param {Boolean} value
|
219
|
+
* @param {Boolean} oldValue
|
220
|
+
* @protected
|
221
|
+
*/
|
222
|
+
afterSetAnimatedRowSorting(value, oldValue) {
|
223
|
+
if (value && !this.getPlugin('grid-animate-rows')) {
|
224
|
+
import('./plugin/AnimateRows.mjs').then(module => {
|
225
|
+
let me = this,
|
226
|
+
plugins = me.plugins || [];
|
227
|
+
|
228
|
+
plugins.push({
|
229
|
+
module : module.default,
|
230
|
+
appName : me.appName,
|
231
|
+
windowId: me.windowId,
|
232
|
+
...me.pluginAnimateRowsConfig
|
233
|
+
});
|
234
|
+
|
235
|
+
me.plugins = plugins
|
236
|
+
})
|
237
|
+
}
|
238
|
+
}
|
239
|
+
|
207
240
|
/**
|
208
241
|
* Triggered after the availableHeight config got changed
|
209
242
|
* @param {Number} value
|
@@ -364,6 +397,25 @@ class GridView extends Component {
|
|
364
397
|
oldValue !== undefined && this.createViewData()
|
365
398
|
}
|
366
399
|
|
400
|
+
/**
|
401
|
+
* Triggered after the store config got changed
|
402
|
+
* @param {Number} value
|
403
|
+
* @param {Number} oldValue
|
404
|
+
* @protected
|
405
|
+
*/
|
406
|
+
afterSetStore(value, oldValue) {
|
407
|
+
let me = this,
|
408
|
+
listeners = {
|
409
|
+
filter : me.onStoreFilter,
|
410
|
+
load : me.onStoreLoad,
|
411
|
+
recordChange: me.onStoreRecordChange,
|
412
|
+
scope : me
|
413
|
+
};
|
414
|
+
|
415
|
+
oldValue?.un(listeners);
|
416
|
+
value ?.on(listeners);
|
417
|
+
}
|
418
|
+
|
367
419
|
/**
|
368
420
|
* @param {Object} data
|
369
421
|
* @param {String} [data.cellId]
|
@@ -608,7 +660,8 @@ class GridView extends Component {
|
|
608
660
|
* @param args
|
609
661
|
*/
|
610
662
|
destroy(...args) {
|
611
|
-
this.store = null;
|
663
|
+
this.store = null; // remove the listeners
|
664
|
+
|
612
665
|
super.destroy(...args)
|
613
666
|
}
|
614
667
|
|
@@ -849,6 +902,33 @@ class GridView extends Component {
|
|
849
902
|
this.fireRowEvent(data, 'rowDoubleClick')
|
850
903
|
}
|
851
904
|
|
905
|
+
/**
|
906
|
+
*
|
907
|
+
*/
|
908
|
+
onStoreFilter() {
|
909
|
+
this.onStoreLoad()
|
910
|
+
}
|
911
|
+
|
912
|
+
/**
|
913
|
+
* @param {Object[]} data
|
914
|
+
* @protected
|
915
|
+
*/
|
916
|
+
onStoreLoad(data) {
|
917
|
+
let me = this;
|
918
|
+
|
919
|
+
me.createViewData();
|
920
|
+
|
921
|
+
if (me.mounted) {
|
922
|
+
me.timeout(50).then(() => {
|
923
|
+
Neo.main.DomAccess.scrollTo({
|
924
|
+
direction: 'top',
|
925
|
+
id : me.vdom.id,
|
926
|
+
value : 0
|
927
|
+
})
|
928
|
+
})
|
929
|
+
}
|
930
|
+
}
|
931
|
+
|
852
932
|
/**
|
853
933
|
* @param {Object} data
|
854
934
|
* @param {Object[]} data.fields Each field object contains the keys: name, oldValue, value
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import Button from '../../button/Base.mjs';
|
2
1
|
import Column from './Base.mjs';
|
3
2
|
|
4
3
|
/**
|
@@ -16,6 +15,20 @@ class Component extends Column {
|
|
16
15
|
* @member {Function|Object|null} component=null
|
17
16
|
*/
|
18
17
|
component: null,
|
18
|
+
/**
|
19
|
+
* @member {Object} defaults
|
20
|
+
* @protected
|
21
|
+
*/
|
22
|
+
defaults: null,
|
23
|
+
/**
|
24
|
+
* Components can delegate event listeners (or button handlers) into methods somewhere inside
|
25
|
+
* the view controller or component tree hierarchy.
|
26
|
+
*
|
27
|
+
* In this case, it is helpful to know what the related record is, so we are adding the record
|
28
|
+
* to the component as a property. By default, as 'record', but this config can change the property name.
|
29
|
+
* @member {String} recordProperty='record'
|
30
|
+
*/
|
31
|
+
recordProperty: 'record',
|
19
32
|
/**
|
20
33
|
* @member {String} type='component'
|
21
34
|
* @protected
|
@@ -29,9 +42,19 @@ class Component extends Column {
|
|
29
42
|
*/
|
30
43
|
map = new Map()
|
31
44
|
|
45
|
+
/**
|
46
|
+
* Override as needed inside class extensions
|
47
|
+
* @param {Object} config
|
48
|
+
* @param {Record} record
|
49
|
+
* @returns {Object}
|
50
|
+
*/
|
51
|
+
applyRecordConfigs(config, record) {
|
52
|
+
return config
|
53
|
+
}
|
54
|
+
|
32
55
|
/**
|
33
56
|
* @param {Object} data
|
34
|
-
* @param {Neo.
|
57
|
+
* @param {Neo.column.Base} data.column
|
35
58
|
* @param {Number} data.columnIndex
|
36
59
|
* @param {String} data.dataField
|
37
60
|
* @param {Neo.grid.Container} data.gridContainer
|
@@ -42,28 +65,36 @@ class Component extends Column {
|
|
42
65
|
* @returns {*}
|
43
66
|
*/
|
44
67
|
cellRenderer(data) {
|
45
|
-
let {gridContainer, rowIndex} = data,
|
46
|
-
{appName, view, windowId}
|
47
|
-
me
|
48
|
-
|
49
|
-
|
50
|
-
|
68
|
+
let {gridContainer, record, rowIndex} = data,
|
69
|
+
{appName, view, windowId} = gridContainer,
|
70
|
+
me = this,
|
71
|
+
{recordProperty} = me,
|
72
|
+
id = me.getComponentId(rowIndex),
|
73
|
+
component = me.map.get(id),
|
74
|
+
componentConfig = me.component;
|
51
75
|
|
52
76
|
if (Neo.typeOf(componentConfig) === 'Function') {
|
53
77
|
componentConfig = componentConfig(data)
|
54
78
|
}
|
55
79
|
|
80
|
+
componentConfig = me.applyRecordConfigs(componentConfig, record);
|
81
|
+
|
56
82
|
if (component) {
|
57
83
|
delete componentConfig.className;
|
58
84
|
delete componentConfig.module;
|
59
85
|
delete componentConfig.ntype;
|
60
86
|
|
87
|
+
componentConfig[recordProperty] = record;
|
88
|
+
|
61
89
|
component.set(componentConfig)
|
62
90
|
} else {
|
63
91
|
component = Neo.create({
|
92
|
+
...me.defaults,
|
64
93
|
...componentConfig,
|
65
94
|
appName,
|
66
95
|
id,
|
96
|
+
parentComponent : view,
|
97
|
+
[recordProperty]: record,
|
67
98
|
windowId
|
68
99
|
});
|
69
100
|
|
@@ -74,6 +105,17 @@ class Component extends Column {
|
|
74
105
|
|
75
106
|
return component.createVdomReference()
|
76
107
|
}
|
108
|
+
|
109
|
+
/**
|
110
|
+
* @param {Number} rowIndex
|
111
|
+
* @returns {String}
|
112
|
+
*/
|
113
|
+
getComponentId(rowIndex) {
|
114
|
+
let me = this,
|
115
|
+
{view} = me.parent;
|
116
|
+
|
117
|
+
return `${me.id}-component-${rowIndex % (view.availableRows + 2 * view.bufferRowRange)}`
|
118
|
+
}
|
77
119
|
}
|
78
120
|
|
79
121
|
export default Neo.setupClass(Component);
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import ComponentColumn from './Component.mjs';
|
2
|
+
import ProgressComponent from '../../component/Progress.mjs';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @class Neo.grid.column.Progress
|
6
|
+
* @extends Neo.grid.column.Component
|
7
|
+
*/
|
8
|
+
class Progress extends ComponentColumn {
|
9
|
+
static config = {
|
10
|
+
/**
|
11
|
+
* @member {String} className='Neo.grid.column.Progress'
|
12
|
+
* @protected
|
13
|
+
*/
|
14
|
+
className: 'Neo.grid.column.Progress',
|
15
|
+
/**
|
16
|
+
* @member {Object} defaults
|
17
|
+
* @protected
|
18
|
+
*/
|
19
|
+
defaults: {
|
20
|
+
module: ProgressComponent
|
21
|
+
},
|
22
|
+
/**
|
23
|
+
* @member {String} type='progress'
|
24
|
+
* @protected
|
25
|
+
*/
|
26
|
+
type: 'progress'
|
27
|
+
}
|
28
|
+
|
29
|
+
/**
|
30
|
+
* @param {Object} config
|
31
|
+
* @param {Record} record
|
32
|
+
* @returns {Object}
|
33
|
+
*/
|
34
|
+
applyRecordConfigs(config, record) {
|
35
|
+
return {
|
36
|
+
value: record[this.dataField],
|
37
|
+
...config
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
export default Neo.setupClass(Progress);
|
@@ -2,5 +2,6 @@ import AnimatedChange from './AnimatedChange.mjs';
|
|
2
2
|
import Base from './Base.mjs';
|
3
3
|
import Component from './Component.mjs';
|
4
4
|
import Index from './Index.mjs';
|
5
|
+
import Progress from './Progress.mjs';
|
5
6
|
|
6
|
-
export {AnimatedChange, Base, Component, Index};
|
7
|
+
export {AnimatedChange, Base, Component, Index, Progress};
|
@@ -176,7 +176,7 @@ class Button extends BaseButton {
|
|
176
176
|
let me = this,
|
177
177
|
{cls} = me;
|
178
178
|
|
179
|
-
if (value
|
179
|
+
if (value) {
|
180
180
|
NeoArray.remove(cls, 'neo-sort-hidden');
|
181
181
|
|
182
182
|
me.addDomListeners({
|
@@ -211,7 +211,6 @@ class Button extends BaseButton {
|
|
211
211
|
*/
|
212
212
|
destroy(...args) {
|
213
213
|
this.filterField?.destroy();
|
214
|
-
|
215
214
|
super.destroy(...args)
|
216
215
|
}
|
217
216
|
|