From 657f1a748b09780834226c25c2cc3f8347f2f257 Mon Sep 17 00:00:00 2001 From: clintonium-119 Date: Fri, 10 Jan 2025 13:09:39 -0500 Subject: [PATCH 01/22] Replace Libre logo --- app/core/icons/libre_logo.svg | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/app/core/icons/libre_logo.svg b/app/core/icons/libre_logo.svg index b4aa8d7ab4..bd6b7d18d8 100644 --- a/app/core/icons/libre_logo.svg +++ b/app/core/icons/libre_logo.svg @@ -1,14 +1,19 @@ - - - + + + + + + + + + + + + + + + + + - - - - - - - - - From 64c9c6b43178b6f896da854843a9d9e7ba067cc8 Mon Sep 17 00:00:00 2001 From: clintonium-119 Date: Fri, 10 Jan 2025 17:17:46 -0500 Subject: [PATCH 02/22] Add Card component and storybook for Data Connections and Uploader --- .../elements/Card/Banners/DataConnections.png | Bin 0 -> 4224 bytes .../elements/Card/Banners/Uploader.png | Bin 0 -> 15630 bytes app/components/elements/Card/Card.js | 92 ++++++++++++++++++ app/components/elements/Card/index.js | 3 + app/themes/base/containers.js | 22 +++++ app/themes/baseTheme.js | 1 + stories/Card.stories.js | 59 +++++++++++ 7 files changed, 177 insertions(+) create mode 100644 app/components/elements/Card/Banners/DataConnections.png create mode 100644 app/components/elements/Card/Banners/Uploader.png create mode 100644 app/components/elements/Card/Card.js create mode 100644 app/components/elements/Card/index.js create mode 100644 stories/Card.stories.js diff --git a/app/components/elements/Card/Banners/DataConnections.png b/app/components/elements/Card/Banners/DataConnections.png new file mode 100644 index 0000000000000000000000000000000000000000..0248f3b4c08440684a9775e7bffe023ff7ba1c5c GIT binary patch literal 4224 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 + {bannerImage && ( + + + + )} + + + {!!title && ( + + {title} + + )} + + {!!subtitle && ( + + {subtitle} + + )} + + + {children} + + + + ); +} + +Container.propTypes = { + ...BoxProps, + bannerImage: PropTypes.elementType, + title: PropTypes.string, + subtitle: PropTypes.string, + onClick: PropTypes.func.isRequired, +}; + +Container.defaultProps = { + variant: 'fluid', + bannerImage: true, + onClick: noop, +}; + +export default Container; diff --git a/app/components/elements/Card/index.js b/app/components/elements/Card/index.js new file mode 100644 index 0000000000..b7d457fa25 --- /dev/null +++ b/app/components/elements/Card/index.js @@ -0,0 +1,3 @@ +import Card from './Card'; + +export default Card; diff --git a/app/themes/base/containers.js b/app/themes/base/containers.js index 267961fd96..8ae2182e4e 100644 --- a/app/themes/base/containers.js +++ b/app/themes/base/containers.js @@ -54,7 +54,29 @@ export default ({ borders, colors, radii, space }) => { mb: 0, }; + const card = { + ...defaultStyles, + ...fluid, + ...rounded, + borderLeft: ['none', borders.card], + borderRight: ['none', borders.card], + borderTop: borders.card, + borderBottom: borders.card, + bg: 'rgba(240, 245, 255, 1)', + mb: 0, + cursor: 'pointer', + + '.card-content': { + p: space[3], + }, + + '&:hover': { + bg: 'rgba(112, 143, 194, 0.1)', + }, + }; + return { + card, fluid, fluidRounded: { ...fluid, diff --git a/app/themes/baseTheme.js b/app/themes/baseTheme.js index b18447f809..c48ac1c74b 100755 --- a/app/themes/baseTheme.js +++ b/app/themes/baseTheme.js @@ -120,6 +120,7 @@ export const borders = { modal: `1px solid ${colors.border.modal}`, divider: `2px solid ${colors.border.divider}`, dividerDark: `2px solid ${colors.border.dividerDark}`, + card: '1px solid rgba(225, 234, 249, 1)', }; export const fonts = { diff --git a/stories/Card.stories.js b/stories/Card.stories.js new file mode 100644 index 0000000000..6f0a54f347 --- /dev/null +++ b/stories/Card.stories.js @@ -0,0 +1,59 @@ +import React from 'react'; +import { ThemeProvider } from '@emotion/react'; +import { Box, Flex } from 'theme-ui'; +import map from 'lodash/map'; +import { action } from '@storybook/addon-actions'; + +import baseTheme from '../app/themes/baseTheme'; +import Card from '../app/components/elements/Card'; +import UploaderBanner from '../app/components/elements/Card/Banners/Uploader.png'; +import DataConnectionsBanner from '../app/components/elements/Card/Banners/DataConnections.png'; + +/* eslint-disable max-len */ + +const withTheme = (Story) => ( + + + + + +); + +export default { + title: 'Cards', + decorators: [withTheme], +}; + +export const Cards = { + render: () => { + const cards = [ + { + title: 'Connect a Device Account', + subtitle: 'Does your patient have a Dexcom, LibreView, or twiist account? Automatically sync data from these accounts with the patient\'s permission.', + bannerImage: DataConnectionsBanner, + onClick: action('Connect a Device'), + }, + { + title: 'Upload Data Directly with Tidepool Uploader', + subtitle: 'Tidepool Uploader supports over 85 devices. Download Tidepool Uploader to get started.', + bannerImage: UploaderBanner, + onClick: action('Get Uploader'), + }, + ]; + + return ( + + {map(cards, card => )} + + ); + }, + + name: 'Cards', + + parameters: { + design: { + type: 'figma', + url: 'https://www.figma.com/design/LdoOQCUyQKIS2d6fUhfFJx/Cloud-to-Cloud?node-id=2044-16648&t=uxeFnlP3CHzgkNRt-0', + }, + }, +}; From 6319c65573417fee9f04e65707f31d7ef7300ae4 Mon Sep 17 00:00:00 2001 From: clintonium-119 Date: Mon, 13 Jan 2025 15:37:52 -0500 Subject: [PATCH 03/22] Update card banner images --- .../elements/Card/Banners/DataConnections.png | Bin 4224 -> 21978 bytes .../elements/Card/Banners/Uploader.png | Bin 15630 -> 79729 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/app/components/elements/Card/Banners/DataConnections.png b/app/components/elements/Card/Banners/DataConnections.png index 0248f3b4c08440684a9775e7bffe023ff7ba1c5c..44468400d9a89ed2809ef282778ab09775f28c76 100644 GIT binary patch literal 21978 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 literal 4224 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 literal 15630 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 Date: Mon, 13 Jan 2025 15:39:13 -0500 Subject: [PATCH 04/22] Add Data Connection and Uploader cards and modals to no-data view --- app/pages/patientdata/patientdata.js | 192 ++++++++++++--------------- 1 file changed, 86 insertions(+), 106 deletions(-) diff --git a/app/pages/patientdata/patientdata.js b/app/pages/patientdata/patientdata.js index 5b25759dd1..04c259cbf4 100644 --- a/app/pages/patientdata/patientdata.js +++ b/app/pages/patientdata/patientdata.js @@ -42,12 +42,9 @@ import Stats from '../../components/chart/stats'; import { bgLog as BgLog } from '../../components/chart'; import { settings as Settings } from '../../components/chart'; import UploadLaunchOverlay from '../../components/uploadlaunchoverlay'; -import baseTheme, { fontWeights, borders, radii } from '../../themes/baseTheme'; -import { Body1, Title } from '../../components/elements/FontStyles'; -import DexcomLogoIcon from '../../core/icons/DexcomLogo.svg'; +import baseTheme, { breakpoints, colors, radii } from '../../themes/baseTheme'; import Messages from '../../components/messages'; -import UploaderButton from '../../components/uploaderbutton'; import ChartDateRangeModal from '../../components/ChartDateRangeModal'; import ChartDateModal from '../../components/ChartDateModal'; import PrintDateRangeModal from '../../components/PrintDateRangeModal'; @@ -58,8 +55,11 @@ import ToastContext from '../../providers/ToastProvider'; import { Box, Flex } from 'theme-ui'; import Checkbox from '../../components/elements/Checkbox'; import PopoverLabel from '../../components/elements/PopoverLabel'; -import { Paragraph2 } from '../../components/elements/FontStyles'; -import { DIABETES_DATA_TYPES } from '../../core/constants'; +import { Body2, Paragraph2 } from '../../components/elements/FontStyles'; +import Card from '../../components/elements/Card'; +import UploaderBanner from '../../components/elements/Card/Banners/Uploader.png'; +import DataConnectionsBanner from '../../components/elements/Card/Banners/DataConnections.png'; +import DataConnectionsModal from '../../components/datasources/DataConnectionsModal'; const { Loader } = vizComponents; const { getLocalizedCeiling, getTimezoneFromTimePrefs } = vizUtils.datetime; @@ -260,116 +260,93 @@ export const PatientDataClass = createReactClass({ }, renderNoData: function() { - const { t } = this.props; - var content = t('{{patientName}} does not have any data yet.', {patientName: personUtils.patientFullName(this.props.patient)}); - var header = this.renderEmptyHeader('No Data Available'); - var uploadLaunchOverlay = this.state.showUploadOverlay ? this.renderUploadOverlay() : null; + const { t, currentPatientInViewId, isUserPatient, selectedClinicId } = this.props; + const uploadLaunchOverlay = this.state.showUploadOverlay ? this.renderUploadOverlay() : null; + const dataConnectionsModal = this.state.showDataConnectionsModal ? this.renderDataConnectionsModal() : null; - var self = this; - var handleClickUpload = function() { - self.props.trackMetric('Clicked No Data Upload'); - }; - var handleClickBlipNotes = function() { - self.props.trackMetric('Clicked No Data Get Blip Notes'); - }; - var handleClickDexcomConnect = function() { - self.props.trackMetric('Clicked No Data Connect Dexcom'); - self.props.history.push(`/patients/${self.props.currentPatientInViewId}/profile?dexcomConnect=patient-empty-data`); - }; - var handleClickLaunch = function(e) { + const self = this; + + var handleClickUpload = function(e) { if (e) { e.preventDefault(); e.stopPropagation(); } + + const properties = { patientID: currentPatientInViewId }; + if (selectedClinicId) properties.clinicId = selectedClinicId; + self.props.trackMetric('Clicked No Data Upload Card', properties); self.setState({showUploadOverlay: true}); launchCustomProtocol('tidepoolupload://open'); - } + }; - if (this.props.isUserPatient) { - content = ( - - - To upload your data, install Tidepool Uploader - - - - - If you already have Tidepool Uploader, launch it here - - - - - Sync CGM Data - + var handleClickDataConnections = function() { + const properties = { patientID: currentPatientInViewId }; + if (selectedClinicId) properties.clinicId = selectedClinicId; + self.props.trackMetric('Clicked No Data Data Connections Card', properties); + self.setState({showDataConnectionsModal: true}); + }; - - - -

- Already uploaded? Click to reload.
- Need help? Email us at support@tidepool.org or visit our help page. -

-
- ); - } + const cards = [ + { + title: isUserPatient + ? t('Connect an Account') + : t('Connect a Device Account'), + subtitle: isUserPatient + ? t('Do you have a Dexcom, LibreView or twiist account? When you connect an account, data can flow into Tidepool without any extra effort.') + : t('Does your patient have a Dexcom, LibreView, or twiist account? Automatically sync data from these accounts with the patient\'s permission.'), + bannerImage: DataConnectionsBanner, + onClick: handleClickDataConnections, + }, + { + title: t('Upload Data Directly with Tidepool Uploader'), + subtitle: t('Tidepool Uploader supports over 85 devices. Download Tidepool Uploader to get started.'), + bannerImage: UploaderBanner, + onClick: handleClickUpload, + }, + ]; return ( -
- {header} -
-
-
-
- {content} -
-
-
-
+ + + {t('No Data Available')} + + + + {_.map(cards, card => )} + + + + {uploadLaunchOverlay} -
+ {dataConnectionsModal} + ); }, renderUploadOverlay: function() { - return {this.setState({showUploadOverlay: false})}}/> + return {this.setState({ showUploadOverlay: false })}}/> + }, + + renderDataConnectionsModal: function() { + return this.setState({ showDataConnectionsModal: false })} + /> }, renderDatesDialog: function() { @@ -2250,6 +2227,7 @@ export function getFetchers(dispatchProps, ownProps, stateProps, api, options) { export function mapStateToProps(state, props) { let user = null; let patient = null; + let clinicPatient = null; let permissions = {}; let permsOfLoggedInUser = {}; @@ -2272,16 +2250,17 @@ export function mapStateToProps(state, props) { ); if (patient && state.blip.selectedClinicId) { + clinicPatient = _.get(state.blip, [ + 'clinics', + state.blip.selectedClinicId, + 'patients', + state.blip.currentPatientInViewId + ], null); + _.set( patient, 'profile.patient.mrn', - _.get(state.blip, [ - 'clinics', - state.blip.selectedClinicId, - 'patients', - state.blip.currentPatientInViewId, - 'mrn' - ]) + clinicPatient?.mrn ); } @@ -2315,6 +2294,7 @@ export function mapStateToProps(state, props) { user: user, isUserPatient: personUtils.isSame(user, patient), patient: { permissions, ...patient }, + clinicPatient, permsOfLoggedInUser: permsOfLoggedInUser, messageThread: state.blip.messageThread, fetchingPatient: state.blip.working.fetchingPatient.inProgress, From 279951625f1d07042e75e7e974ee0e3113211fb8 Mon Sep 17 00:00:00 2001 From: clintonium-119 Date: Mon, 13 Jan 2025 15:39:44 -0500 Subject: [PATCH 05/22] Update mobile responsiveness of patient navbar header to be consistent with new no-data view --- app/components/navpatientheader/index.js | 41 +++++++++++++++--------- app/pages/patientdata/patientdata.less | 15 +-------- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/app/components/navpatientheader/index.js b/app/components/navpatientheader/index.js index f2e35a6534..2a5d275553 100644 --- a/app/components/navpatientheader/index.js +++ b/app/components/navpatientheader/index.js @@ -12,10 +12,11 @@ import ClinicianMenuOptions from './MenuOptions/Clinician'; import { isClinicianAccount } from '../../core/personutils'; import { getPermissions, getPatientListLink } from './navPatientHeaderHelpers'; import UploadLaunchOverlay from '../../components/uploadlaunchoverlay'; +import { breakpoints } from '../../themes/baseTheme'; const HeaderContainer = ({ children }) => ( - ( ); -const NavPatientHeader = ({ - patient, - user, +const NavPatientHeader = ({ + patient, + user, permsOfLoggedInUser, trackMetric, - clinicFlowActive, - selectedClinicId, - query, + clinicFlowActive, + selectedClinicId, + query, }) => { const history = useHistory(); const [isUploadOverlayOpen, setIsUploadOverlayOpen] = useState(false); @@ -66,42 +67,50 @@ const NavPatientHeader = ({ trackMetric('Clicked Navbar Name'); history.push(`/patients/${patient.userid}/profile`); } - + const handleShare = () => { trackMetric('Clicked Navbar Share Data'); history.push(`/patients/${patient.userid}/share`); } return ( -
+ { isClinicianAccount(user) ? <> - + /> : <> - + /> } { isUploadOverlayOpen && - setIsUploadOverlayOpen(false)} /> + setIsUploadOverlayOpen(false)} /> } -
+ ); } -export default NavPatientHeader; \ No newline at end of file +export default NavPatientHeader; diff --git a/app/pages/patientdata/patientdata.less b/app/pages/patientdata/patientdata.less index 4486ff06be..0cc1facf5c 100644 --- a/app/pages/patientdata/patientdata.less +++ b/app/pages/patientdata/patientdata.less @@ -18,19 +18,6 @@ position: relative; } -// Header -// ==================================== - -.nav-patient-header { - margin: 0 auto 16px; - width: 100%; - max-width: @screen-lg-min; - - @media screen and (max-width: @screen-lg-min) { - padding: 0 20px; - } -} - // Subnav // ==================================== @@ -82,7 +69,7 @@ padding: @patient-data-subnav-vertical-padding @patient-data-subnav-horizontal-padding; font-size: 14px; - + &.patient-data-icon { padding: 0; } From 1089fd96853219ed87a421a7b4f1bdb9f33f06b0 Mon Sep 17 00:00:00 2001 From: clintonium-119 Date: Mon, 13 Jan 2025 17:01:07 -0500 Subject: [PATCH 06/22] Add refresh button to no-data page and clean up styling --- app/pages/patientdata/patientdata.js | 49 ++++++++++++++++++++++---- app/pages/patientdata/patientdata.less | 5 --- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/app/pages/patientdata/patientdata.js b/app/pages/patientdata/patientdata.js index 04c259cbf4..43532210f2 100644 --- a/app/pages/patientdata/patientdata.js +++ b/app/pages/patientdata/patientdata.js @@ -42,7 +42,7 @@ import Stats from '../../components/chart/stats'; import { bgLog as BgLog } from '../../components/chart'; import { settings as Settings } from '../../components/chart'; import UploadLaunchOverlay from '../../components/uploadlaunchoverlay'; -import baseTheme, { breakpoints, colors, radii } from '../../themes/baseTheme'; +import baseTheme, { breakpoints, radii } from '../../themes/baseTheme'; import Messages from '../../components/messages'; import ChartDateRangeModal from '../../components/ChartDateRangeModal'; @@ -52,10 +52,10 @@ import Button from '../../components/elements/Button'; import ToastContext from '../../providers/ToastProvider'; -import { Box, Flex } from 'theme-ui'; +import { Box, Flex, Link } from 'theme-ui'; import Checkbox from '../../components/elements/Checkbox'; import PopoverLabel from '../../components/elements/PopoverLabel'; -import { Body2, Paragraph2 } from '../../components/elements/FontStyles'; +import { Body2, Paragraph1, Paragraph2 } from '../../components/elements/FontStyles'; import Card from '../../components/elements/Card'; import UploaderBanner from '../../components/elements/Card/Banners/Uploader.png'; import DataConnectionsBanner from '../../components/elements/Card/Banners/DataConnections.png'; @@ -321,14 +321,49 @@ export const PatientDataClass = createReactClass({ color: 'white', fontWeight: 'medium', bg: 'blueGreyDark', - textAlign: 'center' + textAlign: 'center', }}>{t('No Data Available')} - - + + {_.map(cards, card => )} - + + + + + Already uploaded? Click to reload. + + + + Need help? Email us at support@tidepool.org or visit our help page. + + + + + + {uploadLaunchOverlay} diff --git a/app/pages/patientdata/patientdata.less b/app/pages/patientdata/patientdata.less index 0cc1facf5c..3b9050bdfc 100644 --- a/app/pages/patientdata/patientdata.less +++ b/app/pages/patientdata/patientdata.less @@ -302,11 +302,6 @@ } } -.patient-no-data-help { - margin-top: 100px; - line-height: 25px; -} - // Footer // ==================================== From 1bd2d26348f356992de3a944c7d5cbb31af4d7c0 Mon Sep 17 00:00:00 2001 From: clintonium-119 Date: Mon, 13 Jan 2025 17:05:05 -0500 Subject: [PATCH 07/22] Small tweak for card borders at mobile breakpoints --- app/themes/base/containers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/themes/base/containers.js b/app/themes/base/containers.js index 8ae2182e4e..d4f46fafd7 100644 --- a/app/themes/base/containers.js +++ b/app/themes/base/containers.js @@ -58,8 +58,8 @@ export default ({ borders, colors, radii, space }) => { ...defaultStyles, ...fluid, ...rounded, - borderLeft: ['none', borders.card], - borderRight: ['none', borders.card], + borderLeft: borders.card, + borderRight: borders.card, borderTop: borders.card, borderBottom: borders.card, bg: 'rgba(240, 245, 255, 1)', From 7f48e7cdc9669ef4ae0724c7efb63eca7d5b8aef Mon Sep 17 00:00:00 2001 From: clintonium-119 Date: Wed, 15 Jan 2025 10:27:06 -0500 Subject: [PATCH 08/22] Move patient data view container styling to theme.containers and improve mobile consistency --- app/components/chart/basics.js | 110 +++--- app/components/chart/bgLog.js | 125 +++---- app/components/chart/daily.js | 81 ++--- app/components/chart/header.js | 13 +- app/components/chart/settings.js | 463 +++++++++++++------------ app/components/chart/trends.js | 199 +++++------ app/pages/patientdata/patientdata.js | 59 ++-- app/pages/patientdata/patientdata.less | 44 --- app/themes/base/containers.js | 35 +- app/themes/baseTheme.js | 2 +- 10 files changed, 562 insertions(+), 569 deletions(-) diff --git a/app/components/chart/basics.js b/app/components/chart/basics.js index 89b9b6e300..0d953feac6 100644 --- a/app/components/chart/basics.js +++ b/app/components/chart/basics.js @@ -4,7 +4,7 @@ import _ from 'lodash'; import bows from 'bows'; import sundial from 'sundial'; import { withTranslation, Trans } from 'react-i18next'; -import { Flex } from 'theme-ui'; +import { Box, Flex } from 'theme-ui'; // tideline dependencies & plugins import tidelineBlip from 'tideline/plugins/blip'; @@ -81,7 +81,7 @@ class Basics extends Component { } return ( -
+
-
-
-
- - {renderedContent} - - {!this.isMissingBasics() && ( - - - - )} -
-
-
-
-
- - - - - - -
-
-
-
-
- ); + ref="header" + /> + + + + + {renderedContent} + + {!this.isMissingBasics() && ( + + )} + + + + + + + + + + + + + ); }; renderChart = () => { diff --git a/app/components/chart/bgLog.js b/app/components/chart/bgLog.js index db211c2722..3075e097b9 100644 --- a/app/components/chart/bgLog.js +++ b/app/components/chart/bgLog.js @@ -259,75 +259,76 @@ class BgLog extends Component { } return ( -
+ {this.isMissingSMBG() ? this.renderMissingSMBGHeader() : this.renderHeader()} -
-
-
- - {renderedContent} + + + + + {renderedContent} + + + - - - - - - -
-
-
-
- - - - - + + + + + + -
-
-
+
+ + + + -
+ ); }; diff --git a/app/components/chart/daily.js b/app/components/chart/daily.js index d4a1218057..78544fd440 100644 --- a/app/components/chart/daily.js +++ b/app/components/chart/daily.js @@ -23,7 +23,7 @@ import ReactDOM from 'react-dom'; import sundial from 'sundial'; import WindowSizeListener from 'react-window-size-listener'; import { withTranslation } from 'react-i18next'; -import { Flex } from 'theme-ui'; +import { Box, Flex } from 'theme-ui'; import Stats from './stats'; import BgSourceToggle from './bgSourceToggle'; @@ -287,7 +287,7 @@ class Daily extends Component { const dataQueryComplete = _.get(this.props, 'data.query.chartType') === 'daily'; return ( -
+
-
-
-
+ ref={this.headerRef} + /> + + + {dataQueryComplete && this.renderChart()} - - - -
-
-
-
- - - - - + {this.props.t('Refresh')} + + + + + + -
-
-
+ + + + + {this.state.hoveredBolus && } -
+ ); }; diff --git a/app/components/chart/header.js b/app/components/chart/header.js index f9d5673c85..f35a43ec71 100644 --- a/app/components/chart/header.js +++ b/app/components/chart/header.js @@ -8,6 +8,7 @@ import PrintRoundedIcon from '@material-ui/icons/PrintRounded'; import colorPalette from '../../themes/colorPalette'; import Icon from '../elements/Icon'; +import { Box } from 'theme-ui'; const Header = withTranslation()(class Header extends Component { static propTypes = { @@ -121,7 +122,7 @@ const Header = withTranslation()(class Header extends Component { }); return ( -
+
{t('Basics')} {t('Daily')} @@ -169,7 +170,7 @@ const Header = withTranslation()(class Header extends Component { {t('Print')}
-
+ ); }; @@ -194,11 +195,9 @@ const Header = withTranslation()(class Header extends Component { render = () => { return ( -
-
- {this.renderStandard()} -
-
+ + {this.renderStandard()} + ); }; diff --git a/app/components/chart/settings.js b/app/components/chart/settings.js index 3c8cf762da..cdcded2a6c 100644 --- a/app/components/chart/settings.js +++ b/app/components/chart/settings.js @@ -273,6 +273,214 @@ const Settings = ({ updateChartPrefs(prefs, false); }, [chartPrefs, updateChartPrefs]); + const renderSettingsSelectionUI = () => ( + + { + if (!deviceSelectionPopupState.isOpen) + trackMetric(prefixSettingsMetric('Device selection open')); + }} + sx={{ flexShrink: 0 }} + > + + + + { + trackMetric(prefixSettingsMetric('Device selection close')); + }} + onClose={() => { + deviceSelectionPopupState.close(); + }} + > + + { + setPendingDevice(event.target.value || null); + }} + /> + + + + + + + + + + + — View settings from + + + { + if (!settingsSelectionPopupState.isOpen) + trackMetric( + prefixSettingsMetric('Settings selection open') + ); + }} + sx={{ flexShrink: 0, alignItems: 'center' }} + > + + + + { + trackMetric(prefixSettingsMetric('Settings selection close')); + }} + onClose={() => { + settingsSelectionPopupState.close(); + }} + > + + + + {t('Past therapy settings')} + + + + { + setPendingSettings(event.target.value || null); + }} + /> + + + + + + + + + + ); + const renderChart = () => { const pumpSettings = _.find(groupedData, { 0: selectedDevice })?.[1]; const selectedSettings = _.find(pumpSettings, { id: selectedSettingsId }); @@ -314,7 +522,7 @@ const Settings = ({ }; return ( -
+
-
-
-
- - { - if (!deviceSelectionPopupState.isOpen) - trackMetric(prefixSettingsMetric('Device selection open')); - }} - sx={{ flexShrink: 0 }} - > - - - - { - trackMetric(prefixSettingsMetric('Device selection close')); - }} - onClose={() => { - deviceSelectionPopupState.close(); - }} - > - - { - setPendingDevice(event.target.value || null); - }} - /> - - - - - - - - - - - — View settings from - - - { - if (!settingsSelectionPopupState.isOpen) - trackMetric( - prefixSettingsMetric('Settings selection open') - ); - }} - sx={{ flexShrink: 0, alignItems: 'center' }} - > - - - - { - trackMetric(prefixSettingsMetric('Settings selection close')); - }} - onClose={() => { - settingsSelectionPopupState.close(); - }} - > - - - - {t('Past therapy settings')} - - - - { - setPendingSettings(event.target.value || null); - }} - /> - - - - - - - - - - - {selectedSettingsId ? renderChart() : renderMissingSettingsMessage()} - - - + + + + + + {selectedSettingsId ? ( + <> + {renderSettingsSelectionUI()} + {renderChart()} + + ) : renderMissingSettingsMessage()} -
-
-
-
+ + + + + + ); }; diff --git a/app/components/chart/trends.js b/app/components/chart/trends.js index 24b3f0b1c6..440a380422 100644 --- a/app/components/chart/trends.js +++ b/app/components/chart/trends.js @@ -8,7 +8,7 @@ import React, { PureComponent } from 'react'; import sundial from 'sundial'; import WindowSizeListener from 'react-window-size-listener'; import { withTranslation } from 'react-i18next'; -import { Flex } from 'theme-ui'; +import { Box, Flex } from 'theme-ui'; import Header from './header'; import SubNav from './trendssubnav'; @@ -476,102 +476,108 @@ const Trends = withTranslation()(class Trends extends PureComponent { }; return ( -
+ {this.renderHeader()} -
-
+ + + + {this.renderSubNav()} -
- -
- {dataQueryComplete && this.renderChart()} -
- - - - - - {this.props.chartPrefs.trends.showingCbg && ( - <> - - - - - - - - - )} - - {this.props.chartPrefs.trends.showingSmbg && ( - <> - - - - - - - )} - - - {dataQueryComplete && this.renderFocusedCbgDateTraceLabel()} - {dataQueryComplete && this.renderFocusedSMBGPointLabel()} - {dataQueryComplete && this.renderFocusedRangeLabels()} + + +
+ {dataQueryComplete && this.renderChart()}
-
-
-
+ + + + + + {this.props.chartPrefs.trends.showingCbg && ( + <> + + + + + + + + + )} + + {this.props.chartPrefs.trends.showingSmbg && ( + <> + + + + + + + )} + + + + {dataQueryComplete && this.renderFocusedCbgDateTraceLabel()} + {dataQueryComplete && this.renderFocusedSMBGPointLabel()} + {dataQueryComplete && this.renderFocusedRangeLabels()} + + + -
-
-
+ + -
+
); } diff --git a/app/pages/patientdata/patientdata.js b/app/pages/patientdata/patientdata.js index 43532210f2..0709c100ca 100644 --- a/app/pages/patientdata/patientdata.js +++ b/app/pages/patientdata/patientdata.js @@ -236,26 +236,23 @@ export const PatientDataClass = createReactClass({ const { t } = this.props; const headerTitle = title || t('Preparing Chart Data'); return ( -
- ); + + {headerTitle} + + ); }, renderInitialLoading: function() { - var header = this.renderEmptyHeader(); return ( -
- {header} -
-
-
-
-
-
+ + {this.renderEmptyHeader()} + + ); }, @@ -307,31 +304,14 @@ export const PatientDataClass = createReactClass({ ]; return ( - - - {t('No Data Available')} + + {this.renderEmptyHeader(t('No Data Available'))} + {_.map(cards, card => )} @@ -342,6 +322,7 @@ export const PatientDataClass = createReactClass({ flexDirection: 'column', justifyContent: ['flex-start', 'space-between'], flexGrow: 1, + textAlign: 'center', }} > diff --git a/app/pages/patientdata/patientdata.less b/app/pages/patientdata/patientdata.less index 3b9050bdfc..7e619a09ad 100644 --- a/app/pages/patientdata/patientdata.less +++ b/app/pages/patientdata/patientdata.less @@ -29,8 +29,6 @@ .patient-data-subnav-inner { color: @blue-primary; background-color: @blue-gray-dark; - border-radius: 3px 3px 0 0; - padding: 0; } @@ -140,48 +138,6 @@ float: right; } -// Content -// ==================================== - -.patient-data-content-outer { - display: block; - - @media (min-width: @patient-data-sidebar-bp) { - display: flex; - flex-wrap: nowrap; - } -} - -.patient-data-content-inner { - width: 100%; - background-color: #fff; - padding-top: 5px; - padding-bottom: 5px; -} - -.patient-data-content { - min-height: @patient-data-chart-height; - position: relative; -} - -// Sidebar -// ==================================== - -.patient-data-sidebar { - width: 100%; - background-color: #fff; - padding: @spacing-small; - - @media (min-width: @patient-data-sidebar-bp) { - flex-shrink: 0; - width: @patient-data-sidebar-width; - } -} - -.patient-data-sidebar-inner { - position: relative; -} - // Loader // ==================================== .patient-data > .loader { diff --git a/app/themes/base/containers.js b/app/themes/base/containers.js index d4f46fafd7..b050e16b39 100644 --- a/app/themes/base/containers.js +++ b/app/themes/base/containers.js @@ -1,4 +1,4 @@ -export default ({ borders, colors, radii, space }) => { +export default ({ borders, colors, radii, space, breakpoints }) => { const defaultStyles = { mx: [0, 'auto'], bg: colors.white, @@ -75,8 +75,41 @@ export default ({ borders, colors, radii, space }) => { }, }; + const patientData = { + ...bordered, + mx: [0, 4, null, null, 'auto'], + width: ['auto', null, null, 'calc(100% - 48px)'], + maxWidth: breakpoints[3], + overflow: 'hidden', + }; + + const patientDataInner = { + display: 'flex', + p: 3, + pb: 4, + bg: 'white', + minHeight: [0, 0, '50vh'], + flexDirection: 'row', + flexWrap: ['wrap', null, 'nowrap'], + gap: 4, + }; + + const patientDataContent = { + width: ['100%', null, 'auto'], + flexGrow: 1, + }; + + const patientDataSidebar = { + width: ['100%', null, '240px', '320px'], + flexShrink: 0, + }; + return { card, + patientData, + patientDataInner, + patientDataContent, + patientDataSidebar, fluid, fluidRounded: { ...fluid, diff --git a/app/themes/baseTheme.js b/app/themes/baseTheme.js index c48ac1c74b..eb3499e655 100755 --- a/app/themes/baseTheme.js +++ b/app/themes/baseTheme.js @@ -178,7 +178,7 @@ const variants = { tables: tables({ borders, colors, fonts, fontSizes, shadows, radii }), tags: tags({ colors, fonts, radii, fontWeights }), toasts: toasts({ borders, colors, radii, fontSizes, shadows }), - containers: containers({ borders, colors, radii, space }), + containers: containers({ borders, colors, radii, space, breakpoints }), }; const defaultText = { From f681004318bb0c744b567e52cd0990f42500d3d1 Mon Sep 17 00:00:00 2001 From: clintonium-119 Date: Wed, 15 Jan 2025 11:42:03 -0500 Subject: [PATCH 09/22] Add horizontal Card variant --- app/components/elements/Card/Card.js | 30 +++++++++++------------ app/themes/base/containers.js | 22 +++++++++++++++++ stories/Card.stories.js | 36 +++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 17 deletions(-) diff --git a/app/components/elements/Card/Card.js b/app/components/elements/Card/Card.js index a955e92fc1..3bee99dcc2 100644 --- a/app/components/elements/Card/Card.js +++ b/app/components/elements/Card/Card.js @@ -6,20 +6,15 @@ import noop from 'lodash/noop'; import { Body1, Title } from '../FontStyles'; export function Container(props) { - const { onClick, title, subtitle, bannerImage, children, ...themeProps } = props; + const { onClick, title, subtitle, bannerImage, children, variant, ...themeProps } = props; return ( {bannerImage && ( - + )} - - {children} - + {!!children && ( + + {children} + + )} ); @@ -81,10 +78,11 @@ Container.propTypes = { title: PropTypes.string, subtitle: PropTypes.string, onClick: PropTypes.func.isRequired, + variant: PropTypes.oneOf(['containers.card', 'containers.cardHorizontal']) }; Container.defaultProps = { - variant: 'fluid', + variant: 'containers.card', bannerImage: true, onClick: noop, }; diff --git a/app/themes/base/containers.js b/app/themes/base/containers.js index b050e16b39..221664c1dd 100644 --- a/app/themes/base/containers.js +++ b/app/themes/base/containers.js @@ -66,6 +66,10 @@ export default ({ borders, colors, radii, space, breakpoints }) => { mb: 0, cursor: 'pointer', + '.card-banner-image': { + height: ['90px', null, '120px'], + }, + '.card-content': { p: space[3], }, @@ -75,6 +79,23 @@ export default ({ borders, colors, radii, space, breakpoints }) => { }, }; + const cardHorizontal = { + ...card, + width: '100%', + display: 'flex', + // flexWrap: ['wrap', 'nowrap'], + flexWrap: ['wrap', null, 'nowrap'], + + '.card-banner-image': { + maxWidth: ['100%', null, '200px'], + // maxWidth: ['100%', '180px', '200px'], + }, + + '.card-content': { + p: space[3], + }, + }; + const patientData = { ...bordered, mx: [0, 4, null, null, 'auto'], @@ -106,6 +127,7 @@ export default ({ borders, colors, radii, space, breakpoints }) => { return { card, + cardHorizontal, patientData, patientDataInner, patientDataContent, diff --git a/stories/Card.stories.js b/stories/Card.stories.js index 6f0a54f347..640d43f416 100644 --- a/stories/Card.stories.js +++ b/stories/Card.stories.js @@ -48,7 +48,41 @@ export const Cards = { ); }, - name: 'Cards', + name: 'Default', + + parameters: { + design: { + type: 'figma', + url: 'https://www.figma.com/design/LdoOQCUyQKIS2d6fUhfFJx/Cloud-to-Cloud?node-id=2044-16648&t=uxeFnlP3CHzgkNRt-0', + }, + }, +}; + +export const HorizontalCards = { + render: () => { + const cards = [ + { + title: 'Connect a Device Account', + subtitle: 'Does your patient have a Dexcom, LibreView, or twiist account? Automatically sync data from these accounts with the patient\'s permission.', + bannerImage: DataConnectionsBanner, + onClick: action('Connect a Device'), + }, + { + title: 'Upload Data Directly with Tidepool Uploader', + subtitle: 'Tidepool Uploader supports over 85 devices. Download Tidepool Uploader to get started.', + bannerImage: UploaderBanner, + onClick: action('Get Uploader'), + }, + ]; + + return ( + + {map(cards, card => )} + + ); + }, + + name: 'Horizontal', parameters: { design: { From 5a446dd1458a6e70ea25b401f47961f71a020481 Mon Sep 17 00:00:00 2001 From: clintonium-119 Date: Wed, 15 Jan 2025 17:17:11 -0500 Subject: [PATCH 10/22] Add data connections to Therapy Settings view --- app/components/chart/settings.js | 124 ++++++++++++++++-- app/components/datasources/DataConnections.js | 6 +- .../datasources/DataConnectionsModal.js | 6 +- app/pages/clinicworkspace/ClinicPatients.js | 1 - app/pages/patientdata/patientdata.js | 6 +- app/themes/base/containers.js | 4 +- locales/en/translation.json | 2 +- locales/es/translation.json | 2 +- locales/fr/translation.json | 2 +- 9 files changed, 132 insertions(+), 21 deletions(-) diff --git a/app/components/chart/settings.js b/app/components/chart/settings.js index cdcded2a6c..3b5212182e 100644 --- a/app/components/chart/settings.js +++ b/app/components/chart/settings.js @@ -3,10 +3,12 @@ import bows from 'bows'; import PropTypes from 'prop-types'; import React, { useState, useCallback, useEffect } from 'react'; import { Trans, withTranslation } from 'react-i18next'; -import { Flex, Box, Text } from 'theme-ui'; +import { Flex, Box, Text, Divider, Link } from 'theme-ui'; import moment from 'moment-timezone'; import KeyboardArrowDownRoundedIcon from '@material-ui/icons/KeyboardArrowDownRounded'; import DateRangeRoundedIcon from '@material-ui/icons/DateRangeRounded'; +import AddRoundedIcon from '@material-ui/icons/AddRounded'; +import launchCustomProtocol from 'custom-protocol-detection'; import { bindPopover, @@ -28,7 +30,15 @@ import Button from '../elements/Button'; import Popover from '../elements/Popover'; import RadioGroup from '../../components/elements/RadioGroup'; import { usePrevious } from '../../core/hooks'; +import { clinicPatientFromAccountInfo } from '../../core/personutils'; import Icon from '../elements/Icon'; +import { useSelector } from 'react-redux'; +import DataConnections, { activeProviders } from '../../components/datasources/DataConnections'; +import DataConnectionsBanner from '../../components/elements/Card/Banners/DataConnections.png'; +import DataConnectionsModal from '../../components/datasources/DataConnectionsModal'; +import Card from '../elements/Card'; +import { Body1, MediumTitle } from '../elements/FontStyles'; +import Uploadlaunchoverlay from '../uploadlaunchoverlay'; const log = bows('Settings View'); @@ -60,6 +70,8 @@ const Settings = ({ onSwitchToBgLog, onClickPrint, patient, + clinicPatient, + isUserPatient, trackMetric, updateChartPrefs, uploadUrl, @@ -78,6 +90,10 @@ const Settings = ({ const [devices, setDevices] = useState([]); const [groupedData, setGroupedData] = useState([]); const previousSelectedDevice = usePrevious(selectedDevice); + const selectedClinicId = useSelector(state => state.blip.selectedClinicId); + const [showDataConnectionsModal, setShowDataConnectionsModal] = useState(false); + const [showUploadOverlay, setShowUploadOverlay] = useState(false); + const patientData = clinicPatient || clinicPatientFromAccountInfo(patient); const deviceSelectionPopupState = usePopupState({ variant: 'popover', @@ -259,6 +275,14 @@ const Settings = ({ onSwitchToBgLog(); }, [onSwitchToBgLog]); + + const handleClickDataConnections = function() { + const properties = { patientID: currentPatientInViewId }; + if (selectedClinicId) properties.clinicId = selectedClinicId; + trackMetric('Clicked No Data Data Connections Card', properties); + setShowDataConnectionsModal(true); + }; + const toggleSettingsSection = useCallback((deviceKey, scheduleOrProfileKey) => { const prefs = _.cloneDeep(chartPrefs); @@ -502,25 +526,98 @@ const Settings = ({ }; const renderMissingSettingsMessage = () => { - const handleClickUpload = () => { - trackMetric('Clicked Partial Data Upload, No Settings'); + const handleClickUpload = function(e) { + if (e) { + e.preventDefault(); + e.stopPropagation(); + } + + const properties = { patientID: currentPatientInViewId }; + if (selectedClinicId) properties.clinicId = selectedClinicId; + trackMetric('Clicked Partial Data Upload, No Settings', properties); + setShowUploadOverlay(true); + launchCustomProtocol('tidepoolupload://open'); }; return ( - -

The Device Settings view shows your basal rates, carb ratios, sensitivity factors and more, but it looks like you haven't uploaded pump data yet.

-

To see your Device Settings, + + This section shows basal rates, carb ratios, sensitivity factors, and more. To see Therapy Settings, upload your pump.

-

- If you just uploaded, try refreshing. -

+ onClick={handleClickUpload} + >upload data from a pump. If you just uploaded try refreshing. +
); }; + const renderDeviceConnectionCard = () => { + const cardProps = { + title: isUserPatient + ? t('Connect an Account') + : t('Connect a Device Account'), + subtitle: isUserPatient + ? t('Do you have a Dexcom, LibreView or twiist account? When you connect an account, data can flow into Tidepool without any extra effort.') + : t('Does your patient have a Dexcom, LibreView, or twiist account? Automatically sync data from these accounts with the patient\'s permission.'), + bannerImage: DataConnectionsBanner, + onClick: handleClickDataConnections, + variant: 'containers.cardHorizontal', + }; + + return ( + + ); + }; + + const renderDataConnectionsModal = () => { + const shownProviders = _.reject(activeProviders, providerName => _.find(patientData?.dataSources, { providerName })); + + return ( + setShowDataConnectionsModal(false)} + /> + ); + }; + + const renderDataConnections = () => { + const shownProviders = _.map(patientData?.dataSources, 'providerName'); + + let showAddDevicesButton = false; + _.each(activeProviders, providerName => { + if (!_.find(patientData?.dataSources, { providerName })) showAddDevicesButton = true; + }); + + return ( + + + {t('Devices')} + {showAddDevicesButton && ( + + )} + + + + + ); + }; + + const renderUploadOverlay = () => ( + setShowUploadOverlay(false)}/> + ); + return (
+ {patientData?.dataSources?.length > 0 ? renderDataConnections() : renderDeviceConnectionCard()} + + {t('Therapy Settings')} + {selectedSettingsId ? ( <> {renderSettingsSelectionUI()} @@ -568,6 +669,9 @@ const Settings = ({ + + {showDataConnectionsModal && renderDataConnectionsModal()} + {showUploadOverlay && renderUploadOverlay()} ); }; diff --git a/app/components/datasources/DataConnections.js b/app/components/datasources/DataConnections.js index a486223d4a..f1651d7913 100644 --- a/app/components/datasources/DataConnections.js +++ b/app/components/datasources/DataConnections.js @@ -8,6 +8,7 @@ import moment from 'moment-timezone'; import find from 'lodash/find'; import get from 'lodash/get'; import includes from 'lodash/includes'; +import intersection from 'lodash/intersection'; import keys from 'lodash/keys'; import map from 'lodash/map'; import max from 'lodash/max'; @@ -317,6 +318,7 @@ export const getDataConnectionProps = (patient, isLoggedInUser, selectedClinicId export const DataConnections = (props) => { const { patient, + shownProviders, trackMetric, ...themeProps } = props; @@ -519,7 +521,7 @@ export const DataConnections = (props) => { return ( <> - {map(activeProviders, (provider, i) => ( + {map(intersection(shownProviders, activeProviders), (provider, i) => ( { onClose, onBack, patient, + shownProviders, trackMetric, } = props; @@ -164,7 +165,7 @@ export const DataConnectionsModal = (props) => { )} - + @@ -213,6 +214,7 @@ DataConnectionsModal.propTypes = { onClose: PropTypes.func.isRequired, open: PropTypes.bool, patient: PropTypes.object.isRequired, + shownProviders: PropTypes.arrayOf(PropTypes.oneOf(activeProviders)), trackMetric: PropTypes.func.isRequired, }; diff --git a/app/pages/clinicworkspace/ClinicPatients.js b/app/pages/clinicworkspace/ClinicPatients.js index 5d6c5dd8d3..59962865c0 100644 --- a/app/pages/clinicworkspace/ClinicPatients.js +++ b/app/pages/clinicworkspace/ClinicPatients.js @@ -720,7 +720,6 @@ export const ClinicPatients = (props) => { }, [isFirstRender, setToast]); const handlePatientCreatedOrEdited = useCallback(() => { - console.log('creatingClinicCustodialAccount', creatingClinicCustodialAccount); if (patientFormContext?.status?.showDataConnectionsModalNext) { let currentPatient = selectedPatient; diff --git a/app/pages/patientdata/patientdata.js b/app/pages/patientdata/patientdata.js index 0709c100ca..8254b31fd7 100644 --- a/app/pages/patientdata/patientdata.js +++ b/app/pages/patientdata/patientdata.js @@ -263,7 +263,7 @@ export const PatientDataClass = createReactClass({ const self = this; - var handleClickUpload = function(e) { + const handleClickUpload = function(e) { if (e) { e.preventDefault(); e.stopPropagation(); @@ -276,7 +276,7 @@ export const PatientDataClass = createReactClass({ launchCustomProtocol('tidepoolupload://open'); }; - var handleClickDataConnections = function() { + const handleClickDataConnections = function() { const properties = { patientID: currentPatientInViewId }; if (selectedClinicId) properties.clinicId = selectedClinicId; self.props.trackMetric('Clicked No Data Data Connections Card', properties); @@ -500,6 +500,8 @@ export const PatientDataClass = createReactClass({ currentPatientInViewId={this.props.currentPatientInViewId} data={this.props.data} patient={this.props.patient} + clinicPatient={this.props.clinicPatient} + isUserPatient={this.props.isUserPatient} onClickRefresh={this.handleClickRefresh} onClickNoDataRefresh={this.handleClickNoDataRefresh} onSwitchToBasics={this.handleSwitchToBasics} diff --git a/app/themes/base/containers.js b/app/themes/base/containers.js index 221664c1dd..9b908e5124 100644 --- a/app/themes/base/containers.js +++ b/app/themes/base/containers.js @@ -106,8 +106,8 @@ export default ({ borders, colors, radii, space, breakpoints }) => { const patientDataInner = { display: 'flex', - p: 3, - pb: 4, + px: 3, + py: 4, bg: 'white', minHeight: [0, 0, '50vh'], flexDirection: 'row', diff --git a/locales/en/translation.json b/locales/en/translation.json index 73cbc7aea3..f169537110 100644 --- a/locales/en/translation.json +++ b/locales/en/translation.json @@ -493,7 +493,7 @@ "html.peopletable-instructions": "Type a patient name in the search box or click <1>Show All to display all patients.", "html.peopletable-remove-patient-confirm": "<0><0>Are you sure you want to remove patient: <1>{{fullName}}<2> from your list?<1>You will no longer be able to see or comment on their data.", "html.peopletable-remove-patient-tag-confirm": "<0>Are you sure you want to remove the tag: <1><0>{{name}} from the clinic?<1>This tag will also be removed from any patients who have been tagged with it.", - "html.setting-no-uploaded-data": "<0>The Device Settings view shows your basal rates, carb ratios, sensitivity factors and more, but it looks like you haven't uploaded pump data yet.<1>To see your Device Settings, <1>upload your pump.<2>If you just uploaded, try <1>refreshing.", + "html.setting-no-uploaded-data": "", "html.signup-clinician": "If you are a Healthcare Provider and want to create an account, please <1>click here.", "html.signup-invited": "<0>You've been invited to Tidepool.<1>Sign up to view the invitation.", "html.signup-personal": " If you are a provider who lives with diabetes and wants to track and manage your personal diabetes data, please create a separate <1>personal account.", diff --git a/locales/es/translation.json b/locales/es/translation.json index ada954d04c..acbcbd75e2 100644 --- a/locales/es/translation.json +++ b/locales/es/translation.json @@ -493,7 +493,7 @@ "html.peopletable-instructions": "Escriba el nombre de un paciente en el cuadro de búsqueda o haga clic en <1> Mostrar todo para consultar todos los pacientes.", "html.peopletable-remove-patient-confirm": "<0><0>¿Está seguro de que desea eliminar a este paciente: <1>{{fullName}}<2>de su lista?<1>Ya no podrá ver ni comentar sus datos. ", "html.peopletable-remove-patient-tag-confirm": "<0>Are you sure you want to remove the tag: <1><0>{{name}} from the clinic?<1>This tag will also be removed from any patients who have been tagged with it.", - "html.setting-no-uploaded-data": "<0> La vista Configuración del dispositivo muestra las tasas basales, las proporciones de carbohidratos, los factores de sensibilidad y más, pero parece que aún no ha cargado los datos de la bomba. su bomba. <2> Si acaba de cargar, intente <1> actualizar . ", + "html.setting-no-uploaded-data": "", "html.signup-clinician": "Si usted quiere brindar atención médica y desea crear una cuenta, <1> haga clic aquí .", "html.signup-invited": "<0> Ha sido invitado a Tidepool. <1> Regístrese para ver la invitación. ", "html.signup-personal": "Si usted es un personal medico que tiene diabetes y desea rastrear y administrar sus datos personales sobre diabetes, cree una <1> cuenta personal separada.", diff --git a/locales/fr/translation.json b/locales/fr/translation.json index 07f52b1575..4d2fb18af5 100644 --- a/locales/fr/translation.json +++ b/locales/fr/translation.json @@ -493,7 +493,7 @@ "html.peopletable-instructions": "Saisissez le nom d'un patient dans le champ de recherche ou cliquez sur <1>Tout afficher pour afficher tous les patients.", "html.peopletable-remove-patient-confirm": "<0><0>Désirez-vous vraiment retirer les données du patient: <1>{{fullName}}<2> de votre liste?<1>Vous n'aurez plus consulter ou commenter ses données.", "html.peopletable-remove-patient-tag-confirm": "<0>Are you sure you want to remove the tag: <1><0>{{name}} from the clinic?<1>This tag will also be removed from any patients who have been tagged with it.", - "html.setting-no-uploaded-data": "<0>La vue Paramètres de l'appareil affiche votre taux de basale, les ratios de glucides, les facteurs de sensibilité, et plus, mais il semblerait que vous n'avez pas encore téléchargé les données de votre pompe.<1>Pour voir vos Paramètres de l'appareil, <1>téléchargez les données de votre pompe.<2>Si vous venez de faire le téléchargement, essayez de <1>rafraîchir la fenêtre.", + "html.setting-no-uploaded-data": "", "html.signup-clinician": "Si vous êtes un professionnel de la santé et voulez créer un compte, s'il vous plaît <1>cliquez ici.", "html.signup-invited": "<0>Une invitation à rejoindre Tidepool vous a été envoyé.<1>Enregistrez vous pour consulter l'invitation.", "html.signup-personal": " Si vous êtes un aidant naturel qui vit avec le diabète et que vous désirez enregistrer et gérer vos propres données de diabète, veuillez s'il vous plaît créer un <1>compte personnel séparé.", From db2710cdb71b95dad893a4ef053d11e936c0cdbf Mon Sep 17 00:00:00 2001 From: clintonium-119 Date: Thu, 16 Jan 2025 11:35:56 -0500 Subject: [PATCH 11/22] Small mobile responsiveness tweaks to settings view --- app/components/chart/settings.js | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/app/components/chart/settings.js b/app/components/chart/settings.js index 3b5212182e..631dad5474 100644 --- a/app/components/chart/settings.js +++ b/app/components/chart/settings.js @@ -298,7 +298,14 @@ const Settings = ({ }, [chartPrefs, updateChartPrefs]); const renderSettingsSelectionUI = () => ( - + { if (!deviceSelectionPopupState.isOpen) @@ -316,8 +323,6 @@ const Settings = ({ sx={{ fontSize: 2, lineHeight: 1.3, - ml: 2, - mr: 2, fontWeight: 'bold', px: 3, py: 2, @@ -387,7 +392,7 @@ const Settings = ({ - + — View settings from @@ -410,8 +415,6 @@ const Settings = ({ sx={{ fontSize: 1, lineHeight: 1.2, - ml: 2, - mr: 2, px: 3, py: 2, }} @@ -594,15 +597,15 @@ const Settings = ({ return ( - + {t('Devices')} {showAddDevicesButton && ( From 9a761dd6a3cf63d4ba443b5b30a72704860c965d Mon Sep 17 00:00:00 2001 From: clintonium-119 Date: Thu, 16 Jan 2025 12:09:26 -0500 Subject: [PATCH 12/22] Slightly reduce clinic and patient workspace header heights to better match design specs --- app/components/clinic/ClinicWorkspaceHeader.js | 2 +- app/components/navpatientheader/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/clinic/ClinicWorkspaceHeader.js b/app/components/clinic/ClinicWorkspaceHeader.js index a355fc27e9..cd0486223c 100644 --- a/app/components/clinic/ClinicWorkspaceHeader.js +++ b/app/components/clinic/ClinicWorkspaceHeader.js @@ -71,7 +71,7 @@ export const ClinicWorkspaceHeader = (props) => { ( - Date: Fri, 17 Jan 2025 09:48:25 -0500 Subject: [PATCH 13/22] Bump tideline and viz --- package.json | 4 ++-- yarn.lock | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index ae8ae1d7fc..71f02ffae8 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "@storybook/react": "7.5.0", "@storybook/react-webpack5": "7.5.0", "@testing-library/react-hooks": "8.0.1", - "@tidepool/viz": "1.44.0-web-3179-dep-updates.3", + "@tidepool/viz": "1.45.0-web-3274-device-settings-data-sources.1", "async": "2.6.4", "autoprefixer": "10.4.16", "babel-core": "7.0.0-bridge.0", @@ -180,7 +180,7 @@ "terser": "5.22.0", "terser-webpack-plugin": "5.3.9", "theme-ui": "0.16.1", - "tideline": "1.30.0", + "tideline": "1.31.0-web-3274-device-settings-data-sources.1", "tidepool-platform-client": "0.62.0-web-3272-patient-data-linking-after-creation.1", "tidepool-standard-action": "0.1.1", "ua-parser-js": "1.0.36", diff --git a/yarn.lock b/yarn.lock index 738fb28ae3..4b90e82d81 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5278,9 +5278,9 @@ __metadata: languageName: node linkType: hard -"@tidepool/viz@npm:1.44.0-web-3179-dep-updates.3": - version: 1.44.0-web-3179-dep-updates.3 - resolution: "@tidepool/viz@npm:1.44.0-web-3179-dep-updates.3" +"@tidepool/viz@npm:1.45.0-web-3274-device-settings-data-sources.1": + version: 1.45.0-web-3274-device-settings-data-sources.1 + resolution: "@tidepool/viz@npm:1.45.0-web-3274-device-settings-data-sources.1" dependencies: bluebird: 3.7.2 bows: 1.7.2 @@ -5340,7 +5340,7 @@ __metadata: react-dom: 16.x react-redux: 8.x redux: 4.x - checksum: 050cdbc7334512123f632afc0d620b595fdcb3bd481cefd9104713b5e1e0d42e20ef1ddf367eba717232becf223a31fe56b12203c6b5aa1b616d5f0b3fe5f1af + checksum: cba24be88b1bf35b35615909358a062cbfbef4968ce4040adb4721a895a6838addb823578b2f56dc4746694dcaaaf5e249863eb383ab07673759672102f646fa languageName: node linkType: hard @@ -7251,7 +7251,7 @@ __metadata: "@storybook/react": 7.5.0 "@storybook/react-webpack5": 7.5.0 "@testing-library/react-hooks": 8.0.1 - "@tidepool/viz": 1.44.0-web-3179-dep-updates.3 + "@tidepool/viz": 1.45.0-web-3274-device-settings-data-sources.1 async: 2.6.4 autoprefixer: 10.4.16 babel-core: 7.0.0-bridge.0 @@ -7374,7 +7374,7 @@ __metadata: terser: 5.22.0 terser-webpack-plugin: 5.3.9 theme-ui: 0.16.1 - tideline: 1.30.0 + tideline: 1.31.0-web-3274-device-settings-data-sources.1 tidepool-platform-client: 0.62.0-web-3272-patient-data-linking-after-creation.1 tidepool-standard-action: 0.1.1 ua-parser-js: 1.0.36 @@ -20026,9 +20026,9 @@ __metadata: languageName: node linkType: hard -"tideline@npm:1.30.0": - version: 1.30.0 - resolution: "tideline@npm:1.30.0" +"tideline@npm:1.31.0-web-3274-device-settings-data-sources.1": + version: 1.31.0-web-3274-device-settings-data-sources.1 + resolution: "tideline@npm:1.31.0-web-3274-device-settings-data-sources.1" dependencies: bows: 1.7.2 classnames: 2.3.2 @@ -20048,7 +20048,7 @@ __metadata: peerDependencies: babel-core: 6.x || 7.0.0-bridge.0 lodash: ^4.17.21 - checksum: faf7028567b20f5136df1d2f34c70be89929c89269a68664bfad16a5cdd5dee3c8287e49ab95a641fa772f1d806c9dddd40352c3fad07bf01565b029f01d5032 + checksum: 8c14db4706c8410459f06b22f48318e4f963b5f8d4ef49b167fe169ee126533e784ff7ded859b60322fe856d2cae5185baf2eded61d5d8b3543136a865eace14 languageName: node linkType: hard From 1a8ea5a38eb1d3af96c600916b9b5612584a855c Mon Sep 17 00:00:00 2001 From: clintonium-119 Date: Fri, 17 Jan 2025 12:15:28 -0500 Subject: [PATCH 14/22] Fix broken tests --- app/components/chart/basics.js | 124 ++++----- app/components/chart/bgLog.js | 124 ++++----- app/components/chart/daily.js | 226 ++++++++-------- app/components/chart/settings.js | 110 ++++---- app/components/chart/trends.js | 254 +++++++++--------- .../datasources/DataConnectionsModal.js | 2 + app/pages/patientdata/patientdata.js | 4 + test/unit/components/chart/basics.test.js | 2 + test/unit/components/chart/settings.test.js | 83 ++++-- test/unit/pages/patientdata.test.js | 120 ++++++--- 10 files changed, 578 insertions(+), 471 deletions(-) diff --git a/app/components/chart/basics.js b/app/components/chart/basics.js index 0d953feac6..81685b483c 100644 --- a/app/components/chart/basics.js +++ b/app/components/chart/basics.js @@ -81,73 +81,75 @@ class Basics extends Component { } return ( - -
- - - - - {renderedContent} - - {!this.isMissingBasics() && ( - - )} - - - - - + +
+ + + + + {renderedContent} + + {!this.isMissingBasics() && ( + + )} + + + + + + + + - - - - + - +
); }; diff --git a/app/components/chart/bgLog.js b/app/components/chart/bgLog.js index 3075e097b9..6624e40886 100644 --- a/app/components/chart/bgLog.js +++ b/app/components/chart/bgLog.js @@ -259,76 +259,78 @@ class BgLog extends Component { } return ( - - {this.isMissingSMBG() ? this.renderMissingSMBGHeader() : this.renderHeader()} - - - - - {renderedContent} - - - +
+ + {this.isMissingSMBG() ? this.renderMissingSMBGHeader() : this.renderHeader()} + + + + + {renderedContent} - + + + + + - - + - - - + + + + + - - + - - +
); }; diff --git a/app/components/chart/daily.js b/app/components/chart/daily.js index 78544fd440..c364de451a 100644 --- a/app/components/chart/daily.js +++ b/app/components/chart/daily.js @@ -287,123 +287,125 @@ class Daily extends Component { const dataQueryComplete = _.get(this.props, 'data.query.chartType') === 'daily'; return ( - -
- - - - - {dataQueryComplete && this.renderChart()} - - - - - - - + +
+ + + + + {dataQueryComplete && this.renderChart()} + + + + + + + + + + - - - + + {this.state.hoveredBolus && } + {this.state.hoveredSMBG && } + {this.state.hoveredCBG && } + {this.state.hoveredCarb && } + {this.state.hoveredPumpSettingsOverride && } + - {this.state.hoveredBolus && } - {this.state.hoveredSMBG && } - {this.state.hoveredCBG && } - {this.state.hoveredCarb && } - {this.state.hoveredPumpSettingsOverride && } - - + ); }; diff --git a/app/components/chart/settings.js b/app/components/chart/settings.js index 631dad5474..54264c9761 100644 --- a/app/components/chart/settings.js +++ b/app/components/chart/settings.js @@ -114,6 +114,7 @@ const Settings = ({ let groupedBySource = _.groupBy(sortedData, 'source'); + console.log('groupedBySource', groupedBySource); if (_.has(groupedBySource, 'Unspecified Data Source')) { groupedBySource = _.omit(groupedBySource, 'Unspecified Data Source'); } @@ -297,8 +298,9 @@ const Settings = ({ updateChartPrefs(prefs, false); }, [chartPrefs, updateChartPrefs]); - const renderSettingsSelectionUI = () => ( + const renderDeviceSettingsSelectionUI = () => ( { const cardProps = { + id: 'data-connections-card', title: isUserPatient ? t('Connect an Account') : t('Connect a Device Account'), @@ -622,60 +625,63 @@ const Settings = ({ ); return ( - -
- - - - - - {patientData?.dataSources?.length > 0 ? renderDataConnections() : renderDeviceConnectionCard()} - - {t('Therapy Settings')} - - {selectedSettingsId ? ( - <> - {renderSettingsSelectionUI()} - {renderChart()} - - ) : renderMissingSettingsMessage()} - - - - + + {patientData?.dataSources?.length > 0 ? renderDataConnections() : renderDeviceConnectionCard()} + + {t('Therapy Settings')} + + {selectedSettingsId ? ( + <> + {renderDeviceSettingsSelectionUI()} + {renderChart()} + + ) : renderMissingSettingsMessage()} + + + + + - - {showDataConnectionsModal && renderDataConnectionsModal()} - {showUploadOverlay && renderUploadOverlay()} - + {showDataConnectionsModal && renderDataConnectionsModal()} + {showUploadOverlay && renderUploadOverlay()} + + ); }; diff --git a/app/components/chart/trends.js b/app/components/chart/trends.js index 440a380422..c587f74f98 100644 --- a/app/components/chart/trends.js +++ b/app/components/chart/trends.js @@ -476,140 +476,142 @@ const Trends = withTranslation()(class Trends extends PureComponent { }; return ( - - {this.renderHeader()} - - - - - {this.renderSubNav()} - - - -
- {dataQueryComplete && this.renderChart()} -
- - - - - - {this.props.chartPrefs.trends.showingCbg && ( - <> - - - - - - - - - )} - - {this.props.chartPrefs.trends.showingSmbg && ( - <> - - - - - - - )} +
+ + {this.renderHeader()} + + + + + {this.renderSubNav()} + + + +
+ {dataQueryComplete && this.renderChart()} +
+ + + + + + {this.props.chartPrefs.trends.showingCbg && ( + <> + + + + + + + + + )} + + {this.props.chartPrefs.trends.showingSmbg && ( + <> + + + + + + + )} + - - {dataQueryComplete && this.renderFocusedCbgDateTraceLabel()} - {dataQueryComplete && this.renderFocusedSMBGPointLabel()} - {dataQueryComplete && this.renderFocusedRangeLabels()} -
- - - - + + + + + + + - - - - +
+
- - +
); } diff --git a/app/components/datasources/DataConnectionsModal.js b/app/components/datasources/DataConnectionsModal.js index 1c2862340c..42a8b527d1 100644 --- a/app/components/datasources/DataConnectionsModal.js +++ b/app/components/datasources/DataConnectionsModal.js @@ -50,6 +50,8 @@ export const DataConnectionsModal = (props) => { const [patientEmailFormContext, setPatientEmailFormContext] = useState(); const dispatch = useDispatch(); + console.log('updatingClinicPatient', updatingClinicPatient); + const fetchPatientDetails = useCallback(() => { dispatch(actions.async.fetchPatientFromClinic(api, selectedClinicId, patient.id)); }, [dispatch, patient.id, selectedClinicId]) diff --git a/app/pages/patientdata/patientdata.js b/app/pages/patientdata/patientdata.js index 8254b31fd7..e577ddf2bc 100644 --- a/app/pages/patientdata/patientdata.js +++ b/app/pages/patientdata/patientdata.js @@ -197,6 +197,8 @@ export const PatientDataClass = createReactClass({ const isEmptyDataSet = dataFetched === 0; const rangeDataLoaded = isSettings || _.get(this.state, 'chartEndpoints.current.0', 0) !== 0; + console.log('isEmptyDataSet', isEmptyDataSet, this.props.data); + return isEmptyDataSet ? false : !dataFetched || !rangeDataLoaded; @@ -286,6 +288,7 @@ export const PatientDataClass = createReactClass({ const cards = [ { + id: 'data-connections-card', title: isUserPatient ? t('Connect an Account') : t('Connect a Device Account'), @@ -296,6 +299,7 @@ export const PatientDataClass = createReactClass({ onClick: handleClickDataConnections, }, { + id: 'uploader-card', title: t('Upload Data Directly with Tidepool Uploader'), subtitle: t('Tidepool Uploader supports over 85 devices. Download Tidepool Uploader to get started.'), bannerImage: UploaderBanner, diff --git a/test/unit/components/chart/basics.test.js b/test/unit/components/chart/basics.test.js index f5370191ea..f1aa72498b 100644 --- a/test/unit/components/chart/basics.test.js +++ b/test/unit/components/chart/basics.test.js @@ -26,6 +26,7 @@ var expect = chai.expect; import React from 'react'; import _ from 'lodash'; +import moment from 'moment'; import { mount, shallow } from 'enzyme'; import PropTypes from 'prop-types'; @@ -126,6 +127,7 @@ describe('Basics', () => { }, } }); + const noDataMessage = wrapper.find('.patient-data-message').hostNodes(); const chart = wrapper.hostNodes('BasicsChart'); expect(noDataMessage.length).to.equal(0); diff --git a/test/unit/components/chart/settings.test.js b/test/unit/components/chart/settings.test.js index 20840fcec4..db3a0a443f 100644 --- a/test/unit/components/chart/settings.test.js +++ b/test/unit/components/chart/settings.test.js @@ -46,6 +46,21 @@ describe('Settings', () => { bgUnits: MGDL_UNITS, }; + const patient = { + emails: ['user@example.com'], + userid: 'userId123', + username: 'user@example.com', + profile: { + fullName: 'Example User', + clinic: { + role: 'clinic_manager', + }, + patient: { + foo: 'bar', + }, + }, + }; + const baseProps = { chartPrefs: { settings: { @@ -60,6 +75,16 @@ describe('Settings', () => { timezoneAware: false, timezoneName: 'US/Pacific', }, + data: { + combined: [ + { + type: 'pumpSettings', + normalTime: '2023-01-01T00:00:00Z', + source: 'source1', + id: 'id1', + }, + ], + }, }, printReady: false, trackMetric: sinon.stub(), @@ -71,6 +96,7 @@ describe('Settings', () => { onSwitchToDaily: sinon.stub(), onSwitchToSettings: sinon.stub(), onSwitchToBgLog: sinon.stub(), + patient, uploadUrl: '', }; @@ -125,20 +151,7 @@ describe('Settings', () => { const defaultState = { blip: { allUsersMap: { - userId123: { - emails: ['user@example.com'], - userid: 'userId123', - username: 'user@example.com', - profile: { - fullName: 'Example User', - clinic: { - role: 'clinic_manager', - }, - patient: { - foo: 'bar', - }, - }, - }, + userId123: patient, }, loggedInUserId: 'userId123', settings: { @@ -197,6 +210,7 @@ describe('Settings', () => { onSwitchToDaily: sinon.spy(), onSwitchToSettings: sinon.spy(), onSwitchToBgLog: sinon.spy(), + patient, trackMetric: sinon.spy(), uploadUrl: '', pdf: { @@ -204,7 +218,7 @@ describe('Settings', () => { }, }; const settingsElem = React.createElement(Settings, props); - const elem = mount(settingsElem); + const elem = mount({settingsElem}); expect(elem).to.be.ok; const x = elem.find('.patient-data-message'); expect(x).to.be.ok; @@ -225,6 +239,7 @@ describe('Settings', () => { onSwitchToDaily: sinon.spy(), onSwitchToSettings: sinon.spy(), onSwitchToBgLog: sinon.spy(), + patient, trackMetric: sinon.spy(), uploadUrl: '', pdf: { @@ -232,7 +247,7 @@ describe('Settings', () => { }, }; const settingsElem = React.createElement(Settings, props); - const elem = mount(settingsElem); + const elem = mount({settingsElem}); const refreshButton = elem.find('.btn-refresh').hostNodes(); expect(props.onClickRefresh.callCount).to.equal(0); @@ -251,10 +266,11 @@ describe('Settings', () => { }, }, onClickPrint: sinon.spy(), + patient, }); const settingsElem = React.createElement(Settings, props); - const elem = mount(settingsElem); + const elem = mount({settingsElem}); const printLink = elem.find('.printview-print-icon'); expect(printLink).to.be.ok; @@ -356,7 +372,7 @@ describe('Settings', () => { expect(wrapper.find('.pump-settings-container').length).to.equal(1); }); - it('disables device selection apply button when no sources are available', () => { + it('hides device settings selection UI when no sources are available', () => { mountWrapper({ data: { data: { @@ -366,11 +382,11 @@ describe('Settings', () => { }, }); wrapper.update(); - const deviceButton = wrapper.find('button#device-selection'); - expect(deviceButton.props().disabled).to.be.true; + const deviceSettingsSelection = wrapper.find('#device-settings-selection').hostNodes(); + expect(deviceSettingsSelection).to.have.lengthOf(0); }); - it('disables settings selection apply button when no settings are available', () => { + it('hides device settings selection UI when no settings are available', () => { mountWrapper({ data: { data: { @@ -380,8 +396,8 @@ describe('Settings', () => { }, }); wrapper.update(); - const settingsButton = wrapper.find('button#settings-selection'); - expect(settingsButton.props().disabled).to.be.true; + const deviceSettingsSelection = wrapper.find('#device-settings-selection').hostNodes(); + expect(deviceSettingsSelection).to.have.lengthOf(0); }); it('calls trackMetric when device selection popover is opened', () => { @@ -532,12 +548,14 @@ describe('Settings', () => { type: 'pumpSettings', normalTime: moment('2023-01-01T00:00:00Z').valueOf(), source: 'source1', + id: 'id1', deviceSerialNumber: '1234', }, { type: 'pumpSettings', normalTime: moment('2023-01-02T00:00:00Z').valueOf(), source: 'source2', + id: 'id2', deviceSerialNumber: '5678', }, ], @@ -562,6 +580,7 @@ describe('Settings', () => { type: 'pumpSettings', normalTime: moment('2023-01-01T00:00:00Z').valueOf(), source: 'source1', + id: 'id1', }, ], }, @@ -584,6 +603,7 @@ describe('Settings', () => { type: 'pumpSettings', normalTime: moment('2023-01-01T00:00:00Z').valueOf(), source: 'Unspecified Data Source', + id: 'id1', deviceSerialNumber: '1234', }, ], @@ -604,12 +624,14 @@ describe('Settings', () => { type: 'pumpSettings', normalTime: moment('2023-01-01T00:00:00Z').valueOf(), source: 'Unspecified Data Source', + id: 'id1', deviceSerialNumber: '1234', }, { type: 'pumpSettings', normalTime: moment('2023-01-02T00:00:00Z').valueOf(), source: 'source1', + id: 'id2', deviceSerialNumber: '1234', }, ], @@ -634,6 +656,7 @@ describe('Settings', () => { type: 'pumpSettings', normalTime: moment('2023-01-01T00:00:00Z').valueOf(), source: 'source1', + id: 'id1', }, ], }, @@ -659,11 +682,13 @@ describe('Settings', () => { type: 'pumpSettings', normalTime: moment('2023-01-01T00:00:00Z').valueOf(), source: 'source1', + id: 'id1', }, { type: 'pumpSettings', normalTime: moment('2023-01-02T00:00:00Z').valueOf(), source: 'source1', + id: 'id2', }, ], }, @@ -692,16 +717,19 @@ describe('Settings', () => { type: 'pumpSettings', normalTime: moment('2023-01-01T00:00:00Z').valueOf(), source: 'source1', + id: 'id1', }, { type: 'pumpSettings', normalTime: moment('2023-01-01T00:00:00Z').valueOf(), source: 'source2', + id: 'id2', }, { type: 'pumpSettings', normalTime: moment('2023-01-03T00:00:00Z').valueOf(), source: 'source2', + id: 'id3', }, ], }, @@ -730,11 +758,13 @@ describe('Settings', () => { type: 'pumpSettings', normalTime: moment('2023-01-01T20:00:00Z').valueOf(), source: 'source1', + id: 'id1', }, { type: 'pumpSettings', normalTime: moment('2023-01-02T00:00:00Z').valueOf(), source: 'source1', + id: 'id2', }, ], }, @@ -763,16 +793,19 @@ describe('Settings', () => { type: 'pumpSettings', normalTime: moment('2023-01-01T00:00:00Z').valueOf(), source: 'source1', + id: 'id1', }, { type: 'pumpSettings', normalTime: moment('2023-02-01T00:00:00Z').valueOf(), source: 'source1', + id: 'id2', }, { type: 'pumpSettings', normalTime: moment('2022-11-01T00:00:00Z').valueOf(), source: 'source1', + id: 'id3', }, ], }, @@ -804,21 +837,25 @@ describe('Settings', () => { type: 'pumpSettings', normalTime: moment('2023-01-01T00:00:00Z').valueOf(), source: 'source1', + id: 'id1', }, { type: 'pumpSettings', normalTime: moment('2024-01-01T00:00:00Z').valueOf(), source: 'source1', + id: 'id2', }, { type: 'pumpSettings', normalTime: moment('2021-06-01T00:00:00Z').valueOf(), source: 'source1', + id: 'id3', }, { type: 'pumpSettings', normalTime: moment('2018-01-01T00:00:00Z').valueOf(), source: 'source1', + id: 'id4', }, ], }, diff --git a/test/unit/pages/patientdata.test.js b/test/unit/pages/patientdata.test.js index df71e4ff67..5c521ed77e 100644 --- a/test/unit/pages/patientdata.test.js +++ b/test/unit/pages/patientdata.test.js @@ -17,6 +17,9 @@ import { components as vizComponents } from '@tidepool/viz'; import i18next from '../../../app/core/language'; import createReactClass from 'create-react-class'; import { ThemeProvider } from '@emotion/react'; +import { Provider } from 'react-redux'; +import thunk from 'redux-thunk'; +import configureStore from 'redux-mock-store'; import baseTheme from '../../../app/themes/baseTheme'; @@ -24,6 +27,7 @@ const { Loader } = vizComponents; var assert = chai.assert; var expect = chai.expect; +const mockStore = configureStore([thunk]); const t = i18next.t.bind(i18next); @@ -31,6 +35,7 @@ const t = i18next.t.bind(i18next); // otherwise dependencies mocked will be bound to the wrong scope! import PD, { PatientData, PatientDataClass, getFetchers, mapStateToProps } from '../../../app/pages/patientdata/patientdata.js'; import { MGDL_UNITS } from '../../../app/core/constants'; +import { ToastProvider } from '../../../app/providers/ToastProvider.js'; describe('PatientData', function () { const defaultProps = { @@ -71,6 +76,7 @@ describe('PatientData', function () { }; before(() => { + PD.__Rewire__('launchCustomProtocol', _.noop); PD.__Rewire__('Basics', createReactClass({ render: function() { return (
); @@ -103,6 +109,7 @@ describe('PatientData', function () { }); after(() => { + PD.__ResetDependency__('launchCustomProtocol'); PD.__ResetDependency__('Basics'); PD.__ResetDependency__('Trends'); PD.__ResetDependency__('BgLog'); @@ -276,16 +283,18 @@ describe('PatientData', function () { }); }); - describe('no data message', () => { + describe('no data available', () => { + let dataConnectsionCard + let uploaderCard; let wrapper; - let noData; beforeEach(() => { - noData = () => wrapper.find('.patient-data-message-no-data'); + dataConnectsionCard = () => wrapper.find('#data-connections-card'); + uploaderCard = () => wrapper.find('#uploader-card'); }); describe('logged-in user is not current patient targeted for viewing', () => { - it('should render the no data message when no data is present and loading and processingData are false', function() { + it('should render the device connections and uploader cards when no data is present and loading and processingData are false', function() { var props = _.assign({}, defaultProps, { patient: { profile: { @@ -304,11 +313,14 @@ describe('PatientData', function () { } })); - expect(noData().length).to.equal(1); - expect(noData().text()).to.equal('Fooey McBar does not have any data yet.'); + expect(dataConnectsionCard().length).to.equal(1); + expect(dataConnectsionCard().text()).to.contain('Connect a Device Account'); + + expect(uploaderCard().length).to.equal(1); + expect(uploaderCard().text()).to.contain('Upload Data Directly with Tidepool Uploader'); }); - it('should render the no data message when no data is present for current patient', function() { + it('should render the device connections and uploader cards when no data is present for current patient', function() { var props = _.assign({}, defaultProps, { currentPatientInViewId: '40', patient: { @@ -335,13 +347,16 @@ describe('PatientData', function () { } })); - expect(noData().length).to.equal(1); - expect(noData().text()).to.equal('Fooey McBar does not have any data yet.'); + expect(dataConnectsionCard().length).to.equal(1); + expect(dataConnectsionCard().text()).to.contain('Connect a Device Account'); + + expect(uploaderCard().length).to.equal(1); + expect(uploaderCard().text()).to.contain('Upload Data Directly with Tidepool Uploader'); }); }); describe('logged-in user is viewing own data', () => { - it('should render the no data message when no data is present and loading and processingData are false', function() { + it('should render the device connections and uploader cards when no data is present and loading and processingData are false', function() { var props = { isUserPatient: true, fetchingPatient: false, @@ -359,10 +374,14 @@ describe('PatientData', function () { } })); - expect(noData().length).to.equal(1); + expect(dataConnectsionCard().length).to.equal(1); + expect(dataConnectsionCard().text()).to.contain('Connect an Account'); + + expect(uploaderCard().length).to.equal(1); + expect(uploaderCard().text()).to.contain('Upload Data Directly with Tidepool Uploader'); }); - it('should render the no data message when no data is present for current patient', function() { + it('should render the device connections and uploader cards when no data is present for current patient', function() { var props = { currentPatientInViewId: '40', isUserPatient: true, @@ -379,7 +398,7 @@ describe('PatientData', function () { pdf: {}, }; - wrapper = mount(); + wrapper = mount(, {}); wrapper.setProps(_.assign({}, props, { data: { @@ -387,11 +406,15 @@ describe('PatientData', function () { } })); - expect(noData().length).to.equal(1); + expect(dataConnectsionCard().length).to.equal(1); + expect(dataConnectsionCard().text()).to.contain('Connect an Account'); + + expect(uploaderCard().length).to.equal(1); + expect(uploaderCard().text()).to.contain('Upload Data Directly with Tidepool Uploader'); }); - it('should track click on main upload button', function() { - var props = { + it('should track click on Uploader card', function() { + const props = { currentPatientInViewId: '40', isUserPatient: true, patient: { @@ -418,19 +441,16 @@ describe('PatientData', function () { wrapper.update(); - expect(noData().length).to.equal(1); - - var links = wrapper.find('.patient-data-uploader-message a'); - var callCount = props.trackMetric.callCount; - - links.at(0).simulate('click'); + expect(uploaderCard().length).to.equal(1); + const callCount = props.trackMetric.callCount; + uploaderCard().simulate('click'); expect(props.trackMetric.callCount).to.equal(callCount + 1); - expect(props.trackMetric.calledWith('Clicked No Data Upload')).to.be.true; + expect(props.trackMetric.calledWith('Clicked No Data Upload Card')).to.be.true; }); - it('should track click on Dexcom Connect link', function() { - var props = { + it('should track click on Data Connections card', function() { + const props = { currentPatientInViewId: '40', isUserPatient: true, patient: { @@ -444,11 +464,43 @@ describe('PatientData', function () { removingData: { inProgress: false }, generatingPDF: { inProgress: false }, pdf: {}, - history: { push: sinon.stub() }, - trackMetric: sinon.stub() + trackMetric: sinon.stub(), + removeGeneratedPDFS: sinon.stub(), + dataWorkerRemoveDataSuccess: sinon.stub(), }; - wrapper = mount(); + const defaultWorkingState = { + inProgress: false, + completed: null, + notification: null, + }; + + const defaultState = { + blip: { + working: { + updatingClinicPatient: defaultWorkingState, + sendingPatientDataProviderConnectRequest: defaultWorkingState, + }, + }, + }; + + const store = mockStore(defaultState); + + function ProviderWrapper(props) { + const { children } = props; + + return ( + + + {children} + + + ); + } + + wrapper = mount(, { wrappingComponent: ProviderWrapper }); + + wrapper.update(); wrapper.setProps(_.assign({}, props, { data: { @@ -458,16 +510,12 @@ describe('PatientData', function () { wrapper.update(); - var link = wrapper.find('#dexcom-connect-link').hostNodes(); - var callCount = props.trackMetric.callCount; - - link.simulate('click'); - - expect(props.history.push.callCount).to.equal(1); - sinon.assert.calledWith(props.history.push, '/patients/40/profile?dexcomConnect=patient-empty-data'); + expect(dataConnectsionCard().length).to.equal(1); + const callCount = props.trackMetric.callCount; + dataConnectsionCard().simulate('click'); expect(props.trackMetric.callCount).to.equal(callCount + 1); - expect(props.trackMetric.calledWith('Clicked No Data Connect Dexcom')).to.be.true; + expect(props.trackMetric.calledWith('Clicked No Data Data Connections Card')).to.be.true; }); }); }); From 82af58adc6629035d37599f890a3c69cbeec96f0 Mon Sep 17 00:00:00 2001 From: clintonium-119 Date: Mon, 20 Jan 2025 12:28:45 -0500 Subject: [PATCH 15/22] Revert to using Header component for no-data view --- app/components/chart/settings.js | 1 - .../datasources/DataConnectionsModal.js | 2 -- app/pages/patientdata/patientdata.js | 17 +++++++---------- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/app/components/chart/settings.js b/app/components/chart/settings.js index 54264c9761..f8437b5305 100644 --- a/app/components/chart/settings.js +++ b/app/components/chart/settings.js @@ -114,7 +114,6 @@ const Settings = ({ let groupedBySource = _.groupBy(sortedData, 'source'); - console.log('groupedBySource', groupedBySource); if (_.has(groupedBySource, 'Unspecified Data Source')) { groupedBySource = _.omit(groupedBySource, 'Unspecified Data Source'); } diff --git a/app/components/datasources/DataConnectionsModal.js b/app/components/datasources/DataConnectionsModal.js index 42a8b527d1..1c2862340c 100644 --- a/app/components/datasources/DataConnectionsModal.js +++ b/app/components/datasources/DataConnectionsModal.js @@ -50,8 +50,6 @@ export const DataConnectionsModal = (props) => { const [patientEmailFormContext, setPatientEmailFormContext] = useState(); const dispatch = useDispatch(); - console.log('updatingClinicPatient', updatingClinicPatient); - const fetchPatientDetails = useCallback(() => { dispatch(actions.async.fetchPatientFromClinic(api, selectedClinicId, patient.id)); }, [dispatch, patient.id, selectedClinicId]) diff --git a/app/pages/patientdata/patientdata.js b/app/pages/patientdata/patientdata.js index e577ddf2bc..f6c4f7bcb5 100644 --- a/app/pages/patientdata/patientdata.js +++ b/app/pages/patientdata/patientdata.js @@ -197,8 +197,6 @@ export const PatientDataClass = createReactClass({ const isEmptyDataSet = dataFetched === 0; const rangeDataLoaded = isSettings || _.get(this.state, 'chartEndpoints.current.0', 0) !== 0; - console.log('isEmptyDataSet', isEmptyDataSet, this.props.data); - return isEmptyDataSet ? false : !dataFetched || !rangeDataLoaded; @@ -238,14 +236,13 @@ export const PatientDataClass = createReactClass({ const { t } = this.props; const headerTitle = title || t('Preparing Chart Data'); return ( - - {headerTitle} - +
); }, From 7203d57b6a7a5e46acabe6a2d60fd9c5d747de88 Mon Sep 17 00:00:00 2001 From: clintonium-119 Date: Tue, 21 Jan 2025 11:45:03 -0500 Subject: [PATCH 16/22] Update tests --- app/components/chart/settings.js | 18 +- app/components/datasources/DataConnections.js | 1 + app/core/personutils.js | 1 + test/unit/components/chart/settings.test.js | 308 ++++++++++++++++++ test/unit/pages/patientdata.test.js | 24 +- 5 files changed, 334 insertions(+), 18 deletions(-) diff --git a/app/components/chart/settings.js b/app/components/chart/settings.js index f8437b5305..50e7c4387c 100644 --- a/app/components/chart/settings.js +++ b/app/components/chart/settings.js @@ -91,6 +91,7 @@ const Settings = ({ const [groupedData, setGroupedData] = useState([]); const previousSelectedDevice = usePrevious(selectedDevice); const selectedClinicId = useSelector(state => state.blip.selectedClinicId); + const isClinicContext = !!selectedClinicId; const [showDataConnectionsModal, setShowDataConnectionsModal] = useState(false); const [showUploadOverlay, setShowUploadOverlay] = useState(false); const patientData = clinicPatient || clinicPatientFromAccountInfo(patient); @@ -276,10 +277,10 @@ const Settings = ({ }, [onSwitchToBgLog]); - const handleClickDataConnections = function() { - const properties = { patientID: currentPatientInViewId }; + const handleClickDataConnections = function(source) { + const properties = { patientID: currentPatientInViewId, source }; if (selectedClinicId) properties.clinicId = selectedClinicId; - trackMetric('Clicked No Data Data Connections Card', properties); + trackMetric('Clicked Settings Add Data Connections', properties); setShowDataConnectionsModal(true); }; @@ -567,7 +568,7 @@ const Settings = ({ ? t('Do you have a Dexcom, LibreView or twiist account? When you connect an account, data can flow into Tidepool without any extra effort.') : t('Does your patient have a Dexcom, LibreView, or twiist account? Automatically sync data from these accounts with the patient\'s permission.'), bannerImage: DataConnectionsBanner, - onClick: handleClickDataConnections, + onClick: handleClickDataConnections.bind(null, 'card'), variant: 'containers.cardHorizontal', }; @@ -603,10 +604,11 @@ const Settings = ({ {t('Devices')} {showAddDevicesButton && (