uhc-portal-components-react 0.1.43 → 0.1.44
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/CHANGELOG.md +7 -0
- package/dist/ClinicalArtifactEditor.d.ts +15 -1
- package/dist/ClinicalArtifactEditor.d.ts.map +1 -1
- package/dist/ClinicalArtifactEditor.js +31 -3
- package/dist/ClinicalBundleDraftEditor.d.ts +5 -2
- package/dist/ClinicalBundleDraftEditor.d.ts.map +1 -1
- package/dist/ClinicalBundleDraftEditor.js +27 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.1.44 - 2026-10-07
|
|
6
|
+
|
|
7
|
+
- Let the shared IPS editor hydrate claims-first resources from an imported
|
|
8
|
+
document Bundle so they remain locally editable before the single final send.
|
|
9
|
+
- Expose governed terminology source selection with the server default selected
|
|
10
|
+
and optional multi-source searches for typed or dictated clinical text.
|
|
11
|
+
|
|
5
12
|
## 0.1.43 - 2026-10-07
|
|
6
13
|
|
|
7
14
|
- Require the `gdc-common-utils-ts` release that provides the Composition
|
|
@@ -63,7 +63,19 @@ export type ClinicalTerminologySearch = Readonly<{
|
|
|
63
63
|
text: string;
|
|
64
64
|
taxonomyId?: string;
|
|
65
65
|
limit: number;
|
|
66
|
+
sources?: readonly string[];
|
|
66
67
|
}>;
|
|
68
|
+
export type ClinicalTerminologySource = Readonly<{
|
|
69
|
+
id: string;
|
|
70
|
+
label?: string;
|
|
71
|
+
default?: boolean;
|
|
72
|
+
}>;
|
|
73
|
+
export type ClinicalTerminologySourceSearch = (input: Readonly<{
|
|
74
|
+
resourceType: string;
|
|
75
|
+
claim: string;
|
|
76
|
+
language: string;
|
|
77
|
+
taxonomyId?: string;
|
|
78
|
+
}>) => Promise<readonly ClinicalTerminologySource[]>;
|
|
67
79
|
export type ClinicalArtifactEditorCopy = Readonly<{
|
|
68
80
|
title: string;
|
|
69
81
|
description: string;
|
|
@@ -73,6 +85,7 @@ export type ClinicalArtifactEditorCopy = Readonly<{
|
|
|
73
85
|
close: string;
|
|
74
86
|
terminologyLoading: string;
|
|
75
87
|
terminologyUnavailable: string;
|
|
88
|
+
terminologySources?: string;
|
|
76
89
|
readbackMissing: string;
|
|
77
90
|
pending?: string;
|
|
78
91
|
retry?: string;
|
|
@@ -102,6 +115,7 @@ export type ClinicalArtifactEditorProps = Readonly<{
|
|
|
102
115
|
taxonomyId?: string;
|
|
103
116
|
fieldLabel: (claim: string) => string;
|
|
104
117
|
searchTerminology?: (input: ClinicalTerminologySearch) => Promise<readonly ClinicalTerminologyCandidate[]>;
|
|
118
|
+
loadTerminologySources?: ClinicalTerminologySourceSearch;
|
|
105
119
|
saveArtifact: (draft: ClinicalArtifactDraft) => Promise<ClinicalResourceBundleLike | ClinicalArtifactSaveOutcome | undefined>;
|
|
106
120
|
onCancel: () => void;
|
|
107
121
|
onReadback: (bundle: ClinicalResourceBundleLike) => void;
|
|
@@ -111,5 +125,5 @@ export type ClinicalArtifactEditorProps = Readonly<{
|
|
|
111
125
|
* persistence and terminology service access. A successful form submission is
|
|
112
126
|
* published only after the host returns a fresh provider readback Bundle.
|
|
113
127
|
*/
|
|
114
|
-
export declare function ClinicalArtifactEditor({ request, schema, operationSchema, authoringContext, copy, locale, timeZone, taxonomyId, fieldLabel, searchTerminology, saveArtifact, onCancel, onReadback, }: ClinicalArtifactEditorProps): import("react").JSX.Element;
|
|
128
|
+
export declare function ClinicalArtifactEditor({ request, schema, operationSchema, authoringContext, copy, locale, timeZone, taxonomyId, fieldLabel, searchTerminology, loadTerminologySources, saveArtifact, onCancel, onReadback, }: ClinicalArtifactEditorProps): import("react").JSX.Element;
|
|
115
129
|
//# sourceMappingURL=ClinicalArtifactEditor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClinicalArtifactEditor.d.ts","sourceRoot":"","sources":["../src/ClinicalArtifactEditor.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ClinicalArtifactEditor.d.ts","sourceRoot":"","sources":["../src/ClinicalArtifactEditor.tsx"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ import { ClinicalSpeechInputButton } from './ClinicalSpeechInput.js';
|
|
|
10
10
|
* persistence and terminology service access. A successful form submission is
|
|
11
11
|
* published only after the host returns a fresh provider readback Bundle.
|
|
12
12
|
*/
|
|
13
|
-
export function ClinicalArtifactEditor({ request, schema, operationSchema, authoringContext, copy, locale = 'en', timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone, taxonomyId, fieldLabel, searchTerminology, saveArtifact, onCancel, onReadback, }) {
|
|
13
|
+
export function ClinicalArtifactEditor({ request, schema, operationSchema, authoringContext, copy, locale = 'en', timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone, taxonomyId, fieldLabel, searchTerminology, loadTerminologySources, saveArtifact, onCancel, onReadback, }) {
|
|
14
14
|
const titleId = useId();
|
|
15
15
|
const descriptionId = useId();
|
|
16
16
|
const acceptedClaims = useMemo(() => operationSchema
|
|
@@ -53,13 +53,40 @@ export function ClinicalArtifactEditor({ request, schema, operationSchema, autho
|
|
|
53
53
|
const [candidates, setCandidates] = useState([]);
|
|
54
54
|
const [terminologyBusy, setTerminologyBusy] = useState(false);
|
|
55
55
|
const [terminologyError, setTerminologyError] = useState(false);
|
|
56
|
+
const [terminologySources, setTerminologySources] = useState([]);
|
|
57
|
+
const [selectedTerminologySources, setSelectedTerminologySources] = useState([]);
|
|
58
|
+
const [terminologySourcesClaim, setTerminologySourcesClaim] = useState('');
|
|
56
59
|
const [saving, setSaving] = useState(false);
|
|
57
60
|
const [error, setError] = useState('');
|
|
58
61
|
const [pending, setPending] = useState('');
|
|
59
62
|
const draftId = useRef(request.artifactId ?? crypto.randomUUID());
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (!activeTerminologyClaim || !loadTerminologySources)
|
|
65
|
+
return;
|
|
66
|
+
const codeClaim = terminologyCodeClaim(request.resourceType, activeTerminologyClaim);
|
|
67
|
+
let current = true;
|
|
68
|
+
setTerminologySourcesClaim('');
|
|
69
|
+
void loadTerminologySources({ resourceType: request.resourceType, claim: codeClaim, language: locale, taxonomyId }).then((sources) => {
|
|
70
|
+
if (!current)
|
|
71
|
+
return;
|
|
72
|
+
setTerminologySources(sources);
|
|
73
|
+
const defaults = sources.filter(source => source.default).map(source => source.id);
|
|
74
|
+
setSelectedTerminologySources(defaults.length ? defaults : sources[0] ? [sources[0].id] : []);
|
|
75
|
+
setTerminologySourcesClaim(activeTerminologyClaim);
|
|
76
|
+
}).catch(() => {
|
|
77
|
+
if (current) {
|
|
78
|
+
setTerminologySources([]);
|
|
79
|
+
setSelectedTerminologySources([]);
|
|
80
|
+
setTerminologySourcesClaim(activeTerminologyClaim);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
return () => { current = false; };
|
|
84
|
+
}, [activeTerminologyClaim, loadTerminologySources, locale, request.resourceType, taxonomyId]);
|
|
60
85
|
useEffect(() => {
|
|
61
86
|
if (!activeTerminologyClaim || !searchTerminology)
|
|
62
87
|
return;
|
|
88
|
+
if (loadTerminologySources && terminologySourcesClaim !== activeTerminologyClaim)
|
|
89
|
+
return;
|
|
63
90
|
const sourceText = claims[activeTerminologyClaim]?.trim() ?? '';
|
|
64
91
|
if (sourceText.length < 2) {
|
|
65
92
|
setCandidates([]);
|
|
@@ -77,6 +104,7 @@ export function ClinicalArtifactEditor({ request, schema, operationSchema, autho
|
|
|
77
104
|
text: sourceText,
|
|
78
105
|
taxonomyId,
|
|
79
106
|
limit: 20,
|
|
107
|
+
...(selectedTerminologySources.length ? { sources: selectedTerminologySources } : {}),
|
|
80
108
|
}).then((nextCandidates) => {
|
|
81
109
|
if (current)
|
|
82
110
|
setCandidates(nextCandidates);
|
|
@@ -91,7 +119,7 @@ export function ClinicalArtifactEditor({ request, schema, operationSchema, autho
|
|
|
91
119
|
});
|
|
92
120
|
}, 250);
|
|
93
121
|
return () => { current = false; window.clearTimeout(timer); };
|
|
94
|
-
}, [activeTerminologyClaim, claims, locale, request.resourceType, searchTerminology, taxonomyId]);
|
|
122
|
+
}, [activeTerminologyClaim, claims, loadTerminologySources, locale, request.resourceType, searchTerminology, selectedTerminologySources, taxonomyId, terminologySourcesClaim]);
|
|
95
123
|
async function submit() {
|
|
96
124
|
setSaving(true);
|
|
97
125
|
setError('');
|
|
@@ -151,7 +179,7 @@ export function ClinicalArtifactEditor({ request, schema, operationSchema, autho
|
|
|
151
179
|
setActiveTerminologyClaim(claim);
|
|
152
180
|
};
|
|
153
181
|
return _jsxs("div", { className: fieldClassName, children: [_jsxs("span", { className: "uhcp-clinical-editor-field-heading", children: [_jsxs("label", { htmlFor: inputId, children: [label, requiredClaims.has(claim) ? ' *' : ''] }), isSpeechCompatibleField(parameter, schemaNode) ? _jsx(ClinicalSpeechInputButton, { resourceType: request.resourceType, claim: claim, locale: locale, fieldLabel: label, onTranscript: appendTranscript }) : null] }), statusOptions(request.resourceType, parameter) ? _jsxs("select", { id: inputId, "aria-label": label, value: value, required: requiredClaims.has(claim), onChange: update, children: [!requiredClaims.has(claim) ? _jsx("option", { value: "" }) : null, statusOptions(request.resourceType, parameter).map((option) => _jsx("option", { value: option, children: humanize(option) }, option))] }) : isMultiline(parameter) ? _jsx("textarea", { id: inputId, "aria-label": label, value: value, required: requiredClaims.has(claim), rows: 3, onChange: update })
|
|
154
|
-
: _jsx("input", { id: inputId, "aria-label": label, value: value, required: requiredClaims.has(claim), type: fieldInputType(parameter, operationSchema?.properties.claims?.properties?.[claim]), onChange: update }), terminologyEnabled && activeTerminologyClaim === claim ? _jsxs("div", { className: "uhcp-terminology-results", children: [terminologyBusy ? _jsx("small", { role: "status", children: copy.terminologyLoading }) : null, terminologyError ? _jsx("small", { role: "alert", children: copy.terminologyUnavailable }) : null, candidates.length ? _jsx("ul", { children: candidates.map((candidate) => _jsx("li", { children: _jsxs("button", { type: "button", onClick: () => {
|
|
182
|
+
: _jsx("input", { id: inputId, "aria-label": label, value: value, required: requiredClaims.has(claim), type: fieldInputType(parameter, operationSchema?.properties.claims?.properties?.[claim]), onChange: update }), terminologyEnabled && activeTerminologyClaim === claim ? _jsxs("div", { className: "uhcp-terminology-results", children: [terminologySources.length ? _jsxs("label", { children: [copy.terminologySources || 'Coding systems', _jsx("select", { multiple: true, "aria-label": copy.terminologySources || 'Coding systems', value: [...selectedTerminologySources], onChange: (event) => setSelectedTerminologySources([...event.currentTarget.selectedOptions].map(option => option.value)), children: terminologySources.map(source => _jsx("option", { value: source.id, children: source.label || source.id }, source.id)) })] }) : null, terminologyBusy ? _jsx("small", { role: "status", children: copy.terminologyLoading }) : null, terminologyError ? _jsx("small", { role: "alert", children: copy.terminologyUnavailable }) : null, candidates.length ? _jsx("ul", { children: candidates.map((candidate) => _jsx("li", { children: _jsxs("button", { type: "button", onClick: () => {
|
|
155
183
|
setClaims((current) => selectedCodingClaims(request.resourceType, claim, candidate, acceptedClaims, current));
|
|
156
184
|
setCandidates([]);
|
|
157
185
|
setActiveTerminologyClaim(undefined);
|
|
@@ -5,7 +5,7 @@ import 'gdc-common-utils-ts/utils/medication-statement-entry-editor';
|
|
|
5
5
|
import 'gdc-common-utils-ts/utils/observation-entry-editor';
|
|
6
6
|
import 'gdc-common-utils-ts/utils/procedure-entry-editor';
|
|
7
7
|
import type { MultichannelOperationSchema } from 'sos-data-utils-ts/multichannel-operation-schemas';
|
|
8
|
-
import { type ClinicalArtifactAuthoringContext, type ClinicalArtifactEditorCopy, type ClinicalArtifactSchema, type ClinicalTerminologySearch, type ClinicalTerminologyCandidate } from './ClinicalArtifactEditor.js';
|
|
8
|
+
import { type ClinicalArtifactAuthoringContext, type ClinicalArtifactEditorCopy, type ClinicalArtifactSchema, type ClinicalTerminologySearch, type ClinicalTerminologyCandidate, type ClinicalTerminologySourceSearch } from './ClinicalArtifactEditor.js';
|
|
9
9
|
export type ClinicalBundleDraftSchema = Readonly<{
|
|
10
10
|
schema: ClinicalArtifactSchema;
|
|
11
11
|
operationSchema: MultichannelOperationSchema;
|
|
@@ -42,6 +42,9 @@ export type ClinicalBundleDraftEditorProps = Readonly<{
|
|
|
42
42
|
taxonomyId?: string;
|
|
43
43
|
fieldLabel: (claim: string) => string;
|
|
44
44
|
searchTerminology?: (input: ClinicalTerminologySearch) => Promise<readonly ClinicalTerminologyCandidate[]>;
|
|
45
|
+
loadTerminologySources?: ClinicalTerminologySourceSearch;
|
|
46
|
+
/** Optional claims-first document Bundle loaded into the local draft; loading it never persists. */
|
|
47
|
+
initialBundle?: ClinicalBundleDraft;
|
|
45
48
|
onSubmitDraft: (bundle: ClinicalBundleDraft) => Promise<ClinicalBundleDraftSubmitOutcome>;
|
|
46
49
|
}>;
|
|
47
50
|
/**
|
|
@@ -51,5 +54,5 @@ export type ClinicalBundleDraftEditorProps = Readonly<{
|
|
|
51
54
|
* It owns no authorization or persistence: the host supplies subject and
|
|
52
55
|
* provenance and only `onSubmitDraft` may cross a persistence boundary.
|
|
53
56
|
*/
|
|
54
|
-
export declare function ClinicalBundleDraftEditor({ schemas, authoringContext, copy, locale, timeZone, taxonomyId, fieldLabel, searchTerminology, onSubmitDraft, }: ClinicalBundleDraftEditorProps): import("react").JSX.Element;
|
|
57
|
+
export declare function ClinicalBundleDraftEditor({ schemas, authoringContext, copy, locale, timeZone, taxonomyId, fieldLabel, searchTerminology, loadTerminologySources, initialBundle, onSubmitDraft, }: ClinicalBundleDraftEditorProps): import("react").JSX.Element;
|
|
55
58
|
//# sourceMappingURL=ClinicalBundleDraftEditor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClinicalBundleDraftEditor.d.ts","sourceRoot":"","sources":["../src/ClinicalBundleDraftEditor.tsx"],"names":[],"mappings":"AAOA,OAAO,4DAA4D,CAAA;AACnE,OAAO,kDAAkD,CAAA;AACzD,OAAO,qDAAqD,CAAA;AAC5D,OAAO,6DAA6D,CAAA;AACpE,OAAO,oDAAoD,CAAA;AAC3D,OAAO,kDAAkD,CAAA;AACzD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,kDAAkD,CAAA;AACnG,OAAO,EAEL,KAAK,gCAAgC,EAErC,KAAK,0BAA0B,EAE/B,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,4BAA4B,
|
|
1
|
+
{"version":3,"file":"ClinicalBundleDraftEditor.d.ts","sourceRoot":"","sources":["../src/ClinicalBundleDraftEditor.tsx"],"names":[],"mappings":"AAOA,OAAO,4DAA4D,CAAA;AACnE,OAAO,kDAAkD,CAAA;AACzD,OAAO,qDAAqD,CAAA;AAC5D,OAAO,6DAA6D,CAAA;AACpE,OAAO,oDAAoD,CAAA;AAC3D,OAAO,kDAAkD,CAAA;AACzD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,kDAAkD,CAAA;AACnG,OAAO,EAEL,KAAK,gCAAgC,EAErC,KAAK,0BAA0B,EAE/B,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,4BAA4B,EACjC,KAAK,+BAA+B,EACrC,MAAM,6BAA6B,CAAA;AAGpC,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAAC;IAC/C,MAAM,EAAE,sBAAsB,CAAA;IAC9B,eAAe,EAAE,2BAA2B,CAAA;IAC5C,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;CACtB,CAAC,CAAA;AAEF,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,YAAY,EAAE,QAAQ,CAAA;IACtB,IAAI,EAAE,UAAU,CAAA;IAChB,KAAK,EAAE,SAAS,OAAO,EAAE,CAAA;CAC1B,CAAC,CAAA;AAEF,MAAM,MAAM,gCAAgC,GAAG,QAAQ,CAAC;IACtD,KAAK,EAAE,WAAW,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAA;IACzD,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAC,CAAA;AAEF,MAAM,MAAM,6BAA6B,GAAG,QAAQ,CAAC;IACnD,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,0BAA0B,CAAA;CACnC,CAAC,CAAA;AAEF,MAAM,MAAM,8BAA8B,GAAG,QAAQ,CAAC;IACpD,OAAO,EAAE,SAAS,yBAAyB,EAAE,CAAA;IAC7C,gBAAgB,EAAE,gCAAgC,CAAA;IAClD,IAAI,EAAE,6BAA6B,CAAA;IACnC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IACrC,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,OAAO,CAAC,SAAS,4BAA4B,EAAE,CAAC,CAAA;IAC1G,sBAAsB,CAAC,EAAE,+BAA+B,CAAA;IACxD,oGAAoG;IACpG,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,aAAa,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,OAAO,CAAC,gCAAgC,CAAC,CAAA;CAC1F,CAAC,CAAA;AAYF;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,OAAO,EACP,gBAAgB,EAChB,IAAI,EACJ,MAAa,EACb,QAAQ,EACR,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,sBAAsB,EACtB,aAAa,EACb,aAAa,GACd,EAAE,8BAA8B,+BAwFhC"}
|
|
@@ -20,8 +20,8 @@ import { ClinicalActionButton } from './ClinicalActionButton.js';
|
|
|
20
20
|
* It owns no authorization or persistence: the host supplies subject and
|
|
21
21
|
* provenance and only `onSubmitDraft` may cross a persistence boundary.
|
|
22
22
|
*/
|
|
23
|
-
export function ClinicalBundleDraftEditor({ schemas, authoringContext, copy, locale = 'en', timeZone, taxonomyId, fieldLabel, searchTerminology, onSubmitDraft, }) {
|
|
24
|
-
const [artifacts, setArtifacts] = useState(
|
|
23
|
+
export function ClinicalBundleDraftEditor({ schemas, authoringContext, copy, locale = 'en', timeZone, taxonomyId, fieldLabel, searchTerminology, loadTerminologySources, initialBundle, onSubmitDraft, }) {
|
|
24
|
+
const [artifacts, setArtifacts] = useState(() => importedArtifacts(initialBundle, schemas));
|
|
25
25
|
const [editor, setEditor] = useState();
|
|
26
26
|
const [notice, setNotice] = useState('');
|
|
27
27
|
const [error, setError] = useState('');
|
|
@@ -68,7 +68,7 @@ export function ClinicalBundleDraftEditor({ schemas, authoringContext, copy, loc
|
|
|
68
68
|
const title = artifactTitle(artifact.draft);
|
|
69
69
|
return _jsxs("li", { children: [_jsxs("span", { children: [_jsx("strong", { children: title }), _jsx("small", { children: artifact.draft.resourceType })] }), _jsxs("span", { children: [_jsx(ClinicalActionButton, { kind: "edit", label: `${copy.edit} ${title}`, onClick: () => setEditor({ schema: artifact.schema, draft: artifact.draft }) }), _jsx(ClinicalActionButton, { kind: "delete", label: `${copy.remove} ${title}`, onClick: () => setArtifacts((current) => current.filter((candidate) => candidate.draft.id !== artifact.draft.id)) })] })] }, artifact.draft.id);
|
|
70
70
|
}) })] }, label);
|
|
71
|
-
}), artifacts.length === 0 && sections.length === 0 ? _jsx("p", { children: copy.empty }) : null, _jsx("footer", { children: _jsx("button", { type: "button", disabled: artifacts.length === 0 || submitting, onClick: () => void submitDraft(), children: submitting ? copy.submitting : copy.submit }) }), editor ? _jsx(ClinicalArtifactEditor, { request: editorRequest(editor), schema: editor.schema.schema, operationSchema: editor.schema.operationSchema, authoringContext: authoringContext, copy: copy.editor, locale: locale, timeZone: timeZone, taxonomyId: taxonomyId, fieldLabel: fieldLabel, searchTerminology: searchTerminology, saveArtifact: async (draft) => stageArtifact(draft), onCancel: () => setEditor(undefined), onReadback: () => setEditor(undefined) }) : null] });
|
|
71
|
+
}), artifacts.length === 0 && sections.length === 0 ? _jsx("p", { children: copy.empty }) : null, _jsx("footer", { children: _jsx("button", { type: "button", disabled: artifacts.length === 0 || submitting, onClick: () => void submitDraft(), children: submitting ? copy.submitting : copy.submit }) }), editor ? _jsx(ClinicalArtifactEditor, { request: editorRequest(editor), schema: editor.schema.schema, operationSchema: editor.schema.operationSchema, authoringContext: authoringContext, copy: copy.editor, locale: locale, timeZone: timeZone, taxonomyId: taxonomyId, fieldLabel: fieldLabel, searchTerminology: searchTerminology, loadTerminologySources: loadTerminologySources, saveArtifact: async (draft) => stageArtifact(draft), onCancel: () => setEditor(undefined), onReadback: () => setEditor(undefined) }) : null] });
|
|
72
72
|
}
|
|
73
73
|
function editorRequest(editor) {
|
|
74
74
|
return {
|
|
@@ -136,3 +136,27 @@ function artifactTitle(draft) {
|
|
|
136
136
|
const preferred = Object.entries(draft.claims).find(([claim, value]) => typeof value === 'string' && value.trim() && (claim.endsWith('-text') || claim.endsWith('.note') || claim.endsWith('.description')))?.[1];
|
|
137
137
|
return typeof preferred === 'string' ? preferred : draft.resourceType;
|
|
138
138
|
}
|
|
139
|
+
function importedArtifacts(bundle, schemas) {
|
|
140
|
+
if (!bundle || bundle.resourceType !== 'Bundle' || bundle.type !== 'document' || !Array.isArray(bundle.entry))
|
|
141
|
+
return [];
|
|
142
|
+
return bundle.entry.flatMap((entry) => {
|
|
143
|
+
const resource = record(record(entry).resource);
|
|
144
|
+
const schema = schemas.find(candidate => candidate.schema.resourceType === resource.resourceType);
|
|
145
|
+
const claims = record(record(resource.meta).claims);
|
|
146
|
+
const id = String(resource.id || '').trim();
|
|
147
|
+
if (!schema || !id || Object.keys(claims).length === 0)
|
|
148
|
+
return [];
|
|
149
|
+
const stringValues = Object.fromEntries(Object.entries(claims).map(([claim, value]) => [claim, String(value ?? '')]));
|
|
150
|
+
return [{ schema, draft: {
|
|
151
|
+
resourceType: schema.schema.resourceType,
|
|
152
|
+
id,
|
|
153
|
+
sectionCode: schema.schema.sectionCode ?? '',
|
|
154
|
+
mode: 'update',
|
|
155
|
+
claims: stringValues,
|
|
156
|
+
changesBundle: { resourceType: 'Bundle', type: 'batch', data: [{ resource }] },
|
|
157
|
+
} }];
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
function record(value) {
|
|
161
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
162
|
+
}
|
package/package.json
CHANGED