Skip to content

Commit 2c31303

Browse files
authored
Merge pull request #231 from tidepool-org/release-1.14.0
Release 1.14.0 to `develop`
2 parents 1cb5aad + 4e86030 commit 2c31303

File tree

6 files changed

+163
-3
lines changed

6 files changed

+163
-3
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tidepool/viz",
3-
"version": "1.14.0-develop.1",
3+
"version": "1.14.0",
44
"description": "Tidepool data visualization for diabetes device data.",
55
"keywords": [
66
"data visualization"

src/utils/AggregationUtil.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export class AggregationUtil {
3030
moment.utc(this.initialActiveEndpoints.range[0]).tz(this.timezoneName).format('YYYY-MM-DD'),
3131
moment.utc(this.initialActiveEndpoints.range[1]).tz(this.timezoneName).format('YYYY-MM-DD'),
3232
];
33+
this.excludedDevices = _.get(dataUtil, 'excludedDevices', []);
3334

3435
reductio.registerPostProcessor('postProcessBasalAggregations', this.postProcessBasalAggregations);
3536
reductio.registerPostProcessor('postProcessBolusAggregations', this.postProcessBolusAggregations);
@@ -42,6 +43,7 @@ export class AggregationUtil {
4243

4344
aggregateBasals = group => {
4445
this.dataUtil.filter.byType('basal');
46+
this.dataUtil.filter.byDeviceIds(this.excludedDevices);
4547

4648
const reducer = reductio();
4749
reducer.dataList(true);
@@ -60,6 +62,7 @@ export class AggregationUtil {
6062

6163
aggregateBoluses = group => {
6264
this.dataUtil.filter.byType('bolus');
65+
this.dataUtil.filter.byDeviceIds(this.excludedDevices);
6366

6467
const reducer = reductio();
6568
reducer.dataList(true);
@@ -83,6 +86,7 @@ export class AggregationUtil {
8386

8487
aggregateFingersticks = group => {
8588
this.dataUtil.filter.byType('smbg');
89+
this.dataUtil.filter.byDeviceIds(this.excludedDevices);
8690

8791
let reducer = reductio();
8892
reducer.dataList(true);
@@ -127,6 +131,7 @@ export class AggregationUtil {
127131

128132
aggregateSiteChanges = group => {
129133
this.dataUtil.filter.byType('deviceEvent');
134+
this.dataUtil.filter.byDeviceIds(this.excludedDevices);
130135

131136
const reducer = reductio();
132137
reducer.dataList(true);
@@ -147,6 +152,7 @@ export class AggregationUtil {
147152
aggregateDataByDate = group => {
148153
const types = _.map(this.dataUtil.types, d => d.type);
149154
this.dataUtil.filter.byTypes(types);
155+
this.dataUtil.filter.byDeviceIds(this.excludedDevices);
150156

151157
const reducer = reductio();
152158
reducer.dataList(true);
@@ -157,6 +163,7 @@ export class AggregationUtil {
157163
};
158164

159165
aggregateStatsByDate = group => {
166+
this.dataUtil.filter.byDeviceIds(this.excludedDevices);
160167
const reducer = reductio();
161168
reducer.dataList(true);
162169

src/utils/DataUtil.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export class DataUtil {
7474

7575
this.bolusToWizardIdMap = this.bolusToWizardIdMap || {};
7676
this.bolusDatumsByIdMap = this.bolusDatumsByIdMap || {};
77+
this.deviceUploadMap = this.deviceUploadMap || {};
7778
this.wizardDatumsByIdMap = this.wizardDatumsByIdMap || {};
7879
this.latestDatumByType = this.latestDatumByType || {};
7980

@@ -186,6 +187,23 @@ export class DataUtil {
186187
if (d.type === 'bolus') {
187188
this.bolusDatumsByIdMap[d.id] = d;
188189
}
190+
191+
// Generate a map of devices by deviceId
192+
if (!d.deviceId && _.get(d, 'origin.name') === 'com.apple.HealthKit') {
193+
const HKdeviceId = ['HealthKit'];
194+
if (_.get(d, 'origin.payload.sourceRevision.source.name')) {
195+
HKdeviceId.push(_.get(d, 'origin.payload.sourceRevision.source.name'));
196+
}
197+
HKdeviceId.push(d.uploadId.slice(0, 6));
198+
d.deviceId = HKdeviceId.join(' ');
199+
}
200+
if (!d.deviceId && _.get(d, 'payload.transmitterId', false)) {
201+
const dexDeviceId = ['Dexcom', d.uploadId.slice(0, 6)];
202+
d.deviceId = dexDeviceId.join(' ');
203+
}
204+
if (d.deviceId && !this.deviceUploadMap[d.deviceId]) {
205+
this.deviceUploadMap[d.deviceId] = d.uploadId;
206+
}
189207
};
190208

191209
joinWizardAndBolus = d => {
@@ -476,10 +494,12 @@ export class DataUtil {
476494
this.bolusDatumsByIdMap = {};
477495
this.wizardDatumsByIdMap = {};
478496
this.latestDatumByType = {};
497+
this.deviceUploadMap = {};
479498
delete this.bgSources;
480499
delete this.bgPrefs;
481500
delete this.timePrefs;
482501
delete this.latestPumpUpload;
502+
delete this.devices;
483503
this.init();
484504
}
485505
};
@@ -538,6 +558,10 @@ export class DataUtil {
538558
this.dimension.byType = this.data.dimension(d => d.type);
539559
};
540560

561+
buildByDeviceIdDimension = () => {
562+
this.dimension.byDeviceId = this.data.dimension(d => d.deviceId || '');
563+
};
564+
541565
// N.B. May need to become smarter about creating and removing dimensions if we get above 8,
542566
// which would introduce additional performance overhead as per crossfilter docs.
543567
buildDimensions = () => {
@@ -549,6 +573,7 @@ export class DataUtil {
549573
this.buildBySubTypeDimension();
550574
this.buildByTimeDimension();
551575
this.buildByTypeDimension();
576+
this.buildByDeviceIdDimension();
552577
this.endTimer('buildDimensions');
553578
};
554579

@@ -576,6 +601,8 @@ export class DataUtil {
576601
return this.dimension.bySubType.filterExact(subType);
577602
};
578603

604+
this.filter.byDeviceIds = (excludedDeviceIds = []) => this.dimension.byDeviceId.filterFunction(deviceId => !_.includes(excludedDeviceIds, deviceId));
605+
579606
this.filter.byId = id => this.dimension.byId.filterExact(id);
580607
this.endTimer('buildFilters');
581608
};
@@ -597,6 +624,7 @@ export class DataUtil {
597624
this.dimension.bySubType.filterAll();
598625
this.dimension.byId.filterAll();
599626
this.dimension.byDayOfWeek.filterAll();
627+
this.dimension.byDeviceId.filterAll();
600628
this.endTimer('clearFilters');
601629
};
602630

@@ -707,6 +735,43 @@ export class DataUtil {
707735
this.endTimer('setSize');
708736
};
709737

738+
/* eslint-disable no-param-reassign */
739+
setDevices = () => {
740+
this.startTimer('setDevices');
741+
const uploadsById = _.keyBy(this.sort.byTime(this.filter.byType('upload').top(Infinity)), 'uploadId');
742+
this.devices = _.reduce(this.deviceUploadMap, (result, value, key) => {
743+
const upload = uploadsById[value];
744+
let device = { id: key };
745+
746+
if (upload) {
747+
const isContinuous = _.get(upload, 'dataSetType') === 'continuous';
748+
const deviceManufacturer = _.get(upload, 'deviceManufacturers.0', '');
749+
const deviceModel = _.get(upload, 'deviceModel', '');
750+
let label = key;
751+
if (deviceManufacturer || deviceModel) {
752+
if (deviceManufacturer === 'Dexcom' && isContinuous) {
753+
label = 'Dexcom API';
754+
} else {
755+
label = [deviceManufacturer, deviceModel].join(' ');
756+
}
757+
}
758+
device = {
759+
bgm: _.includes(upload.deviceTags, 'bgm'),
760+
cgm: _.includes(upload.deviceTags, 'cgm'),
761+
id: key,
762+
label,
763+
pump: _.includes(upload.deviceTags, 'insulin-pump'),
764+
serialNumber: upload.deviceSerialNumber,
765+
};
766+
}
767+
768+
result.push(device);
769+
return result;
770+
}, []);
771+
this.endTimer('setDevices');
772+
}
773+
/* eslint-enable no-param-reassign */
774+
710775
setMetaData = () => {
711776
this.startTimer('setMetaData');
712777
this.setSize();
@@ -717,6 +782,7 @@ export class DataUtil {
717782
this.setActiveDays();
718783
this.setTypes();
719784
this.setUploadMap();
785+
this.setDevices();
720786
this.setLatestPumpUpload();
721787
this.setIncompleteSuspends();
722788
this.endTimer('setMetaData');
@@ -910,6 +976,12 @@ export class DataUtil {
910976
this.returnRawData = returnRaw;
911977
};
912978

979+
setExcludedDevices = (deviceIds = []) => {
980+
this.startTimer('setExcludedDevices');
981+
this.excludedDevices = deviceIds;
982+
this.endTimer('setExcludedDevices');
983+
}
984+
913985
query = (query = {}) => {
914986
this.log('Query', query);
915987

@@ -928,6 +1000,7 @@ export class DataUtil {
9281000
timePrefs,
9291001
types,
9301002
raw,
1003+
excludedDevices,
9311004
} = query;
9321005

9331006
// N.B. Must ensure that we get the desired endpoints in UTC time so that when we display in
@@ -944,6 +1017,7 @@ export class DataUtil {
9441017
if (timePrefs) this.setTimePrefs(timePrefs);
9451018
this.setEndpoints(endpoints, nextDays, prevDays);
9461019
this.setActiveDays(activeDays);
1020+
this.setExcludedDevices(excludedDevices);
9471021

9481022
const data = {};
9491023

@@ -958,6 +1032,9 @@ export class DataUtil {
9581032
// Filter out any inactive days of the week
9591033
this.filter.byActiveDays(this.activeDays);
9601034

1035+
// Filter out any excluded devices
1036+
this.filter.byDeviceIds(this.excludedDevices);
1037+
9611038
// Generate the stats for current range
9621039
if (this.stats.length && rangeKey === 'current') {
9631040
data[rangeKey].stats = this.getStats(this.stats);
@@ -1111,6 +1188,7 @@ export class DataUtil {
11111188
'latestPumpUpload',
11121189
'patientId',
11131190
'size',
1191+
'devices',
11141192
];
11151193

11161194
const requestedMetaData = _.isString(metaData) ? _.map(metaData.split(','), _.trim) : metaData;

src/utils/StatUtil.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ export class StatUtil {
5151
_.each(bgData, d => this.dataUtil.normalizeDatumBgUnits(d));
5252

5353
const data = {
54-
bgMax: _.maxBy(bgData, 'value').value,
55-
bgMin: _.minBy(bgData, 'value').value,
54+
bgMax: _.get(_.maxBy(bgData, 'value'), 'value', null),
55+
bgMin: _.get(_.minBy(bgData, 'value'), 'value', null),
5656
};
5757

5858
return data;

stories/data/DataUtil.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ stories.add('Query Generator', (props) => {
322322
bgSources: 'bgSources',
323323
latestDatumByType: 'latestDatumByType',
324324
latestPumpUpload: 'latestPumpUpload',
325+
devices: 'devices',
325326
size: 'size',
326327
};
327328

0 commit comments

Comments
 (0)