Skip to content

Commit

Permalink
Merge 24.3 to develop
Browse files Browse the repository at this point in the history
  • Loading branch information
labkey-teamcity committed Mar 26, 2024
2 parents a9c24aa + 412a01e commit 81a18d1
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 72 deletions.
50 changes: 34 additions & 16 deletions snprc_ehr/src/client/SndEventsWidget/SndEventsWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { FC, memo, useState, useEffect } from 'react';
import { EventListingGridPanel } from './components/EventListingGridPanel';
import './styles/sndEventsWidget.scss'
import { FormGroup, ControlLabel, FormControl } from 'react-bootstrap'
import './styles/sndEventsWidget.scss';
import { FormGroup, ControlLabel, FormControl } from 'react-bootstrap';
import { getMultiRow } from './actions';
import { Alert } from '@labkey/components';

Expand All @@ -13,22 +13,36 @@ interface Props {
export const SndEventsWidget: FC<Props> = memo((props: Props) => {
const {filterConfig, hasPermission} = props;
const [subjectIds, setSubjectIds] = useState<string[]>(['']);
const [message, setMessage] = useState<string>(undefined);
const [status, setStatus] = useState<string>(undefined);

useEffect(() => {
(async () => {
if (hasPermission && filterConfig !== undefined && filterConfig.length != 0) {
await getSubjectIdsFromFilters(filterConfig, setSubjectIds);
}
})();
}, [])
}, []);


const handleEnter = (e) => {
setSubjectIds(e.target.value.split(";"))
}
setSubjectIds(e.target.value.split(';'));
};

const handleError = (message: string) => {
setMessage(message);
setStatus("danger");
window.setTimeout(() => setMessage(undefined), 30000);
};

const handleUpdateResponse = (message: string, status: string) => {
setMessage(message);
setStatus(status);
window.setTimeout(() => setMessage(undefined), 30000);
};

const form = () => {
return(
return (
<div>
<form onSubmit={handleEnter}>
<FormGroup className={'subjectId-form'} htmlFor={'standaloneId'}>
Expand All @@ -38,13 +52,13 @@ export const SndEventsWidget: FC<Props> = memo((props: Props) => {
type={'text'}
placeholder={`Enter Subject ID`}
required={true}
onChange={(e: any) => setSubjectIds(e.target.value.split(";"))}
onChange={(e: any) => setSubjectIds(e.target.value.split(';'))}
/>
</FormGroup>
</form>
</div>
)
}
);
};

return (
<div>
Expand All @@ -61,26 +75,30 @@ export const SndEventsWidget: FC<Props> = memo((props: Props) => {
{hasPermission && subjectIds[0] === 'none' && (
<Alert>No animals were found for filter selections</Alert>
)}
{message && (
<Alert bsStyle={status}>{message}</Alert>
)}
{hasPermission && subjectIds && (
<EventListingGridPanel subjectIDs={subjectIds} />
<EventListingGridPanel subjectIDs={subjectIds} onChange={handleUpdateResponse} onError={handleError}/>
)}

</div>
)
})
);
});

const getSubjectIdsFromFilters = async (filterConfig, handleSetSubjectIds) => {
const subjectIds = [];
const filters = filterConfig.filters;
if (filters.inputType === 'roomCage' && filters.room !== null) {
const rooms = filters.room.split(',');
let ids: string[]
let ids: string[];
try {
ids = (await getMultiRow('study', 'demographicsCurLocation', 'room', rooms, []))['rows'].map(a => a.Id);
} catch (err) {
}
catch (err) {
console.log(err);
}
handleSetSubjectIds(ids.length ? ids : ['none'])
handleSetSubjectIds(ids.length ? ids : ['none']);
} else if (filters.inputType === 'multiSubject') {
const ids = filters.nonRemovable['0'] ? filters.nonRemovable['0'].value : ['none'];
handleSetSubjectIds(Array.isArray(ids) ? ids : [ids]);
Expand All @@ -89,4 +107,4 @@ const getSubjectIdsFromFilters = async (filterConfig, handleSetSubjectIds) => {
subjectIds.push(ids);
handleSetSubjectIds(subjectIds);
}
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,27 @@ interface Props {
}

export const AdmissionInfoPopover: FC<Props> = memo((props: Props) => {
const { admitChargeId, eventId } = props;
const {admitChargeId, eventId} = props;

const [admissionInfo, setAdmissionInfo] = useState<JSX.Element[]>([]);

let ref = useRef(null);

const handlePopoverEnter = async () => {
await getAdmitData(eventId, setAdmissionInfo);
}
};

const popover = (
<Popover className={"charge-id-popover"} id={"charge-id-popover"} >
<Popover className={'charge-id-popover'} id={'charge-id-popover'}>
<div>
<h4><strong>Admission Information</strong></h4>
{admissionInfo.map((d, i) => {
return <div key={i}>{d}</div>
return <div key={i}>{d}</div>;
})}
</div>
</Popover>
)
return(
);
return (
<OverlayTrigger
ref={r => (ref = r)}
container={ref.current}
Expand All @@ -38,8 +38,8 @@ export const AdmissionInfoPopover: FC<Props> = memo((props: Props) => {
shouldUpdatePosition={true}>
<span>{admitChargeId}</span>
</OverlayTrigger>
)
})
);
});

const getAdmitData = async (admitEventId, handleSetAdmissionInfo) => {

Expand All @@ -49,24 +49,24 @@ const getAdmitData = async (admitEventId, handleSetAdmissionInfo) => {
display.push(<span><strong>Admit ID:</strong> <i>{info['AdmitId']}</i></span>,
<span><strong>Diagnosis:</strong> <i>{info['Diagnosis']}</i></span>,
<span><strong>Admitting complaint:</strong> <i>{info['AdmittingComplaint']}</i></span>,
<span><strong>Admission date:</strong> <i>{info['AdmitDate'] === null ? 'Not recorded' : info['AdmitDate'].split(" ")[0]}</i></span>)
<span><strong>Admission date:</strong> <i>{info['AdmitDate'] === null ? 'Not recorded' : info['AdmitDate'].split(' ')[0]}</i></span>);

if (info['ReleaseDate'] != null) {
display.push(<span><strong>Release date:</strong> <i>{info['ReleaseDate'].split(" ")[0]}</i></span>)
display.push(<span><strong>Release date:</strong> <i>{info['ReleaseDate'].split(' ')[0]}</i></span>);
}
if (info['Resolution'] != null) {
display.push(<span><strong>Resolution:</strong> <i>{info['Resolution']}</i></span>)
display.push(<span><strong>Resolution:</strong> <i>{info['Resolution']}</i></span>);
}
} else {
display.push(<span><strong>Charge ID:</strong> <i>{info['ChargeId']}</i></span>)
display.push(<span><strong>Charge ID:</strong> <i>{info['ChargeId']}</i></span>);
if (info['Protocol'] != null) {
display.push(<span><strong>IACUC #:</strong> <i>{info['Protocol']}</i></span>,
<span><strong>IACUC Description:</strong> <i>{info['IacucDescription']}</i></span>,
<span><strong>IACUC Assignment Date:</strong> <i>{(info['AssignmentDate'] === null ? 'Not found' : info['AssignmentDate'].split(" ")[0])}</i></span>,
<span><strong>Supervising Vet:</strong> <i>{(info['Veterinarian'] === null ? 'Not recorded' : info['Veterinarian'])}</i></span>)
<span><strong>IACUC Assignment Date:</strong> <i>{(info['AssignmentDate'] === null ? 'Not found' : info['AssignmentDate'].split(' ')[0])}</i></span>,
<span><strong>Supervising Vet:</strong> <i>{(info['Veterinarian'] === null ? 'Not recorded' : info['Veterinarian'])}</i></span>);
} else {
display.push(<span><strong>Description:</strong> <i>{info['Description']}</i></span>)
display.push(<span><strong>Description:</strong> <i>{info['Description']}</i></span>);
}
}
handleSetAdmissionInfo(display);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ import { ProcedureEntryModal } from './ProcedureEntryModal';
import { AdmissionInfoPopover } from './AdmissionInfoPopover';

interface EventListingProps {
subjectIDs: string[]
subjectIDs: string[],
onChange: (message: string, status: string) => any,
onError: (message: string) => any
}

export const EventListingGridPanelImpl: FC<EventListingProps> = memo((props: EventListingProps & InjectedQueryModels) => {
const { subjectIDs, actions, queryModels } = props;
const {subjectIDs, actions, queryModels, onChange, onError} = props;

const [showDialog, setShowDialog] = useState<string>('');
const [eventID, setEventID] = useState<string>('');
Expand All @@ -30,22 +32,22 @@ export const EventListingGridPanelImpl: FC<EventListingProps> = memo((props: Eve
const {queryInfo} = queryModels[subjectIDs[0]];
if (queryInfo) {
const queryCols = new ExtendedMap<string, QueryColumn>();
queryInfo.columns.forEach( (column, key) => {
queryInfo.columns.forEach((column, key) => {
if ((column.name === 'HTMLNarrative')) {
const htmlCol = new QueryColumn({...column, ...{"cell": htmlRenderer}});
const htmlCol = new QueryColumn({...column, ...{'cell': htmlRenderer}});
queryCols.set(key, htmlCol);
} else if ((column.name === 'SubjectId')) {
const editCol = new QueryColumn({...column, ...{"cell": editButtonRenderer}});
const editCol = new QueryColumn({...column, ...{'cell': editButtonRenderer}});
queryCols.set(key, editCol);
} else if ((column.name === 'AdmitChargeId')) {
const admitCol = new QueryColumn({...column, ...{"cell": admitChargeIdPopoverRenderer}});
const admitCol = new QueryColumn({...column, ...{'cell': admitChargeIdPopoverRenderer}});
queryCols.set(key, admitCol);
} else {
queryCols.set(key, column);
}
});

const newQueryInfo = new QueryInfo({...queryInfo, ...{"columns": queryCols}});
const newQueryInfo = new QueryInfo({...queryInfo, ...{'columns': queryCols}});

// Update QueryModel with new QueryInfo
setQueryModel(
Expand All @@ -55,7 +57,7 @@ export const EventListingGridPanelImpl: FC<EventListingProps> = memo((props: Eve
);
}
}
})()
})();

}, [queryModels[subjectIDs[0]]]);

Expand Down Expand Up @@ -83,43 +85,56 @@ export const EventListingGridPanelImpl: FC<EventListingProps> = memo((props: Eve

const htmlRenderer = (data) => {
return (
<div dangerouslySetInnerHTML={{__html: data.get('value')}} />
<div dangerouslySetInnerHTML={{__html: data.get('value')}}/>
);
}
};

const handleClick = (value) => {
// Code to run when the button is clicked
setEventID(value.toString());
toggleDialog('edit');
};

const handleCloseUpdateModal = (message?: string, status?: string) => {
if (message && status) {
actions.loadModel(subjectIDs[0]);
closeDialog();
onChange(message, status);
} else if (message) {
closeDialog();
onError(message);
}
};

const editButtonRenderer = (data, row) => {
return (
<div>
<span>{data.get('value')} </span>
<button className={"pencil-btn"} onClick={function() { handleClick(row.get('EventId').get('value')) }}>
<i className={"fa fa-pencil"}></i>
</button>
<span>{data.get('value')} </span>
<button className={'pencil-btn'} onClick={function () {
handleClick(row.get('EventId').get('value'));
}}>
<i className={'fa fa-pencil'}></i>
</button>
</div>
);
}
};

const admitChargeIdPopoverRenderer = (data, row) => {
const admitChargeId = data.get('value');
const eventId = row.get('EventId').get('value');
return (
<AdmissionInfoPopover admitChargeId={admitChargeId} eventId={eventId} />
)
}
<AdmissionInfoPopover admitChargeId={admitChargeId} eventId={eventId}/>
);
};

/**
* Render the custom buttons that will be displayed on the grid
*/
const renderButtons = () => {
return (
<div className="manage-buttons">
{/*{<Button disabled={subjectIDs.length != 1} bsStyle={'success'} onClick={() => toggleDialog('create')} >*/}
{<Button disabled={true} bsStyle={'success'} onClick={() => toggleDialog('create')} >
{<Button disabled={true /*subjectIDs.length != 1*/} bsStyle={'success'}
onClick={() => toggleDialog('create')}>
New
</Button>}
</div>
Expand All @@ -130,7 +145,7 @@ export const EventListingGridPanelImpl: FC<EventListingProps> = memo((props: Eve
<div>
{queryModel?.queryInfo && (
<GridPanel model={queryModel}
title={"Events for Animal(s) " + subjectIDs.join(', ')}
title={'Events for Animal(s) ' + subjectIDs.join(', ')}
actions={actions}
highlightLastSelectedRow={true}
showPagination={true}
Expand All @@ -146,22 +161,28 @@ export const EventListingGridPanelImpl: FC<EventListingProps> = memo((props: Eve
)}
{showDialog === 'edit' && (
<ProcedureEntryModal onCancel={closeDialog}
onError={handleCloseUpdateModal}
onComplete={handleCloseUpdateModal}
eventId={eventID}
show={showDialog === 'edit'}
/>
)}
{showDialog === 'create' && (
<ProcedureEntryModal show={showDialog === 'create'} onCancel={closeDialog} subjectId={subjectIDs[0]}/>
<ProcedureEntryModal show={showDialog === 'create'}
onCancel={closeDialog}
onError={handleCloseUpdateModal}
onComplete={handleCloseUpdateModal}
subjectId={subjectIDs[0]}/>
)}

</div>
)
);
});

const EventListingGridPanelWithModels = withQueryModels<EventListingProps>(EventListingGridPanelImpl);

export const EventListingGridPanel: FC<EventListingProps> = memo((props: EventListingProps ) => {
const { subjectIDs } = props;
export const EventListingGridPanel: FC<EventListingProps> = memo((props: EventListingProps) => {
const {subjectIDs} = props;

const queryConfigs: QueryConfigMap = useMemo(
() => ({
Expand Down
Loading

0 comments on commit 81a18d1

Please sign in to comment.