Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Provider } from 'react-redux';
import { render, screen } from '@testing-library/react';
import { ThemeProvider } from 'theme-ui';
import theme from '../../../../app/themes/baseTheme';
import EditPatientDialog from '../../../../app/components/navpatientheader/EditPatientDialog';
import EditPatientDialog from '../../../../app/components/modals/EditPatientDialog';
import { ToastProvider } from '../../../../app/providers/ToastProvider';

jest.mock('../../../../app/components/clinic/PatientForm', () => {
Expand Down
8 changes: 5 additions & 3 deletions app/components/datasources/DataConnectionsModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ export const DataConnectionsModal = (props) => {
dataSources,
} : patient;

const [showPatientEmailModal, setShowPatientEmailModal] = useState(false);
const [showPatientEmailModal, setShowPatientEmailModal] = useState(false);
const [processingEmailUpdate, setProcessingEmailUpdate] = useState(false);
const [patientEmailFormContext, setPatientEmailFormContext] = useState();
const dispatch = useDispatch();

const fetchPatientDetails = useCallback(() => {
dispatch(actions.async.fetchPatientFromClinic(api, selectedClinicId, patient.id));
}, [dispatch, patient.id, selectedClinicId])
dispatch(actions.async.fetchPatientFromClinic(api, selectedClinicId, patient?.id));
}, [dispatch, patient?.id, selectedClinicId]);

// Pull the patient on load to ensure the most recent dexcom connection state is made available
useEffect(() => {
Expand Down Expand Up @@ -136,6 +136,8 @@ export const DataConnectionsModal = (props) => {
? t('Learn more.')
: t('Learn more here.');

if (!patient) return null;

return (
<>
<Dialog
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,18 @@ const PATIENT_FORM_SEARCH_DEBOUNCE_MS = 600;
const EditPatientDialog = ({
api,
trackMetric,
clinicPatient,
isOpen,
onClose = noop,
onEditSuccess = noop,
}) => {
const { t } = useTranslation();
const dispatch = useDispatch();

const selectedClinicId = useSelector((state) => state.blip.selectedClinicId);
const currentPatientInViewId = useSelector(state => state.blip.currentPatientInViewId);
const clinicPatient = useSelector(state => selectClinicPatient(state));
const clinic = useSelector(state => state.blip.clinics?.[selectedClinicId]);
const isSmartOnFhir = useSelector(selectIsSmartOnFhirMode);
const patientId = clinicPatient?.id;

const mrnSettings = useMemo(() => clinic?.mrnSettings ?? {}, [clinic?.mrnSettings]);
const existingMRNs = useSelector(state => state.blip.clinicMRNsForPatientFormValidation)?.filter(mrn => mrn !== clinicPatient?.mrn) || [];
Expand All @@ -74,7 +75,8 @@ const EditPatientDialog = ({
const onUpdateSuccess = () => {
if (isOpen) onClose();

dispatch(actions.worker.dataWorkerRemoveDataRequest(null, currentPatientInViewId));
onEditSuccess();
dispatch(actions.worker.dataWorkerRemoveDataRequest(null, patientId));
};

const updatingClinicPatient = useUpdatingClinicPatientWorkingState({ onUpdateSuccess });
Expand All @@ -89,7 +91,7 @@ const EditPatientDialog = ({
setPatientFormContext({ ...formikContext });
};

if (!currentPatientInViewId || !selectedClinicId) return null;
if (!patientId || !selectedClinicId) return null;

return (
<Dialog
Expand Down
3 changes: 2 additions & 1 deletion app/components/navpatientheader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import DemographicInfo from './DemographicInfo';
import PatientMenuOptions from './MenuOptions/Patient';
import ClinicianMenuOptions from './MenuOptions/Clinician';
import UploadLaunchOverlay from '../../components/uploadlaunchoverlay';
import EditPatientDialog from './EditPatientDialog';
import EditPatientDialog from '../modals/EditPatientDialog';

import { isClinicianAccount } from '../../core/personutils';
import { breakpoints } from '../../themes/baseTheme';
Expand Down Expand Up @@ -101,6 +101,7 @@ const NavPatientHeader = ({ api, trackMetric, patient, clinicPatient, user, perm
<EditPatientDialog
api={api}
trackMetric={trackMetric}
clinicPatient={clinicPatient}
isOpen={isEditPatientModalOpen}
onClose={() => setIsEditPatientModalOpen(false)}
/>
Expand Down
59 changes: 58 additions & 1 deletion app/pages/clinicworkspace/TideDashboardV2/Cells.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { useSelector, useDispatch } from 'react-redux';
import { useTranslation, withTranslation } from 'react-i18next';
import { Box, Flex, Text } from 'theme-ui';
import { utils as vizUtils, colors as vizColors } from '@tidepool/viz';
Expand All @@ -13,6 +13,17 @@ import utils from '../../../core/utils';
import { CATEGORY } from './FilterByCategory';
import isUndefined from 'lodash/isUndefined';

import PopoverMenu from '../../../components/elements/PopoverMenu';
import EditIcon from '@material-ui/icons/EditRounded';
import DataInIcon from '../../../core/icons/DataInIcon.svg';

import {
setEditPatientDialogIsOpen,
setEditPatientDialogPatientId,
setDataConnectionsModalIsOpen,
setDataConnectionsModalPatientId,
} from './tideDashboardSlice';

export const COMPACT = '@container (max-width: 1200px)';

export const PatientCell = ({ patient }) => {
Expand Down Expand Up @@ -221,6 +232,52 @@ export const FlagCell = ({ patient, category = null, }) => {
);
};


export const MoreMenuCell = ({ patient }) => {
const { t } = useTranslation();
const dispatch = useDispatch();

const handleOpenEditPatientDialog = () => {
dispatch(setEditPatientDialogIsOpen(true));
dispatch(setEditPatientDialogPatientId(patient.id));
};

const handleOpenDataConnectionsModal = () => {
dispatch(setDataConnectionsModalIsOpen(true));
dispatch(setDataConnectionsModalPatientId(patient.id));
};

return (
<PopoverMenu
id={`action-menu-${patient?.id}`}
items={[{
icon: EditIcon,
iconLabel: t('Edit Patient Details'),
iconPosition: 'left',
id: `edit-${patient?.id}`,
variant: 'actionListItem',
onClick: (_popupState) => {
_popupState.close();
handleOpenEditPatientDialog();
},
text: t('Edit Patient Details'),
}, {
iconSrc: DataInIcon,
iconLabel: t('Bring Data into Tidepool'),
iconPosition: 'left',
id: `edit-data-connections-${patient?.id}`,
variant: 'actionListItem',
onClick: (_popupState) => {
_popupState.close();
handleOpenDataConnectionsModal();
},
text: t('Bring Data into Tidepool'),
}]}
sx={{ position: 'relative', left: '-2px' }}
/>
);
};

export default {
PatientCell,
NumericTemplateCell,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import DataConnectionsModal from '../../../components/datasources/DataConnectionsModal';
import { closeModals } from './tideDashboardSlice';

const DataConnectionsModalController = ({ patients }) => {
const dispatch = useDispatch();

const dataConnectionsModal = useSelector(state => state.blip.tideDashboard.dataConnectionsModal);
const { patientId, isOpen } = dataConnectionsModal;

const patient = patients.find(patient => patient.id === patientId);

const handleClose = () => dispatch(closeModals());

return (
<DataConnectionsModal
open={isOpen}
patient={patient}
onClose={handleClose}
/>
);
};

export default DataConnectionsModalController;
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { closeModals } from './tideDashboardSlice';
import { RTKQueryApi } from '../../../redux/api/baseApi';
import EditPatientDialog from '../../../components/modals/EditPatientDialog';
import { tagTypes } from './tideDashboardApi';

const { TIDE_DASHBOARD_PATIENTS } = tagTypes;

const trackMetric = () => {};

const EditPatientDialogController = ({ api, patients }) => {
const dispatch = useDispatch();
const editPatientDialog = useSelector(state => state.blip.tideDashboard.editPatientDialog);

const clinicPatient = patients.find(patient => patient.id === editPatientDialog.patientId);

const handleCloseModal = () => {
dispatch(closeModals());
};

const handleEditSuccess = () => {
dispatch(RTKQueryApi.util.invalidateTags([TIDE_DASHBOARD_PATIENTS]));
};

return (
<>
<EditPatientDialog
api={api}
trackMetric={trackMetric}
clinicPatient={clinicPatient}
isOpen={editPatientDialog.isOpen}
onClose={handleCloseModal}
onEditSuccess={handleEditSuccess}
/>
</>
);
};

export default EditPatientDialogController;
18 changes: 15 additions & 3 deletions app/pages/clinicworkspace/TideDashboardV2/TideDashboardV2.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,16 @@ import useTableColumns from './useTableColumns';
import EmptyContentNode from './EmptyContentNode';
import FilterBySites from './FilterBySites';
import PatientCount from '../components/PatientCount';
import EditPatientDialogController from './EditPatientDialogController';
import DataConnectionsModalController from './DataConnectionsModalController';

const LIMIT = 12;

const Divider = () => <Box id='filter-divider' mx={2} sx={{ border: `1px solid ${vizColors.gray05}`, height: '24px' }}></Box>;

const Gap = () => <Box sx={{ marginLeft: 'auto' }}></Box>;

const TideDashboard = () => {
const TideDashboard = ({ api, trackMetric }) => {
const { t } = useTranslation();
const dispatch = useDispatch();

Expand Down Expand Up @@ -69,7 +71,7 @@ const TideDashboard = () => {

if (!data) return null;

const tableData = data?.data || [];
const patients = data?.data || [];

const total = data?.meta?.count || 0;

Expand All @@ -95,7 +97,7 @@ const TideDashboard = () => {
variant="condensed"
label="tideDashboardPatientsTable"
columns={tableColumns}
data={tableData}
data={patients}
emptyContentNode={<EmptyContentNode />}
containerProps={{ sx: { containerType: 'inline-size' } }}
// sx={tableStyle}
Expand All @@ -119,6 +121,16 @@ const TideDashboard = () => {
</Flex>
<Box></Box>
</Grid>

<EditPatientDialogController
api={api}
trackMetric={trackMetric}
patients={patients}
/>

<DataConnectionsModalController
patients={patients}
/>
</>
);
};
Expand Down
10 changes: 10 additions & 0 deletions app/pages/clinicworkspace/TideDashboardV2/tideDashboardApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ export const buildGetTideDashboardPatientsParams = (offset, limit, category, las
};
};

export const tagTypes = {
TIDE_DASHBOARD_PATIENTS: 'TIDE_DASHBOARD_PATIENTS',
};

const { TIDE_DASHBOARD_PATIENTS } = tagTypes;

RTKQueryApi.enhanceEndpoints({
addTagTypes: [TIDE_DASHBOARD_PATIENTS],
});

const tideDashboardApi = RTKQueryApi.injectEndpoints({
endpoints: (builder) => ({
Expand All @@ -52,6 +61,7 @@ const tideDashboardApi = RTKQueryApi.injectEndpoints({
...response,
category: arg.category,
}),
providesTags: [TIDE_DASHBOARD_PATIENTS],
}),
}),
});
Expand Down
36 changes: 35 additions & 1 deletion app/pages/clinicworkspace/TideDashboardV2/tideDashboardSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ import { CATEGORY } from './FilterByCategory';
const initialState = {
category: CATEGORY.DEFAULT,
offset: 0,
editPatientDialog: {
patientId: null,
isOpen: false,
},
dataConnectionsModal: {
patientId: null,
isOpen: false,
},
};

const tideDashboardSlice = createSlice({
Expand All @@ -17,9 +25,35 @@ const tideDashboardSlice = createSlice({
setOffset: (state, action) => {
state.offset = action.payload;
},
setEditPatientDialogPatientId: (state, action) => {
state.editPatientDialog.patientId = action.payload;
},
setEditPatientDialogIsOpen: (state, action) => {
state.editPatientDialog.isOpen = action.payload;
},
setDataConnectionsModalPatientId: (state, action) => {
state.dataConnectionsModal.patientId = action.payload;
},
setDataConnectionsModalIsOpen: (state, action) => {
state.dataConnectionsModal.isOpen = action.payload;
},
closeModals: (state) => {
state.editPatientDialog = initialState.editPatientDialog;
state.dataConnectionsModal = initialState.dataConnectionsModal;
},
resetTideDashboardState: () => initialState,
},
});

export const { setCategory, setOffset, resetTideDashboardState } = tideDashboardSlice.actions;
export const {
setCategory,
setOffset,
setEditPatientDialogPatientId,
setEditPatientDialogIsOpen,
setDataConnectionsModalPatientId,
setDataConnectionsModalIsOpen,
closeModals,
resetTideDashboardState,
} = tideDashboardSlice.actions;

export default tideDashboardSlice.reducer;
4 changes: 3 additions & 1 deletion app/pages/clinicworkspace/TideDashboardV2/useTableColumns.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
TimeInAnyHighPercentCell,
TimeInTargetPercentCell,
FlagCell,
MoreMenuCell,
} from './Cells';

import TagListCell from '../components/TagListCell';
Expand Down Expand Up @@ -113,9 +114,10 @@ const getColumnTypes = (t, category, thresholds) => ({
align: 'center',
},
moreMenu: {
title: t(''),
title: '',
field: 'moreMenu',
align: 'center',
render: patient => <MoreMenuCell patient={patient} />,
}, // More
});

Expand Down