Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CBG trends display selections #363

Merged
merged 23 commits into from
Dec 15, 2016
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1d71022
initial work on CBG trends display selections
krystophv Nov 22, 2016
dc4b274
add metric for switching bgm/cgm
krystophv Dec 1, 2016
c61b400
Merged branch master into krystophv/cgm-checkbox
krystophv Dec 1, 2016
8086af7
fix for percent sign on 'median'
krystophv Dec 1, 2016
a770391
add Perf tools for React in dev mode
jebeck Dec 2, 2016
419bfbe
use the actual freaking React production build, o m g
jebeck Dec 2, 2016
8c6ebe6
Merged branch master into krystophv/cgm-checkbox
krystophv Dec 2, 2016
c45488d
remove console log
krystophv Dec 5, 2016
311fda4
Merged branch master into krystophv/cgm-checkbox
krystophv Dec 5, 2016
e4dfde6
more specific props
krystophv Dec 5, 2016
6e07fbe
need to pass current patient id down
krystophv Dec 5, 2016
fc83bb1
adding tracking middleware tests
krystophv Dec 6, 2016
cb4547e
add render/interaction tests for the chart footer
krystophv Dec 8, 2016
063f98c
Merged branch master into krystophv/cgm-checkbox
krystophv Dec 8, 2016
208ac27
bump viz dependency
krystophv Dec 8, 2016
eaba37c
Merge branch 'master' into krystophv/cgm-checkbox
krystophv Dec 9, 2016
4d381e2
v0.14.37
krystophv Dec 9, 2016
35f4a4e
Merge branch 'master'
krystophv Dec 12, 2016
a0c1efa
bump viz dependency
krystophv Dec 12, 2016
0e2a25d
Merge branch 'master'
krystophv Dec 13, 2016
104d2f9
Merge pull request #370 from tidepool-org/jebeck/perf-stuff
krystophv Dec 13, 2016
9d56836
Merged branch master into krystophv/cgm-checkbox
krystophv Dec 13, 2016
828da14
v0.14.40
krystophv Dec 13, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions app/components/chart/footer.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var cx = require('classnames');

import * as viz from '@tidepool/viz';
const TwoOptionToggle = viz.components.TwoOptionToggle;
const RangeSelect = viz.components.RangeSelect;

var tideline = {
log: bows('Footer')
Expand All @@ -41,6 +42,8 @@ var TidelineFooter = React.createClass({
showingCbg: React.PropTypes.bool,
showingSmbg: React.PropTypes.bool,
showingValues: React.PropTypes.bool,
displayFlags: React.PropTypes.object,
currentPatientInViewId: React.PropTypes.string,
},
render: function() {
var refreshLinkClass = cx({
Expand Down Expand Up @@ -88,6 +91,11 @@ var TidelineFooter = React.createClass({
if (this.props.chartType === 'modal') {
if (this.props.showingSmbg) {
rightSide = modalOpts;
} else {
rightSide = <RangeSelect
displayFlags={this.props.displayFlags}
currentPatientInViewId={this.props.currentPatientInViewId}
/>;
}
bgDataToggle = (
<span className="toggle-container">
Expand Down
12 changes: 10 additions & 2 deletions app/components/chart/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ var Modal = React.createClass({
}
},
render: function() {
const { currentPatientInViewId } = this.props;
return (
<div id="tidelineMain">
{this.renderHeader()}
Expand Down Expand Up @@ -97,7 +98,9 @@ var Modal = React.createClass({
showingLines={this.props.chartPrefs.modal.smbgLines}
showingCbg={this.props.chartPrefs.modal.showingCbg}
showingSmbg={this.props.chartPrefs.modal.showingSmbg}
ref="footer" />
displayFlags={this.props.trendsState[currentPatientInViewId].cbgFlags}
currentPatientInViewId={currentPatientInViewId}
ref="footer" />
</div>
);
},
Expand Down Expand Up @@ -365,6 +368,11 @@ var Modal = React.createClass({
toggleBgDataSource: function(e) {
if (e) {
e.preventDefault();
if (this.props.chartPrefs.modal.showingCbg) {
this.props.trackMetric('Trends Click to BGM');
} else {
this.props.trackMetric('Trends Click to CGM');
}
}
var prefs = _.cloneDeep(this.props.chartPrefs);
prefs.modal.showingCbg = !prefs.modal.showingCbg;
Expand Down Expand Up @@ -414,4 +422,4 @@ var Modal = React.createClass({
}
});

module.exports = Modal;
module.exports = Modal;
14 changes: 13 additions & 1 deletion app/redux/utils/trackingMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,26 @@ const trackMetricMap = {
UPDATE_PATIENT_SUCCESS: 'Updated Profile',
UPDATE_USER_SUCCESS: 'Updated Account',
LOGOUT_REQUEST: 'Logged Out',
VERIFY_CUSTODIAL_SUCCESS: 'VCA Home Verification - Verified'
VERIFY_CUSTODIAL_SUCCESS: 'VCA Home Verification - Verified',
};

const interpretMetricMap = {
TURN_ON_CBG_RANGE: function(action) {
return `Turn on ${action.payload.range}${!_.isNaN(parseInt(action.payload.range, 10)) ? encodeURIComponent('%') : ''}`;
},
TURN_OFF_CBG_RANGE: function(action) {
return `Turn off ${action.payload.range}${!_.isNaN(parseInt(action.payload.range, 10)) ? encodeURIComponent('%') : ''}`;
}
}

export default (api) => {
return ({ getState }) => (next) => (action) => {
if (trackMetricMap[action.type]) {
api.metrics.track(trackMetricMap[action.type]);
}
if (interpretMetricMap[action.type]) {
api.metrics.track(interpretMetricMap[action.type](action));
}
return next(action);
};
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"serve-docs": "./node_modules/.bin/gitbook serve"
},
"dependencies": {
"@tidepool/viz": "0.2.20",
"@tidepool/viz": "0.2.21",
"async": "1.5.2",
"babel-core": "6.13.2",
"babel-loader": "6.2.5",
Expand Down
237 changes: 237 additions & 0 deletions test/unit/components/chart/footer.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
/* global chai */
/* global describe */
/* global sinon */
/* global it */

var React = require('react');
var TestUtils = require('react-addons-test-utils');

import { mount } from 'enzyme';
import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';

import * as viz from '@tidepool/viz';
const TwoOptionToggle = viz.components.TwoOptionToggle;
const RangeSelect = viz.components.RangeSelect;

var _ = require('lodash');
var expect = chai.expect;

import Footer from '../../../../app/components/chart/footer';

describe('Footer', function () {
describe('render', function() {
it('should render without problems', function () {
console.error = sinon.stub();
var props = {
chartType: 'Awesome',
onClickBoxOverlay: sinon.stub(),
onClickGroup: sinon.stub(),
onClickLines: sinon.stub(),
onClickValues: sinon.stub(),
onClickRefresh: sinon.stub(),
onClickBgDataToggle: sinon.stub(),
boxOverlay: false,
grouped: true,
showingLines: false,
showingCbg: true,
showingSmbg: false,
showingValues: false,
};
var dailyElem = React.createElement(Footer, props);
var elem = TestUtils.renderIntoDocument(dailyElem);
expect(elem).to.be.ok;
expect(console.error.callCount).to.equal(0);
});

it('should trigger onClickBoxOverlay when modal, showingSmbg and overlayCheckbox changed', function () {
var props = {
chartType: 'modal',
onClickBoxOverlay: sinon.stub(),
onClickGroup: sinon.stub(),
onClickLines: sinon.stub(),
onClickValues: sinon.stub(),
onClickRefresh: sinon.stub(),
onClickBgDataToggle: sinon.stub(),
boxOverlay: false,
grouped: true,
showingLines: false,
showingCbg: false,
showingSmbg: true,
showingValues: false,
};
var dailyElem = React.createElement(Footer, props);
var elem = TestUtils.renderIntoDocument(dailyElem);
expect(elem).to.be.ok;

var overlayCheckbox = TestUtils.scryRenderedDOMComponentsWithTag(elem, 'input')[0];
expect(overlayCheckbox.name).to.equal('overlayCheckbox');
expect(props.onClickBoxOverlay.callCount).to.equal(0);
TestUtils.Simulate.change(overlayCheckbox);
expect(props.onClickBoxOverlay.callCount).to.equal(1);
});

it('should trigger onClickGroup when modal, showingSmbg and groupCheckbox changed', function () {
var props = {
chartType: 'modal',
onClickBoxOverlay: sinon.stub(),
onClickGroup: sinon.stub(),
onClickLines: sinon.stub(),
onClickValues: sinon.stub(),
onClickRefresh: sinon.stub(),
onClickBgDataToggle: sinon.stub(),
boxOverlay: false,
grouped: true,
showingLines: false,
showingCbg: false,
showingSmbg: true,
showingValues: false,
};
var dailyElem = React.createElement(Footer, props);
var elem = TestUtils.renderIntoDocument(dailyElem);
expect(elem).to.be.ok;

var groupCheckbox = TestUtils.scryRenderedDOMComponentsWithTag(elem, 'input')[1];
expect(groupCheckbox.name).to.equal('groupCheckbox');
expect(props.onClickGroup.callCount).to.equal(0);
TestUtils.Simulate.change(groupCheckbox);
expect(props.onClickGroup.callCount).to.equal(1);
});

it('should trigger onClickLines when modal, showingSmbg and linesCheckbox changed', function () {
var props = {
chartType: 'modal',
onClickBoxOverlay: sinon.stub(),
onClickGroup: sinon.stub(),
onClickLines: sinon.stub(),
onClickValues: sinon.stub(),
onClickRefresh: sinon.stub(),
onClickBgDataToggle: sinon.stub(),
boxOverlay: false,
grouped: true,
showingLines: false,
showingCbg: false,
showingSmbg: true,
showingValues: false,
};
var dailyElem = React.createElement(Footer, props);
var elem = TestUtils.renderIntoDocument(dailyElem);
expect(elem).to.be.ok;

var linesCheckbox = TestUtils.scryRenderedDOMComponentsWithTag(elem, 'input')[2];
expect(linesCheckbox.name).to.equal('linesCheckbox');
expect(props.onClickLines.callCount).to.equal(0);
TestUtils.Simulate.change(linesCheckbox);
expect(props.onClickLines.callCount).to.equal(1);
});

it('should trigger onClickValues when weekly and valuesCheckbox changed', function () {
var props = {
chartType: 'weekly',
onClickBoxOverlay: sinon.stub(),
onClickGroup: sinon.stub(),
onClickLines: sinon.stub(),
onClickValues: sinon.stub(),
onClickRefresh: sinon.stub(),
onClickBgDataToggle: sinon.stub(),
boxOverlay: false,
grouped: true,
showingLines: false,
showingCbg: false,
showingSmbg: true,
showingValues: false,
};
var dailyElem = React.createElement(Footer, props);
var elem = TestUtils.renderIntoDocument(dailyElem);
expect(elem).to.be.ok;

var valuesCheckbox = TestUtils.scryRenderedDOMComponentsWithTag(elem, 'input')[0];
expect(valuesCheckbox.name).to.equal('valuesCheckbox');
expect(props.onClickValues.callCount).to.equal(0);
TestUtils.Simulate.change(valuesCheckbox);
expect(props.onClickValues.callCount).to.equal(1);
});

it('should trigger onClickRefresh when refresh button clicked', function () {
var props = {
chartType: 'weekly',
onClickBoxOverlay: sinon.stub(),
onClickGroup: sinon.stub(),
onClickLines: sinon.stub(),
onClickValues: sinon.stub(),
onClickRefresh: sinon.stub(),
onClickBgDataToggle: sinon.stub(),
boxOverlay: false,
grouped: true,
showingLines: false,
showingCbg: false,
showingSmbg: true,
showingValues: false,
};
var dailyElem = React.createElement(Footer, props);
var elem = TestUtils.renderIntoDocument(dailyElem);
expect(elem).to.be.ok;

var refreshButton = TestUtils.findRenderedDOMComponentWithClass(elem, 'btn-refresh');
expect(props.onClickRefresh.callCount).to.equal(0);
TestUtils.Simulate.click(refreshButton);
expect(props.onClickRefresh.callCount).to.equal(1);
});

it('should render a TwoOptionToggle when modal', function () {
var props = {
chartType: 'modal',
onClickBoxOverlay: sinon.stub(),
onClickGroup: sinon.stub(),
onClickLines: sinon.stub(),
onClickValues: sinon.stub(),
onClickRefresh: sinon.stub(),
onClickBgDataToggle: sinon.stub(),
boxOverlay: false,
grouped: true,
showingLines: false,
showingCbg: false,
showingSmbg: true,
showingValues: false,
};
var footer = mount(
<Footer {...props} />
);

expect(footer.find(TwoOptionToggle).length).to.equal(1);
});

it('should render a RangeSelect when modal, showingCbg', function () {
var props = {
chartType: 'modal',
onClickBoxOverlay: sinon.stub(),
onClickGroup: sinon.stub(),
onClickLines: sinon.stub(),
onClickValues: sinon.stub(),
onClickRefresh: sinon.stub(),
onClickBgDataToggle: sinon.stub(),
boxOverlay: false,
grouped: true,
showingLines: false,
showingCbg: true,
showingSmbg: false,
showingValues: false,
displayFlags: {
cbg100Emabled: false,
cbg80Enabeled: true,
cbg50Enabeled: true,
cbgMedianEnabled: true,
},
currentPatientInViewId: 'abc123',
};
// RangeSelect is a redux connect()ed component and needs a Provider/store
var footer = mount(
<Provider store={configureStore([])({})}>
<Footer {...props} />
</Provider>
);

expect(footer.find(RangeSelect).length).to.equal(1);
});
});
});
Loading