neo.mjs 7.7.0 → 7.9.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 (58) hide show
  1. package/apps/ServiceWorker.mjs +2 -2
  2. package/apps/portal/index.html +1 -1
  3. package/apps/portal/neo-config.json +1 -0
  4. package/apps/portal/view/ViewportController.mjs +20 -4
  5. package/apps/portal/view/home/FooterContainer.mjs +1 -1
  6. package/apps/portal/view/learn/{ContentView.mjs → ContentComponent.mjs} +98 -38
  7. package/apps/portal/view/learn/CubeLayoutButton.mjs +77 -0
  8. package/apps/portal/view/learn/MainContainerController.mjs +2 -1
  9. package/apps/portal/view/learn/PageContainer.mjs +4 -4
  10. package/apps/shareddialog/view/DemoDialog.mjs +2 -10
  11. package/apps/shareddialog/view/MainContainerController.mjs +107 -105
  12. package/buildScripts/webpack/json/myApps.template.json +1 -1
  13. package/examples/ServiceWorker.mjs +2 -2
  14. package/examples/table/nestedRecordFields/EditUserDialog.mjs +127 -0
  15. package/examples/table/nestedRecordFields/MainContainer.mjs +113 -0
  16. package/examples/table/nestedRecordFields/MainContainerModel.mjs +61 -0
  17. package/examples/table/nestedRecordFields/MainModel.mjs +41 -0
  18. package/examples/table/nestedRecordFields/MainStore.mjs +54 -0
  19. package/examples/table/nestedRecordFields/app.mjs +6 -0
  20. package/examples/table/nestedRecordFields/index.html +11 -0
  21. package/examples/table/nestedRecordFields/neo-config.json +6 -0
  22. package/package.json +4 -4
  23. package/resources/data/deck/learnneo/pages/Welcome.md +1 -1
  24. package/resources/data/deck/learnneo/pages/benefits/FormsEngine.md +1 -1
  25. package/resources/data/deck/learnneo/pages/guides/PortalApp.md +35 -0
  26. package/resources/data/deck/learnneo/tree.json +1 -0
  27. package/resources/scss/src/apps/portal/learn/PageContainer.scss +5 -0
  28. package/src/DefaultConfig.mjs +2 -2
  29. package/src/collection/Base.mjs +4 -3
  30. package/src/container/Base.mjs +12 -7
  31. package/src/data/Model.mjs +0 -7
  32. package/src/data/RecordFactory.mjs +82 -61
  33. package/src/data/Store.mjs +7 -0
  34. package/src/draggable/DragProxyComponent.mjs +10 -20
  35. package/src/form/field/CheckBox.mjs +12 -7
  36. package/src/form/field/ComboBox.mjs +8 -7
  37. package/src/grid/View.mjs +2 -2
  38. package/src/list/Base.mjs +1 -1
  39. package/src/main/addon/Navigator.mjs +34 -32
  40. package/src/main/addon/WindowPosition.mjs +9 -11
  41. package/src/model/Component.mjs +10 -1
  42. package/src/plugin/Resizable.mjs +12 -6
  43. package/src/tab/Container.mjs +5 -1
  44. package/src/table/View.mjs +31 -15
  45. package/src/table/header/Button.mjs +33 -18
  46. package/test/siesta/siesta.js +1 -0
  47. package/test/siesta/tests/ManagerInstance.mjs +35 -0
  48. package/apps/krausest/README.md +0 -3
  49. package/apps/krausest/TableCollection.mjs +0 -46
  50. package/apps/krausest/app.mjs +0 -8
  51. package/apps/krausest/css/currentStyle.css +0 -2
  52. package/apps/krausest/css/main.css +0 -26
  53. package/apps/krausest/index.html +0 -12
  54. package/apps/krausest/neo-config.json +0 -10
  55. package/apps/krausest/view/MainComponent.mjs +0 -122
  56. package/apps/krausest/view/MainComponentController.mjs +0 -33
  57. package/apps/krausest/view/TableComponent.mjs +0 -152
  58. /package/resources/scss/src/apps/portal/learn/{ContentView.scss → ContentComponent.scss} +0 -0
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='7.7.0'
23
+ * @member {String} version='7.9.0'
24
24
  */
25
- version: '7.7.0'
25
+ version: '7.9.0'
26
26
  }
27
27
 
28
28
  /**
@@ -16,7 +16,7 @@
16
16
  "@type": "Organization",
17
17
  "name": "Neo.mjs"
18
18
  },
19
- "datePublished": "2024-09-20",
19
+ "datePublished": "2024-09-27",
20
20
  "publisher": {
21
21
  "@type": "Organization",
22
22
  "name": "Neo.mjs"
@@ -13,6 +13,7 @@
13
13
  "DragDrop",
14
14
  "HighlightJS",
15
15
  "IntersectionObserver",
16
+ "LocalStorage",
16
17
  "MonacoEditor",
17
18
  "Navigator",
18
19
  "ResizeObserver",
@@ -36,9 +36,9 @@ class ViewportController extends Controller {
36
36
  */
37
37
  defaultHash: '/home',
38
38
  /**
39
- * @member {String} mainContentLayout_='mixed'
39
+ * @member {String} mainContentLayout_='card'
40
40
  */
41
- mainContentLayout_: 'mixed',
41
+ mainContentLayout_: 'card',
42
42
  /**
43
43
  * @member {Object} routes
44
44
  */
@@ -88,14 +88,30 @@ class ViewportController extends Controller {
88
88
  * @protected
89
89
  */
90
90
  afterSetMainContentLayout(value, oldValue) {
91
- let {activeIndex} = this,
92
- container = this.component.getItem('main-content'); // happens before instantiation
91
+ let me = this,
92
+ {activeIndex, windowId} = me,
93
+ container = me.component.getItem('main-content'); // happens before instantiation
94
+
95
+ if (oldValue === undefined) {
96
+ // We can not turn this method itself into async and await the addon response,
97
+ // since the container needs its layout right away
98
+ Neo.main.addon.LocalStorage.readLocalStorageItem({
99
+ key: 'mainContentLayout',
100
+ windowId
101
+ }).then(data => {
102
+ if (data.value !== 'card') {
103
+ me.mainContentLayout = data.value
104
+ }
105
+ })
106
+ }
93
107
 
94
108
  if (value === 'cube') {
95
109
  container.layout = {ntype: 'cube', activeIndex, fitContainer: true, hideInactiveCardsOnDestroy: true}
96
110
  } else {
97
111
  container.layout = {ntype: 'card', activeIndex}
98
112
  }
113
+
114
+ Neo.main.addon.LocalStorage.updateLocalStorageItem({key: 'mainContentLayout', value, windowId})
99
115
  }
100
116
 
101
117
  /**
@@ -111,7 +111,7 @@ class FooterContainer extends Container {
111
111
  }, {
112
112
  module: Component,
113
113
  cls : ['neo-version'],
114
- html : 'v7.7.0'
114
+ html : 'v7.9.0'
115
115
  }]
116
116
  }],
117
117
  /**
@@ -10,16 +10,16 @@ const
10
10
  preNeoComponentRegex = /<pre\s+data-neo-component\s*>([\s\S]*?)<\/pre>/g;
11
11
 
12
12
  /**
13
- * @class Portal.view.learn.ContentView
13
+ * @class Portal.view.learn.ContentComponent
14
14
  * @extends Neo.component.Base
15
15
  */
16
- class ContentView extends Component {
16
+ class ContentComponent extends Component {
17
17
  static config = {
18
18
  /**
19
- * @member {String} className='Portal.view.learn.ContentView'
19
+ * @member {String} className='Portal.view.learn.ContentComponent'
20
20
  * @protected
21
21
  */
22
- className: 'Portal.view.learn.ContentView',
22
+ className: 'Portal.view.learn.ContentComponent',
23
23
  /**
24
24
  * @member {String[]} baseCls=['learn-content']
25
25
  * @protected
@@ -41,6 +41,17 @@ class ContentView extends Component {
41
41
  tag: 'article'
42
42
  }
43
43
 
44
+ /**
45
+ *
46
+ * @member {Neo.component.Base[]} customComponents=[]
47
+ */
48
+ customComponents = []
49
+ /**
50
+ *
51
+ * @member {Neo.code.LivePreview[]} livePreviews=[]
52
+ */
53
+ livePreviews = []
54
+
44
55
  /**
45
56
  * @param {Object} config
46
57
  */
@@ -71,14 +82,36 @@ class ContentView extends Component {
71
82
 
72
83
  let me = this;
73
84
 
74
- value && me.timeout(50).then(() => {
75
- Neo.main.addon.IntersectionObserver.register({
76
- callback: 'findTopmostItem',
77
- id : me.id,
78
- root : `#${me.parentId}`,
79
- windowId: me.windowId
85
+ if (value) {
86
+ me.timeout(50).then(() => {
87
+ me.customComponents.forEach(component => {
88
+ if (!component.mounted && !component.rendering) {
89
+ component.render(true)
90
+ }
91
+ });
92
+
93
+ me.livePreviews.forEach(livePreview => {
94
+ if (!livePreview.mounted && !livePreview.rendering) {
95
+ livePreview.render(true)
96
+ }
97
+ });
98
+
99
+ Neo.main.addon.IntersectionObserver.register({
100
+ callback: 'findTopmostItem',
101
+ id : me.id,
102
+ root : `#${me.parentId}`,
103
+ windowId: me.windowId
104
+ })
80
105
  })
81
- })
106
+ } else if (oldValue !== undefined) {
107
+ me.customComponents.forEach(component => {
108
+ component.mounted = false
109
+ });
110
+
111
+ me.livePreviews.forEach(livePreview => {
112
+ livePreview.mounted = false
113
+ });
114
+ }
82
115
  }
83
116
 
84
117
  /**
@@ -90,6 +123,8 @@ class ContentView extends Component {
90
123
  if (value) {
91
124
  let me = this;
92
125
 
126
+ oldValue && me.destroyChildInstances();
127
+
93
128
  await me.doFetchContent(value);
94
129
 
95
130
  if (oldValue) {
@@ -104,25 +139,55 @@ class ContentView extends Component {
104
139
  }
105
140
  }
106
141
 
142
+ /**
143
+ * Destroy all created child instances
144
+ * @param args
145
+ */
146
+ destroy(...args) {
147
+ this.destroyChildInstances();
148
+ super.destroy(...args)
149
+ }
150
+
151
+ /**
152
+ *
153
+ */
154
+ destroyChildInstances() {
155
+ let me = this;
156
+
157
+ me.customComponents.forEach(component => {
158
+ component.destroy()
159
+ });
160
+
161
+ me.customComponents = [];
162
+
163
+ me.livePreviews.forEach(livePreview => {
164
+ livePreview.destroy()
165
+ });
166
+
167
+ me.livePreviews = []
168
+ }
169
+
107
170
  /**
108
171
  * @param {Object} record
109
172
  * @returns {Promise<void>}
110
173
  */
111
174
  async doFetchContent(record) {
112
- let me = this,
113
- path = me.getModel().getData('contentPath'),
114
- content, data, html, modifiedHtml, neoComponents, neoDivs;
175
+ let me = this,
176
+ {appName, windowId} = me,
177
+ path = me.getModel().getData('contentPath'),
178
+ baseConfigs, content, data, html, instance, modifiedHtml, neoComponents, neoDivs;
115
179
 
116
180
  path += `/pages/${record.id.replaceAll('.', '/')}.md`;
117
181
 
118
182
  if (record.isLeaf && path) {
183
+ baseConfigs = {appName, autoMount: true, autoRender: true, parentComponent: me, windowId};
119
184
  data = await fetch(path);
120
185
  content = await data.text();
121
186
  content = me.updateContentSectionsStore(content); // also replaces ## with h2 tags
122
187
  content = `# ${record.name}\n${content}`;
123
188
  modifiedHtml = await me.highlightPreContent(content);
124
189
  neoComponents = {};
125
- neoDivs = {}
190
+ neoDivs = {};
126
191
 
127
192
  // Replace <pre neo-component></pre> with <div id='neo-component-x'/>
128
193
  // and create a map keyed by ID, whose value is the javascript
@@ -144,30 +209,25 @@ class ContentView extends Component {
144
209
  await me.timeout(Neo.config.environment === 'development' ? 100 : 150);
145
210
 
146
211
  Object.keys(neoComponents).forEach(key => {
147
- Neo.create({
148
- appName : me.appName,
149
- autoMount : true,
150
- autoRender : true,
151
- className : 'Neo.component.Base',
152
- parentComponent: me,
153
- parentId : key,
154
- windowId : me.windowId,
212
+ instance = Neo.create({
213
+ ...baseConfigs,
214
+ className: 'Neo.component.Base',
215
+ parentId : key,
155
216
  ...neoComponents[key]
156
- })
217
+ });
218
+
219
+ me.customComponents.push(instance)
157
220
  });
158
221
 
159
222
  Object.keys(neoDivs).forEach(key => {
160
- // Create LivePreview for each iteration, set value to neoDivs[key]
161
- Neo.create({
162
- module : LivePreview,
163
- appName : me.appName,
164
- autoMount : true,
165
- autoRender : true,
166
- parentComponent: me,
167
- parentId : key,
168
- value : neoDivs[key],
169
- windowId : me.windowId
170
- })
223
+ instance = Neo.create({
224
+ ...baseConfigs,
225
+ module : LivePreview,
226
+ parentId: key,
227
+ value : neoDivs[key]
228
+ });
229
+
230
+ me.livePreviews.push(instance)
171
231
  });
172
232
 
173
233
  Neo.main.addon.IntersectionObserver.observe({
@@ -278,11 +338,11 @@ class ContentView extends Component {
278
338
  record = me.record;
279
339
 
280
340
  if (data.altKey && data.shiftKey && !data.metaKey) {
281
- me.fire('edit', { component: me, record })
341
+ me.fire('edit', {component: me, record})
282
342
  }
283
343
  // Command/windows shift click = refresh
284
344
  else if (!data.altKey && data.shiftKey && data.metaKey) {
285
- me.fire('refresh', { component: me, record })
345
+ me.fire('refresh', {component: me, record})
286
346
  }
287
347
  }
288
348
 
@@ -326,4 +386,4 @@ class ContentView extends Component {
326
386
  }
327
387
  }
328
388
 
329
- export default Neo.setupClass(ContentView);
389
+ export default Neo.setupClass(ContentComponent);
@@ -0,0 +1,77 @@
1
+ import Button from '../../../../src/button/Base.mjs';
2
+
3
+ /**
4
+ * @class Portal.view.learn.CubeLayoutButton
5
+ * @extends Neo.button.Base
6
+ */
7
+ class CubeLayoutButton extends Button {
8
+ static config = {
9
+ /**
10
+ * @member {String} className='Portal.view.learn.CubeLayoutButton'
11
+ * @protected
12
+ */
13
+ className: 'Portal.view.learn.CubeLayoutButton',
14
+ /**
15
+ * @member {String|null} activeLayout_=null
16
+ */
17
+ activeLayout_: null,
18
+ }
19
+
20
+ /**
21
+ * @member {Object} activateText='Activate Cube-Layout'
22
+ */
23
+ activateText = 'Activate Cube-Layout'
24
+ /**
25
+ * @member {Object} deactivateText='Deactivate Cube-Layout'
26
+ */
27
+ deactivateText = 'Deactivate Cube-Layout'
28
+
29
+ /**
30
+ * @member {Portal.view.ViewportController} viewportController
31
+ */
32
+ get viewportController() {
33
+ return this.getController('viewport-controller')
34
+ }
35
+
36
+ /**
37
+ * @param {Object} config
38
+ */
39
+ construct(config) {
40
+ super.construct(config);
41
+
42
+ let me = this;
43
+
44
+ me.activeLayout = me.viewportController.mainContentLayout;
45
+ me.handler = me.changeLayout.bind(me)
46
+ }
47
+
48
+ /**
49
+ * Triggered after the activeLayout config got changed
50
+ * @param {String|null} value
51
+ * @param {String|null} oldValue
52
+ */
53
+ afterSetActiveLayout(value, oldValue) {
54
+ let me = this;
55
+
56
+ if (value) {
57
+ me.viewportController.mainContentLayout = value;
58
+
59
+ if (value === 'card') {
60
+ me.text = me.activateText
61
+ } else if (value === 'mixed') {
62
+ me.text = me.deactivateText
63
+ }
64
+ }
65
+ }
66
+
67
+ /**
68
+ * @param {Object} data
69
+ */
70
+ changeLayout(data) {
71
+ let me = this;
72
+
73
+ me.activeLayout = me.text === me.activateText ? 'mixed' : 'card'
74
+ }
75
+ }
76
+
77
+ export default Neo.setupClass(CubeLayoutButton);
@@ -1,4 +1,5 @@
1
1
  import Controller from '../../../../src/controller/Component.mjs';
2
+ import CubeLayoutButton from './CubeLayoutButton.mjs'; // required for the Portal App .md file
2
3
  import {getSearchParams} from '../../Util.mjs';
3
4
 
4
5
  /**
@@ -140,7 +141,7 @@ class MainContainerController extends Controller {
140
141
  */
141
142
  onRouteDefault(data) {
142
143
  if (!this.getModel().data.currentPageRecord) {
143
- this.onRouteLearnItem({itemId: 'WhyNeo-Intro'})
144
+ this.onRouteLearnItem({itemId: 'benefits.Introduction'})
144
145
  }
145
146
  }
146
147
 
@@ -1,6 +1,6 @@
1
- import Container from '../../../../src/container/Base.mjs';
2
- import ContentView from './ContentView.mjs';
3
- import Toolbar from '../../../../src/toolbar/Base.mjs';
1
+ import Container from '../../../../src/container/Base.mjs';
2
+ import ContentComponent from './ContentComponent.mjs';
3
+ import Toolbar from '../../../../src/toolbar/Base.mjs';
4
4
 
5
5
  /**
6
6
  * @class Portal.view.learn.PageContainer
@@ -29,7 +29,7 @@ class PageContainer extends Container {
29
29
  * @member {Object[]} items
30
30
  */
31
31
  items: [{
32
- module : ContentView,
32
+ module : ContentComponent,
33
33
  reference: 'content',
34
34
  listeners: {
35
35
  edit : 'onContentEdit',
@@ -28,6 +28,7 @@ class DemoDialog extends Dialog {
28
28
  * @member {Object} itemDefaults={labelWidth:70}
29
29
  */
30
30
  itemDefaults: {
31
+ flex : 'none',
31
32
  labelWidth: 70
32
33
  },
33
34
  /**
@@ -35,20 +36,11 @@ class DemoDialog extends Dialog {
35
36
  */
36
37
  items: [{
37
38
  module : TextField,
38
- flex : 'none',
39
39
  labelText: 'Field 1'
40
40
  }, {
41
41
  module : TextField,
42
- flex : 'none',
43
42
  labelText: 'Field 2'
44
- }],
45
- /**
46
- * @member {Object} wrapperStyle={height:'40%',width:'40%'}
47
- */
48
- wrapperStyle: {
49
- height: '40%',
50
- width : '40%'
51
- }
43
+ }]
52
44
  }
53
45
  }
54
46