@nordicsemiconductor/pc-nrfconnect-shared 60.0.0-pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/custom.md +10 -0
- package/.husky/pre-push +3 -0
- package/.renovaterc.json +10 -0
- package/Changelog.md +2973 -0
- package/LICENSE +35 -0
- package/README.md +11 -0
- package/azure-pipelines.yml +34 -0
- package/config/eslintrc.js +190 -0
- package/config/jest.config.js +41 -0
- package/config/prettier.config.js +13 -0
- package/config/tsconfig.json +15 -0
- package/fw/bootloader/graviton_bootloader_v1.0.1-[nRF5_SDK_15.0.1-1.alpha_f76d012].zip +0 -0
- package/jest.config.js +7 -0
- package/main/index.ts +32 -0
- package/mocks/deviceLibMock.ts +21 -0
- package/mocks/electronMock.ts +15 -0
- package/mocks/electronStoreMock.ts +19 -0
- package/mocks/emptyMock.ts +7 -0
- package/mocks/fileMock.ts +13 -0
- package/mocks/gaMock.ts +9 -0
- package/mocks/mockTests.test.ts +15 -0
- package/mocks/packageJsonMock.ts +10 -0
- package/mocks/remoteMock.ts +17 -0
- package/package.json +132 -0
- package/scripts/check-app-properties.ts +197 -0
- package/scripts/check-for-typescript.ts +41 -0
- package/scripts/esbuild-bootstrap.js +15 -0
- package/scripts/esbuild-renderer.js +131 -0
- package/scripts/esbuild.js +57 -0
- package/scripts/installHusky.ts +17 -0
- package/scripts/nordic-publish.ts +485 -0
- package/scripts/nrfconnect-license.ts +277 -0
- package/scripts/prepare-shared-release.ts +122 -0
- package/scripts/release-shared.test.ts +132 -0
- package/scripts/release-shared.ts +207 -0
- package/src/About/About.tsx +25 -0
- package/src/About/AboutButton.tsx +28 -0
- package/src/About/ApplicationCard.tsx +83 -0
- package/src/About/DeviceCard.tsx +74 -0
- package/src/About/DocumentationCard.tsx +18 -0
- package/src/About/DocumentationSection.tsx +24 -0
- package/src/About/Section.tsx +21 -0
- package/src/About/ShortcutButton.tsx +41 -0
- package/src/About/SupportCard.tsx +97 -0
- package/src/About/about.scss +40 -0
- package/src/About/documentationSlice.ts +41 -0
- package/src/About/section.scss +15 -0
- package/src/About/shortcutSlice.ts +52 -0
- package/src/Alert/Alert.module.scss +29 -0
- package/src/Alert/Alert.tsx +37 -0
- package/src/App/App.test.tsx +47 -0
- package/src/App/App.tsx +227 -0
- package/src/App/ConnectedToStore.tsx +19 -0
- package/src/App/VisibilityBar.tsx +103 -0
- package/src/App/app.scss +83 -0
- package/src/App/appLayout.ts +95 -0
- package/src/App/shared.scss +49 -0
- package/src/App/visibility-bar.scss +55 -0
- package/src/Button/Button.tsx +66 -0
- package/src/Button/button.module.scss +154 -0
- package/src/Card/Card.tsx +26 -0
- package/src/Card/card.module.scss +28 -0
- package/src/Device/BrokenDeviceDialog/BrokenDeviceDialog.tsx +58 -0
- package/src/Device/BrokenDeviceDialog/broken-device-dialog.scss +18 -0
- package/src/Device/BrokenDeviceDialog/brokenDeviceDialogSlice.tsx +48 -0
- package/src/Device/DeviceSelector/BasicDeviceInfo.tsx +115 -0
- package/src/Device/DeviceSelector/DeviceIcon.tsx +27 -0
- package/src/Device/DeviceSelector/DeviceList/AnimatedList.tsx +62 -0
- package/src/Device/DeviceSelector/DeviceList/BrokenDevice.tsx +34 -0
- package/src/Device/DeviceSelector/DeviceList/Device.tsx +84 -0
- package/src/Device/DeviceSelector/DeviceList/DeviceList.tsx +113 -0
- package/src/Device/DeviceSelector/DeviceList/EditDeviceButtons.tsx +28 -0
- package/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.tsx +65 -0
- package/src/Device/DeviceSelector/DeviceList/RenameDevice.tsx +22 -0
- package/src/Device/DeviceSelector/DeviceList/broken-device.scss +32 -0
- package/src/Device/DeviceSelector/DeviceList/device-list.scss +64 -0
- package/src/Device/DeviceSelector/DeviceList/device.scss +28 -0
- package/src/Device/DeviceSelector/DeviceList/edit-device-buttons.scss +31 -0
- package/src/Device/DeviceSelector/DeviceList/more-device-info.scss +33 -0
- package/src/Device/DeviceSelector/DeviceList/rename-device.scss +13 -0
- package/src/Device/DeviceSelector/DeviceSelector.test.tsx +342 -0
- package/src/Device/DeviceSelector/DeviceSelector.tsx +173 -0
- package/src/Device/DeviceSelector/Favorite.tsx +49 -0
- package/src/Device/DeviceSelector/SelectDevice.tsx +36 -0
- package/src/Device/DeviceSelector/SelectedDevice.tsx +65 -0
- package/src/Device/DeviceSelector/arrow-down.svg +1 -0
- package/src/Device/DeviceSelector/basic-device-info.scss +62 -0
- package/src/Device/DeviceSelector/device-icon.scss +27 -0
- package/src/Device/DeviceSelector/favorite.scss +17 -0
- package/src/Device/DeviceSelector/select-device.scss +38 -0
- package/src/Device/DeviceSelector/selected-device.scss +57 -0
- package/src/Device/DeviceSetup/DeviceSetupView.tsx +102 -0
- package/src/Device/deviceAutoSelectSlice.ts +144 -0
- package/src/Device/deviceInfo/deviceInfo.ts +254 -0
- package/src/Device/deviceInfo/nRF51-Series-logo.svg +1 -0
- package/src/Device/deviceInfo/nRF52-Series-logo.svg +1 -0
- package/src/Device/deviceInfo/nRF53-Series-logo.svg +1 -0
- package/src/Device/deviceInfo/nRF70-Series_no-background_RGB.svg +36 -0
- package/src/Device/deviceInfo/nRF91-Series-logo.svg +1 -0
- package/src/Device/deviceInfo/ppk-logo.svg +1 -0
- package/src/Device/deviceInfo/unknown-logo.svg +30 -0
- package/src/Device/deviceInfo/unknown-nordic-logo.svg +25 -0
- package/src/Device/deviceLibWrapper.test.ts +97 -0
- package/src/Device/deviceLibWrapper.ts +133 -0
- package/src/Device/deviceLister.test.ts +89 -0
- package/src/Device/deviceLister.ts +396 -0
- package/src/Device/deviceSetup.ts +264 -0
- package/src/Device/deviceSetupSlice.ts +94 -0
- package/src/Device/deviceSlice.ts +248 -0
- package/src/Device/dfu-cc.ts +162 -0
- package/src/Device/initPacket.ts +402 -0
- package/src/Device/jprogOperations.ts +206 -0
- package/src/Device/sdfuOperations.ts +601 -0
- package/src/Dialog/Dialog.test.tsx +134 -0
- package/src/Dialog/Dialog.tsx +236 -0
- package/src/Dialog/dialog.scss +60 -0
- package/src/Dropdown/Dropdown.module.scss +83 -0
- package/src/Dropdown/Dropdown.test.tsx +62 -0
- package/src/Dropdown/Dropdown.tsx +106 -0
- package/src/ErrorBoundary/ErrorBoundary.test.tsx +105 -0
- package/src/ErrorBoundary/ErrorBoundary.tsx +186 -0
- package/src/ErrorBoundary/bug.svg +1 -0
- package/src/ErrorBoundary/error-boundary.scss +102 -0
- package/src/ErrorDialog/ErrorDialog.test.tsx +70 -0
- package/src/ErrorDialog/ErrorDialog.tsx +94 -0
- package/src/ErrorDialog/error.scss +14 -0
- package/src/ErrorDialog/errorDialogSlice.test.ts +64 -0
- package/src/ErrorDialog/errorDialogSlice.ts +80 -0
- package/src/FactoryReset/FactoryResetButton.test.tsx +46 -0
- package/src/FactoryReset/FactoryResetButton.tsx +81 -0
- package/src/InlineInput/InlineInput.tsx +170 -0
- package/src/InlineInput/NumberInlineInput.tsx +107 -0
- package/src/InlineInput/inline-input.scss +38 -0
- package/src/InlineInput/number-inline-input.scss +15 -0
- package/src/Log/LogEntry.tsx +62 -0
- package/src/Log/LogViewer.tsx +54 -0
- package/src/Log/log-entry.scss +30 -0
- package/src/Log/log-viewer.scss +24 -0
- package/src/Log/logSlice.ts +73 -0
- package/src/Log/syncLogToStore.ts +36 -0
- package/src/Logo/Logo.tsx +48 -0
- package/src/Logo/logo.scss +11 -0
- package/src/Logo/nordic-logo-blue-icon-only.png +0 -0
- package/src/Logo/nordic-logo-gray-icon-only.png +0 -0
- package/src/Logo/nordic-logo-white-icon-only.png +0 -0
- package/src/Main/Main.tsx +13 -0
- package/src/Main/main.scss +13 -0
- package/src/MasonryLayout/MasonryLayout.tsx +234 -0
- package/src/MasonryLayout/masonryLayout.module.scss +46 -0
- package/src/NavBar/NavBar.tsx +22 -0
- package/src/NavBar/NavMenu.test.tsx +41 -0
- package/src/NavBar/NavMenu.tsx +53 -0
- package/src/NavBar/NavMenuItem.tsx +41 -0
- package/src/NavBar/nav-bar.scss +26 -0
- package/src/NavBar/nav-menu-item.scss +34 -0
- package/src/OpenApp/openApp.ts +18 -0
- package/src/Panes/FeedbackPane.tsx +149 -0
- package/src/PseudoButton/PseudoButton.tsx +56 -0
- package/src/PseudoButton/pseudo-button.scss +11 -0
- package/src/SerialPort/ConflictingSettingsDialog.tsx +242 -0
- package/src/SerialPort/SerialPort.test.ts +54 -0
- package/src/SerialPort/SerialPort.ts +202 -0
- package/src/Shortcuts/Shortcut-item.scss +33 -0
- package/src/Shortcuts/Shortcut-modal.scss +20 -0
- package/src/Shortcuts/ShortcutItem.tsx +48 -0
- package/src/Shortcuts/ShortcutModal.tsx +67 -0
- package/src/SidePanel/Group.tsx +106 -0
- package/src/SidePanel/SidePanel.tsx +19 -0
- package/src/SidePanel/group.scss +42 -0
- package/src/SidePanel/sidepanel.scss +20 -0
- package/src/Slider/Bar.tsx +24 -0
- package/src/Slider/Factor.test.ts +48 -0
- package/src/Slider/Handle.tsx +121 -0
- package/src/Slider/Slider.test.tsx +25 -0
- package/src/Slider/Slider.tsx +91 -0
- package/src/Slider/Ticks.tsx +54 -0
- package/src/Slider/__snapshots__/Slider.test.tsx.snap +50 -0
- package/src/Slider/bar.scss +24 -0
- package/src/Slider/factor.ts +24 -0
- package/src/Slider/handle.scss +32 -0
- package/src/Slider/percentage.ts +67 -0
- package/src/Slider/range.ts +92 -0
- package/src/Slider/slider.scss +14 -0
- package/src/Slider/ticks.scss +28 -0
- package/src/Slider/variables.scss +16 -0
- package/src/StartStopButton/StartStopButton.tsx +60 -0
- package/src/StartStopButton/play-circle.svg +1 -0
- package/src/StartStopButton/start-stop-button.scss +47 -0
- package/src/StartStopButton/stop-circle.svg +1 -0
- package/src/StateSelector/StateSelector.tsx +64 -0
- package/src/StateSelector/state-selector.scss +38 -0
- package/src/Stepper/Stepper.tsx +139 -0
- package/src/Stepper/stepper.scss +127 -0
- package/src/Toggle/Toggle.tsx +120 -0
- package/src/Toggle/toggle.scss +109 -0
- package/src/bootstrap.scss +14 -0
- package/src/index.ts +146 -0
- package/src/logging/appTransport.test.ts +78 -0
- package/src/logging/appTransport.ts +41 -0
- package/src/logging/describeError.test.ts +38 -0
- package/src/logging/describeError.ts +56 -0
- package/src/logging/index.ts +103 -0
- package/src/logging/logBuffer.test.ts +41 -0
- package/src/logging/logBuffer.ts +24 -0
- package/src/logging/sendInitialLogMessages.ts +64 -0
- package/src/store.ts +60 -0
- package/src/svg.d.ts +15 -0
- package/src/utils/AppTypes.ts +60 -0
- package/src/utils/appDirs.ts +78 -0
- package/src/utils/bleChannels.ts +16 -0
- package/src/utils/classNames.test.ts +29 -0
- package/src/utils/classNames.ts +25 -0
- package/src/utils/colors.scss +46 -0
- package/src/utils/colors.ts +38 -0
- package/src/utils/describeVersion.ts +21 -0
- package/src/utils/environment.ts +6 -0
- package/src/utils/logLibVersions.ts +103 -0
- package/src/utils/open.ts +46 -0
- package/src/utils/packageJson.ts +60 -0
- package/src/utils/persistentStore.ts +144 -0
- package/src/utils/systemReport.ts +160 -0
- package/src/utils/truncateMiddle.test.ts +21 -0
- package/src/utils/truncateMiddle.ts +20 -0
- package/src/utils/usageData.ts +189 -0
- package/src/utils/useHotKey.ts +62 -0
- package/src/utils/useStopwatch.test.tsx +311 -0
- package/src/utils/useStopwatch.ts +140 -0
- package/src/variables.scss +820 -0
- package/styles.scss +88 -0
- package/test/dispatchTo.ts +23 -0
- package/test/index.ts +7 -0
- package/test/jestResolver.js +28 -0
- package/test/setupTests.ts +27 -0
- package/test/testUtil.ts +20 -0
- package/test/testrenderer.tsx +39 -0
- package/tsconfig.json +9 -0
- package/typings/externals.d.ts +31 -0
- package/typings/generated/main/index.d.ts +25 -0
- package/typings/generated/src/About/About.d.ts +4 -0
- package/typings/generated/src/About/AboutButton.d.ts +8 -0
- package/typings/generated/src/About/ApplicationCard.d.ts +3 -0
- package/typings/generated/src/About/DeviceCard.d.ts +3 -0
- package/typings/generated/src/About/DocumentationCard.d.ts +3 -0
- package/typings/generated/src/About/DocumentationSection.d.ts +9 -0
- package/typings/generated/src/About/Section.d.ts +8 -0
- package/typings/generated/src/About/ShortcutButton.d.ts +6 -0
- package/typings/generated/src/About/SupportCard.d.ts +3 -0
- package/typings/generated/src/About/documentationSlice.d.ts +12 -0
- package/typings/generated/src/About/shortcutSlice.d.ts +11 -0
- package/typings/generated/src/Alert/Alert.d.ts +10 -0
- package/typings/generated/src/App/App.d.ts +27 -0
- package/typings/generated/src/App/App.test.d.ts +1 -0
- package/typings/generated/src/App/ConnectedToStore.d.ts +7 -0
- package/typings/generated/src/App/VisibilityBar.d.ts +6 -0
- package/typings/generated/src/App/appLayout.d.ts +17 -0
- package/typings/generated/src/Button/Button.d.ts +13 -0
- package/typings/generated/src/Card/Card.d.ts +7 -0
- package/typings/generated/src/Device/BrokenDeviceDialog/BrokenDeviceDialog.d.ts +4 -0
- package/typings/generated/src/Device/BrokenDeviceDialog/brokenDeviceDialogSlice.d.ts +12 -0
- package/typings/generated/src/Device/DeviceSelector/BasicDeviceInfo.d.ts +11 -0
- package/typings/generated/src/Device/DeviceSelector/DeviceIcon.d.ts +7 -0
- package/typings/generated/src/Device/DeviceSelector/DeviceList/AnimatedList.d.ts +10 -0
- package/typings/generated/src/Device/DeviceSelector/DeviceList/BrokenDevice.d.ts +7 -0
- package/typings/generated/src/Device/DeviceSelector/DeviceList/Device.d.ts +10 -0
- package/typings/generated/src/Device/DeviceSelector/DeviceList/DeviceList.d.ts +10 -0
- package/typings/generated/src/Device/DeviceSelector/DeviceList/EditDeviceButtons.d.ts +9 -0
- package/typings/generated/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.d.ts +7 -0
- package/typings/generated/src/Device/DeviceSelector/DeviceList/RenameDevice.d.ts +6 -0
- package/typings/generated/src/Device/DeviceSelector/DeviceSelector.d.ts +20 -0
- package/typings/generated/src/Device/DeviceSelector/DeviceSelector.test.d.ts +1 -0
- package/typings/generated/src/Device/DeviceSelector/Favorite.d.ts +9 -0
- package/typings/generated/src/Device/DeviceSelector/SelectDevice.d.ts +8 -0
- package/typings/generated/src/Device/DeviceSelector/SelectedDevice.d.ts +7 -0
- package/typings/generated/src/Device/DeviceSetup/DeviceSetupView.d.ts +3 -0
- package/typings/generated/src/Device/deviceAutoSelectSlice.d.ts +28 -0
- package/typings/generated/src/Device/deviceInfo/deviceInfo.d.ts +18 -0
- package/typings/generated/src/Device/deviceLibWrapper.d.ts +8 -0
- package/typings/generated/src/Device/deviceLibWrapper.test.d.ts +1 -0
- package/typings/generated/src/Device/deviceLister.d.ts +25 -0
- package/typings/generated/src/Device/deviceLister.test.d.ts +2 -0
- package/typings/generated/src/Device/deviceSetup.d.ts +40 -0
- package/typings/generated/src/Device/deviceSetupSlice.d.ts +20 -0
- package/typings/generated/src/Device/deviceSlice.d.ts +30 -0
- package/typings/generated/src/Device/dfu-cc.d.ts +3 -0
- package/typings/generated/src/Device/initPacket.d.ts +109 -0
- package/typings/generated/src/Device/jprogOperations.d.ts +2 -0
- package/typings/generated/src/Device/sdfuOperations.d.ts +14 -0
- package/typings/generated/src/Dialog/Dialog.d.ts +64 -0
- package/typings/generated/src/Dialog/Dialog.test.d.ts +1 -0
- package/typings/generated/src/Dropdown/Dropdown.d.ts +16 -0
- package/typings/generated/src/Dropdown/Dropdown.test.d.ts +1 -0
- package/typings/generated/src/ErrorBoundary/ErrorBoundary.d.ts +26 -0
- package/typings/generated/src/ErrorBoundary/ErrorBoundary.test.d.ts +1 -0
- package/typings/generated/src/ErrorDialog/ErrorDialog.d.ts +4 -0
- package/typings/generated/src/ErrorDialog/ErrorDialog.test.d.ts +1 -0
- package/typings/generated/src/ErrorDialog/errorDialogSlice.d.ts +23 -0
- package/typings/generated/src/ErrorDialog/errorDialogSlice.test.d.ts +1 -0
- package/typings/generated/src/FactoryReset/FactoryResetButton.d.ts +12 -0
- package/typings/generated/src/FactoryReset/FactoryResetButton.test.d.ts +1 -0
- package/typings/generated/src/InlineInput/InlineInput.d.ts +14 -0
- package/typings/generated/src/InlineInput/NumberInlineInput.d.ts +12 -0
- package/typings/generated/src/Log/LogEntry.d.ts +7 -0
- package/typings/generated/src/Log/LogViewer.d.ts +5 -0
- package/typings/generated/src/Log/logSlice.d.ts +12 -0
- package/typings/generated/src/Log/syncLogToStore.d.ts +11 -0
- package/typings/generated/src/Logo/Logo.d.ts +6 -0
- package/typings/generated/src/Main/Main.d.ts +6 -0
- package/typings/generated/src/MasonryLayout/MasonryLayout.d.ts +14 -0
- package/typings/generated/src/NavBar/NavBar.d.ts +6 -0
- package/typings/generated/src/NavBar/NavMenu.d.ts +3 -0
- package/typings/generated/src/NavBar/NavMenu.test.d.ts +1 -0
- package/typings/generated/src/NavBar/NavMenuItem.d.ts +10 -0
- package/typings/generated/src/OpenApp/openApp.d.ts +7 -0
- package/typings/generated/src/Panes/FeedbackPane.d.ts +3 -0
- package/typings/generated/src/PseudoButton/PseudoButton.d.ts +10 -0
- package/typings/generated/src/SerialPort/ConflictingSettingsDialog.d.ts +13 -0
- package/typings/generated/src/SerialPort/SerialPort.d.ts +21 -0
- package/typings/generated/src/SerialPort/SerialPort.test.d.ts +1 -0
- package/typings/generated/src/Shortcuts/ShortcutItem.d.ts +8 -0
- package/typings/generated/src/Shortcuts/ShortcutModal.d.ts +8 -0
- package/typings/generated/src/SidePanel/Group.d.ts +16 -0
- package/typings/generated/src/SidePanel/SidePanel.d.ts +7 -0
- package/typings/generated/src/Slider/Bar.d.ts +7 -0
- package/typings/generated/src/Slider/Factor.test.d.ts +1 -0
- package/typings/generated/src/Slider/Handle.d.ts +13 -0
- package/typings/generated/src/Slider/Slider.d.ts +15 -0
- package/typings/generated/src/Slider/Slider.test.d.ts +1 -0
- package/typings/generated/src/Slider/Ticks.d.ts +12 -0
- package/typings/generated/src/Slider/factor.d.ts +1 -0
- package/typings/generated/src/Slider/percentage.d.ts +4 -0
- package/typings/generated/src/Slider/range.d.ts +13 -0
- package/typings/generated/src/StartStopButton/StartStopButton.d.ts +16 -0
- package/typings/generated/src/StateSelector/StateSelector.d.ts +15 -0
- package/typings/generated/src/Stepper/Stepper.d.ts +26 -0
- package/typings/generated/src/Toggle/Toggle.d.ts +19 -0
- package/typings/generated/src/index.d.ts +69 -0
- package/typings/generated/src/logging/appTransport.d.ts +12 -0
- package/typings/generated/src/logging/appTransport.test.d.ts +1 -0
- package/typings/generated/src/logging/describeError.d.ts +2 -0
- package/typings/generated/src/logging/describeError.test.d.ts +1 -0
- package/typings/generated/src/logging/index.d.ts +9 -0
- package/typings/generated/src/logging/logBuffer.d.ts +9 -0
- package/typings/generated/src/logging/logBuffer.test.d.ts +1 -0
- package/typings/generated/src/logging/sendInitialLogMessages.d.ts +2 -0
- package/typings/generated/src/store.d.ts +65 -0
- package/typings/generated/src/utils/AppTypes.d.ts +49 -0
- package/typings/generated/src/utils/appDirs.d.ts +35 -0
- package/typings/generated/src/utils/bleChannels.d.ts +6 -0
- package/typings/generated/src/utils/classNames.d.ts +17 -0
- package/typings/generated/src/utils/classNames.test.d.ts +1 -0
- package/typings/generated/src/utils/colors.d.ts +31 -0
- package/typings/generated/src/utils/describeVersion.d.ts +3 -0
- package/typings/generated/src/utils/environment.d.ts +1 -0
- package/typings/generated/src/utils/logLibVersions.d.ts +2 -0
- package/typings/generated/src/utils/open.d.ts +15 -0
- package/typings/generated/src/utils/packageJson.d.ts +4 -0
- package/typings/generated/src/utils/persistentStore.d.ts +35 -0
- package/typings/generated/src/utils/systemReport.d.ts +4 -0
- package/typings/generated/src/utils/truncateMiddle.d.ts +2 -0
- package/typings/generated/src/utils/truncateMiddle.test.d.ts +1 -0
- package/typings/generated/src/utils/usageData.d.ts +63 -0
- package/typings/generated/src/utils/useHotKey.d.ts +6 -0
- package/typings/generated/src/utils/useStopwatch.d.ts +22 -0
- package/typings/generated/src/utils/useStopwatch.test.d.ts +1 -0
- package/typings/generated/test/dispatchTo.d.ts +3 -0
- package/typings/generated/test/testrenderer.d.ts +5 -0
- package/typings/nrf-intel-hex.d.ts +58 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021 Nordic Semiconductor ASA
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
|
8
|
+
|
|
9
|
+
import type { RootState } from '../store';
|
|
10
|
+
|
|
11
|
+
const appendIfNew = (messages: ErrorMessage[], message: ErrorMessage) => {
|
|
12
|
+
const messageExists = messages.some(
|
|
13
|
+
existingMessage =>
|
|
14
|
+
existingMessage.message === message.message &&
|
|
15
|
+
existingMessage.detail === message.detail
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
return messageExists ? messages : [...messages, message];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export interface ErrorResolutions {
|
|
22
|
+
[key: string]: () => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ErrorMessage {
|
|
26
|
+
message: string;
|
|
27
|
+
detail?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ErrorDialog {
|
|
31
|
+
isVisible: boolean;
|
|
32
|
+
messages: ErrorMessage[];
|
|
33
|
+
errorResolutions?: ErrorResolutions;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const initialState: ErrorDialog = {
|
|
37
|
+
messages: [],
|
|
38
|
+
isVisible: false,
|
|
39
|
+
errorResolutions: undefined,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const slice = createSlice({
|
|
43
|
+
name: 'errorDialog',
|
|
44
|
+
initialState,
|
|
45
|
+
reducers: {
|
|
46
|
+
showDialog: {
|
|
47
|
+
prepare: (
|
|
48
|
+
message: string,
|
|
49
|
+
errorResolutions?: ErrorResolutions,
|
|
50
|
+
detail?: string
|
|
51
|
+
) => ({
|
|
52
|
+
payload: { message: { message, detail }, errorResolutions },
|
|
53
|
+
}),
|
|
54
|
+
reducer: (
|
|
55
|
+
state,
|
|
56
|
+
{
|
|
57
|
+
payload: error,
|
|
58
|
+
}: PayloadAction<{
|
|
59
|
+
message: ErrorMessage;
|
|
60
|
+
errorResolutions?: ErrorResolutions;
|
|
61
|
+
}>
|
|
62
|
+
) => {
|
|
63
|
+
state.isVisible = true;
|
|
64
|
+
state.errorResolutions = error.errorResolutions;
|
|
65
|
+
state.messages = appendIfNew(state.messages, error.message);
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
hideDialog: () => initialState,
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
export const {
|
|
73
|
+
reducer,
|
|
74
|
+
actions: { hideDialog, showDialog },
|
|
75
|
+
} = slice;
|
|
76
|
+
|
|
77
|
+
export const isVisible = (state: RootState) => state.errorDialog.isVisible;
|
|
78
|
+
export const messages = (state: RootState) => state.errorDialog.messages;
|
|
79
|
+
export const errorResolutions = (state: RootState) =>
|
|
80
|
+
state.errorDialog.errorResolutions;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015 Nordic Semiconductor ASA
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { fireEvent, screen } from '@testing-library/react';
|
|
9
|
+
|
|
10
|
+
import render from '../../test/testrenderer';
|
|
11
|
+
import { getAppSpecificStore as store } from '../utils/persistentStore';
|
|
12
|
+
import FactoryResetButton from './FactoryResetButton';
|
|
13
|
+
|
|
14
|
+
const LABEL = 'Factory reset';
|
|
15
|
+
const OKBUTTONTEXT = 'Restore';
|
|
16
|
+
|
|
17
|
+
describe('FactoryReset', () => {
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
jest.resetAllMocks();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should clear store when confirmed', async () => {
|
|
23
|
+
render(<FactoryResetButton label={LABEL} />);
|
|
24
|
+
fireEvent.click(screen.getByText(LABEL));
|
|
25
|
+
await screen.findByText(OKBUTTONTEXT);
|
|
26
|
+
fireEvent.click(screen.getByText(OKBUTTONTEXT));
|
|
27
|
+
expect(store().clear).toHaveBeenCalled();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should not clear store when cancelled', async () => {
|
|
31
|
+
render(<FactoryResetButton label={LABEL} />);
|
|
32
|
+
fireEvent.click(screen.getByText(LABEL));
|
|
33
|
+
await screen.findByText('Cancel');
|
|
34
|
+
fireEvent.click(screen.getByText('Cancel'));
|
|
35
|
+
expect(store().clear).not.toHaveBeenCalled();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('is possible to override reset function', async () => {
|
|
39
|
+
const overrideResetFn = jest.fn();
|
|
40
|
+
render(<FactoryResetButton label={LABEL} resetFn={overrideResetFn} />);
|
|
41
|
+
fireEvent.click(screen.getByText(LABEL));
|
|
42
|
+
await screen.findByText(OKBUTTONTEXT);
|
|
43
|
+
fireEvent.click(screen.getByText(OKBUTTONTEXT));
|
|
44
|
+
expect(overrideResetFn).toHaveBeenCalled();
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015 Nordic Semiconductor ASA
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React, { FC, useRef, useState } from 'react';
|
|
8
|
+
|
|
9
|
+
import Button, { ButtonVariants } from '../Button/Button';
|
|
10
|
+
import { Dialog, DialogButton } from '../Dialog/Dialog';
|
|
11
|
+
import logger from '../logging';
|
|
12
|
+
import { getAppSpecificStore as store } from '../utils/persistentStore';
|
|
13
|
+
|
|
14
|
+
interface Props {
|
|
15
|
+
resetFn?: () => void;
|
|
16
|
+
label: string;
|
|
17
|
+
modalText?: string;
|
|
18
|
+
variant?: ButtonVariants;
|
|
19
|
+
classNames?: string;
|
|
20
|
+
large?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const DEFAULT_MODAL_TEXT =
|
|
24
|
+
'By restoring defaults, all stored app-specific configuration values will be lost. This does not include configurations such as device renames and favorites. Are you sure you want to proceed?';
|
|
25
|
+
|
|
26
|
+
const FactoryResetButton: FC<Props> = ({
|
|
27
|
+
resetFn,
|
|
28
|
+
label,
|
|
29
|
+
modalText,
|
|
30
|
+
variant = 'secondary',
|
|
31
|
+
classNames,
|
|
32
|
+
large = false,
|
|
33
|
+
}) => {
|
|
34
|
+
const [showDialog, setShowDialog] = useState(false);
|
|
35
|
+
useRef(); // showdialog
|
|
36
|
+
const defaultResetFn = () => {
|
|
37
|
+
store().clear();
|
|
38
|
+
logger.info('Successfully restored defaults');
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<>
|
|
43
|
+
<Button
|
|
44
|
+
large={large}
|
|
45
|
+
variant={variant}
|
|
46
|
+
onClick={() => setShowDialog(true)}
|
|
47
|
+
className={classNames}
|
|
48
|
+
>
|
|
49
|
+
{label}
|
|
50
|
+
</Button>
|
|
51
|
+
<Dialog
|
|
52
|
+
isVisible={showDialog}
|
|
53
|
+
closeOnUnfocus
|
|
54
|
+
onHide={() => setShowDialog(false)}
|
|
55
|
+
>
|
|
56
|
+
<Dialog.Header
|
|
57
|
+
title="Restore factory settings"
|
|
58
|
+
headerIcon="alert"
|
|
59
|
+
/>
|
|
60
|
+
<Dialog.Body>{modalText || DEFAULT_MODAL_TEXT}</Dialog.Body>
|
|
61
|
+
<Dialog.Footer>
|
|
62
|
+
<DialogButton
|
|
63
|
+
variant="danger"
|
|
64
|
+
onClick={() => {
|
|
65
|
+
if (resetFn) resetFn();
|
|
66
|
+
else defaultResetFn();
|
|
67
|
+
setShowDialog(false);
|
|
68
|
+
}}
|
|
69
|
+
>
|
|
70
|
+
Restore
|
|
71
|
+
</DialogButton>
|
|
72
|
+
<DialogButton onClick={() => setShowDialog(false)}>
|
|
73
|
+
Cancel
|
|
74
|
+
</DialogButton>
|
|
75
|
+
</Dialog.Footer>
|
|
76
|
+
</Dialog>
|
|
77
|
+
</>
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export default FactoryResetButton;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015 Nordic Semiconductor ASA
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
8
|
+
|
|
9
|
+
import classNames from '../utils/classNames';
|
|
10
|
+
|
|
11
|
+
import './inline-input.scss';
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
This input component is a bit tricky, because it has several constraints:
|
|
15
|
+
|
|
16
|
+
We want to be able validate the input and indicate to the user whether the current input is
|
|
17
|
+
invalid.
|
|
18
|
+
|
|
19
|
+
Users should be able to enter invalid values, we just want to indicate that they are invalid
|
|
20
|
+
and do not use the value unless it is valid. We want to allow users to enter momentarily
|
|
21
|
+
invalid values, because forbidding them to do so would be a pain. E.g. if we have a range from
|
|
22
|
+
100 to 1000, then entering the number 500 would be hard if the system forbids to just type '5'
|
|
23
|
+
because it is below 10).
|
|
24
|
+
|
|
25
|
+
To accomplish the above we need not just one, but two values: An internal value, which is what
|
|
26
|
+
is displayed to the user, can be potentially invalid, and is held in a state local to this
|
|
27
|
+
component. Only when this internal value is valid, then onChange is called, which should update
|
|
28
|
+
the external value, which is passed in as a prop.
|
|
29
|
+
|
|
30
|
+
We want to enable other controls to also update the external value and then have it reflect in
|
|
31
|
+
this input, so the external value and the internal value need to be synchronised, but the
|
|
32
|
+
external value must only overwrite the internal value if the former was changed.
|
|
33
|
+
useSynchronisationIfChangedFromOutside does take care of this by remembering the previous
|
|
34
|
+
external value and comparing with it to determine whether it has changed.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
const useSynchronisationIfChangedFromOutside = (
|
|
38
|
+
externalValue: string,
|
|
39
|
+
setInternalValue: (value: string) => void
|
|
40
|
+
) => {
|
|
41
|
+
const previousExternalValue = useRef(externalValue);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (previousExternalValue.current !== externalValue) {
|
|
44
|
+
setInternalValue(externalValue);
|
|
45
|
+
previousExternalValue.current = externalValue;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
return previousExternalValue.current;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
interface Props {
|
|
52
|
+
disabled?: boolean;
|
|
53
|
+
value: string;
|
|
54
|
+
isValid?: (value: string) => boolean;
|
|
55
|
+
onChange: (value: string) => void;
|
|
56
|
+
onChangeComplete?: (value: string) => void;
|
|
57
|
+
onKeyboardIncrementAction?: () => string;
|
|
58
|
+
onKeyboardDecrementAction?: () => string;
|
|
59
|
+
className?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const InlineInput = React.forwardRef<HTMLInputElement, Props>(
|
|
63
|
+
(
|
|
64
|
+
{
|
|
65
|
+
disabled = false,
|
|
66
|
+
value: externalValue,
|
|
67
|
+
isValid = () => true,
|
|
68
|
+
onChange,
|
|
69
|
+
onChangeComplete = () => {},
|
|
70
|
+
onKeyboardIncrementAction = () => externalValue,
|
|
71
|
+
onKeyboardDecrementAction = () => externalValue,
|
|
72
|
+
className = '',
|
|
73
|
+
},
|
|
74
|
+
ref
|
|
75
|
+
) => {
|
|
76
|
+
const [internalValue, setInternalValue] = useState(externalValue);
|
|
77
|
+
const [initialValue, setInitialValue] = useState(externalValue);
|
|
78
|
+
useSynchronisationIfChangedFromOutside(externalValue, setInternalValue);
|
|
79
|
+
const onChangeIfValid = (newValue: string) => {
|
|
80
|
+
if (disabled) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
setInternalValue(newValue);
|
|
85
|
+
if (isValid(newValue)) {
|
|
86
|
+
if (externalValue !== newValue) {
|
|
87
|
+
onChange(newValue);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const resetToExternalValueOrOnChangeCompleteIfValid = () => {
|
|
93
|
+
if (disabled) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (isValid(internalValue)) {
|
|
98
|
+
if (initialValue !== internalValue) {
|
|
99
|
+
setInitialValue(internalValue);
|
|
100
|
+
onChangeComplete(internalValue);
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
setInternalValue(externalValue);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const onChangeCompleteIfValid = (event: React.KeyboardEvent) => {
|
|
108
|
+
if (disabled) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
event.stopPropagation();
|
|
113
|
+
|
|
114
|
+
if (event.key === 'Enter' && isValid(internalValue)) {
|
|
115
|
+
if (initialValue !== internalValue) {
|
|
116
|
+
setInitialValue(internalValue);
|
|
117
|
+
onChangeComplete(internalValue);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const startKeyboardEvents = (event: React.KeyboardEvent) => {
|
|
123
|
+
if (disabled) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
event.stopPropagation();
|
|
128
|
+
|
|
129
|
+
switch (event.key) {
|
|
130
|
+
case 'ArrowUp':
|
|
131
|
+
onChangeIfValid(onKeyboardIncrementAction());
|
|
132
|
+
break;
|
|
133
|
+
case 'ArrowDown':
|
|
134
|
+
onChangeIfValid(onKeyboardDecrementAction());
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
const stopPropagation = (event: React.MouseEvent) =>
|
|
139
|
+
event.stopPropagation();
|
|
140
|
+
|
|
141
|
+
return (
|
|
142
|
+
<input
|
|
143
|
+
ref={ref}
|
|
144
|
+
type="text"
|
|
145
|
+
className={classNames(
|
|
146
|
+
'inline-input',
|
|
147
|
+
isValid(internalValue) || 'invalid',
|
|
148
|
+
disabled && 'disabled',
|
|
149
|
+
className
|
|
150
|
+
)}
|
|
151
|
+
size={
|
|
152
|
+
Math.max(1, internalValue.length) +
|
|
153
|
+
(process.platform === 'darwin' ? 2 : 0)
|
|
154
|
+
}
|
|
155
|
+
disabled={disabled}
|
|
156
|
+
value={internalValue}
|
|
157
|
+
onFocus={() => {
|
|
158
|
+
setInitialValue(internalValue);
|
|
159
|
+
}}
|
|
160
|
+
onChange={event => onChangeIfValid(event.target.value)}
|
|
161
|
+
onBlur={resetToExternalValueOrOnChangeCompleteIfValid}
|
|
162
|
+
onKeyUp={onChangeCompleteIfValid}
|
|
163
|
+
onKeyDown={startKeyboardEvents}
|
|
164
|
+
onClick={stopPropagation}
|
|
165
|
+
/>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
export default InlineInput;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015 Nordic Semiconductor ASA
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React, { FC } from 'react';
|
|
8
|
+
|
|
9
|
+
import { isFactor } from '../Slider/factor';
|
|
10
|
+
import {
|
|
11
|
+
getStep,
|
|
12
|
+
isValues,
|
|
13
|
+
Range,
|
|
14
|
+
RangeOrValues,
|
|
15
|
+
useValidatedRangeOrValues,
|
|
16
|
+
Values,
|
|
17
|
+
} from '../Slider/range';
|
|
18
|
+
import InlineInput from './InlineInput';
|
|
19
|
+
|
|
20
|
+
import './number-inline-input.scss';
|
|
21
|
+
|
|
22
|
+
export interface Props {
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
value: number;
|
|
25
|
+
range: RangeOrValues;
|
|
26
|
+
onChange: (value: number) => void;
|
|
27
|
+
onChangeComplete?: (value: number) => void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const isInValues = (value: number, values: Values) => values.includes(value);
|
|
31
|
+
|
|
32
|
+
const isInRange = (value: number, { min, max, decimals, step }: Range) =>
|
|
33
|
+
value >= min &&
|
|
34
|
+
value <= max &&
|
|
35
|
+
value === Number(value.toFixed(decimals)) &&
|
|
36
|
+
(step == null ? true : isFactor(value - min, step));
|
|
37
|
+
|
|
38
|
+
const isValid = (value: number, rangeOrValues: RangeOrValues) =>
|
|
39
|
+
isValues(rangeOrValues)
|
|
40
|
+
? isInValues(value, rangeOrValues)
|
|
41
|
+
: isInRange(value, rangeOrValues);
|
|
42
|
+
|
|
43
|
+
const nextInValues = (
|
|
44
|
+
current: number,
|
|
45
|
+
values: Values,
|
|
46
|
+
steps: number
|
|
47
|
+
): number | undefined => {
|
|
48
|
+
const currentIndex = values.indexOf(current);
|
|
49
|
+
const newIndex = currentIndex + steps;
|
|
50
|
+
|
|
51
|
+
return values[newIndex];
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const nextInRange = (current: number, range: Range, steps: number) => {
|
|
55
|
+
const newValue = Number(
|
|
56
|
+
(current + steps * getStep(range)).toFixed(range.decimals)
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
if (newValue >= range.min && newValue <= range.max) {
|
|
60
|
+
return newValue;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const changeValueStepwise = (
|
|
65
|
+
current: number,
|
|
66
|
+
rangeOrValues: RangeOrValues,
|
|
67
|
+
steps: number
|
|
68
|
+
) => {
|
|
69
|
+
const nextValue = isValues(rangeOrValues)
|
|
70
|
+
? nextInValues(current, rangeOrValues, steps)
|
|
71
|
+
: nextInRange(current, rangeOrValues, steps);
|
|
72
|
+
|
|
73
|
+
if (nextValue != null) {
|
|
74
|
+
return nextValue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return nextValue != null ? nextValue : current;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const NumberInlineInput: FC<Props> = ({
|
|
81
|
+
disabled,
|
|
82
|
+
value,
|
|
83
|
+
range,
|
|
84
|
+
onChange,
|
|
85
|
+
onChangeComplete = () => {},
|
|
86
|
+
}) => {
|
|
87
|
+
useValidatedRangeOrValues(range);
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<InlineInput
|
|
91
|
+
className="number-inline-input"
|
|
92
|
+
disabled={disabled}
|
|
93
|
+
value={String(value)}
|
|
94
|
+
isValid={newValue => isValid(Number(newValue), range)}
|
|
95
|
+
onChange={newValue => onChange(Number(newValue))}
|
|
96
|
+
onChangeComplete={newValue => onChangeComplete(Number(newValue))}
|
|
97
|
+
onKeyboardIncrementAction={() =>
|
|
98
|
+
changeValueStepwise(value, range, 1).toString()
|
|
99
|
+
}
|
|
100
|
+
onKeyboardDecrementAction={() =>
|
|
101
|
+
changeValueStepwise(value, range, -1).toString()
|
|
102
|
+
}
|
|
103
|
+
/>
|
|
104
|
+
);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export default NumberInlineInput;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021 Nordic Semiconductor ASA
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
@import "../variables";
|
|
8
|
+
|
|
9
|
+
.inline-input {
|
|
10
|
+
all: inherit;
|
|
11
|
+
|
|
12
|
+
border-bottom-style: solid;
|
|
13
|
+
border-bottom-width: 1px;
|
|
14
|
+
border-bottom-color: transparent;
|
|
15
|
+
|
|
16
|
+
overflow-x: hidden;
|
|
17
|
+
|
|
18
|
+
&:focus {
|
|
19
|
+
border-bottom-color: $gray-200;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
&.invalid {
|
|
23
|
+
border-bottom-color: $brand-danger;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&.disabled {
|
|
27
|
+
// No clue why, but setting the opacity for disabled elements in shared.scss
|
|
28
|
+
// is not effective for the inline input, but it works if we set it here
|
|
29
|
+
opacity: $disabled-opacity;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// To prevent opacity from stacking up
|
|
34
|
+
.disabled, :disabled {
|
|
35
|
+
.inline-input.disabled {
|
|
36
|
+
opacity: 1;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021 Nordic Semiconductor ASA
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
@import "../variables";
|
|
8
|
+
|
|
9
|
+
.number-inline-input {
|
|
10
|
+
text-align: center;
|
|
11
|
+
border-bottom-color: $gray-200;
|
|
12
|
+
font-size: 14px;
|
|
13
|
+
|
|
14
|
+
&:focus { background-color: $white; }
|
|
15
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015 Nordic Semiconductor ASA
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import formatDate from 'date-fns/format';
|
|
9
|
+
import { LogEntry } from 'winston';
|
|
10
|
+
|
|
11
|
+
import { openUrl } from '../utils/open';
|
|
12
|
+
|
|
13
|
+
import './log-entry.scss';
|
|
14
|
+
|
|
15
|
+
const regex = /(.*?)(https?:\/\/[^\s]+)/g;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Convert strings to array of strings and JSX <a> tags for hrefs
|
|
19
|
+
*
|
|
20
|
+
* E.g. 'For reference see: https://github.com/example/doc.md or reboot Windows.'
|
|
21
|
+
* will be converted to:
|
|
22
|
+
* [
|
|
23
|
+
* 'For reference see: ',
|
|
24
|
+
* <a href='https://github.com/example/doc.md'>https://github.com/example/doc.md</a>,
|
|
25
|
+
* ' or reboot Windows.',
|
|
26
|
+
* ]
|
|
27
|
+
*
|
|
28
|
+
* @param {string} str input string
|
|
29
|
+
* @returns {Array} strings and JSX <a> tags
|
|
30
|
+
*/
|
|
31
|
+
function hrefReplacer(str: string) {
|
|
32
|
+
const message = [];
|
|
33
|
+
const remainder = str.replace(regex, (match, before, href, index) => {
|
|
34
|
+
message.push(before);
|
|
35
|
+
message.push(
|
|
36
|
+
<a
|
|
37
|
+
href={href}
|
|
38
|
+
key={index}
|
|
39
|
+
tabIndex={index}
|
|
40
|
+
onClick={() => openUrl(href)}
|
|
41
|
+
onKeyPress={() => {}}
|
|
42
|
+
>
|
|
43
|
+
{href}
|
|
44
|
+
</a>
|
|
45
|
+
);
|
|
46
|
+
return '';
|
|
47
|
+
});
|
|
48
|
+
message.push(remainder);
|
|
49
|
+
return message;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default ({ entry }: { entry: LogEntry }) => {
|
|
53
|
+
const className = `core19-log-entry core19-log-level-${entry.level}`;
|
|
54
|
+
const time = formatDate(new Date(entry.timestamp), 'HH:mm:ss.SSS');
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<div className={className}>
|
|
58
|
+
<div className="core19-log-cell core19-log-time">{time}</div>
|
|
59
|
+
<div className="core19-log-cell">{hrefReplacer(entry.message)}</div>
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015 Nordic Semiconductor ASA
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React, { useEffect, useRef } from 'react';
|
|
8
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
9
|
+
|
|
10
|
+
import { forwardLogEventsFromDeviceLib } from '../Device/deviceLibWrapper';
|
|
11
|
+
import logger from '../logging';
|
|
12
|
+
import sendInitialLogMessages from '../logging/sendInitialLogMessages';
|
|
13
|
+
import LogEntry from './LogEntry';
|
|
14
|
+
import {
|
|
15
|
+
autoScroll as autoScrollSelector,
|
|
16
|
+
logEntries as logEntriesSelector,
|
|
17
|
+
} from './logSlice';
|
|
18
|
+
import startSyncLogToStore from './syncLogToStore';
|
|
19
|
+
|
|
20
|
+
import './log-viewer.scss';
|
|
21
|
+
|
|
22
|
+
export const useInitialisedLog = () => {
|
|
23
|
+
const dispatch = useDispatch();
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
logger.initialise();
|
|
26
|
+
forwardLogEventsFromDeviceLib();
|
|
27
|
+
sendInitialLogMessages();
|
|
28
|
+
const stopSyncLogToStore = startSyncLogToStore(dispatch);
|
|
29
|
+
|
|
30
|
+
return stopSyncLogToStore;
|
|
31
|
+
}, [dispatch]);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default () => {
|
|
35
|
+
useInitialisedLog();
|
|
36
|
+
|
|
37
|
+
const autoScroll = useSelector(autoScrollSelector);
|
|
38
|
+
const logEntries = useSelector(logEntriesSelector);
|
|
39
|
+
const logContainer = useRef<HTMLDivElement>(null);
|
|
40
|
+
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (autoScroll && logContainer.current?.lastChild) {
|
|
43
|
+
(logContainer.current?.lastChild as Element).scrollIntoView();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div ref={logContainer} className="core19-log">
|
|
49
|
+
{logEntries.map(entry => (
|
|
50
|
+
<LogEntry entry={entry} key={entry.id} />
|
|
51
|
+
))}
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021 Nordic Semiconductor ASA
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
@import '../variables';
|
|
8
|
+
|
|
9
|
+
.core19-log-entry {
|
|
10
|
+
white-space: nowrap;
|
|
11
|
+
display: table-row;
|
|
12
|
+
min-width: 100%;
|
|
13
|
+
|
|
14
|
+
.core19-log-cell {
|
|
15
|
+
display: table-cell;
|
|
16
|
+
padding: 0 0.7em;
|
|
17
|
+
user-select: text;
|
|
18
|
+
}
|
|
19
|
+
.core19-log-time {
|
|
20
|
+
width: 7em;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.core19-log-level-error {
|
|
25
|
+
color: $brand-danger;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.core19-log-level-warn {
|
|
29
|
+
color: $brand-warning;
|
|
30
|
+
}
|