Skip to content

Commit 097089a

Browse files
authored
Merge pull request #41 from NordicSemiconductor/fix/sliders
Replace slider components
2 parents 148b067 + 31064ce commit 097089a

File tree

6 files changed

+141
-60
lines changed

6 files changed

+141
-60
lines changed

actions/rssiActions.js

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@
3737
import { logger } from 'nrfconnect/core';
3838
import SerialPort from 'serialport';
3939

40-
let port;
40+
let port = null;
4141

42-
let maxScans = 30;
4342
const theRssiData = [];
4443
const theRssiDataMax = [];
4544

@@ -75,9 +74,11 @@ function rssiData() {
7574

7675
function writeAndDrain(cmd) {
7776
return new Promise(resolve => {
78-
port.write(cmd, () => {
79-
port.drain(resolve);
80-
});
77+
if (port) {
78+
port.write(cmd, () => {
79+
port.drain(resolve);
80+
});
81+
}
8182
});
8283
}
8384

@@ -91,16 +92,12 @@ async function stopReading() {
9192
resetRssiData();
9293
}
9394

94-
export function setDelay(delay) {
95-
return () => writeAndDrain(`set delay ${delay}\r`);
96-
}
97-
98-
export function setScanRepeatTimes(repeatTimes) {
99-
return () => writeAndDrain(`set repeat ${repeatTimes}\r`);
95+
export function writeDelay() {
96+
return (dispatch, getState) => writeAndDrain(`set delay ${getState().app.delay}\r`);
10097
}
10198

102-
export function setMaxScans(scans) {
103-
maxScans = scans;
99+
export function writeScanRepeat() {
100+
return (dispatch, getState) => writeAndDrain(`set repeat ${getState().app.scanRepeat}\r`);
104101
}
105102

106103
export function scanAdvertisementChannels(enable) {
@@ -115,7 +112,7 @@ export function toggleLED() {
115112
}
116113

117114
function openWhenClosed(serialPort) {
118-
return dispatch => {
115+
return (dispatch, getState) => {
119116
port = new SerialPort(serialPort.comName, {
120117
baudRate: 115200,
121118
}, () => {
@@ -124,9 +121,8 @@ function openWhenClosed(serialPort) {
124121

125122
(async () => {
126123
await scanAdvertisementChannels(false)();
127-
await setDelay(100)();
128-
await setScanRepeatTimes(1)();
129-
await setMaxScans(30);
124+
await dispatch(writeDelay());
125+
await dispatch(writeScanRepeat());
130126
await startReading();
131127
})();
132128

@@ -144,7 +140,7 @@ function openWhenClosed(serialPort) {
144140
const [ch, d] = buf.splice(0, 2);
145141
if (ch !== 0xff && d !== 0xff) {
146142
theRssiData[ch].unshift(d);
147-
theRssiData[ch].splice(maxScans);
143+
theRssiData[ch].splice(getState().app.maxScans);
148144
theRssiDataMax[ch] = Math.min(...(theRssiData[ch]));
149145
}
150146
}
@@ -167,6 +163,7 @@ export function close() {
167163
if (port && (typeof (port.isOpen) === 'function' ? port.isOpen() : port.isOpen)) {
168164
await stopReading();
169165
await new Promise(resolve => port.close(resolve));
166+
port = null;
170167
} else {
171168
resetRssiData();
172169
}

components/ControlPanel.jsx

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,20 @@
3636

3737
import React from 'react';
3838
import PropTypes from 'prop-types';
39-
import ReactBootstrapSlider from 'react-bootstrap-slider';
4039
import Button from 'react-bootstrap/Button';
4140
import Form from 'react-bootstrap/Form';
4241

42+
import Slider from 'react-rangeslider';
43+
import 'react-rangeslider/lib/index.css';
44+
4345
const ControlPanel = props => {
4446
const {
47+
delay,
48+
scanRepeat,
49+
maxScans,
50+
animationDuration,
51+
writeDelay,
52+
writeScanRepeat,
4553
onDelayChange,
4654
onMaxScansChange,
4755
onChannelScanRepeatChange,
@@ -51,48 +59,46 @@ const ControlPanel = props => {
5159
onToggleLED,
5260
disabled,
5361
} = props;
54-
const sliderDisabled = disabled ? 'disabled' : null;
5562
return (
5663
<Form>
57-
Sweep Delay (ms)<br />
58-
<ReactBootstrapSlider
59-
value={10}
60-
slideStop={event => onDelayChange(event.target.value)}
64+
<Form.Label>Sweep Delay (ms)</Form.Label>
65+
<Slider
66+
value={delay}
67+
title={delay}
6168
max={1000}
6269
min={5}
63-
ticks={[5, 1000]}
64-
ticks_labels={['5', '1000']}
65-
disabled={sliderDisabled}
70+
onChangeComplete={writeDelay}
71+
onChange={value => onDelayChange(value)}
72+
labels={{ 5: '5', [delay]: `${delay}`, 1000: '1000' }}
73+
tooltip={false}
6674
/>
67-
# of sweeps to display maximum value
68-
<ReactBootstrapSlider
69-
value={30}
70-
slideStop={event => onMaxScansChange(event.target.value)}
75+
<Form.Label># of sweeps to display maximum value</Form.Label>
76+
<Slider
77+
value={maxScans}
7178
max={100}
7279
min={1}
73-
ticks={[1, 100]}
74-
ticks_labels={['1', '100']}
75-
disabled={sliderDisabled}
80+
onChange={value => onMaxScansChange(value)}
81+
labels={{ 1: '1', [maxScans]: `${maxScans}`, 100: '100' }}
82+
tooltip={false}
7683
/>
77-
Channel scan repeat
78-
<ReactBootstrapSlider
79-
value={1}
80-
slideStop={event => onChannelScanRepeatChange(event.target.value)}
84+
<Form.Label>Channel scan repeat</Form.Label>
85+
<Slider
86+
value={scanRepeat}
8187
max={100}
8288
min={1}
83-
ticks={[1, 100]}
84-
ticks_labels={['1', '100']}
85-
disabled={sliderDisabled}
89+
onChangeComplete={writeScanRepeat}
90+
onChange={value => onChannelScanRepeatChange(value)}
91+
labels={{ 1: '1', [scanRepeat]: `${scanRepeat}`, 100: '100' }}
92+
tooltip={false}
8693
/>
87-
Animation duration (ms)
88-
<ReactBootstrapSlider
89-
value={500}
90-
slideStop={event => onAnimationDurationChange(event.target.value)}
94+
<Form.Label>Animation duration (ms)</Form.Label>
95+
<Slider
96+
value={animationDuration}
9197
max={1000}
9298
min={10}
93-
ticks={[10, 1000]}
94-
ticks_labels={['10', '1000']}
95-
disabled={sliderDisabled}
99+
onChange={value => onAnimationDurationChange(value)}
100+
labels={{ 10: '10', [animationDuration]: `${animationDuration}`, 1000: '1000' }}
101+
tooltip={false}
96102
/>
97103
<Form.Group controlId="advCheck">
98104
<Form.Check
@@ -116,6 +122,12 @@ const ControlPanel = props => {
116122
};
117123

118124
ControlPanel.propTypes = {
125+
delay: PropTypes.number.isRequired,
126+
scanRepeat: PropTypes.number.isRequired,
127+
maxScans: PropTypes.number.isRequired,
128+
animationDuration: PropTypes.number.isRequired,
129+
writeDelay: PropTypes.func.isRequired,
130+
writeScanRepeat: PropTypes.func.isRequired,
119131
onDelayChange: PropTypes.func.isRequired,
120132
onMaxScansChange: PropTypes.func.isRequired,
121133
onChannelScanRepeatChange: PropTypes.func.isRequired,

index.jsx

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ export default {
7676
),
7777
decorateSidePanel: SidePanel => (
7878
({
79+
delay,
80+
scanRepeat,
81+
maxScans,
82+
animationDuration,
83+
writeDelay,
84+
writeScanRepeat,
7985
onDelayChange,
8086
onMaxScansChange,
8187
onChannelScanRepeatChange,
@@ -87,6 +93,12 @@ export default {
8793
}) => (
8894
<SidePanel>
8995
<ControlPanel
96+
delay={delay}
97+
scanRepeat={scanRepeat}
98+
maxScans={maxScans}
99+
animationDuration={animationDuration}
100+
writeDelay={writeDelay}
101+
writeScanRepeat={writeScanRepeat}
90102
onDelayChange={onDelayChange}
91103
onMaxScansChange={onMaxScansChange}
92104
onChannelScanRepeatChange={onChannelScanRepeatChange}
@@ -101,11 +113,20 @@ export default {
101113
),
102114
mapSidePanelDispatch: (dispatch, props) => ({
103115
...props,
104-
onDelayChange: delay => dispatch(RssiActions.setDelay(delay)),
105-
onMaxScansChange: maxScans => dispatch(RssiActions.setMaxScans(maxScans)),
106-
onChannelScanRepeatChange: scanRepeat => dispatch(
107-
RssiActions.setScanRepeatTimes(scanRepeat),
108-
),
116+
writeDelay: () => dispatch(RssiActions.writeDelay()),
117+
writeScanRepeat: () => dispatch(RssiActions.writeScanRepeat()),
118+
onDelayChange: delay => dispatch({
119+
type: 'RSSI_CHANGE_DELAY',
120+
delay,
121+
}),
122+
onMaxScansChange: maxScans => dispatch({
123+
type: 'RSSI_CHANGE_MAX_SCANS',
124+
maxScans,
125+
}),
126+
onChannelScanRepeatChange: scanRepeat => dispatch({
127+
type: 'RSSI_CHANGE_SCAN_REPEAT',
128+
scanRepeat,
129+
}),
109130
onAnimationDurationChange: animationDuration => dispatch({
110131
type: 'RSSI_CHANGE_ANIMATION_DURATION',
111132
animationDuration,
@@ -119,8 +140,12 @@ export default {
119140
}),
120141
onToggleLED: () => dispatch(RssiActions.toggleLED()),
121142
}),
122-
mapSidePanelState: (state, props) => ({
123-
disabled: state.app.port === null,
143+
mapSidePanelState: ({ app }, props) => ({
144+
disabled: app.port === null,
145+
delay: app.delay,
146+
scanRepeat: app.scanRepeat,
147+
maxScans: app.maxScans,
148+
animationDuration: app.animationDuration,
124149
...props,
125150
}),
126151
mapDeviceSelectorState: (state, props) => ({

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"chart.js": "2.7.3",
3636
"jquery": "3.4.0",
3737
"pc-nrfconnect-devdep": "git+https://github.com/NordicSemiconductor/pc-nrfconnect-devdep.git#semver:^3.0.0",
38-
"react-bootstrap-slider": "2.2.2",
38+
"react-rangeslider": "2.2.0",
3939
"react-chartjs-2": "2.7.4"
4040
},
4141
"dependencies": {},

reducers/appReducer.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
const initialState = {
3838
data: [],
3939
dataMax: [],
40+
delay: 10,
41+
scanRepeat: 1,
42+
maxScans: 30,
4043
animationDuration: 500,
4144
separateFrequencies: false,
4245
port: null,
@@ -50,6 +53,21 @@ export default function reduceApp(state = initialState, action) {
5053
data: action.data,
5154
dataMax: action.dataMax,
5255
};
56+
case 'RSSI_CHANGE_DELAY':
57+
return {
58+
...state,
59+
delay: action.delay,
60+
};
61+
case 'RSSI_CHANGE_MAX_SCANS':
62+
return {
63+
...state,
64+
maxScans: action.maxScans,
65+
};
66+
case 'RSSI_CHANGE_SCAN_REPEAT':
67+
return {
68+
...state,
69+
scanRepeat: action.scanRepeat,
70+
};
5371
case 'RSSI_CHANGE_ANIMATION_DURATION':
5472
return {
5573
...state,

resources/css/index.scss

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
@import '../../node_modules/bootstrap-slider/dist/css/bootstrap-slider.min.css';
2-
31
.core-main-view {
42
height: 100%;
53
}
@@ -18,6 +16,37 @@
1816
font-size: large;
1917
}
2018

21-
.slider.slider-horizontal {
22-
width: 100%;
19+
20+
.rangeslider {
21+
flex: 1;
22+
margin: 5px 10px 40px 10px;
23+
.rangeslider__handle {
24+
width: 10px;
25+
border-radius: 0px;
26+
box-shadow: none;
27+
transform: translate(-50%, -50%);
28+
&:after {
29+
display: none;
30+
}
31+
}
32+
.rangeslider__handle:focus {
33+
outline: none;
34+
}
35+
.rangeslider__labels .rangeslider__label-item {
36+
transform: translate(-50%, 0);
37+
}
38+
39+
li.rangeslider__label-item:nth-child(2) {
40+
background: white;
41+
z-index: 100;
42+
padding: 0 10px;
43+
font-weight: bold;
44+
}
45+
}
46+
.rangeslider-horizontal {
47+
border-radius: 0px;
48+
.rangeslider__fill {
49+
background-color: #0080B7;
50+
border-radius: 0px;
51+
}
2352
}

0 commit comments

Comments
 (0)