neo.mjs 4.1.0 → 4.2.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.
Files changed (44) hide show
  1. package/buildScripts/addConfig.mjs +398 -0
  2. package/buildScripts/createApp.mjs +3 -3
  3. package/buildScripts/createClass.mjs +7 -7
  4. package/examples/grid/covid/GridContainer.mjs +113 -0
  5. package/examples/grid/covid/GridContainerController.mjs +62 -0
  6. package/examples/grid/covid/MainContainer.mjs +36 -0
  7. package/examples/grid/covid/Model.mjs +65 -0
  8. package/examples/grid/covid/Store.mjs +35 -0
  9. package/examples/grid/covid/Util.mjs +165 -0
  10. package/examples/grid/covid/app.mjs +6 -0
  11. package/examples/grid/covid/index.html +11 -0
  12. package/examples/grid/covid/neo-config.json +8 -0
  13. package/package.json +5 -4
  14. package/resources/scss/src/examples/grid/covid/GridContainer.scss +21 -0
  15. package/resources/scss/src/grid/Container.scss +6 -34
  16. package/resources/scss/src/grid/View.scss +73 -1
  17. package/resources/scss/src/grid/header/Button.scss +67 -7
  18. package/resources/scss/src/grid/header/Toolbar.scss +6 -2
  19. package/resources/scss/src/table/View.scss +2 -2
  20. package/resources/scss/theme-dark/grid/Container.scss +17 -0
  21. package/resources/scss/theme-dark/grid/View.scss +29 -0
  22. package/resources/scss/theme-dark/grid/_all.scss +3 -0
  23. package/resources/scss/theme-dark/grid/header/Button.scss +15 -0
  24. package/resources/scss/theme-dark/grid/header/Toolbar.scss +0 -0
  25. package/resources/scss/theme-dark/grid/header/_all.scss +2 -0
  26. package/resources/scss/theme-light/grid/Container.scss +17 -0
  27. package/resources/scss/theme-light/grid/View.scss +29 -0
  28. package/resources/scss/theme-light/grid/_all.scss +3 -0
  29. package/resources/scss/theme-light/grid/header/Button.scss +15 -0
  30. package/resources/scss/theme-light/grid/header/Toolbar.scss +0 -0
  31. package/resources/scss/theme-light/grid/header/_all.scss +2 -0
  32. package/src/grid/Container.mjs +252 -83
  33. package/src/grid/View.mjs +206 -11
  34. package/src/grid/header/Button.mjs +127 -2
  35. package/src/grid/header/Toolbar.mjs +42 -54
  36. package/src/selection/grid/CellColumnModel.mjs +122 -0
  37. package/src/selection/grid/CellColumnRowModel.mjs +122 -0
  38. package/src/selection/grid/CellModel.mjs +184 -0
  39. package/src/selection/grid/CellRowModel.mjs +164 -0
  40. package/src/selection/grid/ColumnModel.mjs +185 -0
  41. package/src/selection/grid/RowModel.mjs +188 -0
  42. package/src/selection/table/RowModel.mjs +26 -32
  43. package/src/table/Container.mjs +9 -13
  44. package/src/table/header/Toolbar.mjs +1 -1
@@ -0,0 +1,2 @@
1
+ @import "Button";
2
+ @import "Toolbar";
@@ -0,0 +1,17 @@
1
+ $neoMap: map-merge($neoMap, (
2
+ 'grid-container-border-color' : #ddd,
3
+ 'grid-container-cell-background-color' : #fff,
4
+ 'grid-container-cell-background-color-even': #f2f2f2,
5
+ 'grid-container-color' : #666,
6
+ 'grid-container-header-cell-border-bottom' : 1px solid #ddd
7
+ ));
8
+
9
+ @if $useCssVars == true {
10
+ :root .neo-theme-light { // .neo-grid-container
11
+ --grid-container-border-color : #{neo(grid-container-border-color)};
12
+ --grid-container-cell-background-color : #{neo(grid-container-cell-background-color)};
13
+ --grid-container-cell-background-color-even: #{neo(grid-container-cell-background-color-even)};
14
+ --grid-container-color : #{neo(grid-container-color)};
15
+ --grid-container-header-cell-border-bottom : #{neo(grid-container-header-cell-border-bottom)};
16
+ }
17
+ }
@@ -0,0 +1,29 @@
1
+ $neoMap: map-merge($neoMap, (
2
+ 'grid-cell-background-color-hover' : lighten(#33343d, 70%),
3
+ 'grid-cellmodel-selected-cell-background-color' : lighten(#64B5F6, 22%),
4
+ 'grid-cellmodel-selected-cell-color' : #2b2b2b,
5
+ 'grid-cellmodel-selected-column-cell-background-color': lighten(#4f558a, 52%),
6
+ 'grid-cellmodel-selected-column-cell-color' : #2b2b2b,
7
+ 'grid-cellrowmodel-selected-cell-background-color' : lighten(#64B5F6, 22%),
8
+ 'grid-cellrowmodel-selected-cell-color' : #2b2b2b,
9
+ 'grid-cellrowmodel-selected-row-cell-background-color': lighten(#4f558a, 52%),
10
+ 'grid-cellrowmodel-selected-row-cell-color' : #2b2b2b,
11
+ 'grid-rowmodel-selected-cell-background-color' : lighten(#64B5F6, 22%),
12
+ 'grid-rowmodel-selected-cell-color' : #2b2b2b
13
+ ));
14
+
15
+ @if $useCssVars == true {
16
+ :root .neo-theme-light { // .neo-grid-view
17
+ --grid-cell-background-color-hover : #{neo(grid-cell-background-color-hover)};
18
+ --grid-cellmodel-selected-cell-background-color : #{neo(grid-cellmodel-selected-cell-background-color)};
19
+ --grid-cellmodel-selected-cell-color : #{neo(grid-cellmodel-selected-cell-color)};
20
+ --grid-cellmodel-selected-column-cell-background-color: #{neo(grid-cellmodel-selected-column-cell-background-color)};
21
+ --grid-cellmodel-selected-column-cell-color : #{neo(grid-cellmodel-selected-column-cell-color)};
22
+ --grid-cellrowmodel-selected-cell-background-color : #{neo(grid-cellrowmodel-selected-cell-background-color)};
23
+ --grid-cellrowmodel-selected-cell-color : #{neo(grid-cellrowmodel-selected-cell-color)};
24
+ --grid-cellrowmodel-selected-row-cell-background-color: #{neo(grid-cellrowmodel-selected-row-cell-background-color)};
25
+ --grid-cellrowmodel-selected-row-cell-color : #{neo(grid-cellrowmodel-selected-row-cell-color)};
26
+ --grid-rowmodel-selected-cell-background-color : #{neo(grid-rowmodel-selected-cell-background-color)};
27
+ --grid-rowmodel-selected-cell-color : #{neo(grid-rowmodel-selected-cell-color)};
28
+ }
29
+ }
@@ -0,0 +1,3 @@
1
+ @import "header/all";
2
+ @import "Container";
3
+ @import "View";
@@ -0,0 +1,15 @@
1
+ $neoMap: map-merge($neoMap, (
2
+ 'grid-header-button-background-color': #5d83a7,
3
+ 'grid-header-button-background-image': none,
4
+ 'grid-header-button-color' : #fff,
5
+ 'grid-header-button-glyph-color' : #fff
6
+ ));
7
+
8
+ @if $useCssVars == true {
9
+ :root .neo-theme-light { // .neo-grid-header-button
10
+ --grid-header-button-background-color: #{neo(grid-header-button-background-color)};
11
+ --grid-header-button-background-image: #{neo(grid-header-button-background-image)};
12
+ --grid-header-button-color : #{neo(grid-header-button-color)};
13
+ --grid-header-button-glyph-color : #{neo(grid-header-button-glyph-color)};
14
+ }
15
+ }
@@ -0,0 +1,2 @@
1
+ @import "Button";
2
+ @import "Toolbar";
@@ -1,10 +1,35 @@
1
- import BaseContainer from '../container/Base.mjs';
1
+ import BaseContainer from '../container/Base.mjs';
2
+ import ClassSystemUtil from '../util/ClassSystem.mjs';
3
+ import RowModel from '../selection/grid/RowModel.mjs';
4
+ import Store from '../data/Store.mjs';
5
+ import View from './View.mjs';
6
+ import * as header from './header/_export.mjs';
2
7
 
3
8
  /**
4
9
  * @class Neo.grid.Container
5
10
  * @extends Neo.container.Base
6
11
  */
7
12
  class Container extends BaseContainer {
13
+ /**
14
+ * Configs for Neo.grid.header.Toolbar
15
+ * @member {Object|null} [headerToolbarConfig=null]
16
+ */
17
+ headerToolbarConfig = null
18
+ /**
19
+ * @member {String|null} headerToolbarId_=null
20
+ */
21
+ headerToolbarId = null
22
+ /**
23
+ * Configs for Neo.grid.View
24
+ * @member {Object|null} [viewConfig=null]
25
+ */
26
+ viewConfig = null
27
+ /**
28
+ * @member {String|null} viewId_=null
29
+ * @protected
30
+ */
31
+ viewId = null
32
+
8
33
  static getConfig() {return {
9
34
  /**
10
35
  * @member {String} className='Neo.grid.Container'
@@ -17,130 +42,183 @@ class Container extends BaseContainer {
17
42
  */
18
43
  ntype: 'grid-container',
19
44
  /**
20
- * todo: testing config, remove when Stores are ready
21
- * @member {Number} amountRows=20
45
+ * @member {String[]} cls=['neo-grid-container']
22
46
  */
23
- amountRows: 20,
47
+ cls: ['neo-grid-container'],
24
48
  /**
25
- * @member {Array} cls=['neo-grid-container']
49
+ * @member {Object[]} columns_=[]
26
50
  */
27
- cls: ['neo-grid-container'],
51
+ columns_: [],
28
52
  /**
29
- * @member {Array} columns=[]
53
+ * Additional used keys for the selection model
54
+ * @member {Object} keys={}
30
55
  */
31
- columns: [],
56
+ keys: {},
32
57
  /**
33
- * @member {String} _layout='base'
58
+ * @member {String} layout='base'
34
59
  */
35
- _layout: 'base',
60
+ layout: 'base',
36
61
  /**
37
- * @member {Array} _items
62
+ * @member {Neo.selection.Model} selectionModel_=null
38
63
  */
39
- _items: [
40
- {
41
- ntype: 'grid-header-toolbar'
42
- },
43
- {
44
- ntype: 'grid-view'
45
- }/*,
46
- {
47
- ntype: 'component',
48
- cls : ['neo-grid-y-scroller'],
49
- style: {
50
- height: 'calc(100% - 32px)',
51
- top : '32px'
52
- },
53
- vdom: {
54
- cn: [{
55
- height: 800
56
- }]
57
- }
58
- }*/
59
- ],
64
+ selectionModel_: null,
65
+ /**
66
+ * @member {Neo.data.Store} store_=null
67
+ */
68
+ store_: null,
60
69
  /**
61
- * @member {Object} _vdom
70
+ * @member {Object} _vdom={cls:['neo-grid-wrapper'],cn:[{cn:[]}]}
62
71
  */
63
72
  _vdom:
64
- {style: {height: '300px', width: '100%'}, cn: [
65
- {cls: ['neo-grid-container'], cn: []}
73
+ {cls: ['neo-grid-wrapper'], cn: [
74
+ {cn: []}
66
75
  ]}
67
76
  }}
68
77
 
69
- get columns() {
70
- return this._columns;
71
- }
72
- set columns(value) {
73
- this._columns = this.createColumns(value); // todo: beforeSetColumns
74
- }
75
-
76
78
  /**
77
79
  * @param {Object} config
78
80
  */
79
81
  construct(config) {
80
82
  super.construct(config);
81
83
 
82
- this.createRandomViewData(this.amountRows);
84
+ let me = this;
85
+
86
+ me.headerToolbarId = Neo.getId('grid-header-toolbar');
87
+ me.viewId = Neo.getId('grid-view');
88
+
89
+ me.items = [{
90
+ module : header.Toolbar,
91
+ id : me.headerToolbarId,
92
+ showHeaderFilters: me.showHeaderFilters,
93
+ ...me.headerToolbarConfig
94
+ }, {
95
+ module : View,
96
+ containerId: me.id,
97
+ id : me.viewId,
98
+ store : me.store,
99
+ ...me.viewConfig
100
+ }];
101
+
102
+ me.vdom.id = me.id + 'wrapper';
103
+
104
+ me.createColumns(me.columns);
83
105
  }
84
106
 
85
107
  /**
86
- * @param columns
87
- * @returns {*}
108
+ * Triggered after the selectionModel config got changed
109
+ * @param {Neo.selection.Model} value
110
+ * @param {Neo.selection.Model} oldValue
111
+ * @protected
88
112
  */
89
- createColumns(columns) {
90
- let me = this;
113
+ afterSetSelectionModel(value, oldValue) {
114
+ this.rendered && value.register(this);
115
+ }
91
116
 
92
- if (!columns || !columns.length) {
93
- Neo.logError('Attempting to create a grid.Container without defined columns', me.id);
117
+ /**
118
+ * Triggered before the columns config gets changed.
119
+ * @param {Object[]} value
120
+ * @param {Object[]} oldValue
121
+ * @protected
122
+ */
123
+ beforeSetColumns(value, oldValue) {
124
+ if (this.configsApplied) {
125
+ return this.createColumns(value);
94
126
  }
95
127
 
96
- columns.forEach(function(column) {
97
- if (column.locked && !column.width) {
98
- Neo.logError('Attempting to create a locked column without a defined width', column, me.id);
99
- }
100
- });
101
-
102
- me.items[0].items = columns;
128
+ return value;
129
+ }
103
130
 
104
- return columns;
131
+ /**
132
+ * Triggered before the selectionModel config gets changed.
133
+ * @param {Neo.selection.Model} value
134
+ * @param {Neo.selection.Model} oldValue
135
+ * @protected
136
+ */
137
+ beforeSetSelectionModel(value, oldValue) {
138
+ oldValue?.destroy();
105
139
 
140
+ return ClassSystemUtil.beforeSetInstance(value, RowModel);
106
141
  }
107
142
 
108
143
  /**
109
- * Dummy method until we have a data package in place
110
- * @param {Number} amountRows
144
+ * Triggered before the store config gets changed.
145
+ * @param {Neo.data.Store} value
146
+ * @param {Neo.data.Store} oldValue
147
+ * @protected
111
148
  */
112
- createRandomViewData(amountRows) {
113
- let me = this,
114
- columns = me.items[0].items,
115
- i = 0,
116
- data = [],
117
- vdom = me.items[1].vdom;
149
+ beforeSetStore(value, oldValue) {
150
+ oldValue?.destroy();
118
151
 
119
- for (; i < amountRows; i++) {
120
- data.push({
121
- cls: ['neo-grid-row'],
122
- cn : []
123
- });
152
+ if (value) {
153
+ let me = this,
154
+
155
+ listeners = {
156
+ filter : me.onStoreFilter,
157
+ load : me.onStoreLoad,
158
+ recordChange: me.onStoreRecordChange,
159
+ scope : me
160
+ };
124
161
 
125
- columns.forEach(function(column, index) {
126
- data[i].cn.push({
127
- cls : ['neo-grid-cell'],
128
- innerHTML: 'Column' + (index + 1) + ' - ' + Math.round(Math.random() / 1.5),
129
- style: {
130
- backgroundColor: Math.round(Math.random() / 1.7) > 0 ? 'brown' : '#3c3f41'
131
- }
162
+ if (value instanceof Store) {
163
+ value.on(listeners);
164
+ value.getCount() > 0 && me.onStoreLoad(value.items);
165
+ } else {
166
+ value = ClassSystemUtil.beforeSetInstance(value, Store, {
167
+ listeners
132
168
  });
133
- });
169
+ }
170
+
171
+ // in case we dynamically change the store, the view needs to get the new reference
172
+ if (me.view) {
173
+ me.view.store = value;
174
+ }
134
175
  }
135
176
 
136
- vdom.cn = data;
177
+ return value;
178
+ }
137
179
 
138
- // we want to ignore id checks inside of the vdom helper
139
- if (me.items[1].vnode) {
140
- me.syncVdomIds(me.items[1].vnode, vdom);
180
+ /**
181
+ * @param {Object[]} columns
182
+ * @returns {*}
183
+ */
184
+ createColumns(columns) {
185
+ let me = this,
186
+ columnDefaults = me.columnDefaults,
187
+ sorters = me.store?.sorters;
188
+
189
+ if (!columns || !columns.length) {
190
+ Neo.logError('Attempting to create a grid.Container without defined columns', me.id);
141
191
  }
142
192
 
143
- me.items[1].vdom = vdom;
193
+ columns.forEach(column => {
194
+ columnDefaults && Neo.assignDefaults(column, columnDefaults);
195
+
196
+ if (column.dock && !column.width) {
197
+ Neo.logError('Attempting to create a docked column without a defined width', column, me.id);
198
+ }
199
+
200
+ if (sorters?.[0]) {
201
+ if (column.field === sorters[0].property) {
202
+ column.isSorted = sorters[0].direction;
203
+ }
204
+ }
205
+
206
+ column.listeners = {
207
+ sort : me.onSortColumn,
208
+ scope: me
209
+ };
210
+ });
211
+
212
+ me.items[0].items = columns;
213
+
214
+ return columns;
215
+ }
216
+
217
+ /**
218
+ * @param {Object[]} inputData
219
+ */
220
+ createViewData(inputData) {
221
+ this.getView().createViewData(inputData);
144
222
  }
145
223
 
146
224
  /**
@@ -151,6 +229,20 @@ class Container extends BaseContainer {
151
229
  return this.vdom.cn[0];
152
230
  }
153
231
 
232
+ /**
233
+ * @returns {Object[]} The new vdom items root
234
+ */
235
+ getVdomItemsRoot() {
236
+ return this.vdom.cn[0];
237
+ }
238
+
239
+ /**
240
+ * @returns {Neo.grid.View}
241
+ */
242
+ getView() {
243
+ return Neo.getComponent(this.viewId) || Neo.get(this.viewId);
244
+ }
245
+
154
246
  /**
155
247
  * @override
156
248
  * @returns {Neo.vdom.VNode}
@@ -158,6 +250,83 @@ class Container extends BaseContainer {
158
250
  getVnodeRoot() {
159
251
  return this.vnode.childNodes[0];
160
252
  }
253
+
254
+ /**
255
+ *
256
+ */
257
+ onConstructed() {
258
+ super.onConstructed();
259
+ this.selectionModel?.register(this);
260
+ }
261
+
262
+ /**
263
+ * @param {Object} opts
264
+ * @param {String} opts.direction
265
+ * @param {String} opts.property
266
+ * @protected
267
+ */
268
+ onSortColumn(opts) {
269
+ let me = this;
270
+
271
+ me.store.sort(opts);
272
+ me.removeSortingCss(opts.property);
273
+ me.onStoreLoad(me.store.items);
274
+ }
275
+
276
+ /**
277
+ *
278
+ */
279
+ onStoreFilter() {
280
+ this.onStoreLoad(this.store.items);
281
+ }
282
+
283
+ /**
284
+ * @param {Object[]} data
285
+ * @protected
286
+ */
287
+ onStoreLoad(data) {
288
+ let me = this,
289
+ listenerId;
290
+
291
+ if (me.rendered) {
292
+ me.createViewData(data);
293
+
294
+ if (me.store.sorters.length < 1) {
295
+ me.removeSortingCss();
296
+ }
297
+ } else {
298
+ listenerId = me.on('rendered', () => {
299
+ me.un('rendered', listenerId);
300
+ setTimeout(() => {
301
+ me.createViewData(data);
302
+ }, 50);
303
+ });
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Gets triggered after changing the value of a record field.
309
+ * E.g. myRecord.foo = 'bar';
310
+ * @param {Object} opts
311
+ * @param {String} opts.field The name of the field which got changed
312
+ * @param {Neo.data.Model} opts.model The model instance of the changed record
313
+ * @param {*} opts.oldValue
314
+ * @param {Object} opts.record
315
+ * @param {*} opts.value
316
+ */
317
+ onStoreRecordChange(opts) {
318
+ this.getView().onStoreRecordChange(opts);
319
+ }
320
+
321
+ /**
322
+ * @param {String} field
323
+ * @protected
324
+ */
325
+ removeSortingCss(field) {
326
+ this.items[0].items.forEach(column => {
327
+ column.field !== field && column.removeSortingCss();
328
+ });
329
+ }
161
330
  }
162
331
 
163
332
  Neo.applyClassConfig(Container);