neo.mjs 8.0.0 → 8.1.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/apps/ServiceWorker.mjs +2 -2
- package/apps/portal/index.html +1 -1
- package/apps/portal/view/about/Container.mjs +0 -2
- package/apps/portal/view/about/MemberContainer.mjs +1 -20
- package/apps/portal/view/home/FooterContainer.mjs +1 -5
- package/examples/ConfigurationViewport.mjs +37 -32
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/grid/cellEditing/MainContainer.mjs +175 -0
- package/examples/grid/cellEditing/MainContainerStateProvider.mjs +62 -0
- package/examples/grid/cellEditing/MainModel.mjs +30 -0
- package/examples/grid/cellEditing/MainStore.mjs +54 -0
- package/examples/grid/cellEditing/app.mjs +6 -0
- package/examples/grid/cellEditing/index.html +11 -0
- package/examples/grid/cellEditing/neo-config.json +6 -0
- package/examples/grid/container/MainContainer.mjs +7 -6
- package/examples/grid/covid/GridContainer.mjs +36 -36
- package/examples/grid/covid/Util.mjs +1 -1
- package/examples/grid/covid/neo-config.json +6 -5
- package/examples/table/cellEditing/MainContainer.mjs +174 -0
- package/examples/table/cellEditing/MainContainerStateProvider.mjs +62 -0
- package/examples/table/cellEditing/MainModel.mjs +30 -0
- package/examples/table/cellEditing/MainStore.mjs +54 -0
- package/examples/table/cellEditing/app.mjs +6 -0
- package/examples/table/cellEditing/index.html +11 -0
- package/examples/table/cellEditing/neo-config.json +6 -0
- package/examples/table/nestedRecordFields/MainContainerStateProvider.mjs +2 -1
- package/package.json +8 -8
- package/resources/scss/src/apps/portal/home/FooterContainer.scss +11 -2
- package/resources/scss/src/examples/grid/covid/GridContainer.scss +1 -1
- package/resources/scss/src/grid/Container.scss +13 -23
- package/resources/scss/src/grid/View.scss +45 -19
- package/resources/scss/src/grid/header/Button.scss +2 -4
- package/resources/scss/src/grid/header/Toolbar.scss +1 -2
- package/resources/scss/src/grid/plugin/CellEditing.scss +11 -0
- package/resources/scss/src/table/plugin/CellEditing.scss +11 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/Xhr.mjs +1 -1
- package/src/button/Base.mjs +2 -2
- package/src/collection/Base.mjs +5 -5
- package/src/component/Base.mjs +3 -3
- package/src/component/DateSelector.mjs +15 -0
- package/src/container/Base.mjs +2 -2
- package/src/controller/Base.mjs +3 -3
- package/src/dialog/Base.mjs +2 -2
- package/src/form/field/Base.mjs +3 -6
- package/src/form/field/CheckBox.mjs +2 -2
- package/src/form/field/ComboBox.mjs +18 -2
- package/src/form/field/Date.mjs +10 -4
- package/src/form/field/FileUpload.mjs +4 -4
- package/src/form/field/Hidden.mjs +2 -2
- package/src/form/field/Text.mjs +2 -2
- package/src/grid/Container.mjs +340 -43
- package/src/grid/View.mjs +599 -124
- package/src/grid/header/Button.mjs +331 -36
- package/src/grid/header/Toolbar.mjs +111 -4
- package/src/grid/plugin/CellEditing.mjs +30 -0
- package/src/layout/Base.mjs +3 -3
- package/src/list/Base.mjs +2 -2
- package/src/list/Circle.mjs +2 -2
- package/src/list/Color.mjs +2 -2
- package/src/list/Component.mjs +2 -2
- package/src/main/DomEvents.mjs +12 -3
- package/src/manager/Base.mjs +3 -3
- package/src/manager/Component.mjs +20 -11
- package/src/manager/DomEvent.mjs +5 -6
- package/src/manager/Focus.mjs +2 -2
- package/src/manager/Instance.mjs +4 -4
- package/src/manager/Task.mjs +2 -2
- package/src/manager/Toast.mjs +3 -3
- package/src/plugin/Base.mjs +18 -4
- package/src/plugin/Popover.mjs +3 -3
- package/src/plugin/PrefixField.mjs +2 -2
- package/src/plugin/Resizable.mjs +3 -7
- package/src/plugin/Responsive.mjs +2 -2
- package/src/selection/Model.mjs +17 -2
- package/src/selection/grid/CellColumnModel.mjs +1 -1
- package/src/selection/grid/CellColumnRowModel.mjs +1 -1
- package/src/selection/grid/CellModel.mjs +1 -1
- package/src/selection/grid/ColumnModel.mjs +2 -2
- package/src/table/Container.mjs +32 -3
- package/src/table/View.mjs +9 -4
- package/src/table/header/Toolbar.mjs +15 -1
- package/src/table/plugin/CellEditing.mjs +330 -0
- package/src/toolbar/Base.mjs +2 -2
- package/src/toolbar/Breadcrumb.mjs +1 -1
- package/src/tooltip/Base.mjs +2 -2
- package/src/util/KeyNavigation.mjs +14 -8
- package/src/worker/Base.mjs +3 -3
- package/src/grid/README.md +0 -3
@@ -0,0 +1,330 @@
|
|
1
|
+
import Plugin from '../../plugin/Base.mjs';
|
2
|
+
import TextField from '../../form/field/Text.mjs';
|
3
|
+
import VdomUtil from '../../util/VDom.mjs';
|
4
|
+
|
5
|
+
/**
|
6
|
+
* @class Neo.table.plugin.CellEditing
|
7
|
+
* @extends Neo.plugin.Base
|
8
|
+
*/
|
9
|
+
class CellEditing extends Plugin {
|
10
|
+
static config = {
|
11
|
+
/**
|
12
|
+
* @member {String} className='Neo.table.plugin.CellEditing'
|
13
|
+
* @protected
|
14
|
+
*/
|
15
|
+
className: 'Neo.table.plugin.CellEditing',
|
16
|
+
/**
|
17
|
+
* @member {String} ntype='plugin-table-cell-editing'
|
18
|
+
* @protected
|
19
|
+
*/
|
20
|
+
ntype: 'plugin-table-cell-editing',
|
21
|
+
/**
|
22
|
+
* @member {String} cellCls='neo-table-cell'
|
23
|
+
*/
|
24
|
+
cellCls: 'neo-table-cell',
|
25
|
+
/**
|
26
|
+
* @member {Boolean} disabled_=false
|
27
|
+
*/
|
28
|
+
disabled_: false,
|
29
|
+
/**
|
30
|
+
* @member {String[]} editorCls=['neo-table-editor']
|
31
|
+
*/
|
32
|
+
editorCls: ['neo-table-editor']
|
33
|
+
}
|
34
|
+
|
35
|
+
/**
|
36
|
+
* Storing editor instances per column
|
37
|
+
* @member {Object} editors={}
|
38
|
+
*/
|
39
|
+
editors = {}
|
40
|
+
/**
|
41
|
+
* Storing the currently mounted editor
|
42
|
+
* @member {Neo.form.field.Base|null} mountedEditor=null
|
43
|
+
*/
|
44
|
+
mountedEditor = null
|
45
|
+
|
46
|
+
/**
|
47
|
+
* @param {Object} config
|
48
|
+
*/
|
49
|
+
construct(config) {
|
50
|
+
super.construct(config);
|
51
|
+
|
52
|
+
let me = this,
|
53
|
+
{owner} = me,
|
54
|
+
{selectionModel} = owner;
|
55
|
+
|
56
|
+
owner.on({
|
57
|
+
cellDoubleClick : me.onCellDoubleClick,
|
58
|
+
focusLeave : me.onFocusLeave,
|
59
|
+
selectionModelChange: me.onSelectionModelChange,
|
60
|
+
scope : me
|
61
|
+
});
|
62
|
+
|
63
|
+
// Connect an already registered selectionModel instance
|
64
|
+
if (Neo.typeOf(selectionModel) === 'NeoInstance') {
|
65
|
+
me.onSelectionModelChange({value: selectionModel})
|
66
|
+
}
|
67
|
+
|
68
|
+
owner.keys.add({
|
69
|
+
Enter: 'onTableKeyDown',
|
70
|
+
Space: 'onTableKeyDown',
|
71
|
+
scope: me
|
72
|
+
})
|
73
|
+
}
|
74
|
+
|
75
|
+
/**
|
76
|
+
* Triggered after the disabled config got changed
|
77
|
+
* @param {Boolean} value
|
78
|
+
* @param {Boolean} oldValue
|
79
|
+
* @protected
|
80
|
+
*/
|
81
|
+
afterSetDisabled(value, oldValue) {
|
82
|
+
oldValue && this.unmountEditor()
|
83
|
+
}
|
84
|
+
|
85
|
+
/**
|
86
|
+
* @param {args} args
|
87
|
+
*/
|
88
|
+
destroy(...args) {
|
89
|
+
Object.values(this.editors).forEach(editor => {
|
90
|
+
editor.destroy(false, true)
|
91
|
+
});
|
92
|
+
|
93
|
+
super.destroy(...args)
|
94
|
+
}
|
95
|
+
|
96
|
+
/**
|
97
|
+
* @param {Object} record
|
98
|
+
* @param {String} dataField
|
99
|
+
* @returns {Promise<void>}
|
100
|
+
*/
|
101
|
+
async mountEditor(record, dataField) {
|
102
|
+
if (this.disabled) {
|
103
|
+
return
|
104
|
+
}
|
105
|
+
|
106
|
+
let me = this,
|
107
|
+
{appName, windowId} = me,
|
108
|
+
{view} = me.owner,
|
109
|
+
cellId = view.getCellId(record, dataField),
|
110
|
+
cellNode = VdomUtil.find(view.vdom, cellId).vdom,
|
111
|
+
column = me.owner.headerToolbar.getColumn(dataField),
|
112
|
+
editor = me.editors[dataField],
|
113
|
+
value = record[dataField];
|
114
|
+
|
115
|
+
if (me.mountedEditor) {
|
116
|
+
await me.unmountEditor();
|
117
|
+
await me.timeout(10)
|
118
|
+
}
|
119
|
+
|
120
|
+
if (!column.editable) {
|
121
|
+
return
|
122
|
+
}
|
123
|
+
|
124
|
+
if (!editor) {
|
125
|
+
me.editors[dataField] = editor = Neo.create({
|
126
|
+
module : TextField,
|
127
|
+
appName,
|
128
|
+
cls : me.editorCls,
|
129
|
+
dataField,
|
130
|
+
hideLabel: true,
|
131
|
+
parentId : view.id,
|
132
|
+
record,
|
133
|
+
value,
|
134
|
+
windowId,
|
135
|
+
|
136
|
+
keys: {
|
137
|
+
Enter : 'onEditorKeyEnter',
|
138
|
+
Escape: 'onEditorKeyEscape',
|
139
|
+
Tab : 'onEditorKeyTab',
|
140
|
+
scope : me
|
141
|
+
},
|
142
|
+
|
143
|
+
...column.editor
|
144
|
+
})
|
145
|
+
} else {
|
146
|
+
editor.originalConfig.value = value;
|
147
|
+
editor.setSilent({record, value})
|
148
|
+
}
|
149
|
+
|
150
|
+
me.mountedEditor = editor;
|
151
|
+
|
152
|
+
cellNode.cn = [editor.createVdomReference()];
|
153
|
+
delete cellNode.innerHTML;
|
154
|
+
|
155
|
+
view.updateDepth = -1;
|
156
|
+
|
157
|
+
await view.promiseUpdate();
|
158
|
+
|
159
|
+
await me.timeout(10);
|
160
|
+
|
161
|
+
editor.focus()
|
162
|
+
}
|
163
|
+
|
164
|
+
/**
|
165
|
+
*
|
166
|
+
* @param {Object} data
|
167
|
+
* @param {Object} data.data
|
168
|
+
* @param {String} data.dataField
|
169
|
+
* @param {Object} data.record
|
170
|
+
* @param {Neo.table.View} data.view
|
171
|
+
* @returns {Promise<void>}
|
172
|
+
*/
|
173
|
+
async onCellDoubleClick({data, dataField, record, view}) {
|
174
|
+
await this.mountEditor(record, dataField)
|
175
|
+
}
|
176
|
+
|
177
|
+
/**
|
178
|
+
* @param {Object} data
|
179
|
+
* @param {Neo.form.field.Base} field
|
180
|
+
* @returns {Promise<void>}
|
181
|
+
*/
|
182
|
+
async onEditorKeyEnter(data, field) {
|
183
|
+
let me = this;
|
184
|
+
|
185
|
+
await me.submitEditor();
|
186
|
+
await me.timeout(20);
|
187
|
+
me.selectCell(data)
|
188
|
+
}
|
189
|
+
|
190
|
+
/**
|
191
|
+
* @param {Object} data
|
192
|
+
* @param {Neo.form.field.Base} field
|
193
|
+
* @returns {Promise<void>}
|
194
|
+
*/
|
195
|
+
async onEditorKeyEscape(data, field) {
|
196
|
+
let me = this;
|
197
|
+
|
198
|
+
await me.unmountEditor();
|
199
|
+
await me.timeout(20);
|
200
|
+
me.selectCell(data)
|
201
|
+
}
|
202
|
+
|
203
|
+
/**
|
204
|
+
* @param {Object} event
|
205
|
+
* @param {Neo.form.field.Base} field
|
206
|
+
* @returns {Promise<void>}
|
207
|
+
*/
|
208
|
+
async onEditorKeyTab(event, field) {
|
209
|
+
let me = this,
|
210
|
+
{store} = me.owner,
|
211
|
+
oldIndex = store.indexOf(field.record),
|
212
|
+
countRecords = store.getCount(),
|
213
|
+
index = (oldIndex + (event.altKey ? -1 : 1) + countRecords) % countRecords,
|
214
|
+
record = store.getAt(index);
|
215
|
+
|
216
|
+
await me.submitEditor();
|
217
|
+
await me.mountEditor(record, field.dataField)
|
218
|
+
}
|
219
|
+
|
220
|
+
/**
|
221
|
+
* @param {Object} data
|
222
|
+
* @returns {Promise<void>}
|
223
|
+
*/
|
224
|
+
async onFocusLeave(data) {
|
225
|
+
await this.unmountEditor()
|
226
|
+
}
|
227
|
+
|
228
|
+
/**
|
229
|
+
* @param {Object} data
|
230
|
+
*/
|
231
|
+
onSelectionChange(data) {
|
232
|
+
// todo: Once we separate cell selections & focus, we can use this event to mount editors
|
233
|
+
// console.log('onSelectionChange', data);
|
234
|
+
}
|
235
|
+
|
236
|
+
/**
|
237
|
+
* @param {Object} data
|
238
|
+
*/
|
239
|
+
onSelectionModelChange(data) {
|
240
|
+
let selectionModel = data.value;
|
241
|
+
|
242
|
+
if (selectionModel.ntype.includes('cell')) {
|
243
|
+
selectionModel.on('selectionChange', this.onSelectionChange, this)
|
244
|
+
}
|
245
|
+
}
|
246
|
+
|
247
|
+
/**
|
248
|
+
* @param {Object} data
|
249
|
+
* @returns {Promise<void>}
|
250
|
+
*/
|
251
|
+
async onTableKeyDown(data) {
|
252
|
+
let me = this,
|
253
|
+
{target} = data,
|
254
|
+
tableView = me.owner.view,
|
255
|
+
dataField, record;
|
256
|
+
|
257
|
+
if (!me.mountedEditor && target.cls?.includes('neo-selected')) {
|
258
|
+
dataField = tableView.getCellDataField(target.id);
|
259
|
+
record = tableView.getRecord(target.id);
|
260
|
+
|
261
|
+
await me.mountEditor(record, dataField)
|
262
|
+
}
|
263
|
+
}
|
264
|
+
|
265
|
+
/**
|
266
|
+
* @param {Object} data
|
267
|
+
* @param {Object[]} data.path
|
268
|
+
*/
|
269
|
+
selectCell({path}) {
|
270
|
+
let me = this,
|
271
|
+
{selectionModel} = me.owner,
|
272
|
+
i = 0,
|
273
|
+
len = path.length,
|
274
|
+
cellId;
|
275
|
+
|
276
|
+
for (; i < len; i++) {
|
277
|
+
if (path[i].cls?.includes(me.cellCls)) {
|
278
|
+
cellId = path[i].id;
|
279
|
+
break
|
280
|
+
}
|
281
|
+
}
|
282
|
+
|
283
|
+
if (cellId) {
|
284
|
+
selectionModel?.deselect(cellId, true); // the cell might still count as selected => silent deselect first
|
285
|
+
selectionModel?.select(cellId);
|
286
|
+
me.owner.focus(cellId)
|
287
|
+
}
|
288
|
+
}
|
289
|
+
|
290
|
+
/**
|
291
|
+
* If the field is valid:
|
292
|
+
* Updates the record field, in case the value of the editor changed,
|
293
|
+
* otherwise unmounts the editor
|
294
|
+
* @returns {Promise<void>}
|
295
|
+
*/
|
296
|
+
async submitEditor() {
|
297
|
+
let me = this,
|
298
|
+
field = me.mountedEditor;
|
299
|
+
|
300
|
+
if (field?.isValid()) {
|
301
|
+
if (field.isDirty) {
|
302
|
+
me.mountedEditor = null;
|
303
|
+
field.record[field.dataField] = field.getSubmitValue()
|
304
|
+
} else {
|
305
|
+
await me.unmountEditor()
|
306
|
+
}
|
307
|
+
}
|
308
|
+
}
|
309
|
+
|
310
|
+
/**
|
311
|
+
* @returns {Promise<void>}
|
312
|
+
*/
|
313
|
+
async unmountEditor() {
|
314
|
+
if (!this.mountedEditor) {
|
315
|
+
return
|
316
|
+
}
|
317
|
+
|
318
|
+
let me = this,
|
319
|
+
record = me.mountedEditor.record,
|
320
|
+
tableView = me.owner.view,
|
321
|
+
rowIndex = tableView.store.indexOf(record);
|
322
|
+
|
323
|
+
me.mountedEditor = null;
|
324
|
+
|
325
|
+
tableView.vdom.cn[rowIndex] = tableView.createRow({record, rowIndex});
|
326
|
+
await tableView.promiseUpdate()
|
327
|
+
}
|
328
|
+
}
|
329
|
+
|
330
|
+
export default Neo.setupClass(CellEditing);
|
package/src/toolbar/Base.mjs
CHANGED
@@ -8,7 +8,7 @@ import NeoArray from '../util/Array.mjs';
|
|
8
8
|
* @class Neo.toolbar.Base
|
9
9
|
* @extends Neo.container.Base
|
10
10
|
*/
|
11
|
-
class
|
11
|
+
class Toolbar extends Container {
|
12
12
|
/**
|
13
13
|
* Valid values for dock
|
14
14
|
* @member {String[]} dockPositions=['top','right','bottom','left', null]
|
@@ -223,4 +223,4 @@ class Base extends Container {
|
|
223
223
|
}
|
224
224
|
}
|
225
225
|
|
226
|
-
export default Neo.setupClass(
|
226
|
+
export default Neo.setupClass(Toolbar);
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import ClassSystemUtil from '../util/ClassSystem.mjs';
|
2
2
|
import HashHistory from '../util/HashHistory.mjs';
|
3
3
|
import Store from '../data/Store.mjs';
|
4
|
-
import Toolbar from '
|
4
|
+
import Toolbar from './Base.mjs';
|
5
5
|
|
6
6
|
/**
|
7
7
|
* @class Neo.toolbar.Breadcrumb
|
package/src/tooltip/Base.mjs
CHANGED
@@ -8,7 +8,7 @@ let singletons = {};
|
|
8
8
|
* @class Neo.tooltip.Base
|
9
9
|
* @extends Neo.container.Base
|
10
10
|
*/
|
11
|
-
class
|
11
|
+
class Tooltip extends Container {
|
12
12
|
static config = {
|
13
13
|
/**
|
14
14
|
* @member {String} className='Neo.tooltip.Base'
|
@@ -368,4 +368,4 @@ class Base extends Container {
|
|
368
368
|
}
|
369
369
|
}
|
370
370
|
|
371
|
-
export default Neo.setupClass(
|
371
|
+
export default Neo.setupClass(Tooltip);
|
@@ -75,10 +75,14 @@ class KeyNavigation extends Base {
|
|
75
75
|
upperCaseKey = me.parseUpperCaseKey(upperCaseKey);
|
76
76
|
|
77
77
|
me.keys.forEach(key => {
|
78
|
-
scope = Neo.get(key.scope);
|
78
|
+
scope = Neo.isString(key.scope) ? Neo.get(key.scope) : key.scope;
|
79
79
|
|
80
80
|
if (key.key.toUpperCase() === upperCaseKey) {
|
81
|
-
|
81
|
+
if (Neo.isFunction(key.fn)) {
|
82
|
+
key.fn.apply(scope, [data, me.component])
|
83
|
+
} else {
|
84
|
+
scope[key.fn]?.apply(scope, [data, me.component])
|
85
|
+
}
|
82
86
|
}
|
83
87
|
})
|
84
88
|
}
|
@@ -94,12 +98,14 @@ class KeyNavigation extends Base {
|
|
94
98
|
keyArray = [];
|
95
99
|
|
96
100
|
if (componentId) {
|
97
|
-
Object.entries(value).forEach(([key,
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
101
|
+
Object.entries(value).forEach(([key, val]) => {
|
102
|
+
if (key !== 'scope') {
|
103
|
+
keyArray.push({
|
104
|
+
fn : val,
|
105
|
+
key,
|
106
|
+
scope: value.scope || componentId // todo: support VCs later on
|
107
|
+
})
|
108
|
+
}
|
103
109
|
});
|
104
110
|
|
105
111
|
value = keyArray
|
package/src/worker/Base.mjs
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
1
|
+
import Base from '../core/Base.mjs';
|
2
2
|
import Observable from '../core/Observable.mjs';
|
3
3
|
import Message from './Message.mjs';
|
4
4
|
import RemoteMethodAccess from './mixin/RemoteMethodAccess.mjs';
|
@@ -9,7 +9,7 @@ import RemoteMethodAccess from './mixin/RemoteMethodAccess.mjs';
|
|
9
9
|
* @extends Neo.core.Base
|
10
10
|
* @abstract
|
11
11
|
*/
|
12
|
-
class
|
12
|
+
class Worker extends Base {
|
13
13
|
static config = {
|
14
14
|
/**
|
15
15
|
* @member {String} className='Neo.worker.Base'
|
@@ -309,4 +309,4 @@ class Base extends CoreBase {
|
|
309
309
|
}
|
310
310
|
}
|
311
311
|
|
312
|
-
export default Neo.setupClass(
|
312
|
+
export default Neo.setupClass(Worker);
|
package/src/grid/README.md
DELETED