neo.mjs 6.8.2 → 6.8.3
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/.github/PULL_REQUEST_TEMPLATE.md +1 -1
- package/apps/ServiceWorker.mjs +2 -2
- package/apps/learnneo/app.mjs +6 -0
- package/apps/learnneo/index.html +11 -0
- package/apps/learnneo/model/Content.mjs +44 -0
- package/apps/learnneo/neo-config.json +6 -0
- package/apps/learnneo/store/Content.mjs +24 -0
- package/apps/learnneo/view/Viewport.mjs +34 -0
- package/apps/learnneo/view/ViewportController.mjs +19 -0
- package/apps/learnneo/view/home/ContentTreeList.mjs +41 -0
- package/apps/learnneo/view/home/MainContainer.mjs +50 -0
- package/apps/learnneo/view/home/MainContainerController.mjs +28 -0
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/form/field/select/MainContainer.mjs +6 -0
- package/examples/todoList/version1/MainComponent.mjs +5 -5
- package/package.json +1 -1
- package/resources/data/learnneo/content.json +27 -0
- package/resources/scss/src/form/field/Picker.scss +0 -1
- package/src/DefaultConfig.mjs +2 -2
- package/src/dialog/Base.mjs +1 -4
- package/src/form/field/FileUpload.mjs +11 -0
- package/src/form/field/Picker.mjs +0 -17
- package/src/form/field/Text.mjs +29 -0
- package/src/form/field/trigger/Picker.mjs +7 -0
@@ -23,7 +23,7 @@ If yes, please describe the impact and migration path for existing applications:
|
|
23
23
|
|
24
24
|
**The PR fulfills these requirements:**
|
25
25
|
|
26
|
-
- [ ] It's submitted to the `dev` branch, _not_ the `
|
26
|
+
- [ ] It's submitted to the `dev` branch, _not_ the `main` branch
|
27
27
|
- [ ] When resolving a specific issue, it's referenced in the PR's title (e.g. `fix #xxx[,#xxx]`, where "xxx" is the issue number)
|
28
28
|
|
29
29
|
If adding a **new feature**, the PR's description includes:
|
package/apps/ServiceWorker.mjs
CHANGED
@@ -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>LearnNeo</title>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<script src="../../src/MicroLoader.mjs" type="module"></script>
|
10
|
+
</body>
|
11
|
+
</html>
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import Model from '../../../src/data/Model.mjs';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* @class LearnNeo.model.Content
|
5
|
+
* @extends Neo.data.Model
|
6
|
+
*/
|
7
|
+
class Content extends Model {
|
8
|
+
static config = {
|
9
|
+
/**
|
10
|
+
* @member {String} className='LearnNeo.model.Content'
|
11
|
+
* @protected
|
12
|
+
*/
|
13
|
+
className: 'LearnNeo.model.Content',
|
14
|
+
/**
|
15
|
+
* @member {Object[]} fields
|
16
|
+
*/
|
17
|
+
fields: [{
|
18
|
+
name: 'className',
|
19
|
+
type: 'String'
|
20
|
+
}, {
|
21
|
+
name: 'collapsed',
|
22
|
+
type: 'Boolean'
|
23
|
+
}, {
|
24
|
+
name: 'id',
|
25
|
+
type: 'Integer'
|
26
|
+
}, {
|
27
|
+
name: 'isLeaf',
|
28
|
+
type: 'Boolean'
|
29
|
+
}, {
|
30
|
+
name: 'name',
|
31
|
+
type: 'String'
|
32
|
+
}, {
|
33
|
+
name: 'parentId',
|
34
|
+
type: 'Integer'
|
35
|
+
}, {
|
36
|
+
name: 'path',
|
37
|
+
type: 'String'
|
38
|
+
}]
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
Neo.applyClassConfig(Content);
|
43
|
+
|
44
|
+
export default Content;
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import ContentModel from '../model/Content.mjs';
|
2
|
+
import Store from '../../../src/data/Store.mjs';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @class LearnNeo.store.Content
|
6
|
+
* @extends Neo.data.Store
|
7
|
+
*/
|
8
|
+
class Content extends Store {
|
9
|
+
static config = {
|
10
|
+
/**
|
11
|
+
* @member {String} className='LearnNeo.store.Content'
|
12
|
+
* @protected
|
13
|
+
*/
|
14
|
+
className: 'LearnNeo.store.Content',
|
15
|
+
/**
|
16
|
+
* @member {Neo.data.Model} model=ContentModel
|
17
|
+
*/
|
18
|
+
model: ContentModel
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
Neo.applyClassConfig(Content);
|
23
|
+
|
24
|
+
export default Content;
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import BaseViewport from '../../../src/container/Viewport.mjs';
|
2
|
+
import ViewportController from './ViewportController.mjs';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @class LearnNeo.view.Viewport
|
6
|
+
* @extends Neo.container.Viewport
|
7
|
+
*/
|
8
|
+
class Viewport extends BaseViewport {
|
9
|
+
static config = {
|
10
|
+
/**
|
11
|
+
* @member {String} className='LearnNeo.view.Viewport'
|
12
|
+
* @protected
|
13
|
+
*/
|
14
|
+
className: 'LearnNeo.view.Viewport',
|
15
|
+
/**
|
16
|
+
* @member {Neo.controller.Component} controller=ViewportController
|
17
|
+
*/
|
18
|
+
controller: ViewportController,
|
19
|
+
/**
|
20
|
+
* @member {Object[]} items
|
21
|
+
*/
|
22
|
+
items: [{
|
23
|
+
module: () => import('./home/MainContainer.mjs')
|
24
|
+
}],
|
25
|
+
/**
|
26
|
+
* @member {Object} layout={ntype:'card'}
|
27
|
+
*/
|
28
|
+
layout: {ntype: 'card'}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
Neo.applyClassConfig(Viewport);
|
33
|
+
|
34
|
+
export default Viewport;
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import Component from '../../../src/controller/Component.mjs';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* @class LearnNeo.view.ViewportController
|
5
|
+
* @extends Neo.controller.Component
|
6
|
+
*/
|
7
|
+
class ViewportController extends Component {
|
8
|
+
static config = {
|
9
|
+
/**
|
10
|
+
* @member {String} className='LearnNeo.view.ViewportController'
|
11
|
+
* @protected
|
12
|
+
*/
|
13
|
+
className: 'LearnNeo.view.ViewportController'
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
Neo.applyClassConfig(ViewportController);
|
18
|
+
|
19
|
+
export default ViewportController;
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import ContentStore from '../../store/Content.mjs'
|
2
|
+
import TreeList from '../../../../src/tree/List.mjs';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @class LearnNeo.view.home.ContentTreeList
|
6
|
+
* @extends Neo.container.Base
|
7
|
+
*/
|
8
|
+
class ContentTreeList extends TreeList {
|
9
|
+
static config = {
|
10
|
+
/**
|
11
|
+
* @member {String} className='LearnNeo.view.home.ContentTreeList'
|
12
|
+
* @protected
|
13
|
+
*/
|
14
|
+
className: 'LearnNeo.view.home.ContentTreeList',
|
15
|
+
/**
|
16
|
+
* @member {Neo.data.Store} store=ContentStore
|
17
|
+
*/
|
18
|
+
store: ContentStore
|
19
|
+
}
|
20
|
+
|
21
|
+
/**
|
22
|
+
* todo: createItems() should get triggered onStoreLoad()
|
23
|
+
*/
|
24
|
+
onConstructed() {
|
25
|
+
super.onConstructed();
|
26
|
+
|
27
|
+
let me = this;
|
28
|
+
|
29
|
+
Neo.Xhr.promiseJson({
|
30
|
+
url: '../../../resources/data/learnneo/content.json'
|
31
|
+
}).then(data => {
|
32
|
+
me.store.data = data.json.data;
|
33
|
+
me.createItems(null, me.getListItemsRoot(), 0);
|
34
|
+
me.update();
|
35
|
+
})
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
Neo.applyClassConfig(ContentTreeList);
|
40
|
+
|
41
|
+
export default ContentTreeList;
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import Container from '../../../../src/container/Base.mjs';
|
2
|
+
import ContentTreeList from './ContentTreeList.mjs';
|
3
|
+
import MainContainerController from './MainContainerController.mjs';
|
4
|
+
import Splitter from '../../../../src/component/Splitter.mjs';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* @class LearnNeo.view.home.MainContainer
|
8
|
+
* @extends Neo.container.Base
|
9
|
+
*/
|
10
|
+
class MainContainer extends Container {
|
11
|
+
static config = {
|
12
|
+
/**
|
13
|
+
* @member {String} className='LearnNeo.view.home.MainContainer'
|
14
|
+
* @protected
|
15
|
+
*/
|
16
|
+
className: 'LearnNeo.view.home.MainContainer',
|
17
|
+
/**
|
18
|
+
* @member {Neo.controller.Component} controller=MainContainerController
|
19
|
+
*/
|
20
|
+
controller: MainContainerController,
|
21
|
+
/**
|
22
|
+
* @member {Object[]} items
|
23
|
+
*/
|
24
|
+
items: [{
|
25
|
+
module: Container,
|
26
|
+
layout: 'fit',
|
27
|
+
width : 300,
|
28
|
+
|
29
|
+
items: [{
|
30
|
+
module : ContentTreeList,
|
31
|
+
listeners: {leafItemClick: 'onContentListLeafClick'}
|
32
|
+
}]
|
33
|
+
}, {
|
34
|
+
module : Splitter,
|
35
|
+
resizeTarget: 'previous'
|
36
|
+
}, {
|
37
|
+
module : Container,
|
38
|
+
layout : {ntype: 'card', activeIndex: null},
|
39
|
+
reference: 'content-container'
|
40
|
+
}],
|
41
|
+
/**
|
42
|
+
* @member {Object} layout={ntype:'hbox',align:'stretch'}
|
43
|
+
*/
|
44
|
+
layout: {ntype: 'hbox', align: 'stretch'}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
Neo.applyClassConfig(MainContainer);
|
49
|
+
|
50
|
+
export default MainContainer;
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import Component from '../../../../src/controller/Component.mjs';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* @class LearnNeo.view.home.MainContainerController
|
5
|
+
* @extends Neo.controller.Component
|
6
|
+
*/
|
7
|
+
class MainContainerController extends Component {
|
8
|
+
static config = {
|
9
|
+
/**
|
10
|
+
* @member {String} className='LearnNeo.view.home.MainContainerController'
|
11
|
+
* @protected
|
12
|
+
*/
|
13
|
+
className: 'LearnNeo.view.home.MainContainerController'
|
14
|
+
}
|
15
|
+
|
16
|
+
/**
|
17
|
+
* @param {Object} record
|
18
|
+
*/
|
19
|
+
onContentListLeafClick(record) {
|
20
|
+
let contentContainer = this.getReference('content-container');
|
21
|
+
|
22
|
+
console.log('onContentListLeafClick', {contentContainer, record});
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
Neo.applyClassConfig(MainContainerController);
|
27
|
+
|
28
|
+
export default MainContainerController;
|
@@ -111,6 +111,12 @@ class MainContainer extends ConfigurationViewport {
|
|
111
111
|
labelText: 'placeholderText',
|
112
112
|
listeners: {change: me.onConfigChange.bind(me, 'placeholderText')},
|
113
113
|
value : me.exampleComponent.placeholderText
|
114
|
+
}, {
|
115
|
+
module : CheckBox,
|
116
|
+
checked : me.exampleComponent.readOnly,
|
117
|
+
labelText: 'readOnly',
|
118
|
+
listeners: {change: me.onConfigChange.bind(me, 'readOnly')},
|
119
|
+
style : {marginTop: '10px'}
|
114
120
|
}, {
|
115
121
|
module : CheckBox,
|
116
122
|
checked : me.exampleComponent.typeAhead,
|
@@ -17,9 +17,9 @@ class MainComponent extends Component {
|
|
17
17
|
width : 300,
|
18
18
|
|
19
19
|
/**
|
20
|
-
* @member {Object[]}
|
20
|
+
* @member {Object[]} items
|
21
21
|
*/
|
22
|
-
|
22
|
+
items: [
|
23
23
|
{id: 1, done: true, text: 'Todo Item 1'},
|
24
24
|
{id: 2, done: false, text: 'Todo Item 2'},
|
25
25
|
{id: 3, done: false, text: 'Todo Item 3'}
|
@@ -51,14 +51,14 @@ class MainComponent extends Component {
|
|
51
51
|
{input: me.onInputFieldChange, delegate: 'todo-input'}
|
52
52
|
]);
|
53
53
|
|
54
|
-
me.createItems(me.
|
54
|
+
me.createItems(me.items || []);
|
55
55
|
}
|
56
56
|
|
57
|
-
createItems(
|
57
|
+
createItems(items) {
|
58
58
|
let me = this,
|
59
59
|
cls;
|
60
60
|
|
61
|
-
|
61
|
+
items.forEach(item => {
|
62
62
|
cls = ['todo-item'];
|
63
63
|
|
64
64
|
if (item.done) {
|
package/package.json
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
{
|
2
|
+
"data": [{
|
3
|
+
"id" : 1,
|
4
|
+
"isLeaf" : false,
|
5
|
+
"name" : "Hello",
|
6
|
+
"parentId": null,
|
7
|
+
"path" : null
|
8
|
+
}, {
|
9
|
+
"id" : 2,
|
10
|
+
"isLeaf" : true,
|
11
|
+
"name" : "Max",
|
12
|
+
"parentId": 1,
|
13
|
+
"path" : null
|
14
|
+
}, {
|
15
|
+
"id" : 3,
|
16
|
+
"isLeaf" : false,
|
17
|
+
"name" : "Hello",
|
18
|
+
"parentId": null,
|
19
|
+
"path" : null
|
20
|
+
}, {
|
21
|
+
"id" : 4,
|
22
|
+
"isLeaf" : true,
|
23
|
+
"name" : "Torsten",
|
24
|
+
"parentId": 3,
|
25
|
+
"path" : null
|
26
|
+
}]
|
27
|
+
}
|
package/src/DefaultConfig.mjs
CHANGED
@@ -236,12 +236,12 @@ const DefaultConfig = {
|
|
236
236
|
useVdomWorker: true,
|
237
237
|
/**
|
238
238
|
* buildScripts/injectPackageVersion.mjs will update this value
|
239
|
-
* @default '6.8.
|
239
|
+
* @default '6.8.3'
|
240
240
|
* @memberOf! module:Neo
|
241
241
|
* @name config.version
|
242
242
|
* @type String
|
243
243
|
*/
|
244
|
-
version: '6.8.
|
244
|
+
version: '6.8.3'
|
245
245
|
};
|
246
246
|
|
247
247
|
Object.assign(DefaultConfig, {
|
package/src/dialog/Base.mjs
CHANGED
@@ -376,10 +376,7 @@ class Base extends Panel {
|
|
376
376
|
me.closeOrHide(false);
|
377
377
|
|
378
378
|
if (me.closeAction === 'hide') {
|
379
|
-
await Neo.applyDeltas(appName,
|
380
|
-
{id, cls: {remove: ['animated-hiding-showing']}},
|
381
|
-
{id, action: 'removeNode'}
|
382
|
-
])
|
379
|
+
await Neo.applyDeltas(appName, {id, action: 'removeNode'})
|
383
380
|
}
|
384
381
|
}
|
385
382
|
|
@@ -691,13 +691,17 @@ class FileUpload extends Base {
|
|
691
691
|
|
692
692
|
delete vdom.inert;
|
693
693
|
|
694
|
+
let isChangeEventNeeded;
|
695
|
+
|
694
696
|
switch (value) {
|
695
697
|
case 'ready':
|
696
698
|
anchor.tag = 'div';
|
697
699
|
anchor.href = '';
|
700
|
+
isChangeEventNeeded = true;
|
698
701
|
break;
|
699
702
|
case 'upload-failed':
|
700
703
|
status.innerHTML = `${me.uploadFailed}${isNaN(me.progress) ? '' : `... (${Math.round(me.progress * 100)}%)`}`;
|
704
|
+
isChangeEventNeeded = true;
|
701
705
|
break;
|
702
706
|
case 'processing':
|
703
707
|
status.innerHTML = `${me.scanning}... (${me.formatSize(me.uploadSize)})`;
|
@@ -706,6 +710,7 @@ class FileUpload extends Base {
|
|
706
710
|
case 'scan-failed':
|
707
711
|
status.innerHTML = `${me.malwareFoundInFile}. \u2022 ${me.fileSize}`;
|
708
712
|
me.error = me.pleaseCheck;
|
713
|
+
isChangeEventNeeded = true;
|
709
714
|
break;
|
710
715
|
case 'downloadable':
|
711
716
|
anchor.tag = 'a';
|
@@ -713,14 +718,20 @@ class FileUpload extends Base {
|
|
713
718
|
[me.documentIdParameter] : me.documentId
|
714
719
|
});
|
715
720
|
status.innerHTML = me.fileSize;
|
721
|
+
isChangeEventNeeded = true;
|
716
722
|
break;
|
717
723
|
case 'not-downloadable':
|
718
724
|
status.innerHTML = me.document ? me.fileSize : `${me.successfullyUploaded} \u2022 ${me.fileSize}`;
|
725
|
+
isChangeEventNeeded = true;
|
719
726
|
break;
|
720
727
|
case 'deleted':
|
721
728
|
status.innerHTML = me.fileWasDeleted;
|
729
|
+
isChangeEventNeeded = true;
|
722
730
|
}
|
723
731
|
|
732
|
+
if (isChangeEventNeeded) {
|
733
|
+
me.fireChangeEvent(me.file)
|
734
|
+
}
|
724
735
|
me.validate();
|
725
736
|
me.update();
|
726
737
|
|
@@ -32,10 +32,6 @@ class Picker extends Text {
|
|
32
32
|
* @protected
|
33
33
|
*/
|
34
34
|
clientRects: null,
|
35
|
-
/**
|
36
|
-
* @member {Boolean} editable_=true
|
37
|
-
*/
|
38
|
-
editable_: true,
|
39
35
|
/**
|
40
36
|
* Additional used keys for the selection model
|
41
37
|
* @member {Object} keys
|
@@ -110,19 +106,6 @@ class Picker extends Text {
|
|
110
106
|
})
|
111
107
|
}
|
112
108
|
|
113
|
-
/**
|
114
|
-
* Triggered after the editable config got changed
|
115
|
-
* @param {Boolean} value
|
116
|
-
* @param {Boolean} oldValue
|
117
|
-
* @protected
|
118
|
-
*/
|
119
|
-
afterSetEditable(value, oldValue) {
|
120
|
-
let cls = this.cls;
|
121
|
-
|
122
|
-
NeoArray.toggle(cls, 'neo-not-editable', !value);
|
123
|
-
this.cls = cls
|
124
|
-
}
|
125
|
-
|
126
109
|
/**
|
127
110
|
* Triggered after the mounted config got changed
|
128
111
|
* @param {Boolean} value
|
package/src/form/field/Text.mjs
CHANGED
@@ -75,6 +75,15 @@ class Text extends Base {
|
|
75
75
|
* @member {String[]|null} disabledChars_=null
|
76
76
|
*/
|
77
77
|
disabledChars_: null,
|
78
|
+
/**
|
79
|
+
* Setting `editable` to `false` means that the input field will be read-only
|
80
|
+
* but the field is still workable and may have its value changed by user interaction.
|
81
|
+
*
|
82
|
+
* For example picker fields such as `Date` and `Select` may still have their
|
83
|
+
* values changed by selecting from the picker using keyboard or pointer.
|
84
|
+
* @member {Boolean} editable_=true
|
85
|
+
*/
|
86
|
+
editable_: true,
|
78
87
|
/**
|
79
88
|
* Configure the value of empty fields. null or an empty string is recommended.
|
80
89
|
* @member {String|null} emptyValue=null
|
@@ -184,6 +193,10 @@ class Text extends Base {
|
|
184
193
|
*/
|
185
194
|
placeholderText_: null,
|
186
195
|
/**
|
196
|
+
* Setting `readOnly` means that the field may not be changed by user interaction.
|
197
|
+
*
|
198
|
+
* The input field will be read-only and other ways of changing the field's value
|
199
|
+
* (such as by operating pickers) will be disabled.
|
187
200
|
* @member {Boolean} readOnly_=false
|
188
201
|
*/
|
189
202
|
readOnly_: false,
|
@@ -342,6 +355,22 @@ class Text extends Base {
|
|
342
355
|
}
|
343
356
|
}
|
344
357
|
|
358
|
+
/**
|
359
|
+
* Triggered after the editable config got changed
|
360
|
+
* @param {Boolean} value
|
361
|
+
* @param {Boolean} oldValue
|
362
|
+
* @protected
|
363
|
+
*/
|
364
|
+
afterSetEditable(value, oldValue) {
|
365
|
+
const
|
366
|
+
me = this,
|
367
|
+
{ cls } = me;
|
368
|
+
|
369
|
+
NeoArray.toggle(cls, 'neo-not-editable', !value);
|
370
|
+
me.cls = cls
|
371
|
+
me.changeInputElKey('readonly', value ? false : true);
|
372
|
+
}
|
373
|
+
|
345
374
|
/**
|
346
375
|
* Triggered after the error config got changed
|
347
376
|
* @param {String|null} value
|
@@ -35,6 +35,13 @@ class Picker extends Base {
|
|
35
35
|
onTriggerClick(data) {
|
36
36
|
this.field.onPickerTriggerClick();
|
37
37
|
}
|
38
|
+
|
39
|
+
/**
|
40
|
+
* @returns {Boolean} true in case the trigger should be hidden
|
41
|
+
*/
|
42
|
+
getHiddenState() {
|
43
|
+
return !this.field.editable;
|
44
|
+
}
|
38
45
|
}
|
39
46
|
|
40
47
|
Neo.applyClassConfig(Picker);
|