neo.mjs 8.0.0 → 8.0.1

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 (55) hide show
  1. package/apps/ServiceWorker.mjs +2 -2
  2. package/apps/portal/index.html +1 -1
  3. package/apps/portal/view/about/Container.mjs +0 -2
  4. package/apps/portal/view/about/MemberContainer.mjs +1 -20
  5. package/apps/portal/view/home/FooterContainer.mjs +1 -5
  6. package/examples/ConfigurationViewport.mjs +37 -32
  7. package/examples/ServiceWorker.mjs +2 -2
  8. package/examples/grid/cellEditing/MainContainer.mjs +175 -0
  9. package/examples/grid/cellEditing/MainContainerStateProvider.mjs +62 -0
  10. package/examples/grid/cellEditing/MainModel.mjs +30 -0
  11. package/examples/grid/cellEditing/MainStore.mjs +54 -0
  12. package/examples/grid/cellEditing/app.mjs +6 -0
  13. package/examples/grid/cellEditing/index.html +11 -0
  14. package/examples/grid/cellEditing/neo-config.json +6 -0
  15. package/examples/grid/container/MainContainer.mjs +7 -6
  16. package/examples/grid/covid/GridContainer.mjs +36 -36
  17. package/examples/grid/covid/Util.mjs +1 -1
  18. package/examples/table/cellEditing/MainContainer.mjs +174 -0
  19. package/examples/table/cellEditing/MainContainerStateProvider.mjs +62 -0
  20. package/examples/table/cellEditing/MainModel.mjs +30 -0
  21. package/examples/table/cellEditing/MainStore.mjs +54 -0
  22. package/examples/table/cellEditing/app.mjs +6 -0
  23. package/examples/table/cellEditing/index.html +11 -0
  24. package/examples/table/cellEditing/neo-config.json +6 -0
  25. package/examples/table/nestedRecordFields/MainContainerStateProvider.mjs +2 -1
  26. package/package.json +5 -5
  27. package/resources/scss/src/apps/portal/home/FooterContainer.scss +11 -2
  28. package/resources/scss/src/grid/Container.scss +0 -13
  29. package/resources/scss/src/grid/plugin/CellEditing.scss +11 -0
  30. package/resources/scss/src/table/plugin/CellEditing.scss +11 -0
  31. package/src/DefaultConfig.mjs +2 -2
  32. package/src/component/DateSelector.mjs +15 -0
  33. package/src/form/field/Base.mjs +1 -4
  34. package/src/form/field/ComboBox.mjs +18 -2
  35. package/src/form/field/Date.mjs +10 -4
  36. package/src/grid/Container.mjs +242 -39
  37. package/src/grid/README.md +1 -1
  38. package/src/grid/View.mjs +282 -129
  39. package/src/grid/header/Button.mjs +327 -36
  40. package/src/grid/header/Toolbar.mjs +68 -4
  41. package/src/grid/plugin/CellEditing.mjs +30 -0
  42. package/src/main/DomEvents.mjs +12 -3
  43. package/src/manager/Focus.mjs +2 -2
  44. package/src/plugin/Base.mjs +15 -1
  45. package/src/plugin/Resizable.mjs +1 -5
  46. package/src/selection/Model.mjs +5 -1
  47. package/src/selection/grid/CellColumnModel.mjs +1 -1
  48. package/src/selection/grid/CellColumnRowModel.mjs +1 -1
  49. package/src/selection/grid/CellModel.mjs +1 -1
  50. package/src/selection/grid/ColumnModel.mjs +2 -2
  51. package/src/table/Container.mjs +32 -3
  52. package/src/table/View.mjs +9 -4
  53. package/src/table/header/Toolbar.mjs +15 -1
  54. package/src/table/plugin/CellEditing.mjs +330 -0
  55. package/src/util/KeyNavigation.mjs +14 -8
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='8.0.0'
23
+ * @member {String} version='8.0.1'
24
24
  */
25
- version: '8.0.0'
25
+ version: '8.0.1'
26
26
  }
27
27
 
28
28
  /**
@@ -16,7 +16,7 @@
16
16
  "@type": "Organization",
17
17
  "name": "Neo.mjs"
18
18
  },
19
- "datePublished": "2024-12-14",
19
+ "datePublished": "2024-12-29",
20
20
  "publisher": {
21
21
  "@type": "Organization",
22
22
  "name": "Neo.mjs"
@@ -29,7 +29,6 @@ class Container extends Base {
29
29
  picture : 'tobiu.png',
30
30
  profileGitHub : 'https://github.com/tobiu',
31
31
  profileLinkedIn: 'https://www.linkedin.com/in/tobiasuhlig/',
32
- profileX : 'https://x.com/UhligTobias',
33
32
  teamRole : 'Co-Founder & Core Team Member'
34
33
  }, {
35
34
  module : MemberContainer,
@@ -38,7 +37,6 @@ class Container extends Base {
38
37
  picture : 'rwaters.png',
39
38
  profileGitHub : 'https://github.com/rwaters',
40
39
  profileLinkedIn: 'https://www.linkedin.com/in/rwaters/',
41
- profileX : 'https://x.com/rwaters',
42
40
  teamRole : 'Co-Founder & Core Team Member'
43
41
  }, {
44
42
  module : MemberContainer,
@@ -36,10 +36,6 @@ class MemberContainer extends Container {
36
36
  * @member {String|null} profileLinkedIn_=null
37
37
  */
38
38
  profileLinkedIn_: null,
39
- /**
40
- * @member {String|null} profileX_=null
41
- */
42
- profileX_: null,
43
39
  /**
44
40
  * @member {String|null} teamRole_=null
45
41
  */
@@ -56,8 +52,6 @@ class MemberContainer extends Container {
56
52
  iconCls: 'portal-profile fa-brands fa-github'
57
53
  }, {
58
54
  iconCls: 'portal-profile fa-brands fa-linkedin'
59
- }, {
60
- iconCls: 'portal-profile fa-brands fa-x-twitter'
61
55
  }]
62
56
  }, {
63
57
  cls : ['portal-profile-component'],
@@ -141,16 +135,6 @@ class MemberContainer extends Container {
141
135
  this.updateProfileButton(this.items[0].items[1], value)
142
136
  }
143
137
 
144
- /**
145
- * Triggered after the profileX config got changed
146
- * @param {String|null} value
147
- * @param {String|null} oldValue
148
- * @protected
149
- */
150
- afterSetProfileX(value, oldValue) {
151
- this.updateProfileButton(this.items[0].items[2], value)
152
- }
153
-
154
138
  /**
155
139
  * Triggered after the teamRole config got changed
156
140
  * @param {String|null} value
@@ -174,10 +158,7 @@ class MemberContainer extends Container {
174
158
  */
175
159
  updateProfileButton(button, url) {
176
160
  if (button.set) {
177
- button.set({
178
- hidden: !url,
179
- url
180
- })
161
+ button.set({hidden: !url, url})
181
162
  } else {
182
163
  // initial values
183
164
  button.hidden = !url;
@@ -101,17 +101,13 @@ class FooterContainer extends Container {
101
101
  iconCls: 'fa-brands fa-facebook',
102
102
  text : 'Facebook',
103
103
  url : 'https://www.facebook.com/neo.mjs'
104
- }, {
105
- iconCls: 'fa-brands fa-x-twitter',
106
- text : 'X',
107
- url : 'https://x.com/neomjs1'
108
104
  }, {
109
105
  module: Component,
110
106
  cls : ['portal-home-footer-spacer']
111
107
  }, {
112
108
  module: Component,
113
109
  cls : ['neo-version'],
114
- html : 'v8.0.0'
110
+ html : 'v8.0.1'
115
111
  }]
116
112
  }],
117
113
  /**
@@ -59,6 +59,37 @@ class ConfigurationViewport extends Viewport {
59
59
  exampleComponentFlex: 2
60
60
  }
61
61
 
62
+ /**
63
+ * Override this method to create the components to show inside the configuration container
64
+ * @returns {Object[]|null}
65
+ */
66
+ createConfigurationComponents() {
67
+ return null
68
+ }
69
+
70
+ /**
71
+ * Override this method to create the component to show inside the current example
72
+ * @returns {Object|Neo.component.Base|null}
73
+ */
74
+ createExampleComponent() {
75
+ return null
76
+ }
77
+
78
+ /**
79
+ * @param {Object} data
80
+ */
81
+ logInstance(data) {
82
+ console.log(this.exampleComponent)
83
+ }
84
+
85
+ /**
86
+ * @param {String} config
87
+ * @param {Object} opts
88
+ */
89
+ onConfigChange(config, opts) {
90
+ this.exampleComponent[config] = opts.value
91
+ }
92
+
62
93
  /**
63
94
  *
64
95
  */
@@ -71,7 +102,12 @@ class ConfigurationViewport extends Viewport {
71
102
  delete me.exampleContainerConfig.style
72
103
  }
73
104
 
74
- me.exampleComponent = me.createExampleComponent();
105
+ me.exampleComponent = me.createExampleComponent();
106
+
107
+ if (Neo.isObject(me.exampleComponent)) {
108
+ me.exampleComponent = Neo.create(me.exampleComponent)
109
+ }
110
+
75
111
  me.configurationComponents = me.createConfigurationComponents() || [];
76
112
 
77
113
  theme = me.exampleComponent.getTheme();
@@ -135,37 +171,6 @@ class ConfigurationViewport extends Viewport {
135
171
  super.onConstructed()
136
172
  }
137
173
 
138
- /**
139
- * Override this method to create the components to show inside the configuration container
140
- * @returns {Object[]|null}
141
- */
142
- createConfigurationComponents() {
143
- return null
144
- }
145
-
146
- /**
147
- * Override this method to create the component to show inside the current example
148
- * @returns {Neo.component.Base|null}
149
- */
150
- createExampleComponent() {
151
- return null
152
- }
153
-
154
- /**
155
- * @param {Object} data
156
- */
157
- logInstance(data) {
158
- console.log(this.exampleComponent)
159
- }
160
-
161
- /**
162
- * @param {String} config
163
- * @param {Object} opts
164
- */
165
- onConfigChange(config, opts) {
166
- this.exampleComponent[config] = opts.value
167
- }
168
-
169
174
  /**
170
175
  * @param {String} config
171
176
  * @param {String} value
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='8.0.0'
23
+ * @member {String} version='8.0.1'
24
24
  */
25
- version: '8.0.0'
25
+ version: '8.0.1'
26
26
  }
27
27
 
28
28
  /**
@@ -0,0 +1,175 @@
1
+ import CellColumnModel from '../../../src/selection/grid/CellColumnModel.mjs';
2
+ import CellColumnRowModel from '../../../src/selection/grid/CellColumnRowModel.mjs';
3
+ import CellModel from '../../../src/selection/grid/CellModel.mjs';
4
+ import CellRowModel from '../../../src/selection/grid/CellRowModel.mjs';
5
+ import CheckBox from '../../../src/form/field/CheckBox.mjs';
6
+ import CountryField from '../../../src/form/field/Country.mjs';
7
+ import ConfigurationViewport from '../../ConfigurationViewport.mjs';
8
+ import DateField from '../../../src/form/field/Date.mjs';
9
+ import GridContainer from '../../../src/grid/Container.mjs';
10
+ import MainContainerStateProvider from './MainContainerStateProvider.mjs';
11
+ import MainStore from './MainStore.mjs';
12
+ import NumberField from '../../../src/form/field/Number.mjs';
13
+ import Radio from '../../../src/form/field/Radio.mjs';
14
+
15
+ /**
16
+ * @class Neo.examples.grid.cellEditing.MainContainer
17
+ * @extends Neo.examples.ConfigurationViewport
18
+ */
19
+ class MainContainer extends ConfigurationViewport {
20
+ static config = {
21
+ className : 'Neo.examples.grid.cellEditing.MainContainer',
22
+ autoMount : true,
23
+ configItemLabelWidth: 130,
24
+ configPanelFlex : 1.5,
25
+ exampleComponentFlex: 3,
26
+ layout : {ntype: 'hbox', align: 'stretch'},
27
+ stateProvider : MainContainerStateProvider
28
+ }
29
+
30
+ /**
31
+ * @param {Object} data
32
+ */
33
+ countryRenderer({record}) {
34
+ let countryStore = this.getStateProvider().getStore('countries');
35
+
36
+ if (countryStore.getCount() > 0) {
37
+ return countryStore.get(record.country).name
38
+ }
39
+
40
+ return ''
41
+ }
42
+
43
+ /**
44
+ * @returns {Object[]}
45
+ */
46
+ createConfigurationComponents() {
47
+ let me = this;
48
+
49
+ const selectionModelRadioDefaults = {
50
+ module : Radio,
51
+ hideValueLabel: false,
52
+ labelText : '',
53
+ name : 'selectionModel',
54
+ width : 350
55
+ };
56
+
57
+ return [{
58
+ module : NumberField,
59
+ labelText: 'height',
60
+ listeners: {change: me.onConfigChange.bind(me, 'height')},
61
+ maxValue : 800,
62
+ minValue : 225,
63
+ stepSize : 5,
64
+ value : me.exampleComponent.height
65
+ }, {
66
+ ...selectionModelRadioDefaults,
67
+ checked : me.exampleComponent.selectionModel.ntype === 'selection-grid-cellmodel',
68
+ labelText : 'selectionModel',
69
+ listeners : {change: me.onRadioChange.bind(me, 'selectionModel', CellModel)},
70
+ style : {marginTop: '10px'},
71
+ valueLabelText: 'Cell'
72
+ }, {
73
+ ...selectionModelRadioDefaults,
74
+ checked : me.exampleComponent.selectionModel.ntype === 'selection-grid-cellcolumnmodel',
75
+ listeners : {change: me.onRadioChange.bind(me, 'selectionModel', CellColumnModel)},
76
+ valueLabelText: 'Cell & Column'
77
+ }, {
78
+ ...selectionModelRadioDefaults,
79
+ checked : me.exampleComponent.selectionModel.ntype === 'selection-grid-cellrowmodel',
80
+ listeners : {change: me.onRadioChange.bind(me, 'selectionModel', CellRowModel)},
81
+ valueLabelText: 'Cell & Row'
82
+ }, {
83
+ ...selectionModelRadioDefaults,
84
+ checked : me.exampleComponent.selectionModel.ntype === 'selection-grid-cellcolumnrowmodel',
85
+ listeners : {change: me.onRadioChange.bind(me, 'selectionModel', CellColumnRowModel)},
86
+ valueLabelText: 'Cell & Column & Row'
87
+ }, {
88
+ module : CheckBox,
89
+ checked : me.exampleComponent.sortable,
90
+ hideLabel : true,
91
+ listeners : {change: me.onConfigChange.bind(me, 'sortable')},
92
+ style : {marginTop: '10px'},
93
+ valueLabelText: 'sortable'
94
+ }, {
95
+ module : CheckBox,
96
+ checked : false, // we can not access the lazy-loaded plugin yet
97
+ hideLabel : true,
98
+ listeners : {change: me.onPluginConfigChange.bind(me, 'disabled')},
99
+ style : {marginTop: '10px'},
100
+ valueLabelText: 'Disable CellEditing'
101
+ }]
102
+ }
103
+
104
+ /**
105
+ * @returns {Object}
106
+ */
107
+ createExampleComponent() {
108
+ return {
109
+ module : GridContainer,
110
+ bind : {store : 'stores.mainStore'},
111
+ cellEditing : true,
112
+ parentId : this.id,
113
+ selectionModel: CellModel,
114
+ store : MainStore,
115
+
116
+ columnDefaults: {
117
+ editable: true,
118
+ width : 200
119
+ },
120
+
121
+ columns: [{
122
+ dataField: 'firstname',
123
+ text : 'Firstname'
124
+ }, {
125
+ dataField: 'randomNumber',
126
+ text : 'Number (step 5)',
127
+
128
+ editor: {
129
+ module : NumberField,
130
+ clearable: false,
131
+ maxValue : 100,
132
+ minValue : 0,
133
+ stepSize : 5
134
+ }
135
+ }, {
136
+ dataField: 'randomDate',
137
+ renderer : ({value}) => new Intl.DateTimeFormat('default').format(value),
138
+ text : 'Random Date',
139
+
140
+ editor: {
141
+ module : DateField,
142
+ clearable: false,
143
+ maxValue : '2024-12-20',
144
+ minValue : '2024-12-10'
145
+ }
146
+ }, {
147
+ dataField: 'country',
148
+ renderer : 'up.countryRenderer',
149
+ text : 'Country',
150
+
151
+ editor: {
152
+ module : CountryField,
153
+ bind : {store: 'stores.countries'},
154
+ clearable : false,
155
+ forceSelection: true,
156
+ valueField : 'code'
157
+ }
158
+ }, {
159
+ dataField: 'githubId',
160
+ editable : false,
161
+ text : 'Github Id (Non-editable)'
162
+ }]
163
+ }
164
+ }
165
+
166
+ /**
167
+ * @param {String} config
168
+ * @param {Object} opts
169
+ */
170
+ onPluginConfigChange(config, opts) {
171
+ this.exampleComponent.getPlugin('grid-cell-editing')[config] = opts.value
172
+ }
173
+ }
174
+
175
+ export default Neo.setupClass(MainContainer);
@@ -0,0 +1,62 @@
1
+ import MainStore from './MainStore.mjs';
2
+ import StateProvider from '../../../src/state/Provider.mjs';
3
+ import Store from '../../../src/data/Store.mjs';
4
+
5
+ const countrySymbol = Symbol.for('country');
6
+
7
+ /**
8
+ * @class Neo.examples.grid.cellEditing.MainContainerStateProvider
9
+ * @extends Neo.state.Provider
10
+ */
11
+ class MainContainerStateProvider extends StateProvider {
12
+ static config = {
13
+ /**
14
+ * @member {String} className='Neo.examples.grid.cellEditing.MainContainerStateProvider'
15
+ * @protected
16
+ */
17
+ className: 'Neo.examples.grid.cellEditing.MainContainerStateProvider',
18
+ /**
19
+ * @member {Object} stores
20
+ */
21
+ stores: {
22
+ countries: {
23
+ module : Store,
24
+ autoLoad : true,
25
+ keyProperty: 'code',
26
+ listeners : {load: 'onCountryStoreLoad'},
27
+ url : '../../../resources/examples/data/countries.json',
28
+
29
+ model: {
30
+ fields: [
31
+ {name: 'code'},
32
+ {name: 'name'}
33
+ ]
34
+ }
35
+ },
36
+ mainStore: MainStore
37
+ }
38
+ }
39
+
40
+ /**
41
+ * @param {Record[]} items
42
+ */
43
+ onCountryStoreLoad(items) {
44
+ let me = this,
45
+ mainStore = me.getStore('mainStore'),
46
+ country;
47
+
48
+ // if the main table store is already loaded, the country field renderer had no data
49
+ if (mainStore.getCount() > 0) {
50
+ mainStore.items.forEach(record => {
51
+ country = record.country;
52
+
53
+ // hack resetting the current value to get a new record change
54
+ record[countrySymbol] = null;
55
+
56
+ record.country = country
57
+ })
58
+ }
59
+ }
60
+ }
61
+
62
+ export default Neo.setupClass(MainContainerStateProvider);
@@ -0,0 +1,30 @@
1
+ import Model from '../../../src/data/Model.mjs';
2
+
3
+ /**
4
+ * @class Neo.examples.grid.cellEditing.MainModel
5
+ * @extends Neo.data.Model
6
+ */
7
+ class MainModel extends Model {
8
+ static config = {
9
+ className: 'Neo.examples.grid.cellEditing.MainModel',
10
+
11
+ fields: [{
12
+ name: 'country',
13
+ type: 'String'
14
+ }, {
15
+ name: 'firstname',
16
+ type: 'String'
17
+ }, {
18
+ name: 'githubId',
19
+ type: 'String'
20
+ }, {
21
+ name: 'randomNumber',
22
+ type: 'Int'
23
+ }, {
24
+ name: 'randomDate',
25
+ type: 'Date'
26
+ }]
27
+ }
28
+ }
29
+
30
+ export default Neo.setupClass(MainModel);
@@ -0,0 +1,54 @@
1
+ import Model from './MainModel.mjs';
2
+ import Store from '../../../src/data/Store.mjs';
3
+
4
+ /**
5
+ * @class Neo.examples.grid.cellEditing.MainStore
6
+ * @extends Neo.data.Store
7
+ */
8
+ class MainStore extends Store {
9
+ static config = {
10
+ className : 'Neo.examples.grid.cellEditing.MainStore',
11
+ keyProperty: 'githubId',
12
+ model : Model,
13
+
14
+ data: [{
15
+ country : 'DE',
16
+ firstname : 'Tobias',
17
+ githubId : 'tobiu',
18
+ randomDate : '2024-12-20',
19
+ randomNumber: 100
20
+ }, {
21
+ country : 'US',
22
+ firstname : 'Rich',
23
+ githubId : 'rwaters',
24
+ randomDate : '2024-12-18',
25
+ randomNumber: 90
26
+ }, {
27
+ country : 'DE',
28
+ firstname : 'Nils',
29
+ githubId : 'mrsunshine',
30
+ randomDate : '2024-12-19',
31
+ randomNumber: 70
32
+ }, {
33
+ country : 'US',
34
+ firstname : 'Gerard',
35
+ githubId : 'camtnbikerrwc',
36
+ randomDate : '2024-12-17',
37
+ randomNumber: 80
38
+ }, {
39
+ country : 'SK',
40
+ firstname : 'Jozef',
41
+ githubId : 'jsakalos',
42
+ randomDate : '2024-12-16',
43
+ randomNumber: 60
44
+ }, {
45
+ country : 'DE',
46
+ firstname : 'Bastian',
47
+ githubId : 'bhaustein',
48
+ randomDate : '2024-12-15',
49
+ randomNumber: 50
50
+ }]
51
+ }
52
+ }
53
+
54
+ export default Neo.setupClass(MainStore);
@@ -0,0 +1,6 @@
1
+ import MainContainer from './MainContainer.mjs';
2
+
3
+ export const onStart = () => Neo.app({
4
+ mainView: MainContainer,
5
+ name : 'Neo.examples.grid.cellEditing'
6
+ });
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE HTML>
2
+ <html>
3
+ <head>
4
+ <meta name="viewport" content="width=device-width, initial-scale=1">
5
+ <meta charset="UTF-8">
6
+ <title>Neo Grid CellEditing</title>
7
+ </head>
8
+ <body>
9
+ <script src="../../../src/MicroLoader.mjs" type="module"></script>
10
+ </body>
11
+ </html>
@@ -0,0 +1,6 @@
1
+ {
2
+ "appPath" : "examples/grid/cellEditing/app.mjs",
3
+ "basePath" : "../../../",
4
+ "environment": "development",
5
+ "mainPath" : "./Main.mjs"
6
+ }
@@ -79,7 +79,8 @@ class MainContainer extends ConfigurationViewport {
79
79
  }
80
80
 
81
81
  createExampleComponent() {
82
- return Neo.create(GridContainer, {
82
+ return {
83
+ module : GridContainer,
83
84
  selectionModel: CellModel,
84
85
  store : MainStore,
85
86
 
@@ -88,12 +89,12 @@ class MainContainer extends ConfigurationViewport {
88
89
  },
89
90
 
90
91
  columns: [
91
- {field: 'firstname', text: 'Firstname'},
92
- {field: 'lastname', text: 'Lastname'},
93
- {field: 'githubId', text: 'Github Id'},
94
- {field: 'country', text: 'Country'}
92
+ {dataField: 'firstname', text: 'Firstname'},
93
+ {dataField: 'lastname', text: 'Lastname'},
94
+ {dataField: 'githubId', text: 'Github Id'},
95
+ {dataField: 'country', text: 'Country'}
95
96
  ]
96
- })
97
+ }
97
98
  }
98
99
  }
99
100