Skip to content

Commit c342cd1

Browse files
Merge pull request #472 from tidepool-org/WEB-2016-ciq-pump-settings-targets-annotations
[WEB-2016] CIQ pump settings annotations
2 parents 59d4371 + 73e2b25 commit c342cd1

File tree

12 files changed

+155
-14
lines changed

12 files changed

+155
-14
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"node": "20.8.0"
55
},
66
"packageManager": "[email protected]",
7-
"version": "1.46.0-web-3501-range-thresholds.5",
7+
"version": "1.46.0-web-2016-ciq-pump-settings-targets-annotations.2",
88
"description": "Tidepool data visualization for diabetes device data.",
99
"keywords": [
1010
"data visualization"
@@ -73,6 +73,7 @@
7373
"react-collapse": "5.1.1",
7474
"react-dimensions": "1.3.1",
7575
"react-dom": "16.14.0",
76+
"react-i18next": "13.3.1",
7677
"react-markdown": "8.0.7",
7778
"react-motion": "0.5.2",
7879
"react-redux": "8.1.3",

src/components/settings/Tandem.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,14 @@
105105
composes: bolusHeaderBackground settingsHeader from './settings.css';
106106
}
107107

108+
.annotations {
109+
margin-left: 40px;
110+
margin-right: 40px;
111+
margin-top: 30px;
112+
font-size: 14px;
113+
font-weight: 500;
114+
}
115+
108116
@media print {
109117

110118
.title {

src/components/settings/Tandem.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import { MGDL_UNITS, MMOLL_UNITS } from '../../utils/constants';
2929
import { deviceName, insulinSettings } from '../../utils/settings/data';
3030
import * as tandemData from '../../utils/settings/tandemData';
3131
import { tandemText } from '../../utils/settings/textData';
32+
import { isControlIQ } from '../../utils/device';
33+
import { Trans } from 'react-i18next';
3234

3335
import i18next from 'i18next';
3436
const t = i18next.t.bind(i18next);
@@ -83,6 +85,14 @@ const Tandem = (props) => {
8385
columns={settingsColumns}
8486
tableStyle={styles.settingsTableInverted}
8587
/>
88+
89+
{isControlIQ(pumpSettings) && (
90+
<div className={styles.annotations}>
91+
<Trans i18nKey="tandem.annotations">
92+
* - The numbers displayed here are the user-defined values. During automation, Tandem Control-IQ uses its own preset Insulin Duration and Target BG. However users can set different values for these parameters that <strong>only</strong> apply in manual mode.
93+
</Trans>
94+
</div>
95+
)}
8696
</CollapsibleContainer>
8797
</div>
8898
);

src/modules/print/SettingsPrintView.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import {
3535
target,
3636
} from '../../utils/settings/nonTandemData';
3737

38-
import { getPumpVocabulary } from '../../utils/device';
38+
import { getPumpVocabulary, isControlIQ } from '../../utils/device';
3939

4040
import {
4141
basalSchedules as profileSchedules,
@@ -206,6 +206,26 @@ class SettingsPrintView extends PrintView {
206206
this.renderInsulinSettings(this.latestPumpUpload.settings, schedule.name);
207207
this.doc.moveDown();
208208
});
209+
210+
if (isControlIQ(this.latestPumpUpload.settings)) {
211+
this.setFill(this.colors.grey);
212+
213+
this.doc
214+
.font(this.font)
215+
.text(t('* - The numbers displayed here are the user-defined values. During automation, Tandem Control-IQ uses its own preset Insulin Duration and Target BG. However users can set different values for these parameters that '), {
216+
continued: true,
217+
lineGap: 4,
218+
})
219+
.font(this.boldFont)
220+
.text(t('only'), {
221+
continued: true,
222+
})
223+
.font(this.font)
224+
.text(t(' apply in manual mode.'));
225+
226+
this.setFill();
227+
this.doc.moveDown();
228+
}
209229
}
210230

211231
renderPumpSettings() {

src/utils/device.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export function isTidepoolLoop(datum = {}) {
4242
}
4343

4444
/**
45-
* Check to see datum is from Twiist Loop
45+
* Check to see if datum is from Twiist Loop
4646
*/
4747
export function isTwiistLoop(datum = {}) {
4848
if (datum.type === 'upload') {
@@ -52,6 +52,13 @@ export function isTwiistLoop(datum = {}) {
5252
return (/^com.dekaresearch.twiist/).test(_.get(datum, 'origin.name', datum?.client?.name || ''));
5353
}
5454

55+
/**
56+
* Check to see if datum is from Control-IQ
57+
*/
58+
export function isControlIQ(datum = {}) {
59+
return _.get(datum, 'deviceId', '').indexOf('tandemCIQ') === 0;
60+
}
61+
5562
/**
5663
* Check to see if datum is from a known Loop device
5764
*/
@@ -68,7 +75,7 @@ export function isLoop(datum = {}) {
6875
*/
6976
export function isAutomatedBasalDevice(manufacturer, pumpSettingsOrUpload = {}, deviceModel) {
7077
return _.includes(_.get(AUTOMATED_BASAL_DEVICE_MODELS, deviceName(manufacturer), []), deviceModel)
71-
|| (manufacturer === 'tandem' && _.get(pumpSettingsOrUpload, 'deviceId', '').indexOf('tandemCIQ') === 0)
78+
|| (manufacturer === 'tandem' && isControlIQ(pumpSettingsOrUpload))
7279
|| isLoop(pumpSettingsOrUpload);
7380
}
7481

@@ -79,7 +86,7 @@ export function isAutomatedBasalDevice(manufacturer, pumpSettingsOrUpload = {},
7986
* @returns {Boolean}
8087
*/
8188
export function isAutomatedBolusDevice(manufacturer, pumpSettingsOrUpload = {}) {
82-
return (manufacturer === 'tandem' && _.get(pumpSettingsOrUpload, 'deviceId', '').indexOf('tandemCIQ') === 0)
89+
return (manufacturer === 'tandem' && isControlIQ(pumpSettingsOrUpload))
8390
|| isDIYLoop(pumpSettingsOrUpload);
8491
}
8592

@@ -90,7 +97,7 @@ export function isAutomatedBolusDevice(manufacturer, pumpSettingsOrUpload = {})
9097
* @returns {Boolean}
9198
*/
9299
export function isSettingsOverrideDevice(manufacturer, pumpSettingsOrUpload = {}) {
93-
return (manufacturer === 'tandem' && _.get(pumpSettingsOrUpload, 'deviceId', '').indexOf('tandemCIQ') === 0)
100+
return (manufacturer === 'tandem' && isControlIQ(pumpSettingsOrUpload))
94101
|| isLoop(pumpSettingsOrUpload);
95102
}
96103

src/utils/settings/data.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import i18next from 'i18next';
2020

2121
import * as datetime from '../datetime';
2222
import * as format from '../format';
23-
import { getPumpVocabulary, isLoop } from '../device';
23+
import { getPumpVocabulary, isControlIQ, isLoop } from '../device';
2424

2525
import {
2626
MAX_BOLUS,
@@ -432,7 +432,7 @@ export function insulinSettings(settings, manufacturer, scheduleName) {
432432
const rows = [
433433
{ setting: deviceLabels[MAX_BASAL], value: maxBasal ? `${maxBasal} U/hr` : '-' },
434434
{ setting: deviceLabels[MAX_BOLUS], value: maxBolus ? `${maxBolus} U` : '-' },
435-
{ setting: deviceLabels[INSULIN_DURATION], value: insulinDuration ? `${insulinDuration} hrs` : '-' },
435+
{ setting: deviceLabels[INSULIN_DURATION] + (isControlIQ(settings) ? '*' : ''), value: insulinDuration ? `${insulinDuration} hrs` : '-' },
436436
];
437437

438438
if (isLoop(settings)) {

src/utils/settings/tandemData.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@
1414
* not, you can obtain one from Tidepool Project at tidepool.org.
1515
* == BSD2 LICENSE ==
1616
*/
17+
import i18next from 'i18next';
18+
19+
import { isControlIQ } from '../device';
1720
import * as data from './data';
1821

22+
const t = i18next.t.bind(i18next);
1923
/**
2024
* basalSchedules
2125
* @param {Object} settings object with basal schedule properties
@@ -61,31 +65,31 @@ function basalRows(schedule, settings, units) {
6165
* basalColumns
6266
* @private
6367
*/
64-
function basalColumns(styles = {}, units) {
68+
function basalColumns(styles = {}, units, CIQAnnotation = false) {
6569
return [
6670
{ key: 'start',
6771
label: 'Start time' },
6872
{ key: 'rate',
6973
label: {
70-
main: 'Basal Rates',
74+
main: t('Basal Rates'),
7175
secondary: 'U/hr',
7276
},
7377
className: styles.basalScheduleHeader },
7478
{ key: 'bgTarget',
7579
label: {
76-
main: 'Target BG',
80+
main: t('Target BG') + (CIQAnnotation ? '*' : ''),
7781
secondary: units,
7882
},
7983
className: styles.bolusSettingsHeader },
8084
{ key: 'carbRatio',
8185
label: {
82-
main: 'Carb Ratio',
86+
main: t('Carb Ratio'),
8387
secondary: 'g/U',
8488
},
8589
className: styles.bolusSettingsHeader },
8690
{ key: 'insulinSensitivity',
8791
label: {
88-
main: 'Correction Factor',
92+
main: t('Correction Factor'),
8993
secondary: `${units}/U`,
9094
},
9195
className: styles.bolusSettingsHeader },
@@ -106,7 +110,7 @@ export function basal(schedule, settings, units, styles = {}) {
106110
scheduleName: schedule.name,
107111
activeAtUpload: (schedule.name === settings.activeSchedule),
108112
title: scheduleLabel(schedule.name, settings.activeSchedule),
109-
columns: basalColumns(styles, units),
113+
columns: basalColumns(styles, units, isControlIQ(settings)),
110114
rows: basalRows(schedule, settings, units),
111115
};
112116
}

test/components/settings/Tandem.test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import { mount, shallow } from 'enzyme';
2222

2323
import CollapsibleContainer from '../../../src/components/settings/common/CollapsibleContainer';
2424
import Tandem from '../../../src/components/settings/Tandem';
25+
import styles from '../../../src/components/settings/Tandem.css';
26+
import { formatClassesAsSelector } from '../../helpers/cssmodules';
2527
import { MGDL_UNITS, MMOLL_UNITS } from '../../../src/utils/constants';
2628
import { formatDecimalNumber } from '../../../src/utils/format';
2729

@@ -190,4 +192,22 @@ describe('Tandem', () => {
190192
expect(insulinSettingsTable.find('tr').at(1).text()).contains('4:05 hrs');
191193
});
192194
});
195+
196+
describe('Tandem C-IQ annotation', () => {
197+
let mounted;
198+
199+
before(() => {
200+
props.pumpSettings = { ...flatrateData, deviceId: 'tandemCIQ123' };
201+
props.bgUnits = MMOLL_UNITS;
202+
props.openedSections = { [flatrateData.activeSchedule]: true };
203+
mounted = mount(
204+
<Tandem {...props} />
205+
);
206+
});
207+
208+
it('should render an annotation', () => {
209+
const annotation = mounted.find(formatClassesAsSelector(styles.annotations)).hostNodes().at(0);
210+
expect(annotation.text()).contains('Tandem Control-IQ uses its own preset');
211+
});
212+
});
193213
});

test/modules/print/SettingsPrintView.test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,12 @@ describe('SettingsPrintView', () => {
388388
// ensure it's rendering 2 tables for each schedule
389389
sinon.assert.callCount(Renderer.renderTable, schedules.length * 2);
390390
});
391+
392+
it('should render an annotation for Tandem C-IQ data', () => {
393+
Renderer = createRenderer({ ...data.tandemFlatrate, deviceId: 'tandemCIQ123' }, opts, MGDL_UNITS);
394+
Renderer.renderTandemProfiles();
395+
sinon.assert.calledWithMatch(Renderer.doc.text, sinon.match('Tandem Control-IQ uses its own preset'));
396+
});
391397
});
392398

393399
describe('renderPumpSettings', () => {

test/utils/device.test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,23 @@ describe('device utility functions', () => {
182182
});
183183
});
184184

185+
describe('isControlIQ', () => {
186+
it('should return `true` for a deviceId starting with tandemCIQ', () => {
187+
const datum = { deviceId: 'tandemCIQ123456' };
188+
expect(device.isControlIQ(datum)).to.be.true;
189+
});
190+
191+
it('should return `false` for a deviceId not starting with tandemCIQ', () => {
192+
const datum = { deviceId: 'tandem123456' };
193+
expect(device.isControlIQ(datum)).to.be.false;
194+
});
195+
196+
it('should return `false` for a datum without a deviceId', () => {
197+
const datum = {};
198+
expect(device.isControlIQ(datum)).to.be.false;
199+
});
200+
});
201+
185202
describe('isLoop', () => {
186203
it('should return `true` for a matching pattern within `origin.name` for DIY Loop or Tidepool Loop', () => {
187204
const diyLoop = { origin: { name: 'com.loopkit.Loop' } };

0 commit comments

Comments
 (0)