From f85aa020244f538d7ddd21425cd51b225073989f Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Wed, 14 Sep 2016 15:41:57 +0200 Subject: [PATCH 01/17] Get rid of error message when exiting app in dev mode --- server.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server.js b/server.js index e35898f6..0ce94244 100644 --- a/server.js +++ b/server.js @@ -39,4 +39,8 @@ function ifPortAvailable(port, runFn) { server.listen(port); } +process.on('SIGINT', function () { + process.exit(); +}); + ifPortAvailable(PORT, () => startHotReloadServer()); From 4e5f329d5ea96030c77654e10dac1100d6d0a17a Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Wed, 14 Sep 2016 16:04:25 +0200 Subject: [PATCH 02/17] Enable sourcemaps for debugging in Chrome devtools --- webpack.config.development.js | 1 + 1 file changed, 1 insertion(+) diff --git a/webpack.config.development.js b/webpack.config.development.js index 7415c150..020b9ccf 100644 --- a/webpack.config.development.js +++ b/webpack.config.development.js @@ -15,6 +15,7 @@ fs.readdirSync('node_modules') }); var config = { + devtool: 'source-map', entry: [ 'webpack-hot-middleware/client?path=http://localhost:9000/__webpack_hmr', './js/index', From 2f9ac9590178509dbac4dd82e53c5df4eac13417 Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Fri, 23 Sep 2016 09:27:44 +0200 Subject: [PATCH 03/17] Introduce monorepo with core, loader, and BLE appmodule --- lerna.json | 4 + package.json | 48 ++----- packages/nrfconnect-appmodule-ble/.babelrc | 19 +++ packages/nrfconnect-appmodule-ble/.npmrc | 3 + .../nrfconnect-appmodule-ble/css}/styles.less | 17 ++- packages/nrfconnect-appmodule-ble/index.html | 27 ++++ packages/nrfconnect-appmodule-ble/index.js | 59 +++++++++ .../js}/actions/adapterActions.js | 0 .../js}/actions/advertisingActions.js | 0 .../js}/actions/appActions.js | 0 .../js}/actions/bleEventActions.js | 0 .../js}/actions/common.js | 0 .../js}/actions/deviceDetailsActions.js | 0 .../js}/actions/discoveryActions.js | 0 .../js}/actions/errorDialogActions.js | 0 .../js}/actions/firmwareUpdateActions.js | 0 .../js}/actions/logActions.js | 0 .../js}/actions/securityActions.js | 0 .../js}/actions/serverSetupActions.js | 0 .../js}/common/Errors.js | 0 .../js}/common/layoutStrategies.js | 0 .../js}/common/treeViewKeyNavigation.js | 0 .../js}/components/AdapterSelector.jsx | 0 .../js}/components/AddNewItem.jsx | 0 .../js}/components/AdvertisingData.jsx | 2 +- .../js}/components/AdvertisingList.jsx | 0 .../js}/components/AdvertisingListEntry.jsx | 0 .../js}/components/AttributeItem.jsx | 0 .../js}/components/AuthKeyEditor.jsx | 0 .../js}/components/BLEEvent.jsx | 0 .../js}/components/CentralDevice.jsx | 0 .../js}/components/CharacteristicEditor.jsx | 4 +- .../js}/components/CharacteristicItem.jsx | 0 .../js}/components/ConfirmationDialog.jsx | 3 +- .../js}/components/ConnectedDevice.jsx | 0 .../ConnectionUpdateRequestEditor.js | 2 +- .../js}/components/Connector.jsx | 0 .../js}/components/CountdownTimer.jsx | 0 .../js}/components/DescriptorEditor.jsx | 3 +- .../js}/components/DescriptorItem.jsx | 0 .../js}/components/DiscoveredDevice.jsx | 0 .../js}/components/EditableField.jsx | 2 +- .../js}/components/EnumeratingAttributes.jsx | 4 +- .../js}/components/HexOnlyEditableField.jsx | 0 .../js}/components/LogEntry.jsx | 0 .../js}/components/PairingEditor.jsx | 0 .../js}/components/SecurityParamsControls.jsx | 0 .../js}/components/ServiceEditor.jsx | 2 +- .../js}/components/ServiceItem.jsx | 0 .../js}/components/UuidLookup.jsx | 0 .../js}/components/deviceDetails.jsx | 0 .../js}/components/discoveryButton.jsx | 0 .../components/input/LabeledInputGroup.jsx | 0 .../js}/components/input/SelectList.jsx | 0 .../js}/components/input/TextArea.jsx | 0 .../js}/components/input/TextInput.jsx | 0 .../js}/components/input/UuidInput.jsx | 2 +- .../js}/components/navbar.jsx | 3 +- .../js}/containers/AdvertisingSetup.jsx | 0 .../js}/containers/App.js | 1 + .../js}/containers/BLEEventDialog.js | 0 .../js}/containers/ConnectionMap.js | 0 .../js}/containers/DeviceDetails.js | 0 .../js}/containers/DiscoveredDevices.js | 5 +- .../js}/containers/ErrorDialog.js | 0 .../js}/containers/LogViewer.js | 0 .../js}/containers/Root.dev.js | 0 .../js}/containers/Root.js | 0 .../js}/containers/Root.prod.js | 0 .../js}/containers/SecurityParamsDialog.js | 0 .../js}/containers/ServerSetup.jsx | 0 .../js}/gattDatabases.js | 0 .../nrfconnect-appmodule-ble/js}/index.js | 15 ++- .../js}/logging/index.js | 0 .../js}/logging/logger.js | 0 .../js}/reducers/adapterReducer.js | 0 .../js}/reducers/advertisingReducer.js | 0 .../js}/reducers/appReducer.js | 0 .../js}/reducers/bleEventReducer.js | 0 .../js}/reducers/deviceDetailsReducer.js | 0 .../js}/reducers/discoveryReducer.js | 0 .../js}/reducers/errorDialogReducer.js | 0 .../js}/reducers/firmwareUpdateReducer.js | 0 .../js}/reducers/index.js | 0 .../js}/reducers/logReducer.js | 0 .../js}/reducers/securityReducer.js | 0 .../js}/reducers/serverSetupReducer.js | 0 .../js}/settings.json | 0 .../js}/settings.json.prod | 0 .../js}/utils/Effects.jsx | 0 .../nrfconnect-appmodule-ble/js}/utils/api.js | 0 .../js}/utils/colorDefinitions.js | 2 +- .../js}/utils/custom_definitions.json | 0 .../js}/utils/definitions.js | 0 .../js}/utils/dummyAttributeData.js | 0 .../js}/utils/fileUtil.js | 0 .../js}/utils/jlinkUtil.js | 0 .../js}/utils/stringUtil.js | 0 .../js}/utils/uuid_definitions.js | 0 .../js}/utils/validateUuid.js | 0 .../nrfconnect-appmodule-ble/package.json | 58 +++++++++ .../resources}/alarm.mp3 | Bin .../resources/icon.png | Bin 0 -> 1377 bytes .../resources}/nordic_usb_icon.png | Bin .../nrfconnect-core/css}/animation.css | 0 .../nrfconnect-core/css}/brand.less | 0 .../css}/colordefinitions.less | 0 .../nrfconnect-core/css}/fontello.css | 0 .../nrfconnect-core/css/styles.less | 11 +- .../nrfconnect-core/css}/variables.less | 0 .../nrfconnect-core/font}/Roboto-Black.ttf | Bin .../font}/Roboto-BlackItalic.ttf | Bin .../nrfconnect-core/font}/Roboto-Bold.ttf | Bin .../font}/Roboto-BoldItalic.ttf | Bin .../nrfconnect-core/font}/Roboto-Italic.ttf | Bin .../nrfconnect-core/font}/Roboto-Light.ttf | Bin .../font}/Roboto-LightItalic.ttf | Bin .../nrfconnect-core/font}/Roboto-Medium.ttf | Bin .../font}/Roboto-MediumItalic.ttf | Bin .../nrfconnect-core/font}/Roboto-Regular.ttf | Bin .../nrfconnect-core/font}/Roboto-Thin.ttf | Bin .../font}/Roboto-ThinItalic.ttf | Bin .../font}/RobotoCondensed-Bold.ttf | Bin .../font}/RobotoCondensed-BoldItalic.ttf | Bin .../font}/RobotoCondensed-Italic.ttf | Bin .../font}/RobotoCondensed-Light.ttf | Bin .../font}/RobotoCondensed-LightItalic.ttf | Bin .../font}/RobotoCondensed-Regular.ttf | Bin .../nrfconnect-core/font}/fontello.eot | Bin .../nrfconnect-core/font}/fontello.svg | 0 .../nrfconnect-core/font}/fontello.ttf | Bin .../nrfconnect-core/font}/fontello.woff | Bin .../nrfconnect-core/font}/fontello.woff2 | Bin index.js => packages/nrfconnect-core/index.js | 119 ++++++------------ .../js/actions/errorDialogActions.js | 62 +++++++++ .../js/components/input/LabeledInputGroup.jsx | 29 +++++ .../js/components/input/SelectList.jsx | 35 ++++++ .../js/components/input/TextArea.jsx | 33 +++++ .../js/components/input/TextInput.jsx | 40 ++++++ .../js}/containers/DevTools.dev.js | 0 .../js}/containers/DevTools.js | 0 .../js}/containers/DevTools.prod.js | 0 .../js/containers/ErrorDialog.js | 104 +++++++++++++++ packages/nrfconnect-core/js/index.js | 31 +++++ .../js/reducers/errorDialogReducer.js | 68 ++++++++++ .../js}/store/configureStore.js | 15 +-- packages/nrfconnect-core/package.json | 35 ++++++ .../resources}/ajax-loader.gif | Bin .../resources}/fontello-271d664f/LICENSE.txt | 0 .../resources}/fontello-271d664f/README.txt | 0 .../resources}/fontello-271d664f/config.json | 0 .../fontello-271d664f/css/animation.css | 0 .../fontello-271d664f/css/fontello-codes.css | 0 .../css/fontello-embedded.css | 0 .../css/fontello-ie7-codes.css | 0 .../fontello-271d664f/css/fontello-ie7.css | 0 .../fontello-271d664f/css/fontello.css | 0 .../resources}/fontello-271d664f/demo.html | 0 .../nrfconnect-core/resources/nrfconnect.icns | Bin .../nrfconnect-core/resources/nrfconnect.ico | Bin .../nrfconnect-core/resources/nrfconnect.png | Bin .../resources}/nrfconnect_neg.png | Bin .../nrfconnect-core/settings.js | 0 packages/nrfconnect-core/webpack.config.js | 13 ++ .../css/components/appmodule-list-item.less | 8 ++ .../css/components/appmodule-loader.less | 19 +++ .../nrfconnect-loader/index.html | 2 +- packages/nrfconnect-loader/index.js | 81 ++++++++++++ .../js/actions/appActions.js | 51 ++++++++ .../js/components/AppmoduleList.jsx | 56 +++++++++ .../js/components/AppmoduleListItem.jsx | 45 +++++++ .../js/components/AppmoduleLoader.jsx | 56 +++++++++ .../nrfconnect-loader/js/containers/App.jsx | 71 +++++++++++ .../nrfconnect-loader/js/containers/Root.jsx | 29 +++-- packages/nrfconnect-loader/js/index.js | 46 +++++++ .../js/reducers/appReducer.js | 48 +++++++ .../nrfconnect-loader/js/reducers/index.js | 16 ++- packages/nrfconnect-loader/js/settings.json | 1 + .../nrfconnect-loader/js/settings.json.prod | 1 + packages/nrfconnect-loader/js/utils/api.js | 23 ++++ .../js/utils/appmoduleRepository.js | 28 +++++ packages/nrfconnect-loader/package.json | 65 ++++++++++ packages/nrfconnect-loader/resources/icon.png | Bin 0 -> 941 bytes .../resources/splashScreen.html | 0 .../resources/splashScreen.png | Bin webpack.config.development.js | 35 ++++-- 186 files changed, 1359 insertions(+), 202 deletions(-) create mode 100644 lerna.json create mode 100644 packages/nrfconnect-appmodule-ble/.babelrc create mode 100644 packages/nrfconnect-appmodule-ble/.npmrc rename {css => packages/nrfconnect-appmodule-ble/css}/styles.less (97%) create mode 100644 packages/nrfconnect-appmodule-ble/index.html create mode 100644 packages/nrfconnect-appmodule-ble/index.js rename {js => packages/nrfconnect-appmodule-ble/js}/actions/adapterActions.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/actions/advertisingActions.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/actions/appActions.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/actions/bleEventActions.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/actions/common.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/actions/deviceDetailsActions.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/actions/discoveryActions.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/actions/errorDialogActions.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/actions/firmwareUpdateActions.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/actions/logActions.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/actions/securityActions.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/actions/serverSetupActions.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/common/Errors.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/common/layoutStrategies.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/common/treeViewKeyNavigation.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/AdapterSelector.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/AddNewItem.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/AdvertisingData.jsx (99%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/AdvertisingList.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/AdvertisingListEntry.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/AttributeItem.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/AuthKeyEditor.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/BLEEvent.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/CentralDevice.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/CharacteristicEditor.jsx (98%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/CharacteristicItem.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/ConfirmationDialog.jsx (90%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/ConnectedDevice.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/ConnectionUpdateRequestEditor.js (99%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/Connector.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/CountdownTimer.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/DescriptorEditor.jsx (98%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/DescriptorItem.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/DiscoveredDevice.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/EditableField.jsx (99%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/EnumeratingAttributes.jsx (84%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/HexOnlyEditableField.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/LogEntry.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/PairingEditor.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/SecurityParamsControls.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/ServiceEditor.jsx (98%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/ServiceItem.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/UuidLookup.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/deviceDetails.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/discoveryButton.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/input/LabeledInputGroup.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/input/SelectList.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/input/TextArea.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/input/TextInput.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/input/UuidInput.jsx (97%) rename {js => packages/nrfconnect-appmodule-ble/js}/components/navbar.jsx (94%) rename {js => packages/nrfconnect-appmodule-ble/js}/containers/AdvertisingSetup.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/containers/App.js (99%) rename {js => packages/nrfconnect-appmodule-ble/js}/containers/BLEEventDialog.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/containers/ConnectionMap.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/containers/DeviceDetails.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/containers/DiscoveredDevices.js (96%) rename {js => packages/nrfconnect-appmodule-ble/js}/containers/ErrorDialog.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/containers/LogViewer.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/containers/Root.dev.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/containers/Root.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/containers/Root.prod.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/containers/SecurityParamsDialog.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/containers/ServerSetup.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/gattDatabases.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/index.js (74%) rename {js => packages/nrfconnect-appmodule-ble/js}/logging/index.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/logging/logger.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/reducers/adapterReducer.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/reducers/advertisingReducer.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/reducers/appReducer.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/reducers/bleEventReducer.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/reducers/deviceDetailsReducer.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/reducers/discoveryReducer.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/reducers/errorDialogReducer.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/reducers/firmwareUpdateReducer.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/reducers/index.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/reducers/logReducer.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/reducers/securityReducer.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/reducers/serverSetupReducer.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/settings.json (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/settings.json.prod (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/utils/Effects.jsx (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/utils/api.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/utils/colorDefinitions.js (97%) rename {js => packages/nrfconnect-appmodule-ble/js}/utils/custom_definitions.json (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/utils/definitions.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/utils/dummyAttributeData.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/utils/fileUtil.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/utils/jlinkUtil.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/utils/stringUtil.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/utils/uuid_definitions.js (100%) rename {js => packages/nrfconnect-appmodule-ble/js}/utils/validateUuid.js (100%) create mode 100644 packages/nrfconnect-appmodule-ble/package.json rename {resources => packages/nrfconnect-appmodule-ble/resources}/alarm.mp3 (100%) create mode 100644 packages/nrfconnect-appmodule-ble/resources/icon.png rename {resources => packages/nrfconnect-appmodule-ble/resources}/nordic_usb_icon.png (100%) rename {css => packages/nrfconnect-core/css}/animation.css (100%) rename {css => packages/nrfconnect-core/css}/brand.less (100%) rename {css => packages/nrfconnect-core/css}/colordefinitions.less (100%) rename {css => packages/nrfconnect-core/css}/fontello.css (100%) rename js/components/DevTools.prod.jsx => packages/nrfconnect-core/css/styles.less (75%) rename {css => packages/nrfconnect-core/css}/variables.less (100%) rename {font => packages/nrfconnect-core/font}/Roboto-Black.ttf (100%) rename {font => packages/nrfconnect-core/font}/Roboto-BlackItalic.ttf (100%) rename {font => packages/nrfconnect-core/font}/Roboto-Bold.ttf (100%) rename {font => packages/nrfconnect-core/font}/Roboto-BoldItalic.ttf (100%) rename {font => packages/nrfconnect-core/font}/Roboto-Italic.ttf (100%) rename {font => packages/nrfconnect-core/font}/Roboto-Light.ttf (100%) rename {font => packages/nrfconnect-core/font}/Roboto-LightItalic.ttf (100%) rename {font => packages/nrfconnect-core/font}/Roboto-Medium.ttf (100%) rename {font => packages/nrfconnect-core/font}/Roboto-MediumItalic.ttf (100%) rename {font => packages/nrfconnect-core/font}/Roboto-Regular.ttf (100%) rename {font => packages/nrfconnect-core/font}/Roboto-Thin.ttf (100%) rename {font => packages/nrfconnect-core/font}/Roboto-ThinItalic.ttf (100%) rename {font => packages/nrfconnect-core/font}/RobotoCondensed-Bold.ttf (100%) rename {font => packages/nrfconnect-core/font}/RobotoCondensed-BoldItalic.ttf (100%) rename {font => packages/nrfconnect-core/font}/RobotoCondensed-Italic.ttf (100%) rename {font => packages/nrfconnect-core/font}/RobotoCondensed-Light.ttf (100%) rename {font => packages/nrfconnect-core/font}/RobotoCondensed-LightItalic.ttf (100%) rename {font => packages/nrfconnect-core/font}/RobotoCondensed-Regular.ttf (100%) rename {font => packages/nrfconnect-core/font}/fontello.eot (100%) rename {font => packages/nrfconnect-core/font}/fontello.svg (100%) rename {font => packages/nrfconnect-core/font}/fontello.ttf (100%) rename {font => packages/nrfconnect-core/font}/fontello.woff (100%) rename {font => packages/nrfconnect-core/font}/fontello.woff2 (100%) rename index.js => packages/nrfconnect-core/index.js (61%) create mode 100644 packages/nrfconnect-core/js/actions/errorDialogActions.js create mode 100644 packages/nrfconnect-core/js/components/input/LabeledInputGroup.jsx create mode 100644 packages/nrfconnect-core/js/components/input/SelectList.jsx create mode 100644 packages/nrfconnect-core/js/components/input/TextArea.jsx create mode 100644 packages/nrfconnect-core/js/components/input/TextInput.jsx rename {js => packages/nrfconnect-core/js}/containers/DevTools.dev.js (100%) rename {js => packages/nrfconnect-core/js}/containers/DevTools.js (100%) rename {js => packages/nrfconnect-core/js}/containers/DevTools.prod.js (100%) create mode 100644 packages/nrfconnect-core/js/containers/ErrorDialog.js create mode 100644 packages/nrfconnect-core/js/index.js create mode 100644 packages/nrfconnect-core/js/reducers/errorDialogReducer.js rename {js => packages/nrfconnect-core/js}/store/configureStore.js (81%) create mode 100644 packages/nrfconnect-core/package.json rename {resources => packages/nrfconnect-core/resources}/ajax-loader.gif (100%) rename {resources => packages/nrfconnect-core/resources}/fontello-271d664f/LICENSE.txt (100%) rename {resources => packages/nrfconnect-core/resources}/fontello-271d664f/README.txt (100%) rename {resources => packages/nrfconnect-core/resources}/fontello-271d664f/config.json (100%) rename {resources => packages/nrfconnect-core/resources}/fontello-271d664f/css/animation.css (100%) rename {resources => packages/nrfconnect-core/resources}/fontello-271d664f/css/fontello-codes.css (100%) rename {resources => packages/nrfconnect-core/resources}/fontello-271d664f/css/fontello-embedded.css (100%) rename {resources => packages/nrfconnect-core/resources}/fontello-271d664f/css/fontello-ie7-codes.css (100%) rename {resources => packages/nrfconnect-core/resources}/fontello-271d664f/css/fontello-ie7.css (100%) rename {resources => packages/nrfconnect-core/resources}/fontello-271d664f/css/fontello.css (100%) rename {resources => packages/nrfconnect-core/resources}/fontello-271d664f/demo.html (100%) rename nrfconnect.icns => packages/nrfconnect-core/resources/nrfconnect.icns (100%) rename nrfconnect.ico => packages/nrfconnect-core/resources/nrfconnect.ico (100%) rename nrfconnect.png => packages/nrfconnect-core/resources/nrfconnect.png (100%) rename {resources => packages/nrfconnect-core/resources}/nrfconnect_neg.png (100%) rename settings.js => packages/nrfconnect-core/settings.js (100%) create mode 100644 packages/nrfconnect-core/webpack.config.js create mode 100644 packages/nrfconnect-loader/css/components/appmodule-list-item.less create mode 100644 packages/nrfconnect-loader/css/components/appmodule-loader.less rename index.html => packages/nrfconnect-loader/index.html (82%) create mode 100644 packages/nrfconnect-loader/index.js create mode 100644 packages/nrfconnect-loader/js/actions/appActions.js create mode 100644 packages/nrfconnect-loader/js/components/AppmoduleList.jsx create mode 100644 packages/nrfconnect-loader/js/components/AppmoduleListItem.jsx create mode 100644 packages/nrfconnect-loader/js/components/AppmoduleLoader.jsx create mode 100644 packages/nrfconnect-loader/js/containers/App.jsx rename js/components/DevTools.dev.jsx => packages/nrfconnect-loader/js/containers/Root.jsx (51%) create mode 100644 packages/nrfconnect-loader/js/index.js create mode 100644 packages/nrfconnect-loader/js/reducers/appReducer.js rename js/components/DevTools.jsx => packages/nrfconnect-loader/js/reducers/index.js (66%) create mode 100644 packages/nrfconnect-loader/js/settings.json create mode 100644 packages/nrfconnect-loader/js/settings.json.prod create mode 100644 packages/nrfconnect-loader/js/utils/api.js create mode 100644 packages/nrfconnect-loader/js/utils/appmoduleRepository.js create mode 100644 packages/nrfconnect-loader/package.json create mode 100644 packages/nrfconnect-loader/resources/icon.png rename splashScreen.html => packages/nrfconnect-loader/resources/splashScreen.html (100%) rename splashScreen.png => packages/nrfconnect-loader/resources/splashScreen.png (100%) diff --git a/lerna.json b/lerna.json new file mode 100644 index 00000000..b1f53c34 --- /dev/null +++ b/lerna.json @@ -0,0 +1,4 @@ +{ + "lerna": "2.0.0-beta.28", + "version": "0.0.0" +} diff --git a/package.json b/package.json index 43bf28f8..8f9525f0 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,13 @@ }, "main": "index.js", "scripts": { - "start": "concurrently -k \"node server.js\" \"cross-env ENV=development electron .\"", - "build": "webpack --config webpack.config.production.js" + "start": "cd packages/nrfconnect-loader && npm start", + "build": "lerna-run npm run build", + "postinstall": "npm run bootstrap && npm run build", + "bootstrap": "lerna bootstrap", + "updated": "lerna updated", + "test": "lerna-run npm test", + "clean": "npm install lerna lerna-run && lerna-run npm run clean && rimraf node_modules" }, "author": "Nordic Semiconductor ASA", "license": "Proprietary", @@ -30,11 +35,10 @@ "file-loader": "0.9.0", "install": "0.8.1", "json-loader": "0.5.4", + "lerna": "2.0.0-beta.28", + "less": "^2.7.1", "less-loader": "2.2.3", "q": "1.4.1", - "redux-devtools": "3.3.1", - "redux-devtools-dock-monitor": "1.1.1", - "redux-devtools-log-monitor": "1.0.11", "run-sequence": "1.2.2", "style-loader": "0.13.1", "webpack": "1.13.2", @@ -42,39 +46,5 @@ "webpack-hot-middleware": "2.12.2", "webpack-target-electron-renderer": "0.4.0", "yargs": "5.0.0" - }, - "dependencies": { - "atom-keymap": "6.3.2", - "babel-polyfill": "6.13.0", - "bootstrap": "3.3.7", - "change-case": "3.0.0", - "immutable": "3.8.1", - "jquery": "3.1.0", - "less": "2.7.1", - "moment": "2.14.1", - "open": "0.0.5", - "pc-ble-driver-js": "https://github.com/NordicSemiconductor/pc-ble-driver-js.git#v0.9.0", - "pc-nrfjprog-js": "https://github.com/NordicSemiconductor/pc-nrfjprog-js.git#v0.3.0", - "react": "15.3.1", - "react-addons-linked-state-mixin": "15.3.1", - "react-bootstrap": "0.30.3", - "react-dom": "15.3.1", - "react-infinite": "NordicSemiconductor/react-infinite#upgrade-to-react-15", - "react-onclickoutside": "5.5.0", - "react-redux": "4.4.5", - "react-textarea-autosize": "4.0.5", - "redux": "3.6.0", - "redux-logger": "2.6.1", - "redux-promise-middleware": "4.0.0", - "redux-storage": "4.1.1", - "redux-thunk": "2.1.0", - "semver": "5.3.0", - "serialport": "^3.1.2", - "sqlite3": "3.1.4", - "tween.js": "16.3.5", - "underscore": "1.8.3", - "util": "0.10.3", - "uuid-v4": "0.1.0", - "winston": "2.2.0" } } diff --git a/packages/nrfconnect-appmodule-ble/.babelrc b/packages/nrfconnect-appmodule-ble/.babelrc new file mode 100644 index 00000000..6a20fff1 --- /dev/null +++ b/packages/nrfconnect-appmodule-ble/.babelrc @@ -0,0 +1,19 @@ +{ + "presets": [ "react", "es2015", "stage-2" ], + "plugins": [ + "add-module-exports" + ], + "env": { + "test": { + "plugins": [ + [ + "babel-plugin-webpack-loaders", + { + "config": "../../webpack.config.test.js", + "verbose": false + } + ] + ] + } + } +} diff --git a/packages/nrfconnect-appmodule-ble/.npmrc b/packages/nrfconnect-appmodule-ble/.npmrc new file mode 100644 index 00000000..becabadb --- /dev/null +++ b/packages/nrfconnect-appmodule-ble/.npmrc @@ -0,0 +1,3 @@ +runtime = electron +target = 1.2.8 +disturl = https://atom.io/download/atom-shell diff --git a/css/styles.less b/packages/nrfconnect-appmodule-ble/css/styles.less similarity index 97% rename from css/styles.less rename to packages/nrfconnect-appmodule-ble/css/styles.less index 9bec7b6b..fbab3e59 100644 --- a/css/styles.less +++ b/packages/nrfconnect-appmodule-ble/css/styles.less @@ -10,10 +10,7 @@ * */ -@import "~bootstrap/less/bootstrap.less"; -@import (inline) "./fontello.css"; -@import (inline) "./animation.css"; -@import "./variables.less"; +@import "~nrfconnect-core/css/variables.less"; .nomargin { margin: 0px; @@ -79,14 +76,14 @@ font-family: "Roboto Condensed"; font-style: normal; font-weight: 300; - src: url('../font/RobotoCondensed-Light.ttf') format('truetype'); + src: url('~nrfconnect-core/font/RobotoCondensed-Light.ttf') format('truetype'); } @font-face { font-family: "Roboto"; font-style: italic; font-weight: 300; - src: url("../font/Roboto-LightItalic.ttf") format('truetype'); + src: url("~nrfconnect-core/font/Roboto-LightItalic.ttf") format('truetype'); } /* Normal */ @@ -94,14 +91,14 @@ font-family: "Roboto"; font-style: normal; font-weight: 400; - src: url('../font/Roboto-Regular.ttf') format('truetype'); + src: url('~nrfconnect-core/font/Roboto-Regular.ttf') format('truetype'); } @font-face { font-family: "Roboto"; font-style: italic; font-weight: 400; - src: url('../font/Roboto-Italic.ttf') format('truetype'); + src: url('~nrfconnect-core/font/Roboto-Italic.ttf') format('truetype'); } /* Bold */ @@ -109,14 +106,14 @@ font-family: "Roboto"; font-style: normal; font-weight: 700; - src: url('../font/Roboto-Bold.ttf') format('truetype'); + src: url('~nrfconnect-core/font/Roboto-Bold.ttf') format('truetype'); } @font-face { font-family: "Roboto"; font-style: italic; font-weight: 700; - src: url('../font/Roboto-BoldItalic.ttf') format('truetype'); + src: url('~nrfconnect-core/font/Roboto-BoldItalic.ttf') format('truetype'); } .tree-view { diff --git a/packages/nrfconnect-appmodule-ble/index.html b/packages/nrfconnect-appmodule-ble/index.html new file mode 100644 index 00000000..877ee9ee --- /dev/null +++ b/packages/nrfconnect-appmodule-ble/index.html @@ -0,0 +1,27 @@ + + + + + nRF Connect + + +
+
+
+ + + + + diff --git a/packages/nrfconnect-appmodule-ble/index.js b/packages/nrfconnect-appmodule-ble/index.js new file mode 100644 index 00000000..467ece53 --- /dev/null +++ b/packages/nrfconnect-appmodule-ble/index.js @@ -0,0 +1,59 @@ +/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + + 'use strict'; + +var electron = require('electron'); +var ipcMain = electron.ipcMain; +var dialog = electron.dialog; +var shell = electron.shell; +var core = require('nrfconnect-core/index'); + +if (electron.app.isReady()) { + initBrowserWindow(); +} else { + electron.app.on('ready', function () { + initBrowserWindow(); + }); +} + +function initBrowserWindow() { + const packageJson = require('./package.json'); + const browserWindow = core.createBrowserWindow({ + title: packageJson.config.title, + url: 'file://' + __dirname + '/index.html', + icon: __dirname + '/' + packageJson.config.icon, + menu: true + }); + + browserWindow.webContents.on('new-window', function (e, url) { + e.preventDefault(); + shell.openExternal(url); + }); +} + +var filters = [ + { name: 'nRF Connect Server Setup', extensions: ['ncs', 'json'] }, + { name: 'All Files', extensions: ['*'] }, +]; + +ipcMain.on('save-server-setup', function (event, arg) { + event.sender.send('save-server-setup-reply', + dialog.showSaveDialog({ filters: filters, })); +}); + +ipcMain.on('load-server-setup', function (event, arg) { + event.sender.send('load-server-setup-reply', + dialog.showOpenDialog({ filters: filters, + properties: ['openFile'], + })); +}); diff --git a/js/actions/adapterActions.js b/packages/nrfconnect-appmodule-ble/js/actions/adapterActions.js similarity index 100% rename from js/actions/adapterActions.js rename to packages/nrfconnect-appmodule-ble/js/actions/adapterActions.js diff --git a/js/actions/advertisingActions.js b/packages/nrfconnect-appmodule-ble/js/actions/advertisingActions.js similarity index 100% rename from js/actions/advertisingActions.js rename to packages/nrfconnect-appmodule-ble/js/actions/advertisingActions.js diff --git a/js/actions/appActions.js b/packages/nrfconnect-appmodule-ble/js/actions/appActions.js similarity index 100% rename from js/actions/appActions.js rename to packages/nrfconnect-appmodule-ble/js/actions/appActions.js diff --git a/js/actions/bleEventActions.js b/packages/nrfconnect-appmodule-ble/js/actions/bleEventActions.js similarity index 100% rename from js/actions/bleEventActions.js rename to packages/nrfconnect-appmodule-ble/js/actions/bleEventActions.js diff --git a/js/actions/common.js b/packages/nrfconnect-appmodule-ble/js/actions/common.js similarity index 100% rename from js/actions/common.js rename to packages/nrfconnect-appmodule-ble/js/actions/common.js diff --git a/js/actions/deviceDetailsActions.js b/packages/nrfconnect-appmodule-ble/js/actions/deviceDetailsActions.js similarity index 100% rename from js/actions/deviceDetailsActions.js rename to packages/nrfconnect-appmodule-ble/js/actions/deviceDetailsActions.js diff --git a/js/actions/discoveryActions.js b/packages/nrfconnect-appmodule-ble/js/actions/discoveryActions.js similarity index 100% rename from js/actions/discoveryActions.js rename to packages/nrfconnect-appmodule-ble/js/actions/discoveryActions.js diff --git a/js/actions/errorDialogActions.js b/packages/nrfconnect-appmodule-ble/js/actions/errorDialogActions.js similarity index 100% rename from js/actions/errorDialogActions.js rename to packages/nrfconnect-appmodule-ble/js/actions/errorDialogActions.js diff --git a/js/actions/firmwareUpdateActions.js b/packages/nrfconnect-appmodule-ble/js/actions/firmwareUpdateActions.js similarity index 100% rename from js/actions/firmwareUpdateActions.js rename to packages/nrfconnect-appmodule-ble/js/actions/firmwareUpdateActions.js diff --git a/js/actions/logActions.js b/packages/nrfconnect-appmodule-ble/js/actions/logActions.js similarity index 100% rename from js/actions/logActions.js rename to packages/nrfconnect-appmodule-ble/js/actions/logActions.js diff --git a/js/actions/securityActions.js b/packages/nrfconnect-appmodule-ble/js/actions/securityActions.js similarity index 100% rename from js/actions/securityActions.js rename to packages/nrfconnect-appmodule-ble/js/actions/securityActions.js diff --git a/js/actions/serverSetupActions.js b/packages/nrfconnect-appmodule-ble/js/actions/serverSetupActions.js similarity index 100% rename from js/actions/serverSetupActions.js rename to packages/nrfconnect-appmodule-ble/js/actions/serverSetupActions.js diff --git a/js/common/Errors.js b/packages/nrfconnect-appmodule-ble/js/common/Errors.js similarity index 100% rename from js/common/Errors.js rename to packages/nrfconnect-appmodule-ble/js/common/Errors.js diff --git a/js/common/layoutStrategies.js b/packages/nrfconnect-appmodule-ble/js/common/layoutStrategies.js similarity index 100% rename from js/common/layoutStrategies.js rename to packages/nrfconnect-appmodule-ble/js/common/layoutStrategies.js diff --git a/js/common/treeViewKeyNavigation.js b/packages/nrfconnect-appmodule-ble/js/common/treeViewKeyNavigation.js similarity index 100% rename from js/common/treeViewKeyNavigation.js rename to packages/nrfconnect-appmodule-ble/js/common/treeViewKeyNavigation.js diff --git a/js/components/AdapterSelector.jsx b/packages/nrfconnect-appmodule-ble/js/components/AdapterSelector.jsx similarity index 100% rename from js/components/AdapterSelector.jsx rename to packages/nrfconnect-appmodule-ble/js/components/AdapterSelector.jsx diff --git a/js/components/AddNewItem.jsx b/packages/nrfconnect-appmodule-ble/js/components/AddNewItem.jsx similarity index 100% rename from js/components/AddNewItem.jsx rename to packages/nrfconnect-appmodule-ble/js/components/AddNewItem.jsx diff --git a/js/components/AdvertisingData.jsx b/packages/nrfconnect-appmodule-ble/js/components/AdvertisingData.jsx similarity index 99% rename from js/components/AdvertisingData.jsx rename to packages/nrfconnect-appmodule-ble/js/components/AdvertisingData.jsx index 226a2383..b0e91db9 100644 --- a/js/components/AdvertisingData.jsx +++ b/packages/nrfconnect-appmodule-ble/js/components/AdvertisingData.jsx @@ -15,7 +15,7 @@ import React, {PropTypes} from 'react'; import { Dropdown, DropdownButton, MenuItem } from 'react-bootstrap'; -import TextInput from './input/TextInput'; +import { TextInput } from 'nrfconnect-core'; import UuidLookup from '../components/UuidLookup'; import { uuid16bitServiceDefinitions, uuid128bitServiceDefinitions } from '../utils/uuid_definitions'; diff --git a/js/components/AdvertisingList.jsx b/packages/nrfconnect-appmodule-ble/js/components/AdvertisingList.jsx similarity index 100% rename from js/components/AdvertisingList.jsx rename to packages/nrfconnect-appmodule-ble/js/components/AdvertisingList.jsx diff --git a/js/components/AdvertisingListEntry.jsx b/packages/nrfconnect-appmodule-ble/js/components/AdvertisingListEntry.jsx similarity index 100% rename from js/components/AdvertisingListEntry.jsx rename to packages/nrfconnect-appmodule-ble/js/components/AdvertisingListEntry.jsx diff --git a/js/components/AttributeItem.jsx b/packages/nrfconnect-appmodule-ble/js/components/AttributeItem.jsx similarity index 100% rename from js/components/AttributeItem.jsx rename to packages/nrfconnect-appmodule-ble/js/components/AttributeItem.jsx diff --git a/js/components/AuthKeyEditor.jsx b/packages/nrfconnect-appmodule-ble/js/components/AuthKeyEditor.jsx similarity index 100% rename from js/components/AuthKeyEditor.jsx rename to packages/nrfconnect-appmodule-ble/js/components/AuthKeyEditor.jsx diff --git a/js/components/BLEEvent.jsx b/packages/nrfconnect-appmodule-ble/js/components/BLEEvent.jsx similarity index 100% rename from js/components/BLEEvent.jsx rename to packages/nrfconnect-appmodule-ble/js/components/BLEEvent.jsx diff --git a/js/components/CentralDevice.jsx b/packages/nrfconnect-appmodule-ble/js/components/CentralDevice.jsx similarity index 100% rename from js/components/CentralDevice.jsx rename to packages/nrfconnect-appmodule-ble/js/components/CentralDevice.jsx diff --git a/js/components/CharacteristicEditor.jsx b/packages/nrfconnect-appmodule-ble/js/components/CharacteristicEditor.jsx similarity index 98% rename from js/components/CharacteristicEditor.jsx rename to packages/nrfconnect-appmodule-ble/js/components/CharacteristicEditor.jsx index f2b6de85..1947bfee 100644 --- a/js/components/CharacteristicEditor.jsx +++ b/packages/nrfconnect-appmodule-ble/js/components/CharacteristicEditor.jsx @@ -15,10 +15,8 @@ import React, { PropTypes } from 'react'; import { ButtonToolbar, Button, Checkbox } from 'react-bootstrap'; -import TextInput from './input/TextInput'; +import { TextInput, SelectList, LabeledInputGroup } from 'nrfconnect-core'; import UuidInput from './input/UuidInput'; -import SelectList from './input/SelectList'; -import LabeledInputGroup from './input/LabeledInputGroup'; import HexOnlyEditableField from './HexOnlyEditableField.jsx'; diff --git a/js/components/CharacteristicItem.jsx b/packages/nrfconnect-appmodule-ble/js/components/CharacteristicItem.jsx similarity index 100% rename from js/components/CharacteristicItem.jsx rename to packages/nrfconnect-appmodule-ble/js/components/CharacteristicItem.jsx diff --git a/js/components/ConfirmationDialog.jsx b/packages/nrfconnect-appmodule-ble/js/components/ConfirmationDialog.jsx similarity index 90% rename from js/components/ConfirmationDialog.jsx rename to packages/nrfconnect-appmodule-ble/js/components/ConfirmationDialog.jsx index b047a81e..4c0eba75 100644 --- a/js/components/ConfirmationDialog.jsx +++ b/packages/nrfconnect-appmodule-ble/js/components/ConfirmationDialog.jsx @@ -16,6 +16,7 @@ import React from 'react'; import {Modal} from 'react-bootstrap'; import {Button} from 'react-bootstrap'; +import spinnerImage from 'nrfconnect-core/resources/ajax-loader.gif'; var ConfirmationDialog = React.createClass({ getInitialState() { @@ -43,7 +44,7 @@ var ConfirmationDialog = React.createClass({

{this.props.text}

- +   diff --git a/js/components/ConnectedDevice.jsx b/packages/nrfconnect-appmodule-ble/js/components/ConnectedDevice.jsx similarity index 100% rename from js/components/ConnectedDevice.jsx rename to packages/nrfconnect-appmodule-ble/js/components/ConnectedDevice.jsx diff --git a/js/components/ConnectionUpdateRequestEditor.js b/packages/nrfconnect-appmodule-ble/js/components/ConnectionUpdateRequestEditor.js similarity index 99% rename from js/components/ConnectionUpdateRequestEditor.js rename to packages/nrfconnect-appmodule-ble/js/components/ConnectionUpdateRequestEditor.js index c6b7b55c..61771e85 100644 --- a/js/components/ConnectionUpdateRequestEditor.js +++ b/packages/nrfconnect-appmodule-ble/js/components/ConnectionUpdateRequestEditor.js @@ -15,7 +15,7 @@ import React, { PropTypes } from 'react'; import { Button } from 'react-bootstrap'; -import TextInput from './input/TextInput' +import { TextInput } from 'nrfconnect-core' import { BLEEventType } from '../actions/common'; diff --git a/js/components/Connector.jsx b/packages/nrfconnect-appmodule-ble/js/components/Connector.jsx similarity index 100% rename from js/components/Connector.jsx rename to packages/nrfconnect-appmodule-ble/js/components/Connector.jsx diff --git a/js/components/CountdownTimer.jsx b/packages/nrfconnect-appmodule-ble/js/components/CountdownTimer.jsx similarity index 100% rename from js/components/CountdownTimer.jsx rename to packages/nrfconnect-appmodule-ble/js/components/CountdownTimer.jsx diff --git a/js/components/DescriptorEditor.jsx b/packages/nrfconnect-appmodule-ble/js/components/DescriptorEditor.jsx similarity index 98% rename from js/components/DescriptorEditor.jsx rename to packages/nrfconnect-appmodule-ble/js/components/DescriptorEditor.jsx index 9275440a..3be11046 100644 --- a/js/components/DescriptorEditor.jsx +++ b/packages/nrfconnect-appmodule-ble/js/components/DescriptorEditor.jsx @@ -15,9 +15,8 @@ import React, { PropTypes } from 'react'; import { ButtonToolbar, Button, Checkbox, InputGroup } from 'react-bootstrap'; -import TextInput from './input/TextInput'; +import { TextInput, SelectList } from 'nrfconnect-core'; import UuidInput from './input/UuidInput'; -import SelectList from './input/SelectList'; import HexOnlyEditableField from './HexOnlyEditableField.jsx'; diff --git a/js/components/DescriptorItem.jsx b/packages/nrfconnect-appmodule-ble/js/components/DescriptorItem.jsx similarity index 100% rename from js/components/DescriptorItem.jsx rename to packages/nrfconnect-appmodule-ble/js/components/DescriptorItem.jsx diff --git a/js/components/DiscoveredDevice.jsx b/packages/nrfconnect-appmodule-ble/js/components/DiscoveredDevice.jsx similarity index 100% rename from js/components/DiscoveredDevice.jsx rename to packages/nrfconnect-appmodule-ble/js/components/DiscoveredDevice.jsx diff --git a/js/components/EditableField.jsx b/packages/nrfconnect-appmodule-ble/js/components/EditableField.jsx similarity index 99% rename from js/components/EditableField.jsx rename to packages/nrfconnect-appmodule-ble/js/components/EditableField.jsx index 1966fca4..aec06199 100644 --- a/js/components/EditableField.jsx +++ b/packages/nrfconnect-appmodule-ble/js/components/EditableField.jsx @@ -17,7 +17,7 @@ import ReactDOM from 'react-dom'; import onClickOutside from 'react-onclickoutside'; import TextareaAutosize from 'react-textarea-autosize'; -import TextArea from './input/TextArea'; +import { TextArea } from 'nrfconnect-core'; import $ from 'jquery'; diff --git a/js/components/EnumeratingAttributes.jsx b/packages/nrfconnect-appmodule-ble/js/components/EnumeratingAttributes.jsx similarity index 84% rename from js/components/EnumeratingAttributes.jsx rename to packages/nrfconnect-appmodule-ble/js/components/EnumeratingAttributes.jsx index 584a13df..8efb44e1 100644 --- a/js/components/EnumeratingAttributes.jsx +++ b/packages/nrfconnect-appmodule-ble/js/components/EnumeratingAttributes.jsx @@ -14,6 +14,8 @@ import React from 'react'; +import spinnerImage from 'nrfconnect-core/resources/ajax-loader.gif'; + export default class EnumeratingAttributes extends React.PureComponent { render() { const barList = []; @@ -26,7 +28,7 @@ export default class EnumeratingAttributes extends React.PureComponent {
{barList}
- +
); diff --git a/js/components/HexOnlyEditableField.jsx b/packages/nrfconnect-appmodule-ble/js/components/HexOnlyEditableField.jsx similarity index 100% rename from js/components/HexOnlyEditableField.jsx rename to packages/nrfconnect-appmodule-ble/js/components/HexOnlyEditableField.jsx diff --git a/js/components/LogEntry.jsx b/packages/nrfconnect-appmodule-ble/js/components/LogEntry.jsx similarity index 100% rename from js/components/LogEntry.jsx rename to packages/nrfconnect-appmodule-ble/js/components/LogEntry.jsx diff --git a/js/components/PairingEditor.jsx b/packages/nrfconnect-appmodule-ble/js/components/PairingEditor.jsx similarity index 100% rename from js/components/PairingEditor.jsx rename to packages/nrfconnect-appmodule-ble/js/components/PairingEditor.jsx diff --git a/js/components/SecurityParamsControls.jsx b/packages/nrfconnect-appmodule-ble/js/components/SecurityParamsControls.jsx similarity index 100% rename from js/components/SecurityParamsControls.jsx rename to packages/nrfconnect-appmodule-ble/js/components/SecurityParamsControls.jsx diff --git a/js/components/ServiceEditor.jsx b/packages/nrfconnect-appmodule-ble/js/components/ServiceEditor.jsx similarity index 98% rename from js/components/ServiceEditor.jsx rename to packages/nrfconnect-appmodule-ble/js/components/ServiceEditor.jsx index d6c13304..10f2175b 100644 --- a/js/components/ServiceEditor.jsx +++ b/packages/nrfconnect-appmodule-ble/js/components/ServiceEditor.jsx @@ -15,8 +15,8 @@ import React, { PropTypes } from 'react'; import { ButtonToolbar, Button } from 'react-bootstrap'; +import { TextInput } from 'nrfconnect-core'; import UuidInput from './input/UuidInput'; -import TextInput from './input/TextInput'; import { getUuidName, uuidServiceDefinitions } from '../utils/uuid_definitions'; diff --git a/js/components/ServiceItem.jsx b/packages/nrfconnect-appmodule-ble/js/components/ServiceItem.jsx similarity index 100% rename from js/components/ServiceItem.jsx rename to packages/nrfconnect-appmodule-ble/js/components/ServiceItem.jsx diff --git a/js/components/UuidLookup.jsx b/packages/nrfconnect-appmodule-ble/js/components/UuidLookup.jsx similarity index 100% rename from js/components/UuidLookup.jsx rename to packages/nrfconnect-appmodule-ble/js/components/UuidLookup.jsx diff --git a/js/components/deviceDetails.jsx b/packages/nrfconnect-appmodule-ble/js/components/deviceDetails.jsx similarity index 100% rename from js/components/deviceDetails.jsx rename to packages/nrfconnect-appmodule-ble/js/components/deviceDetails.jsx diff --git a/js/components/discoveryButton.jsx b/packages/nrfconnect-appmodule-ble/js/components/discoveryButton.jsx similarity index 100% rename from js/components/discoveryButton.jsx rename to packages/nrfconnect-appmodule-ble/js/components/discoveryButton.jsx diff --git a/js/components/input/LabeledInputGroup.jsx b/packages/nrfconnect-appmodule-ble/js/components/input/LabeledInputGroup.jsx similarity index 100% rename from js/components/input/LabeledInputGroup.jsx rename to packages/nrfconnect-appmodule-ble/js/components/input/LabeledInputGroup.jsx diff --git a/js/components/input/SelectList.jsx b/packages/nrfconnect-appmodule-ble/js/components/input/SelectList.jsx similarity index 100% rename from js/components/input/SelectList.jsx rename to packages/nrfconnect-appmodule-ble/js/components/input/SelectList.jsx diff --git a/js/components/input/TextArea.jsx b/packages/nrfconnect-appmodule-ble/js/components/input/TextArea.jsx similarity index 100% rename from js/components/input/TextArea.jsx rename to packages/nrfconnect-appmodule-ble/js/components/input/TextArea.jsx diff --git a/js/components/input/TextInput.jsx b/packages/nrfconnect-appmodule-ble/js/components/input/TextInput.jsx similarity index 100% rename from js/components/input/TextInput.jsx rename to packages/nrfconnect-appmodule-ble/js/components/input/TextInput.jsx diff --git a/js/components/input/UuidInput.jsx b/packages/nrfconnect-appmodule-ble/js/components/input/UuidInput.jsx similarity index 97% rename from js/components/input/UuidInput.jsx rename to packages/nrfconnect-appmodule-ble/js/components/input/UuidInput.jsx index 42f4e3e0..874751ff 100644 --- a/js/components/input/UuidInput.jsx +++ b/packages/nrfconnect-appmodule-ble/js/components/input/UuidInput.jsx @@ -3,7 +3,7 @@ import React, { PropTypes } from 'react'; import UuidLookup from '../UuidLookup'; -import TextInput from './TextInput'; +import { TextInput } from 'nrfconnect-core'; import { getUuidName } from '../../utils/uuid_definitions'; import { validateUuid } from '../../utils/validateUuid'; diff --git a/js/components/navbar.jsx b/packages/nrfconnect-appmodule-ble/js/components/navbar.jsx similarity index 94% rename from js/components/navbar.jsx rename to packages/nrfconnect-appmodule-ble/js/components/navbar.jsx index 388624f2..de4c4a11 100644 --- a/js/components/navbar.jsx +++ b/packages/nrfconnect-appmodule-ble/js/components/navbar.jsx @@ -14,6 +14,7 @@ import React from 'react'; +import logo from 'nrfconnect-core/resources/nrfconnect_neg.png'; import AdapterSelector from './AdapterSelector'; export default class NavBar extends React.PureComponent { @@ -45,7 +46,7 @@ export default class NavBar extends React.PureComponent { return (
- +
diff --git a/js/containers/AdvertisingSetup.jsx b/packages/nrfconnect-appmodule-ble/js/containers/AdvertisingSetup.jsx similarity index 100% rename from js/containers/AdvertisingSetup.jsx rename to packages/nrfconnect-appmodule-ble/js/containers/AdvertisingSetup.jsx diff --git a/js/containers/App.js b/packages/nrfconnect-appmodule-ble/js/containers/App.js similarity index 99% rename from js/containers/App.js rename to packages/nrfconnect-appmodule-ble/js/containers/App.js index 5a3129f9..3d502a12 100644 --- a/js/containers/App.js +++ b/packages/nrfconnect-appmodule-ble/js/containers/App.js @@ -12,6 +12,7 @@ 'use strict'; +import 'nrfconnect-core/css/styles.less'; import '../../css/styles.less'; import React, { PropTypes } from 'react'; diff --git a/js/containers/BLEEventDialog.js b/packages/nrfconnect-appmodule-ble/js/containers/BLEEventDialog.js similarity index 100% rename from js/containers/BLEEventDialog.js rename to packages/nrfconnect-appmodule-ble/js/containers/BLEEventDialog.js diff --git a/js/containers/ConnectionMap.js b/packages/nrfconnect-appmodule-ble/js/containers/ConnectionMap.js similarity index 100% rename from js/containers/ConnectionMap.js rename to packages/nrfconnect-appmodule-ble/js/containers/ConnectionMap.js diff --git a/js/containers/DeviceDetails.js b/packages/nrfconnect-appmodule-ble/js/containers/DeviceDetails.js similarity index 100% rename from js/containers/DeviceDetails.js rename to packages/nrfconnect-appmodule-ble/js/containers/DeviceDetails.js diff --git a/js/containers/DiscoveredDevices.js b/packages/nrfconnect-appmodule-ble/js/containers/DiscoveredDevices.js similarity index 96% rename from js/containers/DiscoveredDevices.js rename to packages/nrfconnect-appmodule-ble/js/containers/DiscoveredDevices.js index 5d5f2bdd..d600bc48 100644 --- a/js/containers/DiscoveredDevices.js +++ b/packages/nrfconnect-appmodule-ble/js/containers/DiscoveredDevices.js @@ -21,8 +21,9 @@ import * as AdapterActions from '../actions/adapterActions'; import DiscoveryButton from '../components/discoveryButton'; import DiscoveredDevice from '../components/DiscoveredDevice'; -import TextInput from '../components/input/TextInput'; +import { TextInput } from 'nrfconnect-core'; import { FormGroup, Checkbox } from 'react-bootstrap'; +import spinnerImage from 'nrfconnect-core/resources/ajax-loader.gif'; class DiscoveredDevices extends React.PureComponent { constructor(props) { @@ -87,7 +88,7 @@ class DiscoveredDevices extends React.PureComponent {

Discovered devices - +

diff --git a/js/containers/ErrorDialog.js b/packages/nrfconnect-appmodule-ble/js/containers/ErrorDialog.js similarity index 100% rename from js/containers/ErrorDialog.js rename to packages/nrfconnect-appmodule-ble/js/containers/ErrorDialog.js diff --git a/js/containers/LogViewer.js b/packages/nrfconnect-appmodule-ble/js/containers/LogViewer.js similarity index 100% rename from js/containers/LogViewer.js rename to packages/nrfconnect-appmodule-ble/js/containers/LogViewer.js diff --git a/js/containers/Root.dev.js b/packages/nrfconnect-appmodule-ble/js/containers/Root.dev.js similarity index 100% rename from js/containers/Root.dev.js rename to packages/nrfconnect-appmodule-ble/js/containers/Root.dev.js diff --git a/js/containers/Root.js b/packages/nrfconnect-appmodule-ble/js/containers/Root.js similarity index 100% rename from js/containers/Root.js rename to packages/nrfconnect-appmodule-ble/js/containers/Root.js diff --git a/js/containers/Root.prod.js b/packages/nrfconnect-appmodule-ble/js/containers/Root.prod.js similarity index 100% rename from js/containers/Root.prod.js rename to packages/nrfconnect-appmodule-ble/js/containers/Root.prod.js diff --git a/js/containers/SecurityParamsDialog.js b/packages/nrfconnect-appmodule-ble/js/containers/SecurityParamsDialog.js similarity index 100% rename from js/containers/SecurityParamsDialog.js rename to packages/nrfconnect-appmodule-ble/js/containers/SecurityParamsDialog.js diff --git a/js/containers/ServerSetup.jsx b/packages/nrfconnect-appmodule-ble/js/containers/ServerSetup.jsx similarity index 100% rename from js/containers/ServerSetup.jsx rename to packages/nrfconnect-appmodule-ble/js/containers/ServerSetup.jsx diff --git a/js/gattDatabases.js b/packages/nrfconnect-appmodule-ble/js/gattDatabases.js similarity index 100% rename from js/gattDatabases.js rename to packages/nrfconnect-appmodule-ble/js/gattDatabases.js diff --git a/js/index.js b/packages/nrfconnect-appmodule-ble/js/index.js similarity index 74% rename from js/index.js rename to packages/nrfconnect-appmodule-ble/js/index.js index 449f22c9..da118c93 100644 --- a/js/index.js +++ b/packages/nrfconnect-appmodule-ble/js/index.js @@ -10,8 +10,6 @@ * */ -'use strict'; - require('babel-polyfill'); var settings = require('./settings.json'); @@ -24,10 +22,12 @@ if (!settings || settings.production === undefined || settings.production === nu var React = require('react'); var renderReact = require('react-dom').render; +var Root = require('./containers/Root'); -var configureStore = require('./store/configureStore'); +var configureStore = require('nrfconnect-core').configureStore; +var rootReducer = require('./reducers'); var initialState = window.__INITIAL_STATE__ || {}; -var store = configureStore(initialState); +var store = configureStore(initialState, rootReducer); let App = require('./containers/Root'); const render = (Component) => { @@ -35,9 +35,12 @@ const render = (Component) => { }; render(App); +// Webpack hot module replacement (HMR) if (module.hot) { + module.hot.accept('./reducers', () => + store.replaceReducer(require('./reducers')) + ); module.hot.accept('./containers/Root', function() { - let newApp = require('./containers/Root'); - render(newApp); + render(require('./containers/Root')); }); } diff --git a/js/logging/index.js b/packages/nrfconnect-appmodule-ble/js/logging/index.js similarity index 100% rename from js/logging/index.js rename to packages/nrfconnect-appmodule-ble/js/logging/index.js diff --git a/js/logging/logger.js b/packages/nrfconnect-appmodule-ble/js/logging/logger.js similarity index 100% rename from js/logging/logger.js rename to packages/nrfconnect-appmodule-ble/js/logging/logger.js diff --git a/js/reducers/adapterReducer.js b/packages/nrfconnect-appmodule-ble/js/reducers/adapterReducer.js similarity index 100% rename from js/reducers/adapterReducer.js rename to packages/nrfconnect-appmodule-ble/js/reducers/adapterReducer.js diff --git a/js/reducers/advertisingReducer.js b/packages/nrfconnect-appmodule-ble/js/reducers/advertisingReducer.js similarity index 100% rename from js/reducers/advertisingReducer.js rename to packages/nrfconnect-appmodule-ble/js/reducers/advertisingReducer.js diff --git a/js/reducers/appReducer.js b/packages/nrfconnect-appmodule-ble/js/reducers/appReducer.js similarity index 100% rename from js/reducers/appReducer.js rename to packages/nrfconnect-appmodule-ble/js/reducers/appReducer.js diff --git a/js/reducers/bleEventReducer.js b/packages/nrfconnect-appmodule-ble/js/reducers/bleEventReducer.js similarity index 100% rename from js/reducers/bleEventReducer.js rename to packages/nrfconnect-appmodule-ble/js/reducers/bleEventReducer.js diff --git a/js/reducers/deviceDetailsReducer.js b/packages/nrfconnect-appmodule-ble/js/reducers/deviceDetailsReducer.js similarity index 100% rename from js/reducers/deviceDetailsReducer.js rename to packages/nrfconnect-appmodule-ble/js/reducers/deviceDetailsReducer.js diff --git a/js/reducers/discoveryReducer.js b/packages/nrfconnect-appmodule-ble/js/reducers/discoveryReducer.js similarity index 100% rename from js/reducers/discoveryReducer.js rename to packages/nrfconnect-appmodule-ble/js/reducers/discoveryReducer.js diff --git a/js/reducers/errorDialogReducer.js b/packages/nrfconnect-appmodule-ble/js/reducers/errorDialogReducer.js similarity index 100% rename from js/reducers/errorDialogReducer.js rename to packages/nrfconnect-appmodule-ble/js/reducers/errorDialogReducer.js diff --git a/js/reducers/firmwareUpdateReducer.js b/packages/nrfconnect-appmodule-ble/js/reducers/firmwareUpdateReducer.js similarity index 100% rename from js/reducers/firmwareUpdateReducer.js rename to packages/nrfconnect-appmodule-ble/js/reducers/firmwareUpdateReducer.js diff --git a/js/reducers/index.js b/packages/nrfconnect-appmodule-ble/js/reducers/index.js similarity index 100% rename from js/reducers/index.js rename to packages/nrfconnect-appmodule-ble/js/reducers/index.js diff --git a/js/reducers/logReducer.js b/packages/nrfconnect-appmodule-ble/js/reducers/logReducer.js similarity index 100% rename from js/reducers/logReducer.js rename to packages/nrfconnect-appmodule-ble/js/reducers/logReducer.js diff --git a/js/reducers/securityReducer.js b/packages/nrfconnect-appmodule-ble/js/reducers/securityReducer.js similarity index 100% rename from js/reducers/securityReducer.js rename to packages/nrfconnect-appmodule-ble/js/reducers/securityReducer.js diff --git a/js/reducers/serverSetupReducer.js b/packages/nrfconnect-appmodule-ble/js/reducers/serverSetupReducer.js similarity index 100% rename from js/reducers/serverSetupReducer.js rename to packages/nrfconnect-appmodule-ble/js/reducers/serverSetupReducer.js diff --git a/js/settings.json b/packages/nrfconnect-appmodule-ble/js/settings.json similarity index 100% rename from js/settings.json rename to packages/nrfconnect-appmodule-ble/js/settings.json diff --git a/js/settings.json.prod b/packages/nrfconnect-appmodule-ble/js/settings.json.prod similarity index 100% rename from js/settings.json.prod rename to packages/nrfconnect-appmodule-ble/js/settings.json.prod diff --git a/js/utils/Effects.jsx b/packages/nrfconnect-appmodule-ble/js/utils/Effects.jsx similarity index 100% rename from js/utils/Effects.jsx rename to packages/nrfconnect-appmodule-ble/js/utils/Effects.jsx diff --git a/js/utils/api.js b/packages/nrfconnect-appmodule-ble/js/utils/api.js similarity index 100% rename from js/utils/api.js rename to packages/nrfconnect-appmodule-ble/js/utils/api.js diff --git a/js/utils/colorDefinitions.js b/packages/nrfconnect-appmodule-ble/js/utils/colorDefinitions.js similarity index 97% rename from js/utils/colorDefinitions.js rename to packages/nrfconnect-appmodule-ble/js/utils/colorDefinitions.js index 04296f4c..919b57f9 100644 --- a/js/utils/colorDefinitions.js +++ b/packages/nrfconnect-appmodule-ble/js/utils/colorDefinitions.js @@ -14,7 +14,7 @@ import {remote} from 'electron'; import { logger } from '../logging'; -import '../../css/colordefinitions.less'; +import 'nrfconnect-core/css/colordefinitions.less'; const CSS_CLASS_PREFIX = 'colordefinition'; const FALLBACK_COLOR = {r: 255, g: 0, b: 0}; diff --git a/js/utils/custom_definitions.json b/packages/nrfconnect-appmodule-ble/js/utils/custom_definitions.json similarity index 100% rename from js/utils/custom_definitions.json rename to packages/nrfconnect-appmodule-ble/js/utils/custom_definitions.json diff --git a/js/utils/definitions.js b/packages/nrfconnect-appmodule-ble/js/utils/definitions.js similarity index 100% rename from js/utils/definitions.js rename to packages/nrfconnect-appmodule-ble/js/utils/definitions.js diff --git a/js/utils/dummyAttributeData.js b/packages/nrfconnect-appmodule-ble/js/utils/dummyAttributeData.js similarity index 100% rename from js/utils/dummyAttributeData.js rename to packages/nrfconnect-appmodule-ble/js/utils/dummyAttributeData.js diff --git a/js/utils/fileUtil.js b/packages/nrfconnect-appmodule-ble/js/utils/fileUtil.js similarity index 100% rename from js/utils/fileUtil.js rename to packages/nrfconnect-appmodule-ble/js/utils/fileUtil.js diff --git a/js/utils/jlinkUtil.js b/packages/nrfconnect-appmodule-ble/js/utils/jlinkUtil.js similarity index 100% rename from js/utils/jlinkUtil.js rename to packages/nrfconnect-appmodule-ble/js/utils/jlinkUtil.js diff --git a/js/utils/stringUtil.js b/packages/nrfconnect-appmodule-ble/js/utils/stringUtil.js similarity index 100% rename from js/utils/stringUtil.js rename to packages/nrfconnect-appmodule-ble/js/utils/stringUtil.js diff --git a/js/utils/uuid_definitions.js b/packages/nrfconnect-appmodule-ble/js/utils/uuid_definitions.js similarity index 100% rename from js/utils/uuid_definitions.js rename to packages/nrfconnect-appmodule-ble/js/utils/uuid_definitions.js diff --git a/js/utils/validateUuid.js b/packages/nrfconnect-appmodule-ble/js/utils/validateUuid.js similarity index 100% rename from js/utils/validateUuid.js rename to packages/nrfconnect-appmodule-ble/js/utils/validateUuid.js diff --git a/packages/nrfconnect-appmodule-ble/package.json b/packages/nrfconnect-appmodule-ble/package.json new file mode 100644 index 00000000..5aa6103f --- /dev/null +++ b/packages/nrfconnect-appmodule-ble/package.json @@ -0,0 +1,58 @@ +{ + "name": "nrfconnect-appmodule-ble", + "version": "1.0.0", + "description": "A natural first choice for BLE development", + "homepage": "http://infocenter.nordicsemi.com/nrf-connect/ble", + "main": "index.js", + "author": "Nordic Semiconductor ASA", + "license": "Proprietary", + "scripts": { + "start": "../../node_modules/.bin/concurrently -k \"node ../../server.js\" \"../../node_modules/.bin/cross-env ENV=development ../../node_modules/.bin/electron .\"", + "build": "../../node_modules/.bin/webpack --config ../../webpack.config.production.js", + "test": "../../node_modules/.bin/cross-env BABEL_DISABLE_CACHE=1 jest js/" + }, + "config": { + "title": "Bluetooth Low Energy (BLE)", + "icon": "resources/icon.png" + }, + "devDependencies": { + "redux-devtools": "3.3.1", + "redux-devtools-dock-monitor": "1.1.1", + "redux-devtools-log-monitor": "1.0.11" + }, + "dependencies": { + "atom-keymap": "6.3.2", + "babel-polyfill": "6.13.0", + "bootstrap": "3.3.7", + "change-case": "3.0.0", + "immutable": "3.8.1", + "jquery": "3.1.0", + "less": "2.7.1", + "moment": "2.14.1", + "nrfconnect-core": "1.0.0", + "open": "0.0.5", + "pc-ble-driver-js": "https://github.com/NordicSemiconductor/pc-ble-driver-js.git#v0.9.0", + "pc-nrfjprog-js": "https://github.com/NordicSemiconductor/pc-nrfjprog-js.git#v0.3.0", + "react": "15.3.1", + "react-addons-linked-state-mixin": "15.3.1", + "react-bootstrap": "0.30.3", + "react-dom": "15.3.1", + "react-infinite": "NordicSemiconductor/react-infinite#upgrade-to-react-15", + "react-onclickoutside": "5.5.0", + "react-redux": "4.4.5", + "react-textarea-autosize": "4.0.5", + "redux": "3.6.0", + "redux-logger": "2.6.1", + "redux-promise-middleware": "4.0.0", + "redux-storage": "4.1.1", + "redux-thunk": "2.1.0", + "semver": "5.3.0", + "serialport": "^3.1.2", + "sqlite3": "3.1.4", + "tween.js": "16.3.5", + "underscore": "1.8.3", + "util": "0.10.3", + "uuid-v4": "0.1.0", + "winston": "2.2.0" + } +} diff --git a/resources/alarm.mp3 b/packages/nrfconnect-appmodule-ble/resources/alarm.mp3 similarity index 100% rename from resources/alarm.mp3 rename to packages/nrfconnect-appmodule-ble/resources/alarm.mp3 diff --git a/packages/nrfconnect-appmodule-ble/resources/icon.png b/packages/nrfconnect-appmodule-ble/resources/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3ce8bf4d281a50df9668e99a932717ba5eabc776 GIT binary patch literal 1377 zcmV-n1)lneP)VGd000McNliru;0X>4HVw(>u*?7e1nx;h zK~!ko-C93P8&@3u?ugGNk}*CzO6WjrM4~KF32nqcBD;xXDP76}9mv!LSE^B~OkILu zX_qPq3=K=CvcNz)MY2SQRWYEXjuA@~Pyi1ND89473dx7WFeO0kIVx$Szm4G683!(?01xdg)`2)_p+`%>Z0~RE~v~B`T=)8Qc z;`13o2myf4Ul);HT(3&EpM|z@-sLHKT|trYJ^L0D$((*)E?+QtoylAz{{)Y3dLpiWz3mCuiFQB`6E^#FMlv2w1r-` z4>MQFJZ@9OTB&H>?N;t+3Cvt!Ernkz6)^|_32ae?xxx9Y-K3Ydb)ttN&>ack2Ir&x zHZBPW&aPuDDPlOefnZw3IK?>nXo<14^@h(^%amR|aq5bNTO>yqn@D{<@ z^+WY!ZIzTm(X*D(*a``3sllkmhE=8JSXCwEaB_p1+m|QMgw;+C#|_)*bSx#RnWs%G zNCLiCIqe(*nww-^kg}&yP}Ib&BZCw9zoGg-mR&|H3&gx?!EI{PR?(XII0OtXHoXX> z7x7WSq7KpMZ!{Ays)Ey@*BM3v*QNS745O_7i@#YPXrra}9W|eEu<%RmJI1L8b^oe? jKC0K3J@%m + {label} + + {children} + + + ); + } +} + +export default LabeledInputGroup; diff --git a/packages/nrfconnect-core/js/components/input/SelectList.jsx b/packages/nrfconnect-core/js/components/input/SelectList.jsx new file mode 100644 index 00000000..0b6025be --- /dev/null +++ b/packages/nrfconnect-core/js/components/input/SelectList.jsx @@ -0,0 +1,35 @@ +import React, { PropTypes } from 'react'; +import { FormGroup, ControlLabel, FormControl, InputGroup } from 'react-bootstrap'; + +class TextInput extends React.PureComponent { + static propTypes = { + id: PropTypes.string, + label: PropTypes.string.isRequired, + labelClassName: PropTypes.string, + wrapperClassName: PropTypes.string + }; + + static defaultProps = { + labelClassName: 'col-md-3 text-right', + wrapperClassName: 'col-md-9' + }; + + render() { + const { id, label, children, labelClassName, wrapperClassName, ...props } = this.props; + + return ( + + { + label && {label} + } + + + {children} + + + + ); + } +} + +export default TextInput; diff --git a/packages/nrfconnect-core/js/components/input/TextArea.jsx b/packages/nrfconnect-core/js/components/input/TextArea.jsx new file mode 100644 index 00000000..9a57396c --- /dev/null +++ b/packages/nrfconnect-core/js/components/input/TextArea.jsx @@ -0,0 +1,33 @@ +import React, { PropTypes } from 'react'; +import { FormGroup, ControlLabel, FormControl, InputGroup } from 'react-bootstrap'; + +class TextArea extends React.PureComponent { + static propTypes = { + id: PropTypes.string, + label: PropTypes.string, + labelClassName: PropTypes.string, + wrapperClassName: PropTypes.string + }; + + static defaultProps = { + labelClassName: 'col-md-3 text-right', + wrapperClassName: 'col-md-9' + }; + + render() { + const { id, label, labelClassName, wrapperClassName, ...props } = this.props; + + return ( + + { + label && {label} + } + + + + + ); + } +} + +export default TextArea; diff --git a/packages/nrfconnect-core/js/components/input/TextInput.jsx b/packages/nrfconnect-core/js/components/input/TextInput.jsx new file mode 100644 index 00000000..104121f0 --- /dev/null +++ b/packages/nrfconnect-core/js/components/input/TextInput.jsx @@ -0,0 +1,40 @@ +import React, { PropTypes } from 'react'; +import { FormGroup, ControlLabel, FormControl, InputGroup } from 'react-bootstrap'; + +class TextInput extends React.PureComponent { + static propTypes = { + id: PropTypes.string, + label: PropTypes.string, + validationState: PropTypes.string, + buttonAfter: PropTypes.node, + hasFeedback: PropTypes.bool, + labelClassName: PropTypes.string, + wrapperClassName: PropTypes.string, + inline: PropTypes.bool + }; + + static defaultProps = { + labelClassName: 'col-md-3 text-right', + wrapperClassName: 'col-md-9' + }; + + render() { + const { id, label, hasFeedback, validationState, buttonAfter, labelClassName, wrapperClassName, inline, ...props } = this.props; + let bsClassProp = inline && {bsClass: 'form-inline'}; + + return ( + + { + label && {label} + } + + + { hasFeedback && } + { buttonAfter && { buttonAfter } } + + + ); + } +} + +export default TextInput; \ No newline at end of file diff --git a/js/containers/DevTools.dev.js b/packages/nrfconnect-core/js/containers/DevTools.dev.js similarity index 100% rename from js/containers/DevTools.dev.js rename to packages/nrfconnect-core/js/containers/DevTools.dev.js diff --git a/js/containers/DevTools.js b/packages/nrfconnect-core/js/containers/DevTools.js similarity index 100% rename from js/containers/DevTools.js rename to packages/nrfconnect-core/js/containers/DevTools.js diff --git a/js/containers/DevTools.prod.js b/packages/nrfconnect-core/js/containers/DevTools.prod.js similarity index 100% rename from js/containers/DevTools.prod.js rename to packages/nrfconnect-core/js/containers/DevTools.prod.js diff --git a/packages/nrfconnect-core/js/containers/ErrorDialog.js b/packages/nrfconnect-core/js/containers/ErrorDialog.js new file mode 100644 index 00000000..128983a7 --- /dev/null +++ b/packages/nrfconnect-core/js/containers/ErrorDialog.js @@ -0,0 +1,104 @@ +/* Copyright (c) 2016 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + + 'use strict'; + +import React, { PropTypes } from 'react'; + +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; + +import * as ErrorActions from '../actions/errorDialogActions'; +import { Modal, Button } from 'react-bootstrap'; + +export class ErrorDialog extends React.PureComponent { + constructor(props) { + super(props); + } + + _createErrorHtml(index, error) { + const { + debug, + } = this.props; + + let html; + + if (debug === true) { + html = (

{error.stack}

); + } else { + html = (

{error.message}

); + } + + return html; + } + + render() { + const { + visible, + errors, + closeErrorDialog, + } = this.props; + + let _errors = []; + + errors.forEach((error, index) => _errors.push(this._createErrorHtml(index, error))); + + return ( +
+ closeErrorDialog()}> + + Error! + + + {_errors} + + + + + +
+ ); + } +} + +ErrorDialog.propTypes = { + errors: PropTypes.object.isRequired, + visible: PropTypes.bool.isRequired, + closeErrorDialog: PropTypes.func.isRequired, + toggleDebug: PropTypes.func.isRequired, +}; + +function mapStateToProps(state) { + const { + errorDialog, + } = state; + + return { + visible: errorDialog.visible, + errors: errorDialog.errors, + debug: errorDialog.debug, + }; +} + +function mapDispatchToProps(dispatch) { + const retval = Object.assign( + {}, + bindActionCreators(ErrorActions, dispatch) + ); + + return retval; +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(ErrorDialog); diff --git a/packages/nrfconnect-core/js/index.js b/packages/nrfconnect-core/js/index.js new file mode 100644 index 00000000..a9b645e5 --- /dev/null +++ b/packages/nrfconnect-core/js/index.js @@ -0,0 +1,31 @@ +const actions = { + errorDialogActions: require('./actions/errorDialogActions') +}; + +const components = { + LabeledInputGroup: require('./components/input/LabeledInputGroup'), + SelectList: require('./components/input/SelectList'), + TextArea: require('./components/input/TextArea'), + TextInput: require('./components/input/TextInput') +}; + +const containers = { + DevTools: require('./containers/DevTools').default, + ErrorDialog: require('./containers/ErrorDialog').default +}; + +const reducers = { + errorDialogReducer: require('./reducers/errorDialogReducer') +}; + +const store = { + configureStore: require('./store/configureStore') +}; + +module.exports = Object.assign({}, + actions, + components, + containers, + reducers, + store +); diff --git a/packages/nrfconnect-core/js/reducers/errorDialogReducer.js b/packages/nrfconnect-core/js/reducers/errorDialogReducer.js new file mode 100644 index 00000000..b47a5801 --- /dev/null +++ b/packages/nrfconnect-core/js/reducers/errorDialogReducer.js @@ -0,0 +1,68 @@ +/* Copyright (c) 2016 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + + 'use strict'; + +import * as ErrorDialogActions from '../actions/errorDialogActions'; + +import { Record, List } from 'immutable'; + +const InitialState = Record({ + visible: false, + errors: List(), + debug: false, +}); + +const initialState = new InitialState(); + +function hideAndClearErrors(state) { + // Only clear the list of errors if we are not in debug mode. + if (state.debug !== true) { + state = state.set('errors', state.errors.clear()); + } + + return state.set('visible', false); +} + +function showErrors(state, errors) { + if (errors !== undefined) { + if (errors.constructor !== Array) { + state = addErrorMessage(state, errors); + } else { + errors.forEach(error => { + state = addErrorMessage(state, error); + }); + } + } + + return state.set('visible', true); +} + +function addErrorMessage(state, error) { + return state.set('errors', state.errors.push(error)); +} + +export default function errorDialog(state = initialState, action) +{ + switch (action.type) { + case ErrorDialogActions.CLOSE: + return hideAndClearErrors(state); + case ErrorDialogActions.SHOW_ERROR_MESSAGES: + return showErrors(state, action.errors); + case ErrorDialogActions.ADD_ERROR_MESSAGE: + return addErrorMessage(state, action.error); + case ErrorDialogActions.TOGGLE_DEBUG: + return toggleDebug(state); + default: + return state; + } +} diff --git a/js/store/configureStore.js b/packages/nrfconnect-core/js/store/configureStore.js similarity index 81% rename from js/store/configureStore.js rename to packages/nrfconnect-core/js/store/configureStore.js index 6a03b6ae..da0d946b 100644 --- a/js/store/configureStore.js +++ b/packages/nrfconnect-core/js/store/configureStore.js @@ -19,9 +19,7 @@ import createLogger from 'redux-logger'; import DevTools from '../containers/DevTools'; import Immutable from 'immutable'; -import rootReducer from '../reducers'; - -export default function configureStore(initialState) { +export default function configureStore(initialState, rootReducer) { const middleware = [ thunkMiddleware, ]; @@ -59,14 +57,5 @@ export default function configureStore(initialState) { )(createStore); } - const store = finalCreateStore(rootReducer, initialState); - - // Check if we can hot reload, if so we hot replace reducers - if (module.hot) { - module.hot.accept('../reducers', () => - store.replaceReducer(require('../reducers')) - ); - } - - return store; + return finalCreateStore(rootReducer, initialState); } diff --git a/packages/nrfconnect-core/package.json b/packages/nrfconnect-core/package.json new file mode 100644 index 00000000..0da675e3 --- /dev/null +++ b/packages/nrfconnect-core/package.json @@ -0,0 +1,35 @@ +{ + "name": "nrfconnect-core", + "version": "1.0.0", + "description": "Core components for nRF Connect", + "repository": { + "type": "git", + "url": "https://github.com/NordicSemiconductor/pc-yggdrasil.git" + }, + "scripts": { + "build": "../../node_modules/.bin/webpack --config webpack.config.js", + "test": "../../node_modules/.bin/cross-env BABEL_DISABLE_CACHE=1 ../../node_modules/.bin/jest js/", + "clean": "../../node_modules/.bin/rimraf node_modules" + }, + "main": "dist/nrfconnect-core.min.js", + "author": "Nordic Semiconductor ASA", + "license": "Proprietary", + "devDependencies": { + "enzyme": "2.4.1", + "react-addons-test-utils": "15.3.1", + "react-test-renderer": "15.3.1", + "redux-devtools": "3.3.1", + "redux-devtools-dock-monitor": "1.1.1", + "redux-devtools-log-monitor": "1.0.11" + }, + "dependencies": { + "bootstrap": "3.3.7", + "react": "15.3.2", + "react-bootstrap": "0.30.3", + "react-dom": "15.3.1", + "react-redux": "4.4.5", + "redux": "3.6.0", + "redux-logger": "2.6.1", + "redux-thunk": "2.1.0" + } +} diff --git a/resources/ajax-loader.gif b/packages/nrfconnect-core/resources/ajax-loader.gif similarity index 100% rename from resources/ajax-loader.gif rename to packages/nrfconnect-core/resources/ajax-loader.gif diff --git a/resources/fontello-271d664f/LICENSE.txt b/packages/nrfconnect-core/resources/fontello-271d664f/LICENSE.txt similarity index 100% rename from resources/fontello-271d664f/LICENSE.txt rename to packages/nrfconnect-core/resources/fontello-271d664f/LICENSE.txt diff --git a/resources/fontello-271d664f/README.txt b/packages/nrfconnect-core/resources/fontello-271d664f/README.txt similarity index 100% rename from resources/fontello-271d664f/README.txt rename to packages/nrfconnect-core/resources/fontello-271d664f/README.txt diff --git a/resources/fontello-271d664f/config.json b/packages/nrfconnect-core/resources/fontello-271d664f/config.json similarity index 100% rename from resources/fontello-271d664f/config.json rename to packages/nrfconnect-core/resources/fontello-271d664f/config.json diff --git a/resources/fontello-271d664f/css/animation.css b/packages/nrfconnect-core/resources/fontello-271d664f/css/animation.css similarity index 100% rename from resources/fontello-271d664f/css/animation.css rename to packages/nrfconnect-core/resources/fontello-271d664f/css/animation.css diff --git a/resources/fontello-271d664f/css/fontello-codes.css b/packages/nrfconnect-core/resources/fontello-271d664f/css/fontello-codes.css similarity index 100% rename from resources/fontello-271d664f/css/fontello-codes.css rename to packages/nrfconnect-core/resources/fontello-271d664f/css/fontello-codes.css diff --git a/resources/fontello-271d664f/css/fontello-embedded.css b/packages/nrfconnect-core/resources/fontello-271d664f/css/fontello-embedded.css similarity index 100% rename from resources/fontello-271d664f/css/fontello-embedded.css rename to packages/nrfconnect-core/resources/fontello-271d664f/css/fontello-embedded.css diff --git a/resources/fontello-271d664f/css/fontello-ie7-codes.css b/packages/nrfconnect-core/resources/fontello-271d664f/css/fontello-ie7-codes.css similarity index 100% rename from resources/fontello-271d664f/css/fontello-ie7-codes.css rename to packages/nrfconnect-core/resources/fontello-271d664f/css/fontello-ie7-codes.css diff --git a/resources/fontello-271d664f/css/fontello-ie7.css b/packages/nrfconnect-core/resources/fontello-271d664f/css/fontello-ie7.css similarity index 100% rename from resources/fontello-271d664f/css/fontello-ie7.css rename to packages/nrfconnect-core/resources/fontello-271d664f/css/fontello-ie7.css diff --git a/resources/fontello-271d664f/css/fontello.css b/packages/nrfconnect-core/resources/fontello-271d664f/css/fontello.css similarity index 100% rename from resources/fontello-271d664f/css/fontello.css rename to packages/nrfconnect-core/resources/fontello-271d664f/css/fontello.css diff --git a/resources/fontello-271d664f/demo.html b/packages/nrfconnect-core/resources/fontello-271d664f/demo.html similarity index 100% rename from resources/fontello-271d664f/demo.html rename to packages/nrfconnect-core/resources/fontello-271d664f/demo.html diff --git a/nrfconnect.icns b/packages/nrfconnect-core/resources/nrfconnect.icns similarity index 100% rename from nrfconnect.icns rename to packages/nrfconnect-core/resources/nrfconnect.icns diff --git a/nrfconnect.ico b/packages/nrfconnect-core/resources/nrfconnect.ico similarity index 100% rename from nrfconnect.ico rename to packages/nrfconnect-core/resources/nrfconnect.ico diff --git a/nrfconnect.png b/packages/nrfconnect-core/resources/nrfconnect.png similarity index 100% rename from nrfconnect.png rename to packages/nrfconnect-core/resources/nrfconnect.png diff --git a/resources/nrfconnect_neg.png b/packages/nrfconnect-core/resources/nrfconnect_neg.png similarity index 100% rename from resources/nrfconnect_neg.png rename to packages/nrfconnect-core/resources/nrfconnect_neg.png diff --git a/settings.js b/packages/nrfconnect-core/settings.js similarity index 100% rename from settings.js rename to packages/nrfconnect-core/settings.js diff --git a/packages/nrfconnect-core/webpack.config.js b/packages/nrfconnect-core/webpack.config.js new file mode 100644 index 00000000..4ac50d97 --- /dev/null +++ b/packages/nrfconnect-core/webpack.config.js @@ -0,0 +1,13 @@ +var path = require('path'); +var config = require('../../webpack.config.production'); + +config.output = { + path: path.resolve('dist'), + publicPath: './dist/', + filename: 'nrfconnect-core.min.js', + library: 'nrfconnect-core', + libraryTarget: 'umd', + umdNameDefine: true +}; + +module.exports = config; diff --git a/packages/nrfconnect-loader/css/components/appmodule-list-item.less b/packages/nrfconnect-loader/css/components/appmodule-list-item.less new file mode 100644 index 00000000..bb94b0ba --- /dev/null +++ b/packages/nrfconnect-loader/css/components/appmodule-list-item.less @@ -0,0 +1,8 @@ +.appmodule-list-item { + display: flex; + + .appmodule-icon { + height: 40px; + margin-right: 10px; + } +} diff --git a/packages/nrfconnect-loader/css/components/appmodule-loader.less b/packages/nrfconnect-loader/css/components/appmodule-loader.less new file mode 100644 index 00000000..b73bffbe --- /dev/null +++ b/packages/nrfconnect-loader/css/components/appmodule-loader.less @@ -0,0 +1,19 @@ +@import "~nrfconnect-core/css/brand.less"; + +.appmodule-loader { + background-color: @brand-primary; + + .appmodule-loader-logo { + float: right; + height: 55px; + } + + .appmodule-loader-heading { + color: @brand-base; + font-weight: bold; + vertical-align: middle; + display: inline-block; + padding: 10px 10px 0 10px; + height: 55px; + } +} diff --git a/index.html b/packages/nrfconnect-loader/index.html similarity index 82% rename from index.html rename to packages/nrfconnect-loader/index.html index 290fdb91..1a895e1d 100644 --- a/index.html +++ b/packages/nrfconnect-loader/index.html @@ -19,7 +19,7 @@ diff --git a/packages/nrfconnect-loader/index.js b/packages/nrfconnect-loader/index.js new file mode 100644 index 00000000..ca6cc4c3 --- /dev/null +++ b/packages/nrfconnect-loader/index.js @@ -0,0 +1,81 @@ +/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + + 'use strict'; + +var electron = require('electron'); +var app = electron.app; +var BrowserWindow = electron.BrowserWindow; +require('nrfconnect-core/index'); + +var splashScreen = null; +var loaderWindow = null; + +var ipcMain = electron.ipcMain; + +ipcMain.on('load-appmodule', function (event, name) { + require(name); + loaderWindow.close(); +}); + +app.on('ready', function () { + splashScreen = new BrowserWindow({ + width: 400, + height: 223, + frame: false, + alwaysOnTop: true, + skipTaskbar: true, + resizable: false, + show: false, + transparent: true + }); + + splashScreen.loadURL('file://' + __dirname + '/resources/splashScreen.html'); + splashScreen.on('closed', function () { + splashScreen = null; + }); + + splashScreen.show(); + + loaderWindow = new BrowserWindow({ + width: 500, + height: 370, + resizable: false, + show: false, + icon: __dirname + '/resources/icon.png', + }); + // Remove this to enable menu and Chrome devtools + loaderWindow.setMenu(null); + + loaderWindow.loadURL('file://' + __dirname + '/index.html'); + + loaderWindow.on('closed', function () { + loaderWindow = null; + if (splashScreen) { + splashScreen.close(); + } + }); + + loaderWindow.webContents.on('did-finish-load', function () { + if (splashScreen) { + splashScreen.close(); + } + + loaderWindow.setTitle('nRF Connect v1.0'); + loaderWindow.show(); + }); + + loaderWindow.webContents.on('new-window', function (e, url) { + e.preventDefault(); + electron.shell.openExternal(url); + }); +}); diff --git a/packages/nrfconnect-loader/js/actions/appActions.js b/packages/nrfconnect-loader/js/actions/appActions.js new file mode 100644 index 00000000..c94970ad --- /dev/null +++ b/packages/nrfconnect-loader/js/actions/appActions.js @@ -0,0 +1,51 @@ +/* Copyright (c) 2016 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +'use strict'; + +import { getAppmodules } from '../utils/appmoduleRepository'; +import { errorDialogActions } from 'nrfconnect-core'; +const { showErrorDialog } = errorDialogActions; + +export const SELECT_APPMODULE = 'APP_SELECT_APPMODULE'; +export const LOAD_APPMODULES_SUCCESS = 'APP_LOAD_APPMODULES_SUCCESS'; + +export function selectAppmoduleAction(appmodule) { + return { + type: SELECT_APPMODULE, + appmodule: appmodule + }; +} + +export function loadAppmodulesSuccessAction(appmodules) { + return { + type: LOAD_APPMODULES_SUCCESS, + appmodules: appmodules + }; +} + +export function loadAppmodulesAction() { + return dispatch => { + return loadAppmodules().then( + appmodules => dispatch(loadAppmodulesSuccessAction(appmodules)) + ).catch( + error => dispatch(showErrorDialog(error)) + ); + }; +} + +function loadAppmodules() { + return new Promise(resolve => { + resolve(getAppmodules()); + }); +} + diff --git a/packages/nrfconnect-loader/js/components/AppmoduleList.jsx b/packages/nrfconnect-loader/js/components/AppmoduleList.jsx new file mode 100644 index 00000000..1249e151 --- /dev/null +++ b/packages/nrfconnect-loader/js/components/AppmoduleList.jsx @@ -0,0 +1,56 @@ +/* Copyright (c) 2016 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +'use strict'; + +import React, { PropTypes } from 'react'; +import Immutable from 'immutable'; +import AppmoduleListItem from './AppmoduleListItem'; + +export default class AppmoduleList extends React.PureComponent { + + constructor(props) { + super(props); + this._onAppmoduleClicked = this._onAppmoduleClicked.bind(this); + } + + static propTypes = { + appmodules: PropTypes.instanceOf(Immutable.List).isRequired, + onAppmoduleSelected: PropTypes.func.isRequired + }; + + _onAppmoduleClicked(appmodule) { + this.props.onAppmoduleSelected(appmodule); + } + + render() { + const { appmodules } = this.props; + + return ( +
+
+ { + appmodules.map(appmodule => { + return this._onAppmoduleClicked(appmodule)} + /> + }) + } +
+
+ ); + } +} diff --git a/packages/nrfconnect-loader/js/components/AppmoduleListItem.jsx b/packages/nrfconnect-loader/js/components/AppmoduleListItem.jsx new file mode 100644 index 00000000..495a8da4 --- /dev/null +++ b/packages/nrfconnect-loader/js/components/AppmoduleListItem.jsx @@ -0,0 +1,45 @@ +/* Copyright (c) 2016 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +'use strict'; + +import '../../css/components/appmodule-list-item.less'; + +import React, { PropTypes } from 'react'; + +export default class AppmoduleListItem extends React.PureComponent { + + static propTypes = { + title: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + icon: PropTypes.string.isRequired, + onClick: PropTypes.func.isRequired + }; + + render() { + const { title, description, icon, onClick } = this.props; + + return ( + +
+
+ +
+
+

{title}

+

{description}

+
+
+
+ ); + } +} diff --git a/packages/nrfconnect-loader/js/components/AppmoduleLoader.jsx b/packages/nrfconnect-loader/js/components/AppmoduleLoader.jsx new file mode 100644 index 00000000..a4ecf2a7 --- /dev/null +++ b/packages/nrfconnect-loader/js/components/AppmoduleLoader.jsx @@ -0,0 +1,56 @@ +/* Copyright (c) 2016 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +'use strict'; + +import '../../css/components/appmodule-loader.less'; +import logo from 'nrfconnect-core/resources/nrfconnect_neg.png'; + +import React, { PropTypes } from 'react'; +import { Checkbox } from 'react-bootstrap'; +import Immutable from 'immutable'; +import AppmoduleList from './AppmoduleList'; + +export default class AppmoduleLoader extends React.PureComponent { + + constructor(props) { + super(props); + } + + static propTypes = { + appmodules: PropTypes.instanceOf(Immutable.List).isRequired, + onAppmoduleSelected: PropTypes.func.isRequired + }; + + render() { + const { appmodules, onAppmoduleSelected } = this.props; + + return ( +
+
+
+ + + +
+
+

nRF Connect

+
+
+
+ + Remember my choice +
+
+ ); + } +} diff --git a/packages/nrfconnect-loader/js/containers/App.jsx b/packages/nrfconnect-loader/js/containers/App.jsx new file mode 100644 index 00000000..8d75e3aa --- /dev/null +++ b/packages/nrfconnect-loader/js/containers/App.jsx @@ -0,0 +1,71 @@ +/* Copyright (c) 2016 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +'use strict'; + +import 'nrfconnect-core/css/styles.less'; + +import React, { PropTypes } from 'react'; +import { connect } from 'react-redux'; +import AppmoduleLoader from '../components/AppmoduleLoader'; +import { ErrorDialog } from 'nrfconnect-core'; +import Immutable from 'immutable'; +import { ipcRenderer } from 'electron'; +import { loadAppmodulesAction } from '../actions/appActions'; + +class AppContainer extends React.PureComponent { + + constructor(props) { + super(props); + } + + static propTypes = { + appmodules: PropTypes.instanceOf(Immutable.List).isRequired, + onAppmoduleSelected: PropTypes.func.isRequired + }; + + componentDidMount() { + this.props.loadAppmodules(); + } + + render() { + return ( +
+ + +
+ ); + } +} + +function mapStateToProps(state) { + const { app } = state; + + return { + appmodules: app.appmodules + }; +} + +function mapDispatchToProps(dispatch) { + return { + onAppmoduleSelected: appmodule => ipcRenderer.send('load-appmodule', appmodule.name, appmodule.icon), + loadAppmodules: () => dispatch(loadAppmodulesAction()) + }; +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(AppContainer); diff --git a/js/components/DevTools.dev.jsx b/packages/nrfconnect-loader/js/containers/Root.jsx similarity index 51% rename from js/components/DevTools.dev.jsx rename to packages/nrfconnect-loader/js/containers/Root.jsx index 46cad263..0f237e91 100644 --- a/js/components/DevTools.dev.jsx +++ b/packages/nrfconnect-loader/js/containers/Root.jsx @@ -10,16 +10,23 @@ * */ - 'use strict'; +'use strict'; -import React from 'react'; -import { createDevTools } from 'redux-devtools'; -import LogMonitor from 'redux-devtools-log-monitor'; -import DockMonitor from 'redux-devtools-dock-monitor'; +import React, { PropTypes } from 'react'; +import { Provider } from 'react-redux'; +import App from './App'; -export default createDevTools( - - - -); +export default class Root extends React.PureComponent { + render() { + const { store } = this.props; + return ( + + + + ); + } +} + +Root.propTypes = { + store: PropTypes.object.isRequired, +}; diff --git a/packages/nrfconnect-loader/js/index.js b/packages/nrfconnect-loader/js/index.js new file mode 100644 index 00000000..da118c93 --- /dev/null +++ b/packages/nrfconnect-loader/js/index.js @@ -0,0 +1,46 @@ +/* Copyright (c) 2016 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +require('babel-polyfill'); + +var settings = require('./settings.json'); + +if (!settings || settings.production === undefined || settings.production === null || settings.production === true) { + process.env.NODE_ENV = 'production'; +} else { + process.env.NODE_ENV = 'development'; +} + +var React = require('react'); +var renderReact = require('react-dom').render; +var Root = require('./containers/Root'); + +var configureStore = require('nrfconnect-core').configureStore; +var rootReducer = require('./reducers'); +var initialState = window.__INITIAL_STATE__ || {}; +var store = configureStore(initialState, rootReducer); + +let App = require('./containers/Root'); +const render = (Component) => { + renderReact(, document.getElementById('app')); +}; +render(App); + +// Webpack hot module replacement (HMR) +if (module.hot) { + module.hot.accept('./reducers', () => + store.replaceReducer(require('./reducers')) + ); + module.hot.accept('./containers/Root', function() { + render(require('./containers/Root')); + }); +} diff --git a/packages/nrfconnect-loader/js/reducers/appReducer.js b/packages/nrfconnect-loader/js/reducers/appReducer.js new file mode 100644 index 00000000..c8ae1658 --- /dev/null +++ b/packages/nrfconnect-loader/js/reducers/appReducer.js @@ -0,0 +1,48 @@ +/* Copyright (c) 2016 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +'use strict'; + +import { Record, List } from 'immutable'; + +import * as AppActions from '../actions/appActions'; +import { getImmutableAppmodule } from '../utils/api'; + +const InitialState = Record({ + selectedAppmodule: null, + appmodules: List() +}); + +const initialState = new InitialState(); + +export default function (state = initialState, action) { + switch (action.type) { + case AppActions.SELECT_APPMODULE: + return setSelectedAppmodule(state, action.name); + case AppActions.LOAD_APPMODULES_SUCCESS: + return setAppmoduleList(state, action.appmodules); + default: + return state; + } +} + +function setSelectedAppmodule(state, name) { + return state.set('selectedAppmodule', name); +} + +function setAppmoduleList(state, appmodules) { + const appmoduleArray = appmodules.map(appmodule => { + return getImmutableAppmodule(appmodule); + }); + return state.set('appmodules', List(appmoduleArray)); +} + diff --git a/js/components/DevTools.jsx b/packages/nrfconnect-loader/js/reducers/index.js similarity index 66% rename from js/components/DevTools.jsx rename to packages/nrfconnect-loader/js/reducers/index.js index 647e8e6c..9a20dbce 100644 --- a/js/components/DevTools.jsx +++ b/packages/nrfconnect-loader/js/reducers/index.js @@ -10,10 +10,14 @@ * */ - 'use strict'; +'use strict'; -if (process.env.NODE_ENV === 'production') { - module.exports = require('./DevTools.prod'); -} else { - module.exports = require('./DevTools.dev'); -} +import { combineReducers } from 'redux'; + +import app from './appReducer'; +import { errorDialogReducer as errorDialog } from 'nrfconnect-core'; + +export default combineReducers({ + app, + errorDialog +}); diff --git a/packages/nrfconnect-loader/js/settings.json b/packages/nrfconnect-loader/js/settings.json new file mode 100644 index 00000000..203abac0 --- /dev/null +++ b/packages/nrfconnect-loader/js/settings.json @@ -0,0 +1 @@ +{"production": false} diff --git a/packages/nrfconnect-loader/js/settings.json.prod b/packages/nrfconnect-loader/js/settings.json.prod new file mode 100644 index 00000000..e344f5c4 --- /dev/null +++ b/packages/nrfconnect-loader/js/settings.json.prod @@ -0,0 +1 @@ +{"production": true} diff --git a/packages/nrfconnect-loader/js/utils/api.js b/packages/nrfconnect-loader/js/utils/api.js new file mode 100644 index 00000000..76c56b98 --- /dev/null +++ b/packages/nrfconnect-loader/js/utils/api.js @@ -0,0 +1,23 @@ +import { Record } from 'immutable'; + +const ImmutableAppmodule = Record({ + name: null, + version: null, + title: null, + description: null, + author: null, + icon: null, + path: null +}); + +export function getImmutableAppmodule(appmodule) { + return new ImmutableAppmodule({ + name: appmodule.name, + version: appmodule.version, + title: appmodule.title, + description: appmodule.description, + author: appmodule.author, + icon: appmodule.icon, + path: appmodule.path + }); +} \ No newline at end of file diff --git a/packages/nrfconnect-loader/js/utils/appmoduleRepository.js b/packages/nrfconnect-loader/js/utils/appmoduleRepository.js new file mode 100644 index 00000000..892e029e --- /dev/null +++ b/packages/nrfconnect-loader/js/utils/appmoduleRepository.js @@ -0,0 +1,28 @@ +import fs from 'fs'; +import { remote } from 'electron'; + +const APP_PATH = remote.getGlobal('appPath'); + +export function getAppmoduleDirectories() { + const packageJson = require('../../package.json'); + return packageJson.appmodules; +} + +export function getAppmodules() { + const appmoduleDirectories = getAppmoduleDirectories(); + return appmoduleDirectories.map(directory => { + const contents = fs.readFileSync(`${APP_PATH}/node_modules/${directory}/package.json`); + return createAppmoduleConfig(JSON.parse(contents)); + }); +} + +function createAppmoduleConfig(packageJson) { + return { + name: packageJson.name, + description: packageJson.description, + version: packageJson.version, + author: packageJson.author, + title: packageJson.config.title, + icon: `${APP_PATH}/node_modules/${packageJson.name}/${packageJson.config.icon}`, + }; +} diff --git a/packages/nrfconnect-loader/package.json b/packages/nrfconnect-loader/package.json new file mode 100644 index 00000000..ab1146be --- /dev/null +++ b/packages/nrfconnect-loader/package.json @@ -0,0 +1,65 @@ +{ + "name": "nrfconnect-loader", + "version": "1.0.0", + "description": "Appmodule loader for nRF Connect", + "repository": { + "type": "git", + "url": "https://github.com/NordicSemiconductor/pc-yggdrasil.git" + }, + "main": "index.js", + "scripts": { + "start": "../../node_modules/.bin/concurrently -k \"node ../../server.js\" \"../../node_modules/.bin/cross-env LOADER_ENV=development ../../node_modules/.bin/electron .\"", + "build": "../../node_modules/.bin/webpack --config ../../webpack.config.production.js" + }, + "author": "Nordic Semiconductor ASA", + "license": "Proprietary", + "devDependencies": { + "redux-devtools": "3.3.1", + "redux-devtools-dock-monitor": "1.1.1", + "redux-devtools-log-monitor": "1.0.11" + }, + "dependencies": { + "atom-keymap": "6.3.2", + "babel-polyfill": "6.13.0", + "bootstrap": "3.3.7", + "change-case": "3.0.0", + "immutable": "3.8.1", + "jquery": "3.1.0", + "less": "2.7.1", + "moment": "2.14.1", + "nrfconnect-core": "1.0.0", + "nrfconnect-appmodule-ble": "1.0.0", + "open": "0.0.5", + "react": "15.3.2", + "react-addons-linked-state-mixin": "15.3.1", + "react-bootstrap": "0.30.3", + "react-dom": "15.3.1", + "react-onclickoutside": "5.5.0", + "react-redux": "4.4.5", + "react-textarea-autosize": "4.0.5", + "redux": "3.6.0", + "redux-logger": "2.6.1", + "redux-promise-middleware": "4.0.0", + "redux-storage": "4.1.1", + "redux-thunk": "2.1.0", + "semver": "5.3.0", + "serialport": "^3.1.2", + "sqlite3": "3.1.4", + "tween.js": "16.3.5", + "underscore": "1.8.3", + "util": "0.10.3", + "uuid-v4": "0.1.0", + "winston": "2.2.0" + }, + "appmodules": [ + "nrfconnect-appmodule-ble" + ], + "jest": { + "testRegex": "(/__tests__/.*|\\.(test|spec))\\.jsx?$", + "moduleFileExtensions": [ + "js", + "jsx", + "json" + ] + } +} diff --git a/packages/nrfconnect-loader/resources/icon.png b/packages/nrfconnect-loader/resources/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e6470704845548bb06d8ce2bb76c25c41073dc6e GIT binary patch literal 941 zcmV;e15*5nP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;(#7eog=Y10G34K~!i%)tXPL(_j?Ey9Afu5?n%;;1XPd zOK=CBI}t~Yq!UL@bmmALIC=;^K~#{3qJpR(vA;Gq-d@iA`lX36IdG^Z-=A~xoqHST zTX{51v)*yL<6MEZbu0H6yBnMRkY!-g%07S#hwBGyzg;$WuAa||XbL!(*!_dp?D6^c z&*sLPht2BZ?ktHmG&-y?&}Dwk;*Dr@*kWK0jz~?IBYm7Y1LRB%o+Hs}=nUL^_gD^| zBhhN;46NTil7r_+v>GNiz&^e`^8ahE?#rv&FT;PThkc87X!8fq=$qy~u3=F`h|mwGTqtp`UnaO=a<=E?W>?J9pk zY;J#i))grEwl5&=(F%zdpIO8*O`{lK^O|^2xES&CRM!zNYw6p;U;~IKbrc1}l-ect z6x5tS23WAKcmq*WYZ}#wDqVvNsJt5xKpUh0vv_4~GCP4$4fuDEh}ilN#I*=cPsM^} zpfH*NHqD+YT|~`+YK|{zW7dhNw>b7J0~~#Z(kpMW0XvA|5 zA(*mLvT4(8Fin$dRi~r8<-Pf-_j%lsMQxmd{eADN62Vkp!{5 zW*lVT)Df#6e0&_}H8^YcOV5#+GsOjnF@GJu` zYm*AZrf;@udA0#azDuV;;bQb(#Rm>DU_>Bu5Nqta#J9 P00000NkvXXu0mjf4NR}L literal 0 HcmV?d00001 diff --git a/splashScreen.html b/packages/nrfconnect-loader/resources/splashScreen.html similarity index 100% rename from splashScreen.html rename to packages/nrfconnect-loader/resources/splashScreen.html diff --git a/splashScreen.png b/packages/nrfconnect-loader/resources/splashScreen.png similarity index 100% rename from splashScreen.png rename to packages/nrfconnect-loader/resources/splashScreen.png diff --git a/webpack.config.development.js b/webpack.config.development.js index 020b9ccf..23807897 100644 --- a/webpack.config.development.js +++ b/webpack.config.development.js @@ -5,14 +5,19 @@ var webpackTargetElectronRenderer = require('webpack-target-electron-renderer'); // Add all node modules as externals, but keep the require behavior. // http://jlongster.com/Backend-Apps-with-Webpack--Part-I -var nodeModules = {}; -fs.readdirSync('node_modules') - .filter(function(x) { - return ['.bin'].indexOf(x) === -1; - }) - .forEach(function(mod) { - nodeModules[mod] = 'commonjs ' + mod; +function createExternals(moduleDirectories) { + var externals = {}; + moduleDirectories.forEach(function (directory) { + fs.readdirSync(directory) + .filter(function(x) { + return ['.bin'].indexOf(x) === -1; + }) + .forEach(function(mod) { + externals[mod] = 'commonjs ' + mod; + }); }); + return externals; +} var config = { devtool: 'source-map', @@ -27,29 +32,33 @@ var config = { exclude: /node_modules/ }, { test: /\.json$/, - loader: 'json' + loader: 'json-loader' }, { test: /\.less$/, - loader: "style!css!less" + loader: "style-loader!css-loader!less-loader" }, { - test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/, - loader: 'file' + test: /\.(png|gif|ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/, + loader: 'file-loader' }] }, output: { - path: __dirname + '/dist', + path: path.resolve('dist'), publicPath: 'http://localhost:9000/dist/', filename: 'bundle.js' }, resolve: { + resolve: { root: path.resolve("./node_modules") }, extensions: ['', '.js', '.jsx', '.json'] }, plugins: [ new webpack.optimize.OccurenceOrderPlugin(), new webpack.HotModuleReplacementPlugin() ], - externals: nodeModules + externals: createExternals([ + 'node_modules', + __dirname + '/node_modules' + ]) }; config.target = webpackTargetElectronRenderer(config); From 0c9b61f83474c3ccc1cb62092af66826ec317e5c Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Thu, 29 Sep 2016 12:27:31 +0200 Subject: [PATCH 04/17] Patch the Node module loader to avoid issues with peer dependencies React et.al is defined as peerDependencies in nrfconnect-core/package.json. These are installed at development time, but they are not bundled with the library, so those who depend on nrfconnect-core need to add their own React dependency in their package.json. This works fine when the library is built and published, but during development there will be a node_modules directory (with React) in nrfconnect-core, and this causes problems. When other projects import React components from nrfconnect-core, the Node module loader will first look for React in nrfconnect-core/node_modules. The other projects will provide their own React dependency, and that leads to two copies of React being loaded at the same time. In general, we do not want anything from nrfconnect-core/node_modules to be loaded by other projects. To avoid this we patch Node's module loader. For more info see: https://www.sharpoblunto.com/News/2016/01/25/testing-react-component-libraries-using-npm-link --- packages/nrfconnect-core/js/loader.js | 44 +++++++++++++++++++++++++++ packages/nrfconnect-core/package.json | 27 ++++++++++------ 2 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 packages/nrfconnect-core/js/loader.js diff --git a/packages/nrfconnect-core/js/loader.js b/packages/nrfconnect-core/js/loader.js new file mode 100644 index 00000000..fa051243 --- /dev/null +++ b/packages/nrfconnect-core/js/loader.js @@ -0,0 +1,44 @@ +const m = require('module'); +const originalLoad = m._load; + +const packageConfig = require('../package.json'); +const peerDeps = packageConfig.peerDependencies; + +/** + We need to ensure that the users copy of peer dependencies are used, and not this + libraries own local copy (React component tests will fail as it doesn't like it + when multiple copies are loaded at once). To fix this we'll do some patching of + the Node module loader. + + https://www.sharpoblunto.com/News/2016/01/25/testing-react-component-libraries-using-npm-link + */ +if (peerDeps) { + m._load = function (request, parent, isMain) { + if (peerDeps[request]) { + const parents = []; + while (parent) { + parents.push(parent); + parent = parent.parent; + } + // reverse the usual node module resolution. Instead + // of trying to load a local copy of the module and + // going up until we find one, we will try to resolve + // from the top down, this way peerDeps are preferentially + // loaded from the parent instead. + parent = parents.pop(); + while (parent) { + try { + return originalLoad(request, parent, isMain); + } + catch (ex) { + parent = parents.pop(); + } + } + } else { + return originalLoad(request, parent, isMain); + } + } +} +//Now export the library components +module.exports = require('../dist/nrfconnect-core.min.js'); +m._load = originalLoad; \ No newline at end of file diff --git a/packages/nrfconnect-core/package.json b/packages/nrfconnect-core/package.json index 0da675e3..aa7ed82e 100644 --- a/packages/nrfconnect-core/package.json +++ b/packages/nrfconnect-core/package.json @@ -11,25 +11,34 @@ "test": "../../node_modules/.bin/cross-env BABEL_DISABLE_CACHE=1 ../../node_modules/.bin/jest js/", "clean": "../../node_modules/.bin/rimraf node_modules" }, - "main": "dist/nrfconnect-core.min.js", + "main": "js/loader.js", "author": "Nordic Semiconductor ASA", "license": "Proprietary", "devDependencies": { - "enzyme": "2.4.1", - "react-addons-test-utils": "15.3.1", - "react-test-renderer": "15.3.1", - "redux-devtools": "3.3.1", - "redux-devtools-dock-monitor": "1.1.1", - "redux-devtools-log-monitor": "1.0.11" - }, - "dependencies": { "bootstrap": "3.3.7", + "enzyme": "2.4.1", "react": "15.3.2", + "react-addons-test-utils": "15.3.1", "react-bootstrap": "0.30.3", "react-dom": "15.3.1", "react-redux": "4.4.5", + "react-test-renderer": "15.3.1", "redux": "3.6.0", + "redux-devtools": "3.3.1", + "redux-devtools-dock-monitor": "1.1.1", + "redux-devtools-log-monitor": "1.0.11", "redux-logger": "2.6.1", "redux-thunk": "2.1.0" + }, + "peerDependencies": { + "react": "^15.3.0", + "bootstrap": "^3.3.0", + "react-bootstrap": "^0.30.3", + "redux": "^3.6.0", + "redux-devtools": "^3.3.1", + "redux-devtools-dock-monitor": "^1.1.1", + "redux-devtools-log-monitor": "^1.0.11", + "redux-logger": "^2.6.1", + "redux-thunk": "^2.1.0" } } From cd8e3ab9f54b30350a00f129ecddd9a129028256 Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Fri, 23 Sep 2016 09:39:06 +0200 Subject: [PATCH 05/17] Add testing with jest for the new appmodule loader components --- .babelrc | 17 +++- package.json | 3 + .../__tests__/AppmoduleList-test.jsx | 22 +++++ .../__tests__/AppmoduleLoader-test.jsx | 32 +++++++ .../AppmoduleLoader-test.jsx.snap | 87 +++++++++++++++++++ packages/nrfconnect-loader/package.json | 6 +- webpack.config.test.js | 5 ++ 7 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 packages/nrfconnect-loader/js/components/__tests__/AppmoduleList-test.jsx create mode 100644 packages/nrfconnect-loader/js/components/__tests__/AppmoduleLoader-test.jsx create mode 100644 packages/nrfconnect-loader/js/components/__tests__/__snapshots__/AppmoduleLoader-test.jsx.snap create mode 100644 webpack.config.test.js diff --git a/.babelrc b/.babelrc index 5ff4bc1a..6a20fff1 100644 --- a/.babelrc +++ b/.babelrc @@ -2,5 +2,18 @@ "presets": [ "react", "es2015", "stage-2" ], "plugins": [ "add-module-exports" - ] -} \ No newline at end of file + ], + "env": { + "test": { + "plugins": [ + [ + "babel-plugin-webpack-loaders", + { + "config": "../../webpack.config.test.js", + "verbose": false + } + ] + ] + } + } +} diff --git a/package.json b/package.json index 8f9525f0..32472ae1 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,10 @@ "devDependencies": { "asar": "0.12.3", "babel-core": "6.14.0", + "babel-jest": "15.0.0", "babel-loader": "6.2.5", "babel-plugin-add-module-exports": "0.2.1", + "babel-plugin-webpack-loaders": "0.7.1", "babel-preset-es2015": "6.14.0", "babel-preset-react": "6.11.1", "babel-preset-stage-2": "6.13.0", @@ -34,6 +36,7 @@ "express": "4.14.0", "file-loader": "0.9.0", "install": "0.8.1", + "jest": "15.1.1", "json-loader": "0.5.4", "lerna": "2.0.0-beta.28", "less": "^2.7.1", diff --git a/packages/nrfconnect-loader/js/components/__tests__/AppmoduleList-test.jsx b/packages/nrfconnect-loader/js/components/__tests__/AppmoduleList-test.jsx new file mode 100644 index 00000000..b1711949 --- /dev/null +++ b/packages/nrfconnect-loader/js/components/__tests__/AppmoduleList-test.jsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import { List } from 'immutable'; +import { getImmutableAppmodule } from '../../utils/api'; +import AppmoduleList from '../AppmoduleList'; +import AppmoduleListItem from '../AppmoduleListItem'; + +const appmodules = List.of(getImmutableAppmodule({ + name: 'nrfconnect-appmodule-ble', + title: 'ble', + description: 'ble description', + icon: 'resources/ble-icon.png' +})); + +it('calls onAppmoduleSelected when appmodule is clicked', () => { + const onAppmoduleSelectedMock = jest.fn(); + const wrapper = mount(); + + wrapper.find(AppmoduleListItem).simulate('click'); + + expect(onAppmoduleSelectedMock).toBeCalled(); +}); diff --git a/packages/nrfconnect-loader/js/components/__tests__/AppmoduleLoader-test.jsx b/packages/nrfconnect-loader/js/components/__tests__/AppmoduleLoader-test.jsx new file mode 100644 index 00000000..9e8b41ea --- /dev/null +++ b/packages/nrfconnect-loader/js/components/__tests__/AppmoduleLoader-test.jsx @@ -0,0 +1,32 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import { List } from 'immutable'; +import { getImmutableAppmodule } from '../../utils/api'; +import AppmoduleLoader from '../AppmoduleLoader'; + +// Have to mock react-dom due to bug: https://github.com/facebook/react/issues/7386 +// Can be removed after upgrade to react 15.4.0. +jest.mock('react-dom'); + +const appmodules = List.of( + getImmutableAppmodule({ + name: 'nrfconnect-appmodule-ble', + title: 'ble', + description: 'ble description', + icon: 'resources/ble-icon.png' + }), + getImmutableAppmodule({ + name: 'nrfconnect-appmodule-mesh', + title: 'mesh', + description: 'mesh description', + icon: 'resources/mesh-icon.png' + }) +); + +it('renders correctly', () => { + const tree = renderer.create( + {}} /> + ).toJSON(); + + expect(tree).toMatchSnapshot(); +}); diff --git a/packages/nrfconnect-loader/js/components/__tests__/__snapshots__/AppmoduleLoader-test.jsx.snap b/packages/nrfconnect-loader/js/components/__tests__/__snapshots__/AppmoduleLoader-test.jsx.snap new file mode 100644 index 00000000..8f60b30f --- /dev/null +++ b/packages/nrfconnect-loader/js/components/__tests__/__snapshots__/AppmoduleLoader-test.jsx.snap @@ -0,0 +1,87 @@ +exports[`test renders correctly 1`] = ` +
+
+
+ + + +
+
+

+ nRF Connect +

+
+
+ +
+`; diff --git a/packages/nrfconnect-loader/package.json b/packages/nrfconnect-loader/package.json index ab1146be..d0e7e78a 100644 --- a/packages/nrfconnect-loader/package.json +++ b/packages/nrfconnect-loader/package.json @@ -9,11 +9,15 @@ "main": "index.js", "scripts": { "start": "../../node_modules/.bin/concurrently -k \"node ../../server.js\" \"../../node_modules/.bin/cross-env LOADER_ENV=development ../../node_modules/.bin/electron .\"", - "build": "../../node_modules/.bin/webpack --config ../../webpack.config.production.js" + "build": "../../node_modules/.bin/webpack --config ../../webpack.config.production.js", + "test": "../../node_modules/.bin/cross-env BABEL_DISABLE_CACHE=1 ../../node_modules/.bin/jest js/" }, "author": "Nordic Semiconductor ASA", "license": "Proprietary", "devDependencies": { + "enzyme": "2.4.1", + "react-addons-test-utils": "15.3.1", + "react-test-renderer": "15.3.1", "redux-devtools": "3.3.1", "redux-devtools-dock-monitor": "1.1.1", "redux-devtools-log-monitor": "1.0.11" diff --git a/webpack.config.test.js b/webpack.config.test.js new file mode 100644 index 00000000..ff804eda --- /dev/null +++ b/webpack.config.test.js @@ -0,0 +1,5 @@ +const config = require('./webpack.config.development'); +module.exports = { + module: config.module, + resolve: config.resolve +}; From 8044f622eb2bf01ef5a0e9cb3ff0b6afd14cdf46 Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Thu, 22 Sep 2016 09:42:21 +0200 Subject: [PATCH 06/17] Ability to run test/clean/build for all packages from the root dir --- package.json | 2 ++ packages/nrfconnect-appmodule-ble/package.json | 3 ++- packages/nrfconnect-loader/package.json | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 32472ae1..cd36bc0b 100644 --- a/package.json +++ b/package.json @@ -39,9 +39,11 @@ "jest": "15.1.1", "json-loader": "0.5.4", "lerna": "2.0.0-beta.28", + "lerna-run": "0.0.2", "less": "^2.7.1", "less-loader": "2.2.3", "q": "1.4.1", + "rimraf": "^2.5.4", "run-sequence": "1.2.2", "style-loader": "0.13.1", "webpack": "1.13.2", diff --git a/packages/nrfconnect-appmodule-ble/package.json b/packages/nrfconnect-appmodule-ble/package.json index 5aa6103f..6303a00d 100644 --- a/packages/nrfconnect-appmodule-ble/package.json +++ b/packages/nrfconnect-appmodule-ble/package.json @@ -9,7 +9,8 @@ "scripts": { "start": "../../node_modules/.bin/concurrently -k \"node ../../server.js\" \"../../node_modules/.bin/cross-env ENV=development ../../node_modules/.bin/electron .\"", "build": "../../node_modules/.bin/webpack --config ../../webpack.config.production.js", - "test": "../../node_modules/.bin/cross-env BABEL_DISABLE_CACHE=1 jest js/" + "test": "../../node_modules/.bin/cross-env BABEL_DISABLE_CACHE=1 ../../node_modules/.bin/jest js/", + "clean": "../../node_modules/.bin/rimraf node_modules" }, "config": { "title": "Bluetooth Low Energy (BLE)", diff --git a/packages/nrfconnect-loader/package.json b/packages/nrfconnect-loader/package.json index d0e7e78a..888e867e 100644 --- a/packages/nrfconnect-loader/package.json +++ b/packages/nrfconnect-loader/package.json @@ -10,7 +10,8 @@ "scripts": { "start": "../../node_modules/.bin/concurrently -k \"node ../../server.js\" \"../../node_modules/.bin/cross-env LOADER_ENV=development ../../node_modules/.bin/electron .\"", "build": "../../node_modules/.bin/webpack --config ../../webpack.config.production.js", - "test": "../../node_modules/.bin/cross-env BABEL_DISABLE_CACHE=1 ../../node_modules/.bin/jest js/" + "test": "../../node_modules/.bin/cross-env BABEL_DISABLE_CACHE=1 ../../node_modules/.bin/jest js/", + "clean": "../../node_modules/.bin/rimraf node_modules" }, "author": "Nordic Semiconductor ASA", "license": "Proprietary", From 16e4a9a7cdf98b9af6ac59dba6315e13fd6b4d6b Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Thu, 22 Sep 2016 14:26:50 +0200 Subject: [PATCH 07/17] Replace settings.json with NODE_ENV variable --- packages/nrfconnect-appmodule-ble/index.html | 2 +- packages/nrfconnect-appmodule-ble/js/index.js | 8 -------- packages/nrfconnect-appmodule-ble/package.json | 2 +- packages/nrfconnect-core/js/containers/DevTools.js | 6 +++--- packages/nrfconnect-core/js/store/configureStore.js | 2 +- packages/nrfconnect-loader/js/index.js | 8 -------- packages/nrfconnect-loader/js/settings.json | 1 - packages/nrfconnect-loader/js/settings.json.prod | 1 - setup.bat | 7 ------- setup.sh | 5 ----- 10 files changed, 6 insertions(+), 36 deletions(-) delete mode 100644 packages/nrfconnect-loader/js/settings.json delete mode 100644 packages/nrfconnect-loader/js/settings.json.prod diff --git a/packages/nrfconnect-appmodule-ble/index.html b/packages/nrfconnect-appmodule-ble/index.html index 877ee9ee..0e6015cf 100644 --- a/packages/nrfconnect-appmodule-ble/index.html +++ b/packages/nrfconnect-appmodule-ble/index.html @@ -19,7 +19,7 @@ diff --git a/packages/nrfconnect-appmodule-ble/js/index.js b/packages/nrfconnect-appmodule-ble/js/index.js index da118c93..dfb7d3f2 100644 --- a/packages/nrfconnect-appmodule-ble/js/index.js +++ b/packages/nrfconnect-appmodule-ble/js/index.js @@ -12,14 +12,6 @@ require('babel-polyfill'); -var settings = require('./settings.json'); - -if (!settings || settings.production === undefined || settings.production === null || settings.production === true) { - process.env.NODE_ENV = 'production'; -} else { - process.env.NODE_ENV = 'development'; -} - var React = require('react'); var renderReact = require('react-dom').render; var Root = require('./containers/Root'); diff --git a/packages/nrfconnect-appmodule-ble/package.json b/packages/nrfconnect-appmodule-ble/package.json index 6303a00d..f6073dcd 100644 --- a/packages/nrfconnect-appmodule-ble/package.json +++ b/packages/nrfconnect-appmodule-ble/package.json @@ -7,7 +7,7 @@ "author": "Nordic Semiconductor ASA", "license": "Proprietary", "scripts": { - "start": "../../node_modules/.bin/concurrently -k \"node ../../server.js\" \"../../node_modules/.bin/cross-env ENV=development ../../node_modules/.bin/electron .\"", + "start": "../../node_modules/.bin/concurrently -k \"node ../../server.js\" \"../../node_modules/.bin/cross-env NODE_ENV=development ../../node_modules/.bin/electron .\"", "build": "../../node_modules/.bin/webpack --config ../../webpack.config.production.js", "test": "../../node_modules/.bin/cross-env BABEL_DISABLE_CACHE=1 ../../node_modules/.bin/jest js/", "clean": "../../node_modules/.bin/rimraf node_modules" diff --git a/packages/nrfconnect-core/js/containers/DevTools.js b/packages/nrfconnect-core/js/containers/DevTools.js index 647e8e6c..bb19fbeb 100644 --- a/packages/nrfconnect-core/js/containers/DevTools.js +++ b/packages/nrfconnect-core/js/containers/DevTools.js @@ -12,8 +12,8 @@ 'use strict'; -if (process.env.NODE_ENV === 'production') { - module.exports = require('./DevTools.prod'); -} else { +if (process.env.NODE_ENV === 'development') { module.exports = require('./DevTools.dev'); +} else { + module.exports = require('./DevTools.prod'); } diff --git a/packages/nrfconnect-core/js/store/configureStore.js b/packages/nrfconnect-core/js/store/configureStore.js index da0d946b..59e504bb 100644 --- a/packages/nrfconnect-core/js/store/configureStore.js +++ b/packages/nrfconnect-core/js/store/configureStore.js @@ -24,7 +24,7 @@ export default function configureStore(initialState, rootReducer) { thunkMiddleware, ]; - const isProduction = process.env.NODE_ENV === 'production'; + const isProduction = process.env.NODE_ENV !== 'development'; let finalCreateStore; diff --git a/packages/nrfconnect-loader/js/index.js b/packages/nrfconnect-loader/js/index.js index da118c93..dfb7d3f2 100644 --- a/packages/nrfconnect-loader/js/index.js +++ b/packages/nrfconnect-loader/js/index.js @@ -12,14 +12,6 @@ require('babel-polyfill'); -var settings = require('./settings.json'); - -if (!settings || settings.production === undefined || settings.production === null || settings.production === true) { - process.env.NODE_ENV = 'production'; -} else { - process.env.NODE_ENV = 'development'; -} - var React = require('react'); var renderReact = require('react-dom').render; var Root = require('./containers/Root'); diff --git a/packages/nrfconnect-loader/js/settings.json b/packages/nrfconnect-loader/js/settings.json deleted file mode 100644 index 203abac0..00000000 --- a/packages/nrfconnect-loader/js/settings.json +++ /dev/null @@ -1 +0,0 @@ -{"production": false} diff --git a/packages/nrfconnect-loader/js/settings.json.prod b/packages/nrfconnect-loader/js/settings.json.prod deleted file mode 100644 index e344f5c4..00000000 --- a/packages/nrfconnect-loader/js/settings.json.prod +++ /dev/null @@ -1 +0,0 @@ -{"production": true} diff --git a/setup.bat b/setup.bat index 59886fb5..1948d085 100644 --- a/setup.bat +++ b/setup.bat @@ -55,10 +55,6 @@ call npm install call npm run build call npm prune --production -echo "Setting up release settings" -rename js\settings.json settings.json.dev -rename js\settings.json.prod settings.json - echo "Copy driver" copy node_modules\pc-ble-driver-js\build\driver\Release\pc-ble-driver.dll node_modules\pc-ble-driver-js\build\Release\pc-ble-driver.dll @@ -94,7 +90,4 @@ if ["%SIGNTOOL_PATH%"] == [""] goto cleanup :cleanup popd -rename js\settings.json settings.json.prod -rename js\settings.json.dev settings.json - echo "Finished" diff --git a/setup.sh b/setup.sh index 5427ea4f..826d03c4 100755 --- a/setup.sh +++ b/setup.sh @@ -59,8 +59,6 @@ export YGGDRASIL_APP_ROOT_DIR="$YGGDRASIL_DEPLOY_DIR/$YGGDRASIL_APP_DIR" rm -rf node_modules -mv js/settings.json js/settings.json.dev -mv js/settings.json.prod js/settings.json npm install npm run build @@ -81,6 +79,3 @@ cd "$YGGDRASIL_DEPLOY_DIR" tar czf $YGGDRASIL_NAME-$YGGDRASIL_FULL_VERSION-$YGGDRASIL_PLATFORM-$npm_config_arch.tar.gz "$YGGDRASIL_APP_DIR" popd - -mv js/settings.json js/settings.json.prod -mv js/settings.json.dev js/settings.json From 17dc4a03b713c34bf08e8c354379370f260576b8 Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Thu, 22 Sep 2016 15:45:57 +0200 Subject: [PATCH 08/17] Bundle hex files with webpack instead of copying them in setup --- .../js/actions/firmwareUpdateActions.js | 13 ++++++++----- setup.bat | 2 -- setup.sh | 2 -- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/nrfconnect-appmodule-ble/js/actions/firmwareUpdateActions.js b/packages/nrfconnect-appmodule-ble/js/actions/firmwareUpdateActions.js index 9bdc9e45..ed6539ed 100644 --- a/packages/nrfconnect-appmodule-ble/js/actions/firmwareUpdateActions.js +++ b/packages/nrfconnect-appmodule-ble/js/actions/firmwareUpdateActions.js @@ -17,7 +17,6 @@ export const HIDE_FIRMWARE_UPDATE_REQUEST = 'HIDE_FIRMWARE_UPDATE_REQUEST'; export const UPDATE_FIRMWARE = 'UPDATE_FIRMWARE'; export const SHOW_FIRMWARE_UPDATE_SPINNER = 'SHOW_FIRMWARE_UPDATE_SPINNER'; -import path from 'path'; import { remote } from 'electron'; import { openAdapter } from './adapterActions'; import { DebugProbe } from 'pc-nrfjprog-js'; @@ -33,10 +32,9 @@ function _updateFirmware(dispatch, getState, adapter) { const probe = new DebugProbe(); - const appPath = remote.getGlobal('appPath'); - - const pathHexS130 = path.resolve(appPath, './hex/connectivity_115k2_with_s130_2.0.1.hex'); - const pathHexS132 = path.resolve(appPath, './hex/connectivity_115k2_with_s132_2.0.1.hex'); + const projectDir = _getProjectDirectory(); + const pathHexS130 = projectDir + require('file!pc-ble-driver-js/pc-ble-driver/hex/connectivity_115k2_with_s130_2.0.1.hex'); + const pathHexS132 = projectDir + require('file!pc-ble-driver-js/pc-ble-driver/hex/connectivity_115k2_with_s132_2.0.1.hex'); probe.program(parseInt(adapterToUse.state.serialNumber, 10), [pathHexS130, pathHexS132], err => { console.log(err); @@ -56,6 +54,11 @@ function _updateFirmware(dispatch, getState, adapter) { }); } +function _getProjectDirectory() { + // pathname is /path/to/index.html, but we want just the directory + return location.pathname.replace(/[^\/]*$/, ''); +} + function showFirmwareUpdateRequestAction(adapter, foundVersion, latestVersion) { return { type: SHOW_FIRMWARE_UPDATE_REQUEST, diff --git a/setup.bat b/setup.bat index 1948d085..ca67f2f0 100644 --- a/setup.bat +++ b/setup.bat @@ -67,8 +67,6 @@ call electron-packager ./ nrf-connect --platform=win32 --arch=%YGGDRASIL_ELECTRO copy yggdrasil_installer.nsi %YGGDRASIL_DEPLOY_DIR% copy nrfconnect.ico %YGGDRASIL_DEPLOY_DIR% copy LICENSE %YGGDRASIL_DEPLOY_DIR%\nrf-connect-win32-ia32\LICENSE -mkdir %YGGDRASIL_DEPLOY_DIR%\nrf-connect-win32-ia32\hex -copy node_modules\pc-ble-driver-js\pc-ble-driver\hex\connectivity_115k2_with_s13*_2.0.1.hex %YGGDRASIL_DEPLOY_DIR%\nrf-connect-win32-ia32\hex\ cd %YGGDRASIL_DEPLOY_DIR% diff --git a/setup.sh b/setup.sh index 826d03c4..a11348d1 100755 --- a/setup.sh +++ b/setup.sh @@ -64,8 +64,6 @@ npm install npm run build npm prune --production -mkdir ./hex -cp node_modules/pc-ble-driver-js/pc-ble-driver/hex/*.hex ./hex/ electron-packager . "$YGGDRASIL_APP_NAME" --platform=$YGGDRASIL_PLATFORM --arch=$npm_config_arch --icon=$YGGDRASIL_ICON --version=$npm_config_target --overwrite --out=$YGGDRASIL_DEPLOY_DIR --app-version=$YGGDRASIL_VERSION --version-string.CompanyName="Nordic Semiconductor ASA" --version-string.LegalCopyright="Nordic Semiconductor ASA" --version-string.FileDescription="nRF Connect" --version-string.OriginalFilename="nrfconnect" --version-string.FileVersion="$YGGDRASIL_VERSION" --version-string.ProductVersion="$YGGDRASIL_FULL_VERSION" --version-string.ProductName="$YGGDRASIL_NAME" --version-string.InternalName="$YGGDRASIL_NAME" From 7899e39909c6b679980db516185925c3caa64cca Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Thu, 22 Sep 2016 16:22:08 +0200 Subject: [PATCH 09/17] Use new npm commands to clean/build project in setup --- setup.bat | 8 +++----- setup.sh | 9 +++------ 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/setup.bat b/setup.bat index ca67f2f0..70786456 100644 --- a/setup.bat +++ b/setup.bat @@ -2,9 +2,6 @@ echo off echo "Pushing the current directory onto the stack to easier come back to it at end of script" pushd %CD% -echo "Removing node_modules to ensure clean build" -rmdir /s /q node_modules - echo "Node version" call node --version @@ -51,7 +48,8 @@ set npm_config_arch=%YGGDRASIL_ELECTRON_ARCH% set npm_config_disturl=https://atom.io/download/atom-shell echo "Install production" -call npm install +call npm run clean +call npm run bootstrap call npm run build call npm prune --production @@ -62,7 +60,7 @@ echo "Copy runtime redistributable files for Visual Studio" copy "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x86\Microsoft.VC120.CRT\*.dll" node_modules\pc-ble-driver-js\build\Release\ echo "Packaging" -call electron-packager ./ nrf-connect --platform=win32 --arch=%YGGDRASIL_ELECTRON_ARCH% --version=%YGGDRASIL_ELECTRON_VERSION% --overwrite --out=%YGGDRASIL_DEPLOY_DIR% --icon=nrfconnect.ico --app-version=%YGGDRASIL_VERSION% --version-string.CompanyName="Nordic Semiconductor" --version-string.LegalCopyright="Nordic Semiconductor" --version-string.FileDescription="nRF Connect" --version-string.OriginalFilename="nrf-connect.exe" --version-string.FileVersion=%YGGDRASIL_VERSION% --version-string.ProductVersion=%YGGDRASIL_FULL_VERSION% --version-string.ProductName="nRF Connect" --version-string.InternalName="nRF Connect" --asar +call electron-packager nrfconnect-loader nrf-connect --platform=win32 --arch=%YGGDRASIL_ELECTRON_ARCH% --version=%YGGDRASIL_ELECTRON_VERSION% --overwrite --out=%YGGDRASIL_DEPLOY_DIR% --icon=nrfconnect.ico --app-version=%YGGDRASIL_VERSION% --version-string.CompanyName="Nordic Semiconductor" --version-string.LegalCopyright="Nordic Semiconductor" --version-string.FileDescription="nRF Connect" --version-string.OriginalFilename="nrf-connect.exe" --version-string.FileVersion=%YGGDRASIL_VERSION% --version-string.ProductVersion=%YGGDRASIL_FULL_VERSION% --version-string.ProductName="nRF Connect" --version-string.InternalName="nRF Connect" --asar copy yggdrasil_installer.nsi %YGGDRASIL_DEPLOY_DIR% copy nrfconnect.ico %YGGDRASIL_DEPLOY_DIR% diff --git a/setup.sh b/setup.sh index a11348d1..c62b21a3 100755 --- a/setup.sh +++ b/setup.sh @@ -57,15 +57,12 @@ esac export YGGDRASIL_APP_DIR="$YGGDRASIL_APP_NAME-$YGGDRASIL_PLATFORM-$npm_config_arch" export YGGDRASIL_APP_ROOT_DIR="$YGGDRASIL_DEPLOY_DIR/$YGGDRASIL_APP_DIR" -rm -rf node_modules - - -npm install +npm run clean +npm run bootstrap npm run build npm prune --production - -electron-packager . "$YGGDRASIL_APP_NAME" --platform=$YGGDRASIL_PLATFORM --arch=$npm_config_arch --icon=$YGGDRASIL_ICON --version=$npm_config_target --overwrite --out=$YGGDRASIL_DEPLOY_DIR --app-version=$YGGDRASIL_VERSION --version-string.CompanyName="Nordic Semiconductor ASA" --version-string.LegalCopyright="Nordic Semiconductor ASA" --version-string.FileDescription="nRF Connect" --version-string.OriginalFilename="nrfconnect" --version-string.FileVersion="$YGGDRASIL_VERSION" --version-string.ProductVersion="$YGGDRASIL_FULL_VERSION" --version-string.ProductName="$YGGDRASIL_NAME" --version-string.InternalName="$YGGDRASIL_NAME" +electron-packager packages/nrfconnect-loader "$YGGDRASIL_APP_NAME" --platform=$YGGDRASIL_PLATFORM --arch=$npm_config_arch --icon=$YGGDRASIL_ICON --version=$npm_config_target --overwrite --out=$YGGDRASIL_DEPLOY_DIR --app-version=$YGGDRASIL_VERSION --version-string.CompanyName="Nordic Semiconductor ASA" --version-string.LegalCopyright="Nordic Semiconductor ASA" --version-string.FileDescription="nRF Connect" --version-string.OriginalFilename="nrfconnect" --version-string.FileVersion="$YGGDRASIL_VERSION" --version-string.ProductVersion="$YGGDRASIL_FULL_VERSION" --version-string.ProductName="$YGGDRASIL_NAME" --version-string.InternalName="$YGGDRASIL_NAME" cp LICENSE "$YGGDRASIL_APP_ROOT_DIR/LICENSE" tar xvf nrfjprog/$COMMANDLINE_TOOLS_FILE --strip=2 -C $YGGDRASIL_DEPLOY_DIR From 097a91ef391908330cdf2443b3de98e96360b6bf Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Tue, 27 Sep 2016 17:19:16 +0200 Subject: [PATCH 10/17] Create a minimal sample appmodule --- .../nrfconnect-appmodule-sample/index.html | 20 +++++++ packages/nrfconnect-appmodule-sample/index.js | 33 +++++++++++ .../js/actions/appActions.js | 19 ++++++ .../js/components/SimpleCounter.jsx | 20 +++++++ .../__tests__/SimpleCounter-test.jsx | 14 +++++ .../js/containers/App.jsx | 55 ++++++++++++++++++ .../js/containers/Root.jsx | 30 ++++++++++ .../nrfconnect-appmodule-sample/js/index.js | 38 ++++++++++++ .../js/reducers/appReducer.js | 32 ++++++++++ .../js/reducers/index.js | 21 +++++++ .../nrfconnect-appmodule-sample/package.json | 44 ++++++++++++++ .../resources/icon.png | Bin 0 -> 1435 bytes packages/nrfconnect-loader/package.json | 4 +- 13 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 packages/nrfconnect-appmodule-sample/index.html create mode 100644 packages/nrfconnect-appmodule-sample/index.js create mode 100644 packages/nrfconnect-appmodule-sample/js/actions/appActions.js create mode 100644 packages/nrfconnect-appmodule-sample/js/components/SimpleCounter.jsx create mode 100644 packages/nrfconnect-appmodule-sample/js/components/__tests__/SimpleCounter-test.jsx create mode 100644 packages/nrfconnect-appmodule-sample/js/containers/App.jsx create mode 100644 packages/nrfconnect-appmodule-sample/js/containers/Root.jsx create mode 100644 packages/nrfconnect-appmodule-sample/js/index.js create mode 100644 packages/nrfconnect-appmodule-sample/js/reducers/appReducer.js create mode 100644 packages/nrfconnect-appmodule-sample/js/reducers/index.js create mode 100644 packages/nrfconnect-appmodule-sample/package.json create mode 100644 packages/nrfconnect-appmodule-sample/resources/icon.png diff --git a/packages/nrfconnect-appmodule-sample/index.html b/packages/nrfconnect-appmodule-sample/index.html new file mode 100644 index 00000000..2fac063c --- /dev/null +++ b/packages/nrfconnect-appmodule-sample/index.html @@ -0,0 +1,20 @@ + + + + + nRF Connect + + +
+
+
+ + + + diff --git a/packages/nrfconnect-appmodule-sample/index.js b/packages/nrfconnect-appmodule-sample/index.js new file mode 100644 index 00000000..5ede3a53 --- /dev/null +++ b/packages/nrfconnect-appmodule-sample/index.js @@ -0,0 +1,33 @@ +/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +var electron = require('electron'); +var core = require('nrfconnect-core/index'); + +// Support both immediate and delayed initialization +if (electron.app.isReady()) { + initBrowserWindow(); +} else { + electron.app.on('ready', function () { + initBrowserWindow(); + }); +} + +function initBrowserWindow() { + const packageJson = require('./package.json'); + core.createBrowserWindow({ + title: packageJson.config.title, + url: 'file://' + __dirname + '/index.html', + icon: __dirname + '/' + packageJson.config.icon, + menu: true + }); +} diff --git a/packages/nrfconnect-appmodule-sample/js/actions/appActions.js b/packages/nrfconnect-appmodule-sample/js/actions/appActions.js new file mode 100644 index 00000000..caaaae04 --- /dev/null +++ b/packages/nrfconnect-appmodule-sample/js/actions/appActions.js @@ -0,0 +1,19 @@ +/* Copyright (c) 2016 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +export const INCREMENT_COUNTER = 'APP_INCREMENT_COUNTER'; + +export function incrementCounterAction() { + return { + type: INCREMENT_COUNTER + }; +} diff --git a/packages/nrfconnect-appmodule-sample/js/components/SimpleCounter.jsx b/packages/nrfconnect-appmodule-sample/js/components/SimpleCounter.jsx new file mode 100644 index 00000000..80a32e06 --- /dev/null +++ b/packages/nrfconnect-appmodule-sample/js/components/SimpleCounter.jsx @@ -0,0 +1,20 @@ +import React, { PropTypes } from 'react'; +import { Button } from 'react-bootstrap'; + +export default class SimpleCounter extends React.PureComponent { + static propTypes = { + value: PropTypes.number.isRequired, + onIncrement: PropTypes.func.isRequired + }; + + render() { + const { value, onIncrement } = this.props; + + return ( +
+

Value: { value }

+ +
+ ); + } +} diff --git a/packages/nrfconnect-appmodule-sample/js/components/__tests__/SimpleCounter-test.jsx b/packages/nrfconnect-appmodule-sample/js/components/__tests__/SimpleCounter-test.jsx new file mode 100644 index 00000000..2e678374 --- /dev/null +++ b/packages/nrfconnect-appmodule-sample/js/components/__tests__/SimpleCounter-test.jsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import SimpleCounter from '../SimpleCounter'; +import { Button } from 'react-bootstrap'; + +it('calls onIncrement when button is clicked', () => { + const onIncrementMock = jest.fn(); + const counterValue = 0; + const wrapper = mount(); + + wrapper.find(Button).simulate('click'); + + expect(onIncrementMock).toBeCalled(); +}); diff --git a/packages/nrfconnect-appmodule-sample/js/containers/App.jsx b/packages/nrfconnect-appmodule-sample/js/containers/App.jsx new file mode 100644 index 00000000..f29ea2a9 --- /dev/null +++ b/packages/nrfconnect-appmodule-sample/js/containers/App.jsx @@ -0,0 +1,55 @@ +/* Copyright (c) 2016 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +import 'nrfconnect-core/css/styles.less'; + +import React, { PropTypes } from 'react'; +import { connect } from 'react-redux'; +import * as AppActions from '../actions/appActions'; +import SimpleCounter from '../components/SimpleCounter'; + +class AppContainer extends React.PureComponent { + + constructor(props) { + super(props); + } + + render() { + return ( +
+

Sample Application

+ +
+ ); + } +} + +function mapStateToProps(state) { + const { app } = state; + return { + countValue: app.countValue + }; +} + +function mapDispatchToProps(dispatch) { + return { + incrementCounter: () => dispatch(AppActions.incrementCounterAction()) + }; +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(AppContainer); diff --git a/packages/nrfconnect-appmodule-sample/js/containers/Root.jsx b/packages/nrfconnect-appmodule-sample/js/containers/Root.jsx new file mode 100644 index 00000000..a1f9c8d3 --- /dev/null +++ b/packages/nrfconnect-appmodule-sample/js/containers/Root.jsx @@ -0,0 +1,30 @@ +/* Copyright (c) 2016 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +import React, { PropTypes } from 'react'; +import { Provider } from 'react-redux'; +import App from './App'; + +export default class Root extends React.PureComponent { + render() { + const { store } = this.props; + return ( + + + + ); + } +} + +Root.propTypes = { + store: PropTypes.object.isRequired +}; diff --git a/packages/nrfconnect-appmodule-sample/js/index.js b/packages/nrfconnect-appmodule-sample/js/index.js new file mode 100644 index 00000000..dfb7d3f2 --- /dev/null +++ b/packages/nrfconnect-appmodule-sample/js/index.js @@ -0,0 +1,38 @@ +/* Copyright (c) 2016 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +require('babel-polyfill'); + +var React = require('react'); +var renderReact = require('react-dom').render; +var Root = require('./containers/Root'); + +var configureStore = require('nrfconnect-core').configureStore; +var rootReducer = require('./reducers'); +var initialState = window.__INITIAL_STATE__ || {}; +var store = configureStore(initialState, rootReducer); + +let App = require('./containers/Root'); +const render = (Component) => { + renderReact(, document.getElementById('app')); +}; +render(App); + +// Webpack hot module replacement (HMR) +if (module.hot) { + module.hot.accept('./reducers', () => + store.replaceReducer(require('./reducers')) + ); + module.hot.accept('./containers/Root', function() { + render(require('./containers/Root')); + }); +} diff --git a/packages/nrfconnect-appmodule-sample/js/reducers/appReducer.js b/packages/nrfconnect-appmodule-sample/js/reducers/appReducer.js new file mode 100644 index 00000000..350ac047 --- /dev/null +++ b/packages/nrfconnect-appmodule-sample/js/reducers/appReducer.js @@ -0,0 +1,32 @@ +/* Copyright (c) 2016 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +'use strict'; + +import { Record, List } from 'immutable'; + +import * as AppActions from '../actions/appActions'; + +const InitialState = Record({ + countValue: 0 +}); + +const initialState = new InitialState(); + +export default function (state = initialState, action) { + switch (action.type) { + case AppActions.INCREMENT_COUNTER: + return state.update('countValue', value => value + 1); + default: + return state; + } +} diff --git a/packages/nrfconnect-appmodule-sample/js/reducers/index.js b/packages/nrfconnect-appmodule-sample/js/reducers/index.js new file mode 100644 index 00000000..324c5ab6 --- /dev/null +++ b/packages/nrfconnect-appmodule-sample/js/reducers/index.js @@ -0,0 +1,21 @@ +/* Copyright (c) 2016 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +import { combineReducers } from 'redux'; + +import app from './appReducer'; + +const rootReducer = combineReducers({ + app +}); + +export default rootReducer; diff --git a/packages/nrfconnect-appmodule-sample/package.json b/packages/nrfconnect-appmodule-sample/package.json new file mode 100644 index 00000000..1180448d --- /dev/null +++ b/packages/nrfconnect-appmodule-sample/package.json @@ -0,0 +1,44 @@ +{ + "name": "nrfconnect-appmodule-sample", + "version": "0.0.1", + "description": "Sample appmodule for nRF Connect", + "homepage": "http://infocenter.nordicsemi.com/nrf-connect/sample", + "main": "index.js", + "author": "Nordic Semiconductor ASA", + "license": "Proprietary", + "scripts": { + "start": "../../node_modules/.bin/concurrently -k \"node ../../server.js\" \"../../node_modules/.bin/cross-env NODE_ENV=development ../../node_modules/.bin/electron .\"", + "build": "../../node_modules/.bin/webpack --config ../../webpack.config.production.js", + "test": "../../node_modules/.bin/cross-env BABEL_DISABLE_CACHE=1 ../../node_modules/.bin/jest js/", + "clean": "../../node_modules/.bin/rimraf node_modules" + }, + "config": { + "title": "Sample", + "icon": "resources/icon.png" + }, + "devDependencies": { + "enzyme": "2.4.1", + "react-addons-test-utils": "15.3.1", + "react-test-renderer": "15.3.1", + "redux-devtools": "3.3.1", + "redux-devtools-dock-monitor": "1.1.1", + "redux-devtools-log-monitor": "1.0.11" + }, + "dependencies": { + "babel-polyfill": "6.13.0", + "nrfconnect-core": "1.0.0", + "react": "15.3.2", + "react-bootstrap": "0.30.3", + "react-dom": "15.3.1", + "react-redux": "4.4.5", + "redux": "3.6.0" + }, + "jest": { + "testRegex": "(/__tests__/.*|\\.(test|spec))\\.jsx?$", + "moduleFileExtensions": [ + "js", + "jsx", + "json" + ] + } +} diff --git a/packages/nrfconnect-appmodule-sample/resources/icon.png b/packages/nrfconnect-appmodule-sample/resources/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a96283037ebb134e3aa38e8ac1f0feba5878c0a6 GIT binary patch literal 1435 zcmV;M1!Ve(P)VGd000McNliru;0X>4Hw>rru^RvY1t>{G zK~!ko)ml$XT6Y}(_;5&&2TYl;;sc$a@x@Y;E@m@p=QNoIyR_?JU9xpa)9v7?^Wt$=Rkjy1^UALIUtckS^2GJ=39ayCgK_*Pt4(oe+@ZN(5h=cEm z_lL*l^ZS0je|}$H19+CrWQPD;0&oVkX}17O6AI!kd!m5{-UZ-e)Q5dWD2NG;KtA}y zN(B3fy_!PYs8K;zJ9 zg9m`vVgRdG@9&W*!8P-YQQ4heAMUAYnZ}2(sJ6Pk{gceZLh}06U%#g5Ugx zU07?~$I#vDzW9^yzol z@q|kHj+QpdCQ-43IzJkMy2AiyREL1hL80Tq2`F1MqSsX>Jya$=bbalJJqlv=$}E8y_ZizX&@0>6i=CX zJq`dsV>3c&AP<&+(m>{SgtAOyGr~SGDtSG<6-PRn5C-)z>R<`jCq^Z~r=tll3x4c) zLZV>Q?Jbfdlm=3kM=Oc}%lm_ZU}bH`6N1<2&H>bU@g%ggIp;pI+XSV76v)W@_VKb} zktjtv&mZp)?@hu?4tQ1)UZ-2&35B`|)VTo>iM17N+$thqJwGVv;@`jcN%DKijcws# z1d+p9;H$4>XY3j(QC|tAG^K?>=UCPl#N)scCTn-MyQ_4IX1r8C!2g( z9_YMyQZ#VW(FFY0=eSL`mNuhr>MZONqg?t+JrU0?{6Z+zYOv3)$OFxGqaYCf3*5)t zYO|}VP&Yx}Z-v^@il_J2v2kM#;qM>jbfek5zc|lo=_8U!K~9TZl)#Zw{gQ#Z_W50D z*|liU^a9BRw9hreWu|O;zhGQtk}0fRyLT{YRBdS$Js%yuoo%OJKwdtpY1aYypFY8&`HrfwrTzbc3cDUVh%lPwwp+jBm_PDx`k;;8c-(QRR3C4!Bw zf5qyRStt!8sB;5QTUrG{n+!&gT;D2KOXOHXHk17u0Q_J5BDsC*nH-a>#!|N93CZe< z${mhbKX^@k5PO~OvL*|?pS)G|p_%L~38SBCeItRt?3~mtsrujWiEt6npvOJrv p|5pvTJ#9U|?7<^3ggSfO<{!Q-Cb_HhYt{e&002ovPDHLkV1gs>p{f7? literal 0 HcmV?d00001 diff --git a/packages/nrfconnect-loader/package.json b/packages/nrfconnect-loader/package.json index 888e867e..fd46ff26 100644 --- a/packages/nrfconnect-loader/package.json +++ b/packages/nrfconnect-loader/package.json @@ -34,6 +34,7 @@ "moment": "2.14.1", "nrfconnect-core": "1.0.0", "nrfconnect-appmodule-ble": "1.0.0", + "nrfconnect-appmodule-sample": "0.0.1", "open": "0.0.5", "react": "15.3.2", "react-addons-linked-state-mixin": "15.3.1", @@ -57,7 +58,8 @@ "winston": "2.2.0" }, "appmodules": [ - "nrfconnect-appmodule-ble" + "nrfconnect-appmodule-ble", + "nrfconnect-appmodule-sample" ], "jest": { "testRegex": "(/__tests__/.*|\\.(test|spec))\\.jsx?$", From 5b5ffb3cf2d2d2830a54cac25c96ab7683e3b995 Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Wed, 28 Sep 2016 11:18:18 +0200 Subject: [PATCH 11/17] Skip loader if there is only one appmodule --- packages/nrfconnect-loader/index.js | 4 +++- packages/nrfconnect-loader/js/containers/App.jsx | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/nrfconnect-loader/index.js b/packages/nrfconnect-loader/index.js index ca6cc4c3..b8283067 100644 --- a/packages/nrfconnect-loader/index.js +++ b/packages/nrfconnect-loader/index.js @@ -24,7 +24,9 @@ var ipcMain = electron.ipcMain; ipcMain.on('load-appmodule', function (event, name) { require(name); - loaderWindow.close(); + if (loaderWindow) { + loaderWindow.close(); + } }); app.on('ready', function () { diff --git a/packages/nrfconnect-loader/js/containers/App.jsx b/packages/nrfconnect-loader/js/containers/App.jsx index 8d75e3aa..829624d0 100644 --- a/packages/nrfconnect-loader/js/containers/App.jsx +++ b/packages/nrfconnect-loader/js/containers/App.jsx @@ -38,11 +38,18 @@ class AppContainer extends React.PureComponent { } render() { + const { appmodules, onAppmoduleSelected } = this.props; + + if (appmodules.size === 1) { + loadAppmodule(appmodules.first().name); + return null; + } + return (
@@ -50,6 +57,10 @@ class AppContainer extends React.PureComponent { } } +function loadAppmodule(name) { + ipcRenderer.send('load-appmodule', name); +} + function mapStateToProps(state) { const { app } = state; From 7c3fd485f4e8904e1878815d42dde0ffe365747e Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Thu, 29 Sep 2016 16:32:27 +0200 Subject: [PATCH 12/17] Add info about testing and appmodules in README --- README.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a0262c6d..6d712d25 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,26 @@ The application needs to be able to load nrfjprog libraries. This is currently n tar xf nrfjprog/nRF5x-Command-Line-Tools_8_5_0_Linux-x86_64.tar --strip-components=2 -C node_modules/electron-prebuilt/dist +## Working with appmodules + +This project is split into multiple [appmodules](doc/README.md) inside the `packages` directory. When running `npm start` from the root directory, the appmodule loader will be started. When choosing an appmodule, a *pre-built version* of that appmodule will be loaded. If you modify the code, it will not have any effect unless you `npm run build` the appmodule and restart the application. + +When working with appmodules it is normally recommended to navigate to the appmodule directory before running `npm start`. When doing this, the application will hot-reload any changes that are made to the code, providing instant feedback during development. + + cd packages/nrfconnect-appmodule-ble + npm start + +## Testing + +Unit testing of all packages can be performed by running: + + npm test + +Testing of individual packages can be done by navigating to the package directory before running `npm test`: + + cd packages/nrfconnect-appmodule-ble + npm test + ## Creating release packages Scripts have been included in the reop to create release packages. Different artifacts will be created depending on the type of operating system: @@ -75,7 +95,7 @@ The build scripts will set the required environment variables, build nRF Connect Since the build scripts delete the cache folder *node_modules* and reinstalls in production mode it can be a good idea to run the scripts from a separate repository clone folder. ## Color definitions -The main colors used in nRF Connect are defined in the file css/brand.less. The colors defined in the source code base have been modified from the colors used in the official release builds of nRF Connect. This has been done to differentiate the Nordic releases from other source code builds. Please feel free to modify the color definitions to your own liking. +The main colors used in nRF Connect are defined in the file [packages/nrfconnect-core/css/brand.less](packages/nrfconnect-core/css/brand.less). The colors defined in the source code base have been modified from the colors used in the official release builds of nRF Connect. This has been done to differentiate the Nordic releases from other source code builds. Please feel free to modify the color definitions to your own liking. # Related projects nRF Connect builds on top of other sub components that live in their own GitHub repositories: From f8a8d8bc95a0a1ce90d9b51c4a29f383ad103154 Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Tue, 13 Sep 2016 16:05:07 +0200 Subject: [PATCH 13/17] Document appmodule configuration and development --- doc/README.md | 187 ++++++++++++++++++++++++++++++++++++++ doc/nrfconnect-loader.png | Bin 0 -> 26824 bytes 2 files changed, 187 insertions(+) create mode 100644 doc/README.md create mode 100644 doc/nrfconnect-loader.png diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 00000000..bb822b63 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,187 @@ +# nRF Connect Documentation + +## Application Modules (appmodules) + +nRF Connect is modularized into application modules (appmodules). Each +appmodule provides a certain set of features. The appmodules are developed +independently, but may share some common components and resources from the core +module located in `packages/nrfconnect-core`. + +### Loader + +When starting the application, the users will be able to choose which appmodule +they want to load. + +![Loader](nrfconnect-loader.png) + +The appmodule loader is located in `packages/nrfconnect-loader`. The +`package.json` in this directory has dependencies to all appmodules that should be +used by the application. The loader will only display appmodules that are +defined in the `appmodules` field in `package.json`, f.ex: + +``` +"appmodules": [ + "nrfconnect-appmodule-ble", + "nrfconnect-appmodule-sample" +] +``` + +If only one appmodule is defined here, then the loader UI will be skipped, and +the appmodule will be loaded immediately. + +### Configuration + +The appmodules are located in the `packages` directory. Each appmodule has its own +directory containing code and resources, plus a `package.json` where +metadata for the appmodule can be configured. + +Example: + +``` +{ + "name": "nrfconnect-appmodule-ble", + "version": "1.0.0", + "description": "A natural first choice for BLE development", + "homepage": "http://infocenter.nordicsemi.com/nrf-connect/ble", + "main": "index.js", + "author": "Nordic Semiconductor ASA", + "config": { + "title": "Bluetooth Low Energy (BLE)", + "icon": "resources/icon.png" + }, + scripts: { + ... + }, + dependencies: { + ... + } +} +``` + +Fields that are relevant for the nRF Connect application: + +| Field | Required | Description | +| --- | --- | --- | +| `name` | Yes | The name of the appmodule. This name is used to reference the appmodule as a dependency in the main `package.json` file of the application. | +| `version` | Yes | The version of the appmodule. | +| `description` | Yes | The appmodule description. This is displayed in the loader UI. | +| `main` | Yes | The entrypoint of the appmodule. This file should contain code that is run by the Electron main process, which sets up events and initializes the browser window. This is invoked by the loader. | +| `homepage` | No | An URL that contains more information about the appmodule. Currently not in use, but in the future it may be used as a link in the loader UI, and the appmodule's "help" menu. | +| `author` | No | The author of the appmodule. Currently not in use, but in the future it may be displayed in the loader UI, and the appmodule's "about" menu. | +| `config.title` | Yes | The appmodule title. Will be displayed as name of the appmodule in the loader UI. | +| `config.icon` | Yes | Path to an image that will be used as an icon in the loader UI. | + +### Sample appmodule + +When developing a new appmodule, it is recommended to use +[packages/nrfconnect-appmodule-sample](packages/nrfconnect-appmodule-sample) +as a starting point. You can fork this repository and create a copy of +the sample appmodule inside `packages`. + +``` +cp -a packages/nrfconnect-appmodule-sample packages/nrfconnect-appmodule- +``` + +Then edit the relevant fields (author, title, icon, etc.) in `package.json`. +You can then start developing your own components, reducers, and actions +in the `js` directory. Unit testing with jest is enabled, and there is +an example test in the `components` directory. + +You can start the appmodule by running `npm start` in the appmodule directory. +You can also test how the appmodule looks in the loader UI. In that case, +add your appmodule as a dependency in `nrfconnect-loader/package.json` and +add it to the `appmodules` array in the same file. Go to the root of the +project and run `npm run bootstrap` so that the loader and appmodule are +linked. Then run `npm start` in the `nrfconnect-loader` directory. + +### Create appmodule from scratch + +If you want to create an appmodule from scratch, you can create a separate Git +repository and add `nrfconnect-core` as a dependency. You can use +whatever libraries and development tools you desire as long as you +remember the following: +- Your `package.json` must contain the required fields as described in the [configuration section](#configuration). +- The appmodule should follow the naming convention `nrfconnect-appmodule-`. + +The file you specify as `main` in `package.json` is loaded by the appmodule +loader. The code in this file is run by the Electron main process. This code +should create the browser window and load an html file, which finally loads +your JavaScript app. The `nrfconnect-core` module contains a +`createBrowserWindow` function that simplifies this, described in the section +below. + +#### createBrowserWindow + +With `createBrowserWindow` you can easily initialize the Electron browser +window for use with nRF Connect. The behavior of this function can be +configured by passing in a set of options: + +| Option | Required | Default value | Description | +| --- | --- | --- | --- | +| `url` | Yes | - | Path to the html file that should be loaded in the browser window. | +| `title` | No | nRF Connect vX | The title that should be visible in the window title bar. | +| `keepWindowSettings` | No | `true` | If `true`, the window size and maximized status is kept and reused next time the window is opened. | +| *standard Electron option* | - | - | Any standard option from the [Electron BrowserWindow API](https://github.com/electron/electron/blob/master/docs/api/browser-window.md) | + +Example usage: + +``` +var electron = require('electron'); +var core = require('nrfconnect-core/index'); + +if (electron.app.isReady()) { + initBrowserWindow(); +} else { + electron.app.on('ready', function () { + initBrowserWindow(); + }); +} + +function initBrowserWindow() { + core.createBrowserWindow({ + title: 'My nRF Connect appmodule', + url: 'file://' + __dirname + '/index.html', + icon: __dirname + '/resources/icon.png' + }); +} +``` + +If the application is already ready, f.ex. if the appmodule is being loaded from +the nRF Connect loader, we load the browser window immediately. If not, +we wait until the application is ready before loading the window. This allows +us to support loading the appmodule either through the loader or as a +standalone application. + +You can also reuse metadata from your `package.json` when creating the browser +window. Simply require it, and supply the relevant values: + +``` +var packageJson = require('./package.json'); + +core.createBrowserWindow({ + title: packageJson.config.title, + url: 'file://' + __dirname + '/index.html', + icon: __dirname + '/' + packageJson.config.icon +}); +``` + +The `createBrowserWindow` function returns the browser window instance. Refer +to the [Electron BrowserWindow API](https://github.com/electron/electron/blob/master/docs/api/browser-window.md) +to see available events, functions, and properties for this instance. Events can +f.ex. be configured like this: + +``` +var browserWindow = core.createBrowserWindow({...}); + +browserWindow.webContents.on('new-window', function (e, url) { + e.preventDefault(); + shell.openExternal(url); +}); +``` + +### Remaining work + +The following work is planned, but not completed yet: +- Ability to go back to the loader after having selected an appmodule. +- Mechanism for remembering which appmodule the user has selected, so that it can be loaded by default the next time the application starts. +- Online update mechanism for appmodules. diff --git a/doc/nrfconnect-loader.png b/doc/nrfconnect-loader.png new file mode 100644 index 0000000000000000000000000000000000000000..269c72611126479fcf0ba64cd62a307b917d454e GIT binary patch literal 26824 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 literal 0 HcmV?d00001 From c06318ae80b03d0020218b3e901421d2f9102b3e Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Wed, 5 Oct 2016 08:55:17 +0200 Subject: [PATCH 14/17] Bump to latest lerna version for improved Windows support --- lerna.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lerna.json b/lerna.json index b1f53c34..ce9aa5f6 100644 --- a/lerna.json +++ b/lerna.json @@ -1,4 +1,4 @@ { - "lerna": "2.0.0-beta.28", + "lerna": "2.0.0-beta.30", "version": "0.0.0" } diff --git a/package.json b/package.json index cd36bc0b..28d64df8 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "install": "0.8.1", "jest": "15.1.1", "json-loader": "0.5.4", - "lerna": "2.0.0-beta.28", + "lerna": "2.0.0-beta.30", "lerna-run": "0.0.2", "less": "^2.7.1", "less-loader": "2.2.3", From c93fd73a0842802de856866f7c326bdc1bc015c7 Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Wed, 5 Oct 2016 14:26:10 +0200 Subject: [PATCH 15/17] Add spinner component --- .../js/components/ConfirmationDialog.jsx | 8 ++---- .../js/components/EnumeratingAttributes.jsx | 4 +-- .../js/containers/DiscoveredDevices.js | 9 ++----- .../nrfconnect-core/js/components/Spinner.jsx | 27 +++++++++++++++++++ packages/nrfconnect-core/js/index.js | 1 + 5 files changed, 34 insertions(+), 15 deletions(-) create mode 100644 packages/nrfconnect-core/js/components/Spinner.jsx diff --git a/packages/nrfconnect-appmodule-ble/js/components/ConfirmationDialog.jsx b/packages/nrfconnect-appmodule-ble/js/components/ConfirmationDialog.jsx index 4c0eba75..c0aaf93b 100644 --- a/packages/nrfconnect-appmodule-ble/js/components/ConfirmationDialog.jsx +++ b/packages/nrfconnect-appmodule-ble/js/components/ConfirmationDialog.jsx @@ -16,7 +16,7 @@ import React from 'react'; import {Modal} from 'react-bootstrap'; import {Button} from 'react-bootstrap'; -import spinnerImage from 'nrfconnect-core/resources/ajax-loader.gif'; +import {Spinner} from 'nrfconnect-core'; var ConfirmationDialog = React.createClass({ getInitialState() { @@ -27,10 +27,6 @@ var ConfirmationDialog = React.createClass({ }, render() { - const progressStyle = { - visibility: this.props.showProgress ? 'visible' : 'hidden', - }; - const buttonDisabled = this.props.showProgress; const backDrop = this.props.showProgress ? 'static' : false; @@ -44,7 +40,7 @@ var ConfirmationDialog = React.createClass({

{this.props.text}

- +   diff --git a/packages/nrfconnect-appmodule-ble/js/components/EnumeratingAttributes.jsx b/packages/nrfconnect-appmodule-ble/js/components/EnumeratingAttributes.jsx index 8efb44e1..595d68af 100644 --- a/packages/nrfconnect-appmodule-ble/js/components/EnumeratingAttributes.jsx +++ b/packages/nrfconnect-appmodule-ble/js/components/EnumeratingAttributes.jsx @@ -14,7 +14,7 @@ import React from 'react'; -import spinnerImage from 'nrfconnect-core/resources/ajax-loader.gif'; +import { Spinner } from 'nrfconnect-core'; export default class EnumeratingAttributes extends React.PureComponent { render() { @@ -28,7 +28,7 @@ export default class EnumeratingAttributes extends React.PureComponent {
{barList}
- +
); diff --git a/packages/nrfconnect-appmodule-ble/js/containers/DiscoveredDevices.js b/packages/nrfconnect-appmodule-ble/js/containers/DiscoveredDevices.js index d600bc48..9fe7429c 100644 --- a/packages/nrfconnect-appmodule-ble/js/containers/DiscoveredDevices.js +++ b/packages/nrfconnect-appmodule-ble/js/containers/DiscoveredDevices.js @@ -21,9 +21,8 @@ import * as AdapterActions from '../actions/adapterActions'; import DiscoveryButton from '../components/discoveryButton'; import DiscoveredDevice from '../components/DiscoveredDevice'; -import { TextInput } from 'nrfconnect-core'; +import { TextInput, Spinner } from 'nrfconnect-core'; import { FormGroup, Checkbox } from 'react-bootstrap'; -import spinnerImage from 'nrfconnect-core/resources/ajax-loader.gif'; class DiscoveredDevices extends React.PureComponent { constructor(props) { @@ -65,10 +64,6 @@ class DiscoveredDevices extends React.PureComponent { this.discoveryOptions = this.props.discoveryOptions.toJS(); - const progressStyle = { - visibility: isScanning ? 'visible' : 'hidden', - }; - const dirIcon = discoveryOptions.expanded ? 'icon-down-dir' : 'icon-right-dir'; const discoveryOptionsDiv = discoveryOptions.expanded ? @@ -88,7 +83,7 @@ class DiscoveredDevices extends React.PureComponent {

Discovered devices - +

diff --git a/packages/nrfconnect-core/js/components/Spinner.jsx b/packages/nrfconnect-core/js/components/Spinner.jsx new file mode 100644 index 00000000..c788217a --- /dev/null +++ b/packages/nrfconnect-core/js/components/Spinner.jsx @@ -0,0 +1,27 @@ +import React, { PropTypes } from 'react'; +import spinnerImage from '../../resources/ajax-loader.gif'; + +export default class Spinner extends React.PureComponent { + static propTypes = { + size: PropTypes.number, + visible: PropTypes.bool, + className: PropTypes.string + }; + + static defaultProps = { + size: 16, + visible: false, + className: 'spinner' + }; + + render() { + const { size, visible, className } = this.props; + const style = { + visibility: visible ? 'visible' : 'hidden' + }; + + return ( + + ); + } +} diff --git a/packages/nrfconnect-core/js/index.js b/packages/nrfconnect-core/js/index.js index a9b645e5..6ca362bc 100644 --- a/packages/nrfconnect-core/js/index.js +++ b/packages/nrfconnect-core/js/index.js @@ -3,6 +3,7 @@ const actions = { }; const components = { + Spinner: require('./components/Spinner'), LabeledInputGroup: require('./components/input/LabeledInputGroup'), SelectList: require('./components/input/SelectList'), TextArea: require('./components/input/TextArea'), From bd1b13f64b34b47f219f89d54657cccdb6dafad3 Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Wed, 5 Oct 2016 14:34:36 +0200 Subject: [PATCH 16/17] Change from var to let in index.js files --- packages/nrfconnect-appmodule-ble/index.js | 12 +++++------ packages/nrfconnect-appmodule-sample/index.js | 4 ++-- packages/nrfconnect-core/index.js | 20 +++++++++---------- packages/nrfconnect-loader/index.js | 12 +++++------ 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/packages/nrfconnect-appmodule-ble/index.js b/packages/nrfconnect-appmodule-ble/index.js index 467ece53..1f423ef1 100644 --- a/packages/nrfconnect-appmodule-ble/index.js +++ b/packages/nrfconnect-appmodule-ble/index.js @@ -12,11 +12,11 @@ 'use strict'; -var electron = require('electron'); -var ipcMain = electron.ipcMain; -var dialog = electron.dialog; -var shell = electron.shell; -var core = require('nrfconnect-core/index'); +let electron = require('electron'); +let ipcMain = electron.ipcMain; +let dialog = electron.dialog; +let shell = electron.shell; +let core = require('nrfconnect-core/index'); if (electron.app.isReady()) { initBrowserWindow(); @@ -41,7 +41,7 @@ function initBrowserWindow() { }); } -var filters = [ +let filters = [ { name: 'nRF Connect Server Setup', extensions: ['ncs', 'json'] }, { name: 'All Files', extensions: ['*'] }, ]; diff --git a/packages/nrfconnect-appmodule-sample/index.js b/packages/nrfconnect-appmodule-sample/index.js index 5ede3a53..8d0ec532 100644 --- a/packages/nrfconnect-appmodule-sample/index.js +++ b/packages/nrfconnect-appmodule-sample/index.js @@ -10,8 +10,8 @@ * */ -var electron = require('electron'); -var core = require('nrfconnect-core/index'); +let electron = require('electron'); +let core = require('nrfconnect-core/index'); // Support both immediate and delayed initialization if (electron.app.isReady()) { diff --git a/packages/nrfconnect-core/index.js b/packages/nrfconnect-core/index.js index ae1199de..91da8d98 100644 --- a/packages/nrfconnect-core/index.js +++ b/packages/nrfconnect-core/index.js @@ -14,11 +14,11 @@ const VERSION = '1.0'; -var os = require('os'); -var fs = require('fs'); -var electron = require('electron'); -var app = electron.app; -var settings = require('./settings'); +let os = require('os'); +let fs = require('fs'); +let electron = require('electron'); +let app = electron.app; +let settings = require('./settings'); global.keymap = app.getPath('userData') + '/keymap.cson'; global.userDataDir = app.getPath('userData'); @@ -44,7 +44,7 @@ function createBrowserWindow(options) { minHeight: 499, show: false }, options); - var browserWindow = new electron.BrowserWindow(mergedOptions); + let browserWindow = new electron.BrowserWindow(mergedOptions); browserWindow.loadURL(options.url); @@ -67,7 +67,7 @@ function createBrowserWindow(options) { _createDefaultMenu(); } - var title = 'nRF Connect v' + VERSION; + let title = 'nRF Connect v' + VERSION; if (options.title) { title += ' - ' + options.title; } @@ -79,7 +79,7 @@ function createBrowserWindow(options) { } function _createDefaultMenu() { - var template = [ + let template = [ { label: '&File', submenu: [ @@ -150,8 +150,8 @@ function _createDefaultMenu() { }); } - var Menu = electron.Menu; - var menu = Menu.buildFromTemplate(template); + let Menu = electron.Menu; + let menu = Menu.buildFromTemplate(template); Menu.setApplicationMenu(menu); } diff --git a/packages/nrfconnect-loader/index.js b/packages/nrfconnect-loader/index.js index b8283067..8420ac7d 100644 --- a/packages/nrfconnect-loader/index.js +++ b/packages/nrfconnect-loader/index.js @@ -12,15 +12,15 @@ 'use strict'; -var electron = require('electron'); -var app = electron.app; -var BrowserWindow = electron.BrowserWindow; +let electron = require('electron'); +let app = electron.app; +let BrowserWindow = electron.BrowserWindow; require('nrfconnect-core/index'); -var splashScreen = null; -var loaderWindow = null; +let splashScreen = null; +let loaderWindow = null; -var ipcMain = electron.ipcMain; +let ipcMain = electron.ipcMain; ipcMain.on('load-appmodule', function (event, name) { require(name); From 5aeef44113ecf5aa3c462fff19a8e6868857fcd1 Mon Sep 17 00:00:00 2001 From: Magne Rodem Date: Wed, 5 Oct 2016 14:36:51 +0200 Subject: [PATCH 17/17] Use correct component name in SelectList --- packages/nrfconnect-core/js/components/input/SelectList.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nrfconnect-core/js/components/input/SelectList.jsx b/packages/nrfconnect-core/js/components/input/SelectList.jsx index 0b6025be..51d5eb12 100644 --- a/packages/nrfconnect-core/js/components/input/SelectList.jsx +++ b/packages/nrfconnect-core/js/components/input/SelectList.jsx @@ -1,7 +1,7 @@ import React, { PropTypes } from 'react'; import { FormGroup, ControlLabel, FormControl, InputGroup } from 'react-bootstrap'; -class TextInput extends React.PureComponent { +class SelectList extends React.PureComponent { static propTypes = { id: PropTypes.string, label: PropTypes.string.isRequired, @@ -32,4 +32,4 @@ class TextInput extends React.PureComponent { } } -export default TextInput; +export default SelectList;