@openmrs/esm-patient-tests-app 11.3.1-patch.9310 → 11.3.1-patch.9508
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +19 -22
- package/dist/1119.js +1 -1
- package/dist/1197.js +1 -1
- package/dist/{6231.js → 1477.js} +1 -1
- package/dist/1477.js.map +1 -0
- package/dist/1638.js +1 -1
- package/dist/1638.js.map +1 -1
- package/dist/1935.js +1 -0
- package/dist/1935.js.map +1 -0
- package/dist/2146.js +1 -1
- package/dist/2690.js +1 -1
- package/dist/3099.js +1 -1
- package/dist/34.js +1 -0
- package/dist/34.js.map +1 -0
- package/dist/3509.js +1 -1
- package/dist/3509.js.map +1 -1
- package/dist/3584.js +1 -1
- package/dist/4055.js +1 -1
- package/dist/4132.js +1 -1
- package/dist/4300.js +1 -1
- package/dist/4335.js +1 -1
- package/dist/439.js +1 -0
- package/dist/4618.js +1 -1
- package/dist/4652.js +1 -1
- package/dist/4944.js +1 -1
- package/dist/5173.js +1 -1
- package/dist/5241.js +1 -1
- package/dist/5442.js +1 -1
- package/dist/5661.js +1 -1
- package/dist/5670.js +1 -1
- package/dist/6022.js +1 -1
- package/dist/6113.js +1 -0
- package/dist/6113.js.map +1 -0
- package/dist/6301.js +1 -1
- package/dist/6301.js.map +1 -1
- package/dist/6468.js +1 -1
- package/dist/6589.js +1 -0
- package/dist/6679.js +1 -1
- package/dist/6840.js +1 -1
- package/dist/6859.js +1 -1
- package/dist/7097.js +1 -1
- package/dist/7159.js +1 -1
- package/dist/7202.js +1 -0
- package/dist/7202.js.map +1 -0
- package/dist/723.js +1 -1
- package/dist/7617.js +1 -1
- package/dist/790.js +1 -1
- package/dist/790.js.map +1 -1
- package/dist/795.js +1 -1
- package/dist/8163.js +1 -1
- package/dist/8349.js +1 -1
- package/dist/8371.js +1 -0
- package/dist/8555.js +2 -0
- package/dist/8555.js.map +1 -0
- package/dist/8618.js +1 -1
- package/dist/890.js +1 -1
- package/dist/9214.js +1 -1
- package/dist/9538.js +1 -1
- package/dist/9569.js +1 -1
- package/dist/986.js +1 -1
- package/dist/9879.js +1 -1
- package/dist/9895.js +1 -1
- package/dist/9900.js +1 -1
- package/dist/9913.js +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-patient-tests-app.js +1 -1
- package/dist/openmrs-esm-patient-tests-app.js.buildmanifest.json +302 -211
- package/dist/openmrs-esm-patient-tests-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +2 -2
- package/src/edit-test-results/modal/edit-lab-results.modal.tsx +2 -2
- package/src/index.ts +1 -1
- package/src/routes.json +4 -3
- package/src/test-orders/add-test-order/add-test-order.test.tsx +44 -21
- package/src/test-orders/add-test-order/add-test-order.workspace.tsx +152 -21
- package/src/test-orders/add-test-order/test-order-form.component.tsx +60 -68
- package/src/test-orders/add-test-order/test-order.ts +3 -3
- package/src/test-orders/add-test-order/test-type-search.component.tsx +60 -28
- package/src/test-orders/api.ts +2 -6
- package/src/test-orders/lab-order-basket-panel/lab-icon.component.tsx +27 -0
- package/src/test-orders/lab-order-basket-panel/lab-order-basket-item-tile.component.tsx +1 -1
- package/src/test-orders/lab-order-basket-panel/lab-order-basket-panel.extension.tsx +95 -30
- package/src/test-orders/lab-order-basket-panel/lab-order-basket-panel.scss +26 -11
- package/src/test-orders/lab-order-basket-panel/lab-order-basket-panel.test.tsx +12 -10
- package/src/test-results/filter/filter-context.test.tsx +556 -0
- package/src/test-results/filter/filter-context.tsx +1 -1
- package/src/test-results/filter/filter-reducer.test.ts +540 -0
- package/src/test-results/filter/filter-reducer.ts +1 -1
- package/src/test-results/filter/filter-set.component.tsx +75 -48
- package/src/test-results/filter/filter-set.test.tsx +694 -0
- package/src/test-results/filter/filter-types.ts +5 -1
- package/src/test-results/grouped-timeline/grid.component.tsx +4 -2
- package/src/test-results/grouped-timeline/grouped-timeline.component.tsx +20 -22
- package/src/test-results/grouped-timeline/grouped-timeline.test.tsx +3 -2
- package/src/test-results/grouped-timeline/reference-range-helpers.test.ts +37 -1
- package/src/test-results/grouped-timeline/reference-range-helpers.ts +50 -1
- package/src/test-results/grouped-timeline/timeline-data-group.component.tsx +4 -4
- package/src/test-results/grouped-timeline/useObstreeData.test.ts +471 -0
- package/src/test-results/grouped-timeline/useObstreeData.ts +37 -4
- package/src/test-results/individual-results-table/individual-results-table.component.tsx +2 -7
- package/src/test-results/individual-results-table-tablet/individual-results-table-tablet.component.tsx +3 -3
- package/src/test-results/individual-results-table-tablet/lab-set-panel.component.tsx +2 -5
- package/src/test-results/individual-results-table-tablet/usePanelData.tsx +40 -26
- package/src/test-results/loadPatientTestData/helpers.ts +29 -12
- package/src/test-results/loadPatientTestData/usePatientResultsData.ts +18 -7
- package/src/test-results/overview/external-overview.extension.tsx +1 -2
- package/src/test-results/print-modal/print-modal.extension.tsx +1 -1
- package/src/test-results/results-viewer/results-viewer.extension.tsx +8 -4
- package/src/test-results/tree-view/tree-view.component.tsx +18 -5
- package/src/test-results/tree-view/tree-view.test.tsx +119 -2
- package/src/test-results/trendline/trendline.component.tsx +88 -52
- package/src/test-results/ui-elements/{resetFiltersEmptyState → reset-filters-empty-state}/filter-empty-data-illustration.tsx +2 -2
- package/src/test-results/ui-elements/{resetFiltersEmptyState → reset-filters-empty-state}/filter-empty-state.component.tsx +5 -6
- package/src/types.ts +9 -0
- package/translations/am.json +3 -4
- package/translations/ar.json +3 -4
- package/translations/ar_SY.json +3 -4
- package/translations/bn.json +3 -4
- package/translations/cs.json +119 -0
- package/translations/de.json +3 -4
- package/translations/en.json +3 -4
- package/translations/en_US.json +3 -4
- package/translations/es.json +3 -4
- package/translations/es_MX.json +3 -4
- package/translations/fr.json +3 -4
- package/translations/he.json +3 -4
- package/translations/hi.json +3 -4
- package/translations/hi_IN.json +3 -4
- package/translations/id.json +3 -4
- package/translations/it.json +3 -4
- package/translations/ka.json +3 -4
- package/translations/km.json +3 -4
- package/translations/ku.json +3 -4
- package/translations/ky.json +3 -4
- package/translations/lg.json +3 -4
- package/translations/ne.json +3 -4
- package/translations/pl.json +3 -4
- package/translations/pt.json +3 -4
- package/translations/pt_BR.json +3 -4
- package/translations/qu.json +3 -4
- package/translations/ro_RO.json +3 -4
- package/translations/ru_RU.json +3 -4
- package/translations/si.json +3 -4
- package/translations/sq.json +119 -0
- package/translations/sw.json +3 -4
- package/translations/sw_KE.json +3 -4
- package/translations/tr.json +3 -4
- package/translations/tr_TR.json +3 -4
- package/translations/uk.json +3 -4
- package/translations/uz.json +3 -4
- package/translations/uz@Latn.json +3 -4
- package/translations/uz_UZ.json +3 -4
- package/translations/vi.json +3 -4
- package/translations/zh.json +3 -4
- package/translations/zh_CN.json +3 -4
- package/translations/zh_TW.json +119 -0
- package/dist/1479.js +0 -1
- package/dist/1479.js.map +0 -1
- package/dist/5348.js +0 -1
- package/dist/5348.js.map +0 -1
- package/dist/6231.js.map +0 -1
- package/dist/9540.js +0 -2
- package/dist/9540.js.map +0 -1
- package/dist/9838.js +0 -1
- package/dist/9838.js.map +0 -1
- package/src/test-orders/add-test-order/add-test-order.component.tsx +0 -125
- package/src/test-orders/add-test-order/exported-add-test-order.workspace.tsx +0 -30
- /package/dist/{9540.js.LICENSE.txt → 8555.js.LICENSE.txt} +0 -0
- /package/src/test-results/ui-elements/{resetFiltersEmptyState/index.scss → reset-filters-empty-state/filter-empty-state.scss} +0 -0
|
@@ -53,7 +53,7 @@ export type LowestNode = Pick<TreeNode, 'display' | 'flatName'>;
|
|
|
53
53
|
export interface ReducerState {
|
|
54
54
|
checkboxes: TreeCheckboxes;
|
|
55
55
|
parents: TreeParents;
|
|
56
|
-
roots: Array<
|
|
56
|
+
roots: Array<TreeNode>;
|
|
57
57
|
tests: TreeTests;
|
|
58
58
|
lowestParents: Array<TreeNode>;
|
|
59
59
|
}
|
|
@@ -147,3 +147,7 @@ export interface RowData extends TreeNode {
|
|
|
147
147
|
| undefined
|
|
148
148
|
>;
|
|
149
149
|
}
|
|
150
|
+
|
|
151
|
+
export interface EmptyStateProps {
|
|
152
|
+
clearFilter(): void;
|
|
153
|
+
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import styles from './grid.scss';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
interface GridProps {
|
|
5
5
|
children?: React.ReactNode;
|
|
6
6
|
style: React.CSSProperties;
|
|
7
7
|
padding?: boolean;
|
|
8
8
|
dataColumns: number;
|
|
9
|
-
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const Grid: React.FC<GridProps> = ({ dataColumns, style = {}, padding = false, ...props }) => {
|
|
10
12
|
return (
|
|
11
13
|
<div
|
|
12
14
|
style={{
|
|
@@ -21,29 +21,27 @@ export const GroupedTimeline: React.FC<{ patientUuid: string }> = ({ patientUuid
|
|
|
21
21
|
|
|
22
22
|
if (activeTests && timelineData && loaded && tableData) {
|
|
23
23
|
return (
|
|
24
|
-
<div>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const subRows = rowData?.filter((row: { flatName: string }) => panelTestNames.includes(row.flatName));
|
|
24
|
+
<div className={styles.timelineDataContainer}>
|
|
25
|
+
{tableData.map((panel, index) => {
|
|
26
|
+
// Filter rowData to only include tests that belong to this panel
|
|
27
|
+
const panelTestNames = panel.entries.map((entry) => entry.flatName);
|
|
28
|
+
const subRows = rowData?.filter((row: { flatName: string }) => panelTestNames.includes(row.flatName));
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
</div>
|
|
30
|
+
return (
|
|
31
|
+
subRows?.length > 0 && (
|
|
32
|
+
<div key={index}>
|
|
33
|
+
<TimelineDataGroup
|
|
34
|
+
groupNumber={index + 1}
|
|
35
|
+
parent={{ display: panel.key, flatName: panel.key }}
|
|
36
|
+
patientUuid={patientUuid}
|
|
37
|
+
setXScroll={setXScroll}
|
|
38
|
+
subRows={subRows}
|
|
39
|
+
xScroll={xScroll}
|
|
40
|
+
/>
|
|
41
|
+
</div>
|
|
42
|
+
)
|
|
43
|
+
);
|
|
44
|
+
})}
|
|
47
45
|
</div>
|
|
48
46
|
);
|
|
49
47
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render, screen } from '@testing-library/react';
|
|
3
2
|
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
4
|
import { getByTextWithMarkup } from 'tools';
|
|
5
5
|
import { showModal } from '@openmrs/esm-framework';
|
|
6
6
|
import { mockGroupedResults } from '__mocks__';
|
|
@@ -62,7 +62,8 @@ describe('GroupedTimeline', () => {
|
|
|
62
62
|
expect(screen.getByText('Nov 9')).toBeInTheDocument();
|
|
63
63
|
expect(screen.getByText('01:39 AM')).toBeInTheDocument();
|
|
64
64
|
expect(screen.getByText('Total bilirubin')).toBeInTheDocument();
|
|
65
|
-
|
|
65
|
+
// Units are now combined with range, so if there's no range, units won't be displayed separately
|
|
66
|
+
// Total bilirubin doesn't have a range in timelineData, so units are not displayed
|
|
66
67
|
expect(screen.getByText('261.9')).toBeInTheDocument();
|
|
67
68
|
expect(screen.getByText('21.5')).toBeInTheDocument();
|
|
68
69
|
expect(screen.getByText('Serum glutamic-pyruvic transaminase')).toBeInTheDocument();
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
formatRangeWithUnits,
|
|
3
3
|
formatReferenceRange,
|
|
4
4
|
getMostRecentObservationWithRange,
|
|
5
5
|
rangeAlreadyHasUnits,
|
|
6
|
+
selectReferenceRange,
|
|
6
7
|
type ReferenceRanges,
|
|
7
8
|
} from './reference-range-helpers';
|
|
8
9
|
|
|
@@ -269,4 +270,39 @@ describe('Reference Range Helpers', () => {
|
|
|
269
270
|
expect(rangeAlreadyHasUnits('0 – 50', '')).toBe(false);
|
|
270
271
|
});
|
|
271
272
|
});
|
|
273
|
+
|
|
274
|
+
describe('formatRangeWithUnits', () => {
|
|
275
|
+
it('returns "--" when range is undefined', () => {
|
|
276
|
+
expect(formatRangeWithUnits(undefined, 'U/L')).toBe('--');
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('returns "--" when range is empty string', () => {
|
|
280
|
+
expect(formatRangeWithUnits('', 'U/L')).toBe('--');
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('returns range as-is when range already includes units', () => {
|
|
284
|
+
expect(formatRangeWithUnits('0 – 50 U/L', 'U/L')).toBe('0 – 50 U/L');
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('appends units when range does not include units', () => {
|
|
288
|
+
expect(formatRangeWithUnits('0 – 50', 'U/L')).toBe('0 – 50 U/L');
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('returns range without units when units is undefined', () => {
|
|
292
|
+
expect(formatRangeWithUnits('0 – 50', undefined)).toBe('0 – 50');
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('returns range without units when units is empty', () => {
|
|
296
|
+
expect(formatRangeWithUnits('0 – 50', '')).toBe('0 – 50');
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it('handles trimmed strings correctly', () => {
|
|
300
|
+
expect(formatRangeWithUnits(' 0 – 50 ', ' U/L ')).toBe('0 – 50 U/L');
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it('handles range with units and different units parameter', () => {
|
|
304
|
+
// If range already has units, don't append different units
|
|
305
|
+
expect(formatRangeWithUnits('0 – 50 mg/dL', 'U/L')).toBe('0 – 50 mg/dL');
|
|
306
|
+
});
|
|
307
|
+
});
|
|
272
308
|
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { exist } from '../loadPatientTestData/helpers';
|
|
2
|
-
import type { OBSERVATION_INTERPRETATION } from '@openmrs/esm-patient-common-lib';
|
|
3
2
|
|
|
4
3
|
export interface ReferenceRanges {
|
|
5
4
|
hiAbsolute?: number;
|
|
@@ -82,6 +81,56 @@ export function rangeAlreadyHasUnits(range: string | undefined, units: string |
|
|
|
82
81
|
return trimmedRange.endsWith(trimmedUnits) || trimmedRange.endsWith(` ${trimmedUnits}`);
|
|
83
82
|
}
|
|
84
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Checks if a range string already contains any units (common unit patterns).
|
|
86
|
+
* This helps detect if a range already has units even if they differ from the parameter.
|
|
87
|
+
* @param range The formatted range string (e.g., "0 – 50 mg/dL")
|
|
88
|
+
* @returns true if the range appears to already contain units, false otherwise
|
|
89
|
+
*/
|
|
90
|
+
function rangeHasAnyUnits(range: string): boolean {
|
|
91
|
+
if (!range) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const trimmedRange = range.trim();
|
|
96
|
+
// Common unit patterns: ends with common unit abbreviations or contains unit-like patterns
|
|
97
|
+
// This is a heuristic to detect if units are already present
|
|
98
|
+
const unitPattern = /\s+[a-zA-Z\/%°]+$/;
|
|
99
|
+
return unitPattern.test(trimmedRange);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Formats a reference range with units for display, avoiding duplicate units.
|
|
104
|
+
* @param range The formatted range string (may or may not include units)
|
|
105
|
+
* @param units The units string to append if not already present
|
|
106
|
+
* @returns Formatted string with range and units (e.g., "0 – 50 U/L")
|
|
107
|
+
*/
|
|
108
|
+
export function formatRangeWithUnits(range: string | undefined, units: string | undefined): string {
|
|
109
|
+
const trimmedRange = range?.trim() || '';
|
|
110
|
+
const trimmedUnits = units?.trim() || '';
|
|
111
|
+
|
|
112
|
+
// If range is empty, return '--' (even if units exist, we need a range to display)
|
|
113
|
+
if (!trimmedRange) {
|
|
114
|
+
return '--';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Check if range already includes the specific units parameter
|
|
118
|
+
const hasSpecificUnits = rangeAlreadyHasUnits(trimmedRange, trimmedUnits);
|
|
119
|
+
if (hasSpecificUnits) {
|
|
120
|
+
return trimmedRange;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Check if range already has any units (even if different from parameter)
|
|
124
|
+
// This prevents appending units when range already has different units (e.g., "0 – 50 mg/dL" with "U/L" parameter)
|
|
125
|
+
const hasAnyUnits = rangeHasAnyUnits(trimmedRange);
|
|
126
|
+
if (hasAnyUnits) {
|
|
127
|
+
return trimmedRange;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Append units if not already present
|
|
131
|
+
return trimmedUnits ? `${trimmedRange} ${trimmedUnits}` : trimmedRange;
|
|
132
|
+
}
|
|
133
|
+
|
|
85
134
|
/**
|
|
86
135
|
* Finds the most recent observation that has reference range data.
|
|
87
136
|
*/
|
|
@@ -9,8 +9,8 @@ import type {
|
|
|
9
9
|
NewRowStartCellProps,
|
|
10
10
|
TimelineDataGroupProps,
|
|
11
11
|
} from './grouped-timeline-types';
|
|
12
|
+
import { getMostRecentObservationWithRange, formatRangeWithUnits } from './reference-range-helpers';
|
|
12
13
|
import FilterContext from '../filter/filter-context';
|
|
13
|
-
import { getMostRecentObservationWithRange } from './reference-range-helpers';
|
|
14
14
|
import styles from './grouped-timeline.scss';
|
|
15
15
|
|
|
16
16
|
export const ShadowBox: React.FC = () => <div className={styles['shadow-box']} />;
|
|
@@ -131,6 +131,8 @@ const NewRowStartCell: React.FC<NewRowStartCellProps> = ({
|
|
|
131
131
|
});
|
|
132
132
|
}, [patientUuid, conceptUuid, title]);
|
|
133
133
|
|
|
134
|
+
const rangeUnitsDisplay = formatRangeWithUnits(range, units);
|
|
135
|
+
|
|
134
136
|
return (
|
|
135
137
|
<div
|
|
136
138
|
className={styles.rowStartCell}
|
|
@@ -147,9 +149,7 @@ const NewRowStartCell: React.FC<NewRowStartCellProps> = ({
|
|
|
147
149
|
<span className={styles.trendlineLink}>{title}</span>
|
|
148
150
|
)}
|
|
149
151
|
</span>
|
|
150
|
-
<span className={styles.rangeUnits}>
|
|
151
|
-
{range} {units}
|
|
152
|
-
</span>
|
|
152
|
+
<span className={styles.rangeUnits}>{rangeUnitsDisplay}</span>
|
|
153
153
|
</div>
|
|
154
154
|
);
|
|
155
155
|
};
|