neo.mjs 6.9.10 → 6.9.11
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/learnneo/neo-config.json +5 -1
- package/apps/learnneo/store/Content.mjs +1 -1
- package/apps/learnneo/view/Viewport.mjs +12 -1
- package/apps/learnneo/view/home/ContentTreeList.mjs +8 -5
- package/apps/learnneo/view/home/ContentView.mjs +60 -0
- package/apps/learnneo/view/home/MainContainer.mjs +22 -14
- package/apps/learnneo/view/home/MainContainerController.mjs +57 -18
- package/apps/newwebsite/app.mjs +6 -0
- package/apps/newwebsite/index.html +10 -0
- package/apps/newwebsite/neo-config.json +7 -0
- package/apps/newwebsite/view/MainContainer.mjs +59 -0
- package/buildScripts/webpack/json/myApps.template.json +1 -0
- package/examples/ConfigurationViewport.mjs +12 -9
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/button/base/neo-config.json +1 -2
- package/package.json +2 -2
- package/resources/data/{learnneo → deck/learnneo}/p/2023-10-01T18-29-19-158Z.md +3 -6
- package/resources/data/deck/learnneo/p/stylesheet.md +40 -0
- package/resources/data/{learnneo → deck/learnneo}/t.json +19 -2
- package/resources/data/deck/training/p/2022-12-27T21-54-52-300Z.md +11 -0
- package/resources/data/deck/training/p/2022-12-27T21-55-23-144Z.md +43 -0
- package/resources/data/deck/training/p/2022-12-27T21-55-30-948Z.md +1 -0
- package/resources/data/deck/training/p/2022-12-27T21-55-43-542Z.md +84 -0
- package/resources/data/deck/training/p/2022-12-27T22-23-55-083Z.md +1 -0
- package/resources/data/deck/training/p/2022-12-27T22-24-07-886Z.md +8 -0
- package/resources/data/deck/training/p/2022-12-27T22-24-52-295Z.md +8 -0
- package/resources/data/deck/training/p/2022-12-27T22-25-03-853Z.md +5 -0
- package/resources/data/deck/training/p/2022-12-27T22-43-58-924Z.md +10 -0
- package/resources/data/deck/training/p/2022-12-27T22-44-28-881Z.md +3 -0
- package/resources/data/deck/training/p/2022-12-27T22-44-41-791Z.md +4 -0
- package/resources/data/deck/training/p/2022-12-27T22-45-21-032Z.md +7 -0
- package/resources/data/deck/training/p/2022-12-27T22-49-22-078Z.md +4 -0
- package/resources/data/deck/training/p/2022-12-27T22-50-20-626Z.md +4 -0
- package/resources/data/deck/training/p/2022-12-28T16-58-47-786Z.md +0 -0
- package/resources/data/deck/training/p/2022-12-28T16-58-55-192Z.md +9 -0
- package/resources/data/deck/training/p/2022-12-28T17-10-18-058Z.md +15 -0
- package/resources/data/deck/training/p/2022-12-28T17-10-42-296Z.md +40 -0
- package/resources/data/deck/training/p/2022-12-28T17-11-34-653Z.md +41 -0
- package/resources/data/deck/training/p/2022-12-28T17-13-09-994Z.md +0 -0
- package/resources/data/deck/training/p/2022-12-28T21-32-14-420Z.md +0 -0
- package/resources/data/deck/training/p/2022-12-29T01-43-32-431Z.md +7 -0
- package/resources/data/deck/training/p/2022-12-29T15-56-54-485Z.md +7 -0
- package/resources/data/deck/training/p/2022-12-29T15-57-11-499Z.md +7 -0
- package/resources/data/deck/training/p/2022-12-29T16-00-13-223Z.md +7 -0
- package/resources/data/deck/training/p/2022-12-29T18-34-25-826Z.md +4 -0
- package/resources/data/deck/training/p/2022-12-29T18-36-08-226Z.md +106 -0
- package/resources/data/deck/training/p/2022-12-29T18-36-56-893Z.md +112 -0
- package/resources/data/deck/training/p/2022-12-29T19-31-30-507Z.md +31 -0
- package/resources/data/deck/training/p/2022-12-29T19-31-55-091Z.md +14 -0
- package/resources/data/deck/training/p/2022-12-29T20-03-42-628Z.md +9 -0
- package/resources/data/deck/training/p/2022-12-29T20-21-20-669Z.md +7 -0
- package/resources/data/deck/training/p/2022-12-29T20-37-08-919Z.md +46 -0
- package/resources/data/deck/training/p/2022-12-29T20-37-20-344Z.md +43 -0
- package/resources/data/deck/training/p/2022-12-30T19-04-30-990Z.md +8 -0
- package/resources/data/deck/training/p/2022-12-31T18-43-56-338Z.md +7 -0
- package/resources/data/deck/training/p/2022-12-31T18-51-50-682Z.md +1 -0
- package/resources/data/deck/training/p/2022-12-31T18-54-04-176Z.md +4 -0
- package/resources/data/deck/training/p/2022-12-31T22-11-55-555Z.md +112 -0
- package/resources/data/deck/training/p/2022-12-31T23-00-41-222Z.md +6 -0
- package/resources/data/deck/training/p/2022-12-31T23-18-55-655Z.md +69 -0
- package/resources/data/deck/training/p/2022-12-31T23-25-40-735Z.md +21 -0
- package/resources/data/deck/training/p/2022-12-31T23-25-51-014Z.md +7 -0
- package/resources/data/deck/training/p/2023-01-01T17-49-18-429Z.md +3 -0
- package/resources/data/deck/training/p/2023-01-01T18-44-07-034Z.md +34 -0
- package/resources/data/deck/training/p/2023-01-01T18-47-39-766Z.md +15 -0
- package/resources/data/deck/training/p/2023-01-01T19-04-22-830Z.md +4 -0
- package/resources/data/deck/training/p/2023-01-01T21-11-58-025Z.md +25 -0
- package/resources/data/deck/training/p/2023-01-01T21-12-37-340Z.md +23 -0
- package/resources/data/deck/training/p/2023-01-01T21-13-13-880Z.md +8 -0
- package/resources/data/deck/training/p/2023-01-01T21-14-45-740Z.md +98 -0
- package/resources/data/deck/training/p/2023-01-01T21-18-23-886Z.md +26 -0
- package/resources/data/deck/training/p/2023-01-01T21-18-31-316Z.md +19 -0
- package/resources/data/deck/training/p/2023-01-01T21-18-42-290Z.md +23 -0
- package/resources/data/deck/training/p/2023-01-01T21-19-57-020Z.md +24 -0
- package/resources/data/deck/training/p/2023-01-01T21-22-31-184Z.md +13 -0
- package/resources/data/deck/training/p/2023-01-01T21-22-38-317Z.md +17 -0
- package/resources/data/deck/training/p/2023-01-01T21-22-47-693Z.md +20 -0
- package/resources/data/deck/training/p/2023-01-01T21-23-17-716Z.md +39 -0
- package/resources/data/deck/training/p/2023-01-01T21-23-28-532Z.md +22 -0
- package/resources/data/deck/training/p/2023-01-01T21-25-23-899Z.md +3 -0
- package/resources/data/deck/training/p/2023-01-01T21-25-59-742Z.md +1 -0
- package/resources/data/deck/training/p/2023-01-01T21-26-53-748Z.md +12 -0
- package/resources/data/deck/training/p/2023-01-01T23-38-42-863Z.md +2 -0
- package/resources/data/deck/training/p/2023-01-03T02-07-19-014Z.md +143 -0
- package/resources/data/deck/training/p/2023-01-04T01-52-23-454Z.md +76 -0
- package/resources/data/deck/training/p/2023-01-06T23-21-12-009Z.md +127 -0
- package/resources/data/deck/training/p/2023-01-06T23-21-31-685Z.md +81 -0
- package/resources/data/deck/training/p/2023-01-06T23-21-59-596Z.md +36 -0
- package/resources/data/deck/training/p/2023-01-06T23-34-13-897Z.md +87 -0
- package/resources/data/deck/training/p/2023-01-06T23-44-02-340Z.md +0 -0
- package/resources/data/deck/training/p/2023-01-06T23-46-36-687Z.md +1 -0
- package/resources/data/deck/training/p/2023-01-06T23-46-45-783Z.md +33 -0
- package/resources/data/deck/training/p/2023-01-08T00-45-11-144Z.md +50 -0
- package/resources/data/deck/training/p/2023-01-08T01-06-31-267Z.md +41 -0
- package/resources/data/deck/training/p/2023-01-08T01-24-21-088Z.md +95 -0
- package/resources/data/deck/training/p/2023-01-08T01-25-12-557Z.md +11 -0
- package/resources/data/deck/training/p/2023-01-08T01-46-50-723Z.md +25 -0
- package/resources/data/deck/training/p/2023-01-08T02-09-07-802Z.md +18 -0
- package/resources/data/deck/training/p/2023-01-08T02-09-19-678Z.md +66 -0
- package/resources/data/deck/training/p/2023-01-08T02-11-26-333Z.md +29 -0
- package/resources/data/deck/training/p/2023-01-08T17-22-48-841Z.md +14 -0
- package/resources/data/deck/training/p/2023-01-08T20-46-11-806Z.md +5 -0
- package/resources/data/deck/training/p/2023-01-08T20-47-23-682Z.md +5 -0
- package/resources/data/deck/training/p/2023-01-08T20-47-32-064Z.md +13 -0
- package/resources/data/deck/training/p/2023-01-08T20-47-57-045Z.md +0 -0
- package/resources/data/deck/training/p/2023-01-08T20-48-03-791Z.md +18 -0
- package/resources/data/deck/training/p/2023-01-08T20-48-32-466Z.md +9 -0
- package/resources/data/deck/training/p/2023-01-08T20-48-51-322Z.md +20 -0
- package/resources/data/deck/training/p/2023-01-08T20-49-52-741Z.md +0 -0
- package/resources/data/deck/training/p/2023-01-08T20-52-03-556Z.md +0 -0
- package/resources/data/deck/training/p/2023-01-08T20-57-36-333Z.md +2 -0
- package/resources/data/deck/training/p/2023-01-08T20-57-51-136Z.md +5 -0
- package/resources/data/deck/training/p/2023-01-09T00-07-37-951Z.md +0 -0
- package/resources/data/deck/training/p/2023-01-09T00-35-40-671Z.md +3 -0
- package/resources/data/deck/training/p/2023-01-10T01-29-38-148Z.md +10 -0
- package/resources/data/deck/training/p/2023-01-10T01-43-12-166Z.md +31 -0
- package/resources/data/deck/training/p/2023-01-10T02-21-54-303Z.md +10 -0
- package/resources/data/deck/training/p/2023-01-12T01-50-54-617Z.md +74 -0
- package/resources/data/deck/training/p/2023-01-13T19-55-24-735Z.md +14 -0
- package/resources/data/deck/training/p/2023-01-13T20-08-27-068Z.md +28 -0
- package/resources/data/deck/training/p/2023-01-13T20-23-38-411Z.md +25 -0
- package/resources/data/deck/training/p/2023-01-13T20-37-06-267Z.md +13 -0
- package/resources/data/deck/training/p/2023-01-13T21-05-57-708Z.md +8 -0
- package/resources/data/deck/training/p/2023-01-13T21-48-17-258Z.md +20 -0
- package/resources/data/deck/training/p/2023-01-13T22-05-05-799Z.md +14 -0
- package/resources/data/deck/training/p/2023-01-13T22-08-30-863Z.md +17 -0
- package/resources/data/deck/training/p/2023-01-13T23-01-50-449Z.md +4 -0
- package/resources/data/deck/training/p/2023-01-14T00-33-05-958Z.md +62 -0
- package/resources/data/deck/training/p/2023-01-14T00-40-27-784Z.md +229 -0
- package/resources/data/deck/training/p/2023-01-14T00-41-59-081Z.md +153 -0
- package/resources/data/deck/training/p/2023-01-14T13-50-28-199Z.md +19 -0
- package/resources/data/deck/training/p/2023-01-14T13-59-20-275Z.md +6 -0
- package/resources/data/deck/training/p/2023-01-14T14-03-29-456Z.md +3 -0
- package/resources/data/deck/training/p/2023-01-14T14-27-57-678Z.md +7 -0
- package/resources/data/deck/training/p/2023-01-14T17-30-18-228Z.md +33 -0
- package/resources/data/deck/training/p/2023-01-14T18-28-39-316Z.md +1 -0
- package/resources/data/deck/training/p/2023-01-14T18-28-44-115Z.md +4 -0
- package/resources/data/deck/training/p/2023-01-14T18-28-49-548Z.md +18 -0
- package/resources/data/deck/training/p/2023-01-14T18-40-13-758Z.md +10 -0
- package/resources/data/deck/training/p/2023-01-14T19-29-15-291Z.md +12 -0
- package/resources/data/deck/training/p/2023-01-15T18-51-52-134Z.md +83 -0
- package/resources/data/deck/training/p/2023-01-15T20-03-30-073Z.md +11 -0
- package/resources/data/deck/training/p/2023-01-15T22-07-52-073Z.md +16 -0
- package/resources/data/deck/training/p/2023-01-15T22-22-13-517Z.md +12 -0
- package/resources/data/deck/training/p/2023-01-15T22-28-57-508Z.md +131 -0
- package/resources/data/deck/training/p/2023-01-15T22-36-30-913Z.md +115 -0
- package/resources/data/deck/training/p/2023-01-16T16-03-40-770Z.md +12 -0
- package/resources/data/deck/training/p/2023-01-16T20-21-56-859Z.md +5 -0
- package/resources/data/deck/training/p/2023-01-16T20-24-09-690Z.md +24 -0
- package/resources/data/deck/training/p/2023-01-20T12-51-22-646Z.md +21 -0
- package/resources/data/deck/training/p/2023-01-20T13-06-46-614Z.md +9 -0
- package/resources/data/deck/training/p/2023-01-20T13-08-51-600Z.md +7 -0
- package/resources/data/deck/training/p/2023-01-20T15-20-13-363Z.md +26 -0
- package/resources/data/deck/training/p/2023-01-20T15-34-58-813Z.md +75 -0
- package/resources/data/deck/training/p/2023-01-21T16-33-20-458Z.md +33 -0
- package/resources/data/deck/training/p/2023-01-21T16-45-28-263Z.md +28 -0
- package/resources/data/deck/training/p/2023-01-21T16-56-25-452Z.md +3 -0
- package/resources/data/deck/training/p/2023-01-21T17-28-31-493Z.md +6 -0
- package/resources/data/deck/training/p/2023-01-21T19-49-51-918Z.md +13 -0
- package/resources/data/deck/training/p/2023-01-21T20-08-24-452Z.md +15 -0
- package/resources/data/deck/training/p/2023-01-21T20-35-54-947Z.md +20 -0
- package/resources/data/deck/training/p/2023-01-21T20-54-47-603Z.md +39 -0
- package/resources/data/deck/training/p/2023-01-21T20-56-28-184Z.md +25 -0
- package/resources/data/deck/training/p/2023-01-21T20-57-32-927Z.md +4 -0
- package/resources/data/deck/training/p/2023-01-21T23-13-33-394Z.md +6 -0
- package/resources/data/deck/training/p/2023-01-28T19-11-37-464Z.md +24 -0
- package/resources/data/deck/training/p/2023-01-28T20-43-41-188Z.md +9 -0
- package/resources/data/deck/training/p/2023-01-28T20-53-56-476Z.md +8 -0
- package/resources/data/deck/training/p/2023-01-28T20-58-43-776Z.md +10 -0
- package/resources/data/deck/training/p/2023-01-28T22-18-41-259Z.md +33 -0
- package/resources/data/deck/training/p/2023-01-28T22-24-34-808Z.md +24 -0
- package/resources/data/deck/training/p/2023-01-29T16-25-24-528Z.md +44 -0
- package/resources/data/deck/training/p/2023-01-29T21-14-32-588Z.md +12 -0
- package/resources/data/deck/training/p/2023-01-31T19-24-53-504Z.md +8 -0
- package/resources/data/deck/training/p/2023-01-31T20-33-55-855Z.md +11 -0
- package/resources/data/deck/training/p/2023-01-31T20-34-30-261Z.md +7 -0
- package/resources/data/deck/training/p/2023-01-31T20-52-53-367Z.md +43 -0
- package/resources/data/deck/training/p/2023-02-04T15-18-35-682Z.md +20 -0
- package/resources/data/deck/training/p/2023-02-04T15-49-47-597Z.md +14 -0
- package/resources/data/deck/training/p/2023-02-04T18-58-57-808Z.md +1 -0
- package/resources/data/deck/training/p/2023-02-04T20-07-11-288Z.md +1 -0
- package/resources/data/deck/training/p/2023-02-04T20-09-50-169Z.md +1 -0
- package/resources/data/deck/training/p/2023-02-04T20-19-42-740Z.md +8 -0
- package/resources/data/deck/training/p/2023-02-04T20-23-56-013Z.md +12 -0
- package/resources/data/deck/training/p/2023-02-04T20-28-12-391Z.md +20 -0
- package/resources/data/deck/training/p/2023-02-05T00-20-32-554Z.md +16 -0
- package/resources/data/deck/training/p/2023-02-05T00-35-56-282Z.md +13 -0
- package/resources/data/deck/training/p/2023-02-05T15-36-57-182Z.md +24 -0
- package/resources/data/deck/training/p/2023-02-05T17-39-51-712Z.md +70 -0
- package/resources/data/deck/training/p/2023-02-05T17-44-53-815Z.md +195 -0
- package/resources/data/deck/training/p/2023-02-05T17-45-40-114Z.md +92 -0
- package/resources/data/deck/training/p/2023-02-05T18-12-14-489Z.md +60 -0
- package/resources/data/deck/training/p/2023-02-06T00-14-54-457Z.md +9 -0
- package/resources/data/deck/training/p/2023-06-28T18-03-14-313Z.md +8 -0
- package/resources/data/deck/training/p/2023-06-28T18-26-17-290Z.md +7 -0
- package/resources/data/deck/training/p/2023-06-28T21-16-24-034Z.md +40 -0
- package/resources/data/deck/training/p/2023-06-28T21-16-34-972Z.md +16 -0
- package/resources/data/deck/training/p/2023-06-28T21-28-28-379Z.md +4 -0
- package/resources/data/deck/training/p/2023-06-29T23-15-10-411Z.md +5 -0
- package/resources/data/deck/training/p/2023-07-01T15-42-45-193Z.md +433 -0
- package/resources/data/deck/training/p/2023-07-01T21-54-31-329Z.md +6 -0
- package/resources/data/deck/training/p/2023-07-02T16-14-06-970Z.md +14 -0
- package/resources/data/deck/training/p/2023-07-31T00-26-03-842Z.md +4 -0
- package/resources/data/deck/training/p/2023-07-31T00-31-51-933Z.md +10 -0
- package/resources/data/deck/training/p/2023-07-31T00-37-21-927Z.md +205 -0
- package/resources/data/deck/training/p/2023-10-01T18-29-19-158Z.md +76 -0
- package/resources/data/deck/training/p/2023-10-07T19-18-28-517Z.md +102 -0
- package/resources/data/deck/training/p/2023-10-08T20-20-07-934Z.md +75 -0
- package/resources/data/deck/training/p/2023-10-08T20-20-37-336Z.md +29 -0
- package/resources/data/deck/training/p/2023-10-08T20-37-30-658Z.md +0 -0
- package/resources/data/deck/training/p/2023-10-08T21-58-25-809Z.md +68 -0
- package/resources/data/deck/training/p/2023-10-08T22-22-11-013Z.md +0 -0
- package/resources/data/deck/training/p/2023-10-14T19-25-08-153Z.md +119 -0
- package/resources/data/deck/training/t.json +1 -0
- package/resources/scss/src/apps/learnneo/home/{ContentComponent.scss → ContentView.scss} +9 -15
- package/resources/scss/theme-neo-light/Global.scss +46 -0
- package/resources/scss/theme-neo-light/design-tokens/Core.scss +7 -0
- package/resources/scss/theme-neo-light/design-tokens/Semantic.scss +0 -0
- package/resources/scss/theme-neo-light/design-tokens/_all.scss +4 -0
- package/src/DefaultConfig.mjs +4 -4
- package/src/form/field/Text.mjs +2 -2
- package/apps/learnneo/view/home/ContentComponent.mjs +0 -24
- /package/resources/data/{learnneo → deck/learnneo}/p/2023-10-07T19-18-28-517Z.md +0 -0
- /package/resources/data/{learnneo → deck/learnneo}/p/2023-10-08T20-20-07-934Z.md +0 -0
- /package/resources/data/{learnneo → deck/learnneo}/p/2023-10-08T20-20-37-336Z.md +0 -0
- /package/resources/data/{learnneo → deck/learnneo}/p/2023-10-08T20-37-30-658Z.md +0 -0
- /package/resources/data/{learnneo → deck/learnneo}/p/2023-10-08T21-58-25-809Z.md +0 -0
- /package/resources/data/{learnneo → deck/learnneo}/p/2023-10-08T22-22-11-013Z.md +0 -0
- /package/resources/data/{learnneo → deck/learnneo}/p/2023-10-14T19-25-08-153Z.md +0 -0
- /package/resources/data/{learnneo → deck/learnneo}/pages/whyneo.md +0 -0
- /package/resources/data/{learnneo → deck/learnneo}/tree.json +0 -0
- /package/resources/{deck → data/deck}/whyneo.md +0 -0
- /package/resources/scss/src/apps/newwebsite/{MainContainer.css → MainContainer.scss} +0 -0
- /package/resources/scss/theme-neo-light/design-tokens/{Components.scss → Component.scss} +0 -0
@@ -0,0 +1,433 @@
|
|
1
|
+
#Introduction
|
2
|
+
|
3
|
+
During class you'll create three or four apps. The built-in _create-app_ script
|
4
|
+
isn't suitable for this course, so in this lab you'll create a new _create-app-training_
|
5
|
+
script that creates a starter app with content thats' a good starting
|
6
|
+
point for our labs.
|
7
|
+
|
8
|
+
|
9
|
+
#Steps
|
10
|
+
|
11
|
+
??Create the file `workspace/buildScripts/createAppTraining.mjs`
|
12
|
+
|
13
|
+
Use this content. The details don't matter. (Frankly, it's a bit of a mess.)
|
14
|
+
But in a nutshell, the script creates an app with an empty view, view model,
|
15
|
+
and controller. It'll be easier to work with than the default _create-app_ script.
|
16
|
+
|
17
|
+
This is long. Make sure you scroll and copy the entire contents.
|
18
|
+
<pre style="border: thin solid gray; color:gray; padding: 8px; height:200px">
|
19
|
+
import chalk from 'chalk';
|
20
|
+
import {spawnSync} from 'child_process';
|
21
|
+
import {Command} from 'commander/esm.mjs';
|
22
|
+
import envinfo from 'envinfo';
|
23
|
+
import fs from 'fs-extra';
|
24
|
+
import inquirer from 'inquirer';
|
25
|
+
import os from 'os';
|
26
|
+
import path from 'path';
|
27
|
+
|
28
|
+
const __dirname = path.resolve(),
|
29
|
+
cwd = process.cwd(),
|
30
|
+
requireJson = path => JSON.parse(fs.readFileSync((path))),
|
31
|
+
packageJson = requireJson(path.join(__dirname, 'package.json')),
|
32
|
+
insideNeo = packageJson.name === 'neo.mjs',
|
33
|
+
neoPath = insideNeo ? './' : './node_modules/neo.mjs/',
|
34
|
+
addonChoices = fs.readdirSync(path.join(neoPath, '/src/main/addon')).map(item => item.slice(0, -4)),
|
35
|
+
program = new Command(),
|
36
|
+
programName = `${packageJson.name} create-app`,
|
37
|
+
questions = [],
|
38
|
+
scssFolders = fs.readdirSync(path.join(neoPath, '/resources/scss')),
|
39
|
+
themeFolders = [];
|
40
|
+
|
41
|
+
scssFolders.forEach(folder => {
|
42
|
+
if (folder.includes('theme')) {
|
43
|
+
themeFolders.push(`neo-${folder}`);
|
44
|
+
}
|
45
|
+
});
|
46
|
+
|
47
|
+
program
|
48
|
+
.name(programName)
|
49
|
+
.version(packageJson.version)
|
50
|
+
.option('-i, --info', 'print environment debug info')
|
51
|
+
.option('-a, --appName <value>')
|
52
|
+
.option('-m, --mainThreadAddons <value>', `Comma separated list of:\n${addonChoices.join(', ')}\nDefaults to DragDrop, Stylesheet`)
|
53
|
+
.option('-s, --useServiceWorker <value>', '"yes", "no"')
|
54
|
+
.option('-t, --themes <value>', ['all', ...themeFolders, 'none'].join(", "))
|
55
|
+
.option('-u, --useSharedWorkers <value>', '"yes", "no"')
|
56
|
+
.allowUnknownOption()
|
57
|
+
.on('--help', () => {
|
58
|
+
console.log('\nIn case you have any issues, please create a ticket here:');
|
59
|
+
console.log(chalk.cyan(process.env.npm_package_bugs_url));
|
60
|
+
})
|
61
|
+
.parse(process.argv);
|
62
|
+
|
63
|
+
const programOpts = program.opts();
|
64
|
+
|
65
|
+
if (programOpts.info) {
|
66
|
+
console.log(chalk.bold('\nEnvironment Info:'));
|
67
|
+
console.log(`\n current version of ${packageJson.name}: ${packageJson.version}`);
|
68
|
+
console.log(` running from ${__dirname}`);
|
69
|
+
|
70
|
+
envinfo
|
71
|
+
.run({
|
72
|
+
System: ['OS', 'CPU'],
|
73
|
+
Binaries: ['Node', 'npm', 'Yarn'],
|
74
|
+
Browsers: ['Chrome', 'Edge', 'Firefox', 'Safari'],
|
75
|
+
npmPackages: ['neo.mjs']
|
76
|
+
}, {
|
77
|
+
duplicates: true,
|
78
|
+
showNotFound: true
|
79
|
+
})
|
80
|
+
.then(console.log);
|
81
|
+
} else {
|
82
|
+
console.log(chalk.green(programName));
|
83
|
+
|
84
|
+
if (programOpts.mainThreadAddons) {
|
85
|
+
programOpts.mainThreadAddons = programOpts.mainThreadAddons.split(',');
|
86
|
+
}
|
87
|
+
|
88
|
+
if (!programOpts.appName) {
|
89
|
+
questions.push({
|
90
|
+
type: 'input',
|
91
|
+
name: 'appName',
|
92
|
+
message: 'Please choose a name for your neo app:',
|
93
|
+
default: 'MyApp'
|
94
|
+
});
|
95
|
+
}
|
96
|
+
|
97
|
+
if (!programOpts.themes) {
|
98
|
+
questions.push({
|
99
|
+
type: 'list',
|
100
|
+
name: 'themes',
|
101
|
+
message: 'Please choose a theme for your neo app:',
|
102
|
+
choices: ['all', ...themeFolders, 'none'],
|
103
|
+
default: 'all'
|
104
|
+
});
|
105
|
+
}
|
106
|
+
|
107
|
+
if (!programOpts.mainThreadAddons) {
|
108
|
+
questions.push({
|
109
|
+
type: 'checkbox',
|
110
|
+
name: 'mainThreadAddons',
|
111
|
+
message: 'Please choose your main thread addons:',
|
112
|
+
choices: addonChoices,
|
113
|
+
default: ['DragDrop', 'Stylesheet']
|
114
|
+
});
|
115
|
+
}
|
116
|
+
|
117
|
+
if (!programOpts.useSharedWorkers) {
|
118
|
+
questions.push({
|
119
|
+
type: 'list',
|
120
|
+
name: 'useSharedWorkers',
|
121
|
+
message: 'Do you want to use SharedWorkers? Pick yes for multiple main threads (Browser Windows):',
|
122
|
+
choices: ['yes', 'no'],
|
123
|
+
default: 'no'
|
124
|
+
});
|
125
|
+
}
|
126
|
+
|
127
|
+
if (!programOpts.useServiceWorker) {
|
128
|
+
questions.push({
|
129
|
+
type: 'list',
|
130
|
+
name: 'useServiceWorker',
|
131
|
+
message: 'Do you want to use a ServiceWorker for caching assets?',
|
132
|
+
choices: ['yes', 'no'],
|
133
|
+
default: 'no'
|
134
|
+
});
|
135
|
+
}
|
136
|
+
|
137
|
+
inquirer.prompt(questions).then(answers => {
|
138
|
+
let appName = programOpts.appName || answers.appName,
|
139
|
+
mainThreadAddons = programOpts.mainThreadAddons || answers.mainThreadAddons,
|
140
|
+
themes = programOpts.themes || answers.themes,
|
141
|
+
useSharedWorkers = programOpts.useSharedWorkers || answers.useSharedWorkers,
|
142
|
+
useServiceWorker = programOpts.useServiceWorker || answers.useServiceWorker,
|
143
|
+
lAppName = appName.toLowerCase(),
|
144
|
+
appPath = 'apps/' + lAppName + '/',
|
145
|
+
dir = 'apps/' + lAppName,
|
146
|
+
folder = path.resolve(cwd, dir),
|
147
|
+
startDate = new Date();
|
148
|
+
|
149
|
+
if (!Array.isArray(themes)) {
|
150
|
+
themes = [themes];
|
151
|
+
}
|
152
|
+
|
153
|
+
if (themes.length > 0 && !themes.includes('none') && !mainThreadAddons.includes('Stylesheet')) {
|
154
|
+
console.error('ERROR! The Stylesheet mainThreadAddon is mandatory in case you are using themes');
|
155
|
+
console.log('Exiting with error.');
|
156
|
+
process.exit(1);
|
157
|
+
}
|
158
|
+
|
159
|
+
fs.mkdir(path.join(folder, '/view'), {recursive: true}, (err) => {
|
160
|
+
if (err) {
|
161
|
+
throw err;
|
162
|
+
}
|
163
|
+
|
164
|
+
let content, className;
|
165
|
+
const neoSrcPath = `../../../${insideNeo ? '' : 'node_modules/neo.mjs/'}src`;
|
166
|
+
|
167
|
+
const appContent = [
|
168
|
+
"import Viewport from './view/Viewport.mjs';",
|
169
|
+
"",
|
170
|
+
"export const onStart = () => Neo.app({",
|
171
|
+
" mainView: Viewport,",
|
172
|
+
" name : '" + appName + "'",
|
173
|
+
"});"
|
174
|
+
].join(os.EOL);
|
175
|
+
|
176
|
+
fs.writeFileSync(folder + '/app.mjs', appContent);
|
177
|
+
|
178
|
+
const indexContent = `
|
179
|
+
<!DOCTYPE HTML>
|
180
|
+
<html>
|
181
|
+
<head>
|
182
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
183
|
+
<meta charset="UTF-8">
|
184
|
+
<title>${appName}</title>
|
185
|
+
</head>
|
186
|
+
<body>
|
187
|
+
<script src="../../src/MicroLoader.mjs" type="module"></script>
|
188
|
+
<script>
|
189
|
+
new MutationObserver((mutationsList, observer) => {
|
190
|
+
for (let mutation of mutationsList) {
|
191
|
+
for (let addedNode of mutation.addedNodes) {
|
192
|
+
if (addedNode.className && addedNode.className.includes(\'neo-viewport\')) {
|
193
|
+
addedNode.addEventListener("contextmenu", function (e) {
|
194
|
+
if (!(e.ctrlKey || e.metaKey)) return;
|
195
|
+
e.stopPropagation();
|
196
|
+
e.preventDefault();
|
197
|
+
const event = new Event('neo-debug-item-select', {bubbles: true});
|
198
|
+
e.target.dispatchEvent(event);
|
199
|
+
});
|
200
|
+
observer.disconnect(); // We found the viewport so we\'re finished listening
|
201
|
+
}
|
202
|
+
}
|
203
|
+
}
|
204
|
+
}).observe(document.body, {childList: true, subtree: false});
|
205
|
+
</script>
|
206
|
+
</body>
|
207
|
+
</html>
|
208
|
+
`;
|
209
|
+
fs.writeFileSync(path.join(folder, 'index.html'), indexContent);
|
210
|
+
|
211
|
+
|
212
|
+
|
213
|
+
let neoConfig = {
|
214
|
+
appPath: `${insideNeo ? '' : '../../'}${appPath}app.mjs`,
|
215
|
+
basePath: '../../',
|
216
|
+
environment: 'development',
|
217
|
+
mainPath: `${insideNeo ? './' : '../node_modules/neo.mjs/src/'}Main.mjs`
|
218
|
+
};
|
219
|
+
|
220
|
+
if (!(mainThreadAddons.includes('DragDrop') && mainThreadAddons.includes('Stylesheet') && mainThreadAddons.length === 2)) {
|
221
|
+
neoConfig.mainThreadAddons = mainThreadAddons;
|
222
|
+
}
|
223
|
+
|
224
|
+
if (!themes.includes('all')) { // default value
|
225
|
+
if (themes.includes('none')) {
|
226
|
+
neoConfig.themes = [];
|
227
|
+
} else {
|
228
|
+
neoConfig.themes = themes;
|
229
|
+
}
|
230
|
+
}
|
231
|
+
|
232
|
+
if (useSharedWorkers !== 'no') {
|
233
|
+
neoConfig.useSharedWorkers = true;
|
234
|
+
}
|
235
|
+
|
236
|
+
if (useServiceWorker !== 'no') {
|
237
|
+
neoConfig.useServiceWorker = true;
|
238
|
+
}
|
239
|
+
|
240
|
+
if (!insideNeo) {
|
241
|
+
neoConfig.workerBasePath = '../../node_modules/neo.mjs/src/worker/';
|
242
|
+
}
|
243
|
+
|
244
|
+
let configs = Object.entries(neoConfig).sort((a, b) => a[0].localeCompare(b[0]));
|
245
|
+
neoConfig = {};
|
246
|
+
|
247
|
+
configs.forEach(([key, value]) => {
|
248
|
+
neoConfig[key] = value;
|
249
|
+
});
|
250
|
+
|
251
|
+
fs.writeFileSync(path.join(folder, 'neo-config.json'), JSON.stringify(neoConfig, null, 4));
|
252
|
+
|
253
|
+
// App source files: viewport and main view
|
254
|
+
|
255
|
+
|
256
|
+
|
257
|
+
|
258
|
+
// -------------------------------------------------------------------------
|
259
|
+
|
260
|
+
className = 'Viewport';
|
261
|
+
content = `
|
262
|
+
import Base from '${neoSrcPath}/container/Viewport.mjs';
|
263
|
+
import MainView from './MainView.mjs';
|
264
|
+
|
265
|
+
class ${className} extends Base {
|
266
|
+
static config = {
|
267
|
+
className: '${appName}.view.${className}',
|
268
|
+
autoMount: true,
|
269
|
+
layout: {ntype: 'fit'},
|
270
|
+
items: [{module:MainView}],
|
271
|
+
}
|
272
|
+
afterSetMounted(value, oldValue) {
|
273
|
+
super.afterSetMounted(value, oldValue);
|
274
|
+
if (!value) return;
|
275
|
+
this.addDomListeners({
|
276
|
+
"neo-debug-item-select": (event) => {
|
277
|
+
event.path.forEach((item) => {
|
278
|
+
const component = Neo.getComponent(item.id);
|
279
|
+
if (component) console.log(component);
|
280
|
+
});
|
281
|
+
},
|
282
|
+
});
|
283
|
+
}
|
284
|
+
}
|
285
|
+
Neo.applyClassConfig(${className});
|
286
|
+
export default ${className};
|
287
|
+
`;
|
288
|
+
fs.writeFileSync(path.join(`${folder}/view/${className}.mjs`), content);
|
289
|
+
|
290
|
+
|
291
|
+
|
292
|
+
|
293
|
+
// -------------------------------------------------------------------------
|
294
|
+
|
295
|
+
className = 'MainView';
|
296
|
+
content = `
|
297
|
+
import Base from '${neoSrcPath}/container/Base.mjs';
|
298
|
+
import Controller from './${className}Controller.mjs';
|
299
|
+
import ViewModel from './${className}Model.mjs';
|
300
|
+
|
301
|
+
class ${className} extends Base {
|
302
|
+
static config = {
|
303
|
+
className: '${appName}.view.${className}',
|
304
|
+
controller: {module: Controller},
|
305
|
+
model: {module: ViewModel},
|
306
|
+
|
307
|
+
layout: {ntype: 'fit'},
|
308
|
+
items: [],
|
309
|
+
}
|
310
|
+
}
|
311
|
+
|
312
|
+
Neo.applyClassConfig(${className});
|
313
|
+
|
314
|
+
export default ${className};
|
315
|
+
`;
|
316
|
+
fs.writeFileSync(path.join(`${folder}/view/${className}.mjs`), content);
|
317
|
+
|
318
|
+
|
319
|
+
|
320
|
+
|
321
|
+
|
322
|
+
// -------------------------------------------------------------------------
|
323
|
+
|
324
|
+
className = 'MainViewController';
|
325
|
+
content = `
|
326
|
+
import Base from '${neoSrcPath}/controller/Component.mjs';
|
327
|
+
|
328
|
+
class ${className} extends Base {
|
329
|
+
static config = {
|
330
|
+
className: '${appName}.view.${className}',
|
331
|
+
}
|
332
|
+
}
|
333
|
+
|
334
|
+
Neo.applyClassConfig(${className});
|
335
|
+
|
336
|
+
export default ${className};
|
337
|
+
`;
|
338
|
+
fs.writeFileSync(path.join(`${folder}/view/${className}.mjs`), content);
|
339
|
+
|
340
|
+
|
341
|
+
|
342
|
+
|
343
|
+
|
344
|
+
// -------------------------------------------------------------------------
|
345
|
+
|
346
|
+
className = 'MainViewModel';
|
347
|
+
content = `
|
348
|
+
import Base from '${neoSrcPath}/model/Component.mjs';
|
349
|
+
|
350
|
+
class ${className} extends Base {
|
351
|
+
static config = {
|
352
|
+
className: '${appName}.view.${className}',
|
353
|
+
|
354
|
+
data: {}
|
355
|
+
}
|
356
|
+
}
|
357
|
+
|
358
|
+
Neo.applyClassConfig(${className});
|
359
|
+
|
360
|
+
export default ${className};
|
361
|
+
`;
|
362
|
+
fs.writeFileSync(path.join(`${folder}/view/${className}.mjs`), content);
|
363
|
+
|
364
|
+
|
365
|
+
|
366
|
+
|
367
|
+
|
368
|
+
// -------------------------------------------------------------------------
|
369
|
+
|
370
|
+
let appJsonPath = path.resolve(cwd, 'buildScripts/myApps.json'),
|
371
|
+
appJson;
|
372
|
+
|
373
|
+
if (fs.existsSync(appJsonPath)) {
|
374
|
+
appJson = requireJson(appJsonPath);
|
375
|
+
} else {
|
376
|
+
appJsonPath = path.resolve(__dirname, 'buildScripts/webpack/json/myApps.json');
|
377
|
+
|
378
|
+
if (fs.existsSync(appJsonPath)) {
|
379
|
+
appJson = requireJson(appJsonPath);
|
380
|
+
} else {
|
381
|
+
appJson = requireJson(path.resolve(__dirname, 'buildScripts/webpack/json/myApps.template.json'));
|
382
|
+
}
|
383
|
+
}
|
384
|
+
|
385
|
+
if (!appJson.apps.includes(appName)) {
|
386
|
+
appJson.apps.push(appName);
|
387
|
+
appJson.apps.sort();
|
388
|
+
}
|
389
|
+
|
390
|
+
fs.writeFileSync(appJsonPath, JSON.stringify(appJson, null, 4));
|
391
|
+
|
392
|
+
if (mainThreadAddons.includes('HighlightJS')) {
|
393
|
+
spawnSync('node', [
|
394
|
+
'./buildScripts/copyFolder.mjs',
|
395
|
+
'-s',
|
396
|
+
path.resolve(neoPath, 'docs/resources'),
|
397
|
+
'-t',
|
398
|
+
path.resolve(folder, 'resources'),
|
399
|
+
], {env: process.env, cwd: process.cwd(), stdio: 'inherit'});
|
400
|
+
}
|
401
|
+
|
402
|
+
const processTime = (Math.round((new Date - startDate) * 100) / 100000).toFixed(2);
|
403
|
+
console.log(`\nTotal time for ${programName}: ${processTime} s`);
|
404
|
+
|
405
|
+
process.exit();
|
406
|
+
});
|
407
|
+
});
|
408
|
+
}
|
409
|
+
</pre>
|
410
|
+
|
411
|
+
??Add an entry in `workspace/package.json`
|
412
|
+
|
413
|
+
Edit `workspace.package` and add an entry for the new script.
|
414
|
+
|
415
|
+
<pre style="font-size:80%; color:lightgray;border:thin solid gray; padding: 8px;">
|
416
|
+
"scripts": {
|
417
|
+
"add-config": "node ./node_modules/neo.mjs/buildScripts/addConfig.mjs",
|
418
|
+
"build-all": "node ./node_modules/neo.mjs/buildScripts/buildAll.mjs -n",
|
419
|
+
"build-all-questions": "node ./node_modules/neo.mjs/buildScripts/buildAll.mjs",
|
420
|
+
"build-my-apps": "node ./node_modules/neo.mjs/buildScripts/webpack/buildMyApps.mjs",
|
421
|
+
"build-themes": "node ./node_modules/neo.mjs/buildScripts/buildThemes.mjs",
|
422
|
+
"build-threads": "node ./node_modules/neo.mjs/buildScripts/webpack/buildThreads.mjs",
|
423
|
+
"copy-examples": "node ./buildScripts/copyExamples.mjs",
|
424
|
+
"create-app": "node ./node_modules/neo.mjs/buildScripts/createApp.mjs",
|
425
|
+
<span style="color:blue">"create-app-training": "node ./buildScripts/createAppTraining.mjs",</span>
|
426
|
+
"create-class": "node ./node_modules/neo.mjs/buildScripts/createClass.mjs",
|
427
|
+
"generate-docs-json": "node ./node_modules/neo.mjs/buildScripts/docs/jsdocx.mjs",
|
428
|
+
"inject-package-version": "node ./buildScripts/injectPackageVersion.mjs",
|
429
|
+
"server-start": "webpack serve -c ./node_modules/neo.mjs/buildScripts/webpack/webpack.server.config.mjs --open",
|
430
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
431
|
+
"watch-themes": "node ./node_modules/neo.mjs/buildScripts/watchThemes.mjs"
|
432
|
+
},
|
433
|
+
</pre>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
Keep in mind that `Neo.manager.Component.items`, `Neo.find()` and `Neo.findFirst()`
|
2
|
+
are debugging aids _only_, and _should never be used in app logic_.
|
3
|
+
|
4
|
+
Why? There's nothing stopping you from using then, and they would work fine,
|
5
|
+
but those methods completely break encapsulation and scoping
|
6
|
+
rules! Their use would make an application brittle and hard to maintain.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
The `config:{}` is special.
|
2
|
+
|
3
|
+
When you describe a class instance — like we've been doing in `items:[]` or
|
4
|
+
setting up the view model — you're using a config block. That block is applied to
|
5
|
+
the instance being created.
|
6
|
+
|
7
|
+
In a class definition the `static config = {}` is processed by the
|
8
|
+
framework<sup><small>*</small></sup> in order to set up the get/set
|
9
|
+
and lifecycle hooks.
|
10
|
+
|
11
|
+
<br><br><br>
|
12
|
+
|
13
|
+
<small>* via the Neo.applyClassConfig() found at the bottom of each class.</small>
|
14
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Neo takes advantage of the _SharedWorker_ feature supported by most browsers
|
2
|
+
(including Chrome, Firefox, Edge, and Safari). <small><sup>*</sup></small>
|
3
|
+
|
4
|
+
A shared worker is a special web worker that can be access by multiple browsing windows.
|
5
|
+
|
6
|
+
Neo.mjs has the advantage of representing dom content via its vdom — that vdom hierarchy can be
|
7
|
+
trivially mounted in any container, even the shared window's viewport.
|
8
|
+
|
9
|
+
<br><br><br>
|
10
|
+
<small>* <a href="https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker" target="_blank">SharedWorker documentation</a></small>
|
@@ -0,0 +1,205 @@
|
|
1
|
+
#Introduction
|
2
|
+
|
3
|
+
In this lab you'll have the table and map open in their own windows.
|
4
|
+
|
5
|
+
#Steps
|
6
|
+
|
7
|
+
??Create a second app that provides the second window viewport
|
8
|
+
|
9
|
+
Use a terminal window, navigate to your workspace, and run `npm run create-app`.
|
10
|
+
|
11
|
+
Name it **EarthquakesTableWindow**,
|
12
|
+
and **answer Yes** when asked "Do you want to use SharedWorkers?"
|
13
|
+
|
14
|
+
??Inspect the app's `neo-config.json`
|
15
|
+
|
16
|
+
Open `apps/earthquakestablewindow/neo-config.json` and note the `useSharedWorkers` entry
|
17
|
+
|
18
|
+
<pre style="color:lightgray">
|
19
|
+
{
|
20
|
+
"appPath": "../../apps/earthquakestablewindow/app.mjs",
|
21
|
+
"basePath": "../../",
|
22
|
+
"environment": "development",
|
23
|
+
"mainPath": "../node_modules/neo.mjs/src/Main.mjs",
|
24
|
+
<span style="color:blue">"useSharedWorkers": true,</span>
|
25
|
+
"workerBasePath": "../../node_modules/neo.mjs/src/worker/"
|
26
|
+
}
|
27
|
+
</pre>
|
28
|
+
|
29
|
+
??Clean up the new app
|
30
|
+
|
31
|
+
The only thing we need the new app for is its viewport.
|
32
|
+
|
33
|
+
Edit `apps/earthquakestablewindow/MainContainer.mjs` and remove everything except the `className` and the `layout`, and
|
34
|
+
change the layout to `layout:{ntype:'fit'}`. When you're finished it should look like this.
|
35
|
+
|
36
|
+
<pre style="border:thin solid gray; color:gray; font-size:0.8em; padding:1em">
|
37
|
+
import Viewport from '../../../node_modules/neo.mjs/src/container/Viewport.mjs';
|
38
|
+
|
39
|
+
/**
|
40
|
+
* @class EarthquakesTableWindow.view.MainContainer
|
41
|
+
* @extends Neo.container.Viewport
|
42
|
+
*/
|
43
|
+
class MainContainer extends Viewport {
|
44
|
+
static config = {
|
45
|
+
/**
|
46
|
+
* @member {String} className='EarthquakesTableWindow.view.MainContainer'
|
47
|
+
* @protected
|
48
|
+
*/
|
49
|
+
className: 'EarthquakesTableWindow.view.MainContainer',
|
50
|
+
/*
|
51
|
+
* @member {Object} layout={ntype:'fit'}
|
52
|
+
*/
|
53
|
+
layout: {ntype: 'fit'}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
Neo.applyClassConfig(MainContainer);
|
58
|
+
|
59
|
+
export default MainContainer;
|
60
|
+
</pre>
|
61
|
+
|
62
|
+
You're completly finished with EarthquakesTableWindow.
|
63
|
+
To avoid confusion, you might want to close any EarthquakesTableWindow
|
64
|
+
files you have open in your code editor.
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
??Have our Earthquakes app use a shared worker too
|
69
|
+
|
70
|
+
Both apps need to use a shared worker. To enable that in Earthquakes, edit `apps/earthquakes/neo-config.json` and add the entry for _useSharedWorkers_.
|
71
|
+
|
72
|
+
<pre style="color:lightgray">
|
73
|
+
{
|
74
|
+
"appPath": "../../apps/earthquakes/app.mjs",
|
75
|
+
"basePath": "../../",
|
76
|
+
"environment": "development",
|
77
|
+
"mainPath": "../node_modules/neo.mjs/src/Main.mjs",
|
78
|
+
<span style="color:blue">"useSharedWorkers": true,</span>
|
79
|
+
"workerBasePath": "../../node_modules/neo.mjs/src/worker/"
|
80
|
+
}
|
81
|
+
</pre>
|
82
|
+
|
83
|
+
??Note a change in how you debug
|
84
|
+
|
85
|
+
Chrome Devtools lets you inspect shared workers via the special url `chrome://inspect`. To use it,
|
86
|
+
open a new browser window and enter (or copy-and-paste) that exact URL.
|
87
|
+
|
88
|
+
Then select the "Shared workers" option on the left, then click on `inspect` by the entry for _neomjs-app-worker_.
|
89
|
+
|
90
|
+
<img src="resources/images/debugging/ChromeDevToolsInspectWorkers.png"/>
|
91
|
+
|
92
|
+
Clicking `inspect` opens a standard debug window, but with a single execution context.
|
93
|
+
|
94
|
+
<img src="resources/images/debugging/ChromeDevToolsSharedWorkerContext.png"/>
|
95
|
+
|
96
|
+
If you run the app and click on a map item, or a table row, you should see the
|
97
|
+
console logs being run from your event handlers.
|
98
|
+
|
99
|
+
??Add a button used to launch the window
|
100
|
+
|
101
|
+
Edit `MainContainer` and add a second item to the items array. This will be after
|
102
|
+
the map config and before the table config.
|
103
|
+
|
104
|
+
{
|
105
|
+
module: Button,
|
106
|
+
reference: 'openWindowButton',
|
107
|
+
style: {flex: 'none'},
|
108
|
+
text: 'Open table in window',
|
109
|
+
handler: 'onOpenWindowClick'
|
110
|
+
},
|
111
|
+
|
112
|
+
Save and refresh and you should see the new button between the map and table.
|
113
|
+
It occupies the full width because the main container is using `align:'stretch'` for
|
114
|
+
its vbox layout.
|
115
|
+
|
116
|
+
??Create the event handler
|
117
|
+
|
118
|
+
Now edit `MainContainerController` and add a new member function `onOpenWindowClick`.
|
119
|
+
|
120
|
+
The code needs to add a new window using the URL for the EarthquakesTableWindow app.
|
121
|
+
Neo has a method that runs `window.open()` in the main thread. Here's the code.
|
122
|
+
|
123
|
+
onOpenWindowClick() {
|
124
|
+
Neo.Main.windowOpen({
|
125
|
+
url: `../earthquakestablewindow`,
|
126
|
+
windowName: 'earthquakestablewindow' // This could be _blank or whatever you want
|
127
|
+
});
|
128
|
+
}
|
129
|
+
|
130
|
+
Save and refresh, then click the button — a browser tab will open running the
|
131
|
+
empty EarthquakesTableWindow app.
|
132
|
+
|
133
|
+
Close the EarthquakesTableWindow tab.
|
134
|
+
|
135
|
+
(Note that we're not bothering adding logic to see if EarthquakesTableWindow is
|
136
|
+
already open when launching the Earthquakes app. Therefore, before refreshing
|
137
|
+
Earthquakes make sure you've closed EarthquakesTableWindow first.)
|
138
|
+
|
139
|
+
??Detect when the new window launches
|
140
|
+
|
141
|
+
Neo fires an event when applications are connected to the appworker. We need to add a listener
|
142
|
+
to that event. We'll do that in the main controller's `construct` method. Add this as a
|
143
|
+
member method to `MainContainerController`. As you can see, the code adds two listeners
|
144
|
+
to the appworker: `onAppConnect` and `onAppDisconnect`.
|
145
|
+
|
146
|
+
construct(config) {
|
147
|
+
super.construct(config);
|
148
|
+
|
149
|
+
let me = this;
|
150
|
+
Neo.currentWorker.on({
|
151
|
+
connect: me.onAppConnect,
|
152
|
+
disconnect: me.onAppDisconnect,
|
153
|
+
scope: me
|
154
|
+
});
|
155
|
+
}
|
156
|
+
|
157
|
+
The disconnect method will run if the user closes the EarthquakesTableWindow window.
|
158
|
+
We'll use that to move the table back to the main app.
|
159
|
+
|
160
|
+
The connect method runs if the EarthquakesTableWindow launches. In other words,
|
161
|
+
when `onOpenWindowClick` is run, it opens the EarthquakesTableWindow, which in
|
162
|
+
turn triggers the _connect_ event.
|
163
|
+
|
164
|
+
??Code `onAppConnect`
|
165
|
+
|
166
|
+
This is the code you've been waiting for! And it's pretty simple.
|
167
|
+
|
168
|
+
If the newly opened window is EarthquakesTableWindow, then simply remove
|
169
|
+
the table from the Earthquakes main view, and add it to the EarthquakesTableWindow
|
170
|
+
main view. Add this instance method to MainContainerController.
|
171
|
+
|
172
|
+
onAppConnect(data) {
|
173
|
+
let me = this;
|
174
|
+
NeoArray.add(me.connectedApps, data.appName);
|
175
|
+
if (data.appName === 'EarthquakesTableWindow'){
|
176
|
+
let table = me.getReference('table');
|
177
|
+
me.component.remove(table, false) // Params: component, destroy, silent
|
178
|
+
Neo.apps.EarthquakesTableWindow.mainView.add(table);
|
179
|
+
me.getReference('openWindowButton').hidden = true;
|
180
|
+
}
|
181
|
+
}
|
182
|
+
|
183
|
+
Save your changes, and verify that the EarthquakesTableWindow is _not_ open.
|
184
|
+
Then click on the _Open table in window_ button. A new tab should appear, holding
|
185
|
+
the table. The Earthquakes window will just hold the map.
|
186
|
+
|
187
|
+
Click on a table row, then look on the map: the corresponding marker highlights!
|
188
|
+
|
189
|
+
??Contemplate the moment
|
190
|
+
|
191
|
+
This is pretty cool. Seriously.
|
192
|
+
|
193
|
+
There's no special code. We're just moving a component from one container to another.
|
194
|
+
Events are preserved.
|
195
|
+
|
196
|
+
(Note that the map would _not_ have moved in the same way, because the Google map and
|
197
|
+
markers are maintained via Google Maps APIs. In contrast, the Earthquakes table is a
|
198
|
+
normal Neo component — Neo components know their own view structure, so can
|
199
|
+
easily be mounted in any container, including the new window's viewport. To move the
|
200
|
+
map we'd have to write code to fully delete the map in the main view, then add it as
|
201
|
+
a new component in EarthquakesTableWindow. It would only be a few lines of code, but
|
202
|
+
the difference between the map and table provides some insight into how Neo works.)
|
203
|
+
|
204
|
+
|
205
|
+
??Move the table back when the EarthquakesTableWindow closes
|