@openmrs/esm-implementer-tools-app 5.3.3-pre.1237 → 5.3.3-pre.1247
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 +45 -45
- package/__mocks__/react-i18next.js +10 -15
- package/dist/426.js.map +1 -1
- package/dist/560.js +1 -1
- package/dist/560.js.map +1 -1
- package/dist/587.js.map +1 -1
- package/dist/727.js +1 -1
- package/dist/727.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-implementer-tools-app.js +1 -1
- package/dist/openmrs-esm-implementer-tools-app.js.buildmanifest.json +13 -13
- package/dist/routes.json +1 -1
- package/jest.config.js +7 -7
- package/package.json +3 -3
- package/src/backend-dependencies/backend-dependencies.component.tsx +19 -29
- package/src/backend-dependencies/backend-dependencies.styles.scss +2 -2
- package/src/backend-dependencies/openmrs-backend-dependencies.ts +22 -43
- package/src/backend-dependencies/useBackendDependencies.ts +5 -9
- package/src/config-edit-button/config-edit-button.component.tsx +5 -7
- package/src/configuration/configuration.component.tsx +30 -57
- package/src/configuration/configuration.styles.scss +4 -4
- package/src/configuration/configuration.test.tsx +92 -115
- package/src/configuration/interactive-editor/config-subtree.component.tsx +10 -18
- package/src/configuration/interactive-editor/config-tree-for-module.component.tsx +8 -17
- package/src/configuration/interactive-editor/config-tree.component.tsx +5 -9
- package/src/configuration/interactive-editor/description.component.tsx +12 -27
- package/src/configuration/interactive-editor/description.styles.scss +7 -7
- package/src/configuration/interactive-editor/display-value.scss +2 -2
- package/src/configuration/interactive-editor/display-value.tsx +18 -22
- package/src/configuration/interactive-editor/editable-value.component.tsx +19 -44
- package/src/configuration/interactive-editor/editable-value.styles.scss +2 -2
- package/src/configuration/interactive-editor/extension-configure-tree.tsx +7 -11
- package/src/configuration/interactive-editor/extension-slots-config-tree.tsx +24 -56
- package/src/configuration/interactive-editor/layout/subtree.component.tsx +8 -31
- package/src/configuration/interactive-editor/layout/tree-container.component.tsx +3 -3
- package/src/configuration/interactive-editor/value-editor.scss +2 -2
- package/src/configuration/interactive-editor/value-editor.tsx +19 -35
- package/src/configuration/interactive-editor/value-editors/array-editor.tsx +12 -19
- package/src/configuration/interactive-editor/value-editors/concept-search.resource.tsx +4 -7
- package/src/configuration/interactive-editor/value-editors/concept-search.styles.scss +7 -7
- package/src/configuration/interactive-editor/value-editors/concept-search.tsx +15 -32
- package/src/configuration/interactive-editor/value-editors/extension-slot-add.tsx +4 -9
- package/src/configuration/interactive-editor/value-editors/extension-slot-order.tsx +2 -7
- package/src/configuration/interactive-editor/value-editors/extension-slot-remove.tsx +4 -9
- package/src/configuration/interactive-editor/value-editors/object-editor.tsx +10 -20
- package/src/configuration/interactive-editor/value-editors/patient-identifier-type-search.tsx +21 -47
- package/src/configuration/interactive-editor/value-editors/patient-identifier-type.resource.tsx +8 -8
- package/src/configuration/interactive-editor/value-editors/person-attribute-search.resource.tsx +6 -11
- package/src/configuration/interactive-editor/value-editors/person-attribute-search.tsx +20 -47
- package/src/configuration/interactive-editor/value-editors/uuid-search.scss +6 -6
- package/src/configuration/interactive-editor/value-editors/value-editor-field.tsx +27 -54
- package/src/configuration/json-editor/json-editor.component.tsx +11 -17
- package/src/declarations.d.ts +3 -3
- package/src/feature-flags/feature-flags.component.tsx +16 -26
- package/src/feature-flags/frontend-modules.scss +3 -3
- package/src/frontend-modules/frontend-modules.component.tsx +14 -22
- package/src/frontend-modules/frontend-modules.scss +3 -3
- package/src/global-implementer-tools-button.test.tsx +7 -7
- package/src/global-implementer-tools.component.tsx +6 -9
- package/src/hooks.ts +2 -2
- package/src/implementer-tools.button.tsx +8 -8
- package/src/implementer-tools.component.tsx +16 -32
- package/src/implementer-tools.styles.scss +6 -6
- package/src/implementer-tools.test.tsx +3 -3
- package/src/index.ts +11 -25
- package/src/popup/popup.component.tsx +16 -30
- package/src/popup/popup.styles.scss +1 -1
- package/src/store.ts +19 -44
- package/src/types.ts +1 -1
- package/src/ui-editor/extension-overlay.component.tsx +6 -14
- package/src/ui-editor/portal.tsx +1 -1
- package/src/ui-editor/ui-editor.tsx +24 -34
- package/webpack.config.js +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React, { useState, useMemo } from
|
|
2
|
-
import { useTranslation } from
|
|
3
|
-
import uniqueId from
|
|
1
|
+
import React, { useState, useMemo } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import uniqueId from 'lodash-es/uniqueId';
|
|
4
4
|
import {
|
|
5
5
|
InlineLoading,
|
|
6
6
|
Search,
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
StructuredListRow,
|
|
9
9
|
StructuredListWrapper,
|
|
10
10
|
Tile,
|
|
11
|
-
} from
|
|
12
|
-
import { Concept, useConceptLookup } from
|
|
13
|
-
import styles from
|
|
11
|
+
} from '@carbon/react';
|
|
12
|
+
import { Concept, useConceptLookup } from './concept-search.resource';
|
|
13
|
+
import styles from './uuid-search.scss';
|
|
14
14
|
|
|
15
15
|
interface ConceptSearchBoxProps {
|
|
16
16
|
setConcept: (concept) => void;
|
|
@@ -20,7 +20,7 @@ interface ConceptSearchBoxProps {
|
|
|
20
20
|
export function ConceptSearchBox({ setConcept, value }: ConceptSearchBoxProps) {
|
|
21
21
|
const { t } = useTranslation();
|
|
22
22
|
const id = useMemo(() => uniqueId(), []);
|
|
23
|
-
const [conceptToLookup, setConceptToLookup] = useState(
|
|
23
|
+
const [conceptToLookup, setConceptToLookup] = useState('');
|
|
24
24
|
const [selectedConcept, setSelectedConcept] = useState<string>(value);
|
|
25
25
|
const { concepts, isSearchingConcepts } = useConceptLookup(conceptToLookup);
|
|
26
26
|
|
|
@@ -31,14 +31,12 @@ export function ConceptSearchBox({ setConcept, value }: ConceptSearchBoxProps) {
|
|
|
31
31
|
const handleConceptUuidChange = (concept) => {
|
|
32
32
|
setSelectedConcept(concept.uuid);
|
|
33
33
|
setConcept(concept);
|
|
34
|
-
setConceptToLookup(
|
|
34
|
+
setConceptToLookup('');
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
return (
|
|
38
38
|
<div>
|
|
39
|
-
{selectedConcept &&
|
|
40
|
-
<p className={styles.activeUuid}>{selectedConcept}</p>
|
|
41
|
-
)}
|
|
39
|
+
{selectedConcept && <p className={styles.activeUuid}>{selectedConcept}</p>}
|
|
42
40
|
<div className={styles.autocomplete}>
|
|
43
41
|
<Search
|
|
44
42
|
id={`searchbox-${id}`}
|
|
@@ -49,34 +47,21 @@ export function ConceptSearchBox({ setConcept, value }: ConceptSearchBoxProps) {
|
|
|
49
47
|
autoCapitalize="off"
|
|
50
48
|
aria-autocomplete="list"
|
|
51
49
|
role="combobox"
|
|
52
|
-
aria-label={t(
|
|
50
|
+
aria-label={t('searchConceptHelperText', 'Search concepts')}
|
|
53
51
|
aria-controls={`searchbox-${id}`}
|
|
54
52
|
aria-expanded={concepts.length > 0}
|
|
55
|
-
placeholder={t(
|
|
53
|
+
placeholder={t('searchConceptHelperText', 'Search concepts')}
|
|
56
54
|
onChange={handleSearchTermChange}
|
|
57
55
|
/>
|
|
58
56
|
{(() => {
|
|
59
57
|
if (!conceptToLookup) return null;
|
|
60
58
|
if (isSearchingConcepts)
|
|
61
|
-
return (
|
|
62
|
-
<InlineLoading
|
|
63
|
-
className={styles.loader}
|
|
64
|
-
description={t("searching", "Searching") + "..."}
|
|
65
|
-
/>
|
|
66
|
-
);
|
|
59
|
+
return <InlineLoading className={styles.loader} description={t('searching', 'Searching') + '...'} />;
|
|
67
60
|
if (concepts && concepts.length && !isSearchingConcepts) {
|
|
68
61
|
return (
|
|
69
|
-
<StructuredListWrapper
|
|
70
|
-
selection
|
|
71
|
-
id={`searchbox-${id}`}
|
|
72
|
-
className={styles.listbox}
|
|
73
|
-
>
|
|
62
|
+
<StructuredListWrapper selection id={`searchbox-${id}`} className={styles.listbox}>
|
|
74
63
|
{concepts.map((concept: Concept) => (
|
|
75
|
-
<StructuredListRow
|
|
76
|
-
key={concept.uuid}
|
|
77
|
-
role="option"
|
|
78
|
-
aria-selected="true"
|
|
79
|
-
>
|
|
64
|
+
<StructuredListRow key={concept.uuid} role="option" aria-selected="true">
|
|
80
65
|
<StructuredListCell
|
|
81
66
|
onClick={() => {
|
|
82
67
|
handleConceptUuidChange(concept);
|
|
@@ -92,9 +77,7 @@ export function ConceptSearchBox({ setConcept, value }: ConceptSearchBoxProps) {
|
|
|
92
77
|
}
|
|
93
78
|
return (
|
|
94
79
|
<Tile className={styles.emptyResults}>
|
|
95
|
-
<span>
|
|
96
|
-
{t("noConceptsFoundText", "No matching concepts found")}
|
|
97
|
-
</span>
|
|
80
|
+
<span>{t('noConceptsFoundText', 'No matching concepts found')}</span>
|
|
98
81
|
</Tile>
|
|
99
82
|
);
|
|
100
83
|
})()}
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import React, { useState, useEffect } from
|
|
2
|
-
import { MultiSelect } from
|
|
3
|
-
import {
|
|
4
|
-
ExtensionInternalStore,
|
|
5
|
-
getExtensionInternalStore,
|
|
6
|
-
} from "@openmrs/esm-framework/src/internal";
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { MultiSelect } from '@carbon/react';
|
|
3
|
+
import { ExtensionInternalStore, getExtensionInternalStore } from '@openmrs/esm-framework/src/internal';
|
|
7
4
|
|
|
8
5
|
const extensionInternalStore = getExtensionInternalStore();
|
|
9
6
|
|
|
10
7
|
export function ExtensionSlotAdd({ value, setValue }) {
|
|
11
|
-
const [availableExtensions, setAvailableExtensions] = useState<Array<string>>(
|
|
12
|
-
[]
|
|
13
|
-
);
|
|
8
|
+
const [availableExtensions, setAvailableExtensions] = useState<Array<string>>([]);
|
|
14
9
|
|
|
15
10
|
useEffect(() => {
|
|
16
11
|
function update(state: ExtensionInternalStore) {
|
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import React from
|
|
1
|
+
import React from 'react';
|
|
2
2
|
|
|
3
|
-
export function ExtensionSlotOrder({
|
|
4
|
-
slotName,
|
|
5
|
-
slotModuleName,
|
|
6
|
-
value,
|
|
7
|
-
setValue,
|
|
8
|
-
}) {
|
|
3
|
+
export function ExtensionSlotOrder({ slotName, slotModuleName, value, setValue }) {
|
|
9
4
|
return <div>Todo: compose array with extension lookup</div>;
|
|
10
5
|
}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { MultiSelect } from
|
|
3
|
-
import { useAssignedExtensions } from
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { MultiSelect } from '@carbon/react';
|
|
3
|
+
import { useAssignedExtensions } from '@openmrs/esm-framework';
|
|
4
4
|
|
|
5
|
-
export function ExtensionSlotRemove({
|
|
6
|
-
slotName,
|
|
7
|
-
slotModuleName,
|
|
8
|
-
value,
|
|
9
|
-
setValue,
|
|
10
|
-
}) {
|
|
5
|
+
export function ExtensionSlotRemove({ slotName, slotModuleName, value, setValue }) {
|
|
11
6
|
const assignedIds = useAssignedExtensions(slotName).map((e) => e.id);
|
|
12
7
|
|
|
13
8
|
return (
|
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from "@carbon/react";
|
|
9
|
-
import { ValueEditorField } from "./value-editor-field";
|
|
10
|
-
import { ConfigValueDescriptor } from "../editable-value.component";
|
|
11
|
-
import { Type } from "@openmrs/esm-framework";
|
|
12
|
-
import cloneDeep from "lodash-es/cloneDeep";
|
|
13
|
-
import styles from "./object-editor.styles.css";
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StructuredListBody, StructuredListCell, StructuredListRow, StructuredListWrapper, Tile } from '@carbon/react';
|
|
3
|
+
import { ValueEditorField } from './value-editor-field';
|
|
4
|
+
import { ConfigValueDescriptor } from '../editable-value.component';
|
|
5
|
+
import { Type } from '@openmrs/esm-framework';
|
|
6
|
+
import cloneDeep from 'lodash-es/cloneDeep';
|
|
7
|
+
import styles from './object-editor.styles.css';
|
|
14
8
|
|
|
15
9
|
interface ObjectEditorProps {
|
|
16
10
|
element: ConfigValueDescriptor;
|
|
@@ -18,17 +12,13 @@ interface ObjectEditorProps {
|
|
|
18
12
|
setValue: (value: Object) => void;
|
|
19
13
|
}
|
|
20
14
|
|
|
21
|
-
export function ObjectEditor({
|
|
22
|
-
element,
|
|
23
|
-
valueObject,
|
|
24
|
-
setValue,
|
|
25
|
-
}: ObjectEditorProps) {
|
|
15
|
+
export function ObjectEditor({ element, valueObject, setValue }: ObjectEditorProps) {
|
|
26
16
|
return (
|
|
27
17
|
<Tile className={styles.objectEditor}>
|
|
28
18
|
<StructuredListWrapper>
|
|
29
19
|
<StructuredListBody>
|
|
30
20
|
{Object.entries(element).map(([key, schema]) =>
|
|
31
|
-
!key.startsWith(
|
|
21
|
+
!key.startsWith('_') ? (
|
|
32
22
|
<StructuredListRow key={key}>
|
|
33
23
|
<StructuredListCell>
|
|
34
24
|
<ValueEditorField
|
|
@@ -60,7 +50,7 @@ export function ObjectEditor({
|
|
|
60
50
|
/>
|
|
61
51
|
</StructuredListCell>
|
|
62
52
|
</StructuredListRow>
|
|
63
|
-
) : null
|
|
53
|
+
) : null,
|
|
64
54
|
)}
|
|
65
55
|
</StructuredListBody>
|
|
66
56
|
</StructuredListWrapper>
|
package/src/configuration/interactive-editor/value-editors/patient-identifier-type-search.tsx
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
import React, { useState, useMemo } from
|
|
2
|
-
import uniqueId from
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from
|
|
7
|
-
import styles from "./uuid-search.scss";
|
|
8
|
-
import { useTranslation } from "react-i18next";
|
|
9
|
-
import {
|
|
10
|
-
Search,
|
|
11
|
-
StructuredListCell,
|
|
12
|
-
StructuredListRow,
|
|
13
|
-
StructuredListWrapper,
|
|
14
|
-
} from "@carbon/react";
|
|
1
|
+
import React, { useState, useMemo } from 'react';
|
|
2
|
+
import uniqueId from 'lodash-es/uniqueId';
|
|
3
|
+
import { usePatientIdentifierTypes, PatientIdentifierType } from './patient-identifier-type.resource';
|
|
4
|
+
import styles from './uuid-search.scss';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import { Search, StructuredListCell, StructuredListRow, StructuredListWrapper } from '@carbon/react';
|
|
15
7
|
|
|
16
8
|
interface PatientIdentifierTypeSearchBoxProps {
|
|
17
9
|
value: string;
|
|
@@ -22,11 +14,9 @@ export function PatientIdentifierTypeSearchBox({
|
|
|
22
14
|
setPatientIdentifierTypeUuid,
|
|
23
15
|
value,
|
|
24
16
|
}: PatientIdentifierTypeSearchBoxProps) {
|
|
25
|
-
const [searchTerm, setSearchTerm] = useState(
|
|
26
|
-
const { data: patientIdentifierTypes, isLoading } =
|
|
27
|
-
|
|
28
|
-
const [activePatientIdentifierTypeUuid, setActivePatientIdentifierTypeUuid] =
|
|
29
|
-
useState<any>(value);
|
|
17
|
+
const [searchTerm, setSearchTerm] = useState('');
|
|
18
|
+
const { data: patientIdentifierTypes, isLoading } = usePatientIdentifierTypes();
|
|
19
|
+
const [activePatientIdentifierTypeUuid, setActivePatientIdentifierTypeUuid] = useState<any>(value);
|
|
30
20
|
const { t } = useTranslation();
|
|
31
21
|
|
|
32
22
|
const id = useMemo(() => uniqueId(), []);
|
|
@@ -34,27 +24,22 @@ export function PatientIdentifierTypeSearchBox({
|
|
|
34
24
|
const handleUuidChange = (patientIdentifierType: PatientIdentifierType) => {
|
|
35
25
|
setActivePatientIdentifierTypeUuid(patientIdentifierType.uuid);
|
|
36
26
|
setPatientIdentifierTypeUuid(patientIdentifierType.uuid);
|
|
37
|
-
setSearchTerm(
|
|
27
|
+
setSearchTerm('');
|
|
38
28
|
};
|
|
39
29
|
|
|
40
30
|
const handleSearchTermChange = (evt) => setSearchTerm(evt.target.value);
|
|
41
31
|
|
|
42
|
-
const filteredResults: Array<PatientIdentifierType> | undefined =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return undefined;
|
|
50
|
-
}
|
|
51
|
-
}, [isLoading, searchTerm, patientIdentifierTypes]);
|
|
32
|
+
const filteredResults: Array<PatientIdentifierType> | undefined = useMemo(() => {
|
|
33
|
+
if (!isLoading && searchTerm && searchTerm !== '') {
|
|
34
|
+
return patientIdentifierTypes?.filter((type) => type.display.toLowerCase().includes(searchTerm.toLowerCase()));
|
|
35
|
+
} else {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
}, [isLoading, searchTerm, patientIdentifierTypes]);
|
|
52
39
|
|
|
53
40
|
return (
|
|
54
41
|
<div>
|
|
55
|
-
{activePatientIdentifierTypeUuid &&
|
|
56
|
-
<p className={styles.activeUuid}>{activePatientIdentifierTypeUuid}</p>
|
|
57
|
-
)}
|
|
42
|
+
{activePatientIdentifierTypeUuid && <p className={styles.activeUuid}>{activePatientIdentifierTypeUuid}</p>}
|
|
58
43
|
<div className={styles.autocomplete}>
|
|
59
44
|
<Search
|
|
60
45
|
id={`search-input-${id}`}
|
|
@@ -62,12 +47,7 @@ export function PatientIdentifierTypeSearchBox({
|
|
|
62
47
|
type="text"
|
|
63
48
|
size="sm"
|
|
64
49
|
placeholder={
|
|
65
|
-
!isLoading
|
|
66
|
-
? t(
|
|
67
|
-
"searchPersonAttributeHelperText",
|
|
68
|
-
"Person attribute type name"
|
|
69
|
-
)
|
|
70
|
-
: t("loading", "Loading")
|
|
50
|
+
!isLoading ? t('searchPersonAttributeHelperText', 'Person attribute type name') : t('loading', 'Loading')
|
|
71
51
|
}
|
|
72
52
|
onChange={handleSearchTermChange}
|
|
73
53
|
value={searchTerm}
|
|
@@ -75,11 +55,7 @@ export function PatientIdentifierTypeSearchBox({
|
|
|
75
55
|
/>
|
|
76
56
|
{searchTerm ? (
|
|
77
57
|
filteredResults?.length ? (
|
|
78
|
-
<StructuredListWrapper
|
|
79
|
-
selection
|
|
80
|
-
className={styles.listbox}
|
|
81
|
-
id={`searchbox-${id}`}
|
|
82
|
-
>
|
|
58
|
+
<StructuredListWrapper selection className={styles.listbox} id={`searchbox-${id}`}>
|
|
83
59
|
{filteredResults?.map((patientIdentifierType) => (
|
|
84
60
|
<StructuredListRow
|
|
85
61
|
key={patientIdentifierType.uuid}
|
|
@@ -96,9 +72,7 @@ export function PatientIdentifierTypeSearchBox({
|
|
|
96
72
|
))}
|
|
97
73
|
</StructuredListWrapper>
|
|
98
74
|
) : (
|
|
99
|
-
<p className={styles.bodyShort01}>
|
|
100
|
-
{t("noPersonAttributeFoundText", "No matching results found")}
|
|
101
|
-
</p>
|
|
75
|
+
<p className={styles.bodyShort01}>{t('noPersonAttributeFoundText', 'No matching results found')}</p>
|
|
102
76
|
)
|
|
103
77
|
) : null}
|
|
104
78
|
</div>
|
package/src/configuration/interactive-editor/value-editors/patient-identifier-type.resource.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import useSWR from
|
|
2
|
-
import { FetchResponse, openmrsFetch } from
|
|
3
|
-
import { useMemo } from
|
|
1
|
+
import useSWR from 'swr';
|
|
2
|
+
import { FetchResponse, openmrsFetch } from '@openmrs/esm-framework';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
4
|
|
|
5
5
|
export interface PatientIdentifierType {
|
|
6
6
|
uuid: string;
|
|
@@ -15,16 +15,16 @@ export function usePatientIdentifierTypes(): {
|
|
|
15
15
|
data: Array<PatientIdentifierType> | undefined;
|
|
16
16
|
isLoading: boolean;
|
|
17
17
|
} {
|
|
18
|
-
const { data, error } = useSWR<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
const { data, error } = useSWR<FetchResponse<PatientIdentifierTypeResponse>, Error>(
|
|
19
|
+
`/ws/rest/v1/patientidentifiertype`,
|
|
20
|
+
openmrsFetch,
|
|
21
|
+
);
|
|
22
22
|
const memoisedPatientIdentifierTypeData = useMemo(
|
|
23
23
|
() => ({
|
|
24
24
|
data: data?.data?.results,
|
|
25
25
|
isLoading: !data && !error,
|
|
26
26
|
}),
|
|
27
|
-
[data, error]
|
|
27
|
+
[data, error],
|
|
28
28
|
);
|
|
29
29
|
|
|
30
30
|
return memoisedPatientIdentifierTypeData;
|
package/src/configuration/interactive-editor/value-editors/person-attribute-search.resource.tsx
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
import { openmrsFetch } from
|
|
1
|
+
import { openmrsFetch } from '@openmrs/esm-framework';
|
|
2
2
|
|
|
3
|
-
export function fetchPersonAttributeTypeByUuid(
|
|
4
|
-
personAttributeTypeUuid
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
`/ws/rest/v1/personattributetype/${personAttributeTypeUuid}`,
|
|
8
|
-
{
|
|
9
|
-
method: "GET",
|
|
10
|
-
}
|
|
11
|
-
);
|
|
3
|
+
export function fetchPersonAttributeTypeByUuid(personAttributeTypeUuid: string) {
|
|
4
|
+
return openmrsFetch(`/ws/rest/v1/personattributetype/${personAttributeTypeUuid}`, {
|
|
5
|
+
method: 'GET',
|
|
6
|
+
});
|
|
12
7
|
}
|
|
13
8
|
|
|
14
9
|
export function performPersonAttributeTypeSearch(query: string) {
|
|
15
10
|
return openmrsFetch(`/ws/rest/v1/personattributetype/?q=${query}`, {
|
|
16
|
-
method:
|
|
11
|
+
method: 'GET',
|
|
17
12
|
});
|
|
18
13
|
}
|
|
@@ -1,29 +1,20 @@
|
|
|
1
|
-
import React, { useState, useEffect, useMemo } from
|
|
2
|
-
import debounce from
|
|
3
|
-
import uniqueId from
|
|
4
|
-
import { performPersonAttributeTypeSearch } from
|
|
5
|
-
import styles from
|
|
6
|
-
import { useTranslation } from
|
|
7
|
-
import {
|
|
8
|
-
Search,
|
|
9
|
-
StructuredListCell,
|
|
10
|
-
StructuredListRow,
|
|
11
|
-
StructuredListWrapper,
|
|
12
|
-
} from "@carbon/react";
|
|
1
|
+
import React, { useState, useEffect, useMemo } from 'react';
|
|
2
|
+
import debounce from 'lodash-es/debounce';
|
|
3
|
+
import uniqueId from 'lodash-es/uniqueId';
|
|
4
|
+
import { performPersonAttributeTypeSearch } from './person-attribute-search.resource';
|
|
5
|
+
import styles from './uuid-search.scss';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
import { Search, StructuredListCell, StructuredListRow, StructuredListWrapper } from '@carbon/react';
|
|
13
8
|
|
|
14
9
|
interface PersonAttributeTypeSearchBoxProps {
|
|
15
10
|
value: string;
|
|
16
11
|
setPersonAttributeUuid: (personAttributeType) => void;
|
|
17
12
|
}
|
|
18
13
|
|
|
19
|
-
export function PersonAttributeTypeSearchBox({
|
|
20
|
-
|
|
21
|
-
value,
|
|
22
|
-
}: PersonAttributeTypeSearchBoxProps) {
|
|
23
|
-
const [searchTerm, setSearchTerm] = useState("");
|
|
14
|
+
export function PersonAttributeTypeSearchBox({ setPersonAttributeUuid, value }: PersonAttributeTypeSearchBoxProps) {
|
|
15
|
+
const [searchTerm, setSearchTerm] = useState('');
|
|
24
16
|
const [searchResults, setSearchResults] = useState([]);
|
|
25
|
-
const [activePersonAttributeUuid, setActivePersonAttributeUuid] =
|
|
26
|
-
useState<any>(value);
|
|
17
|
+
const [activePersonAttributeUuid, setActivePersonAttributeUuid] = useState<any>(value);
|
|
27
18
|
const { t } = useTranslation();
|
|
28
19
|
const searchTimeoutInMs = 300;
|
|
29
20
|
|
|
@@ -36,7 +27,7 @@ export function PersonAttributeTypeSearchBox({
|
|
|
36
27
|
};
|
|
37
28
|
|
|
38
29
|
const resetSearch = () => {
|
|
39
|
-
setSearchTerm(
|
|
30
|
+
setSearchTerm('');
|
|
40
31
|
setSearchResults([]);
|
|
41
32
|
};
|
|
42
33
|
|
|
@@ -48,11 +39,9 @@ export function PersonAttributeTypeSearchBox({
|
|
|
48
39
|
const ac = new AbortController();
|
|
49
40
|
|
|
50
41
|
if (searchTerm && searchTerm.length >= 2) {
|
|
51
|
-
performPersonAttributeTypeSearch(searchTerm).then(
|
|
52
|
-
(
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
);
|
|
42
|
+
performPersonAttributeTypeSearch(searchTerm).then(({ data: { results } }) => {
|
|
43
|
+
setSearchResults(results.slice(0, 9));
|
|
44
|
+
});
|
|
56
45
|
} else {
|
|
57
46
|
setSearchResults([]);
|
|
58
47
|
}
|
|
@@ -61,9 +50,7 @@ export function PersonAttributeTypeSearchBox({
|
|
|
61
50
|
|
|
62
51
|
return (
|
|
63
52
|
<div>
|
|
64
|
-
{activePersonAttributeUuid &&
|
|
65
|
-
<p className={styles.activeUuid}>{activePersonAttributeUuid}</p>
|
|
66
|
-
)}
|
|
53
|
+
{activePersonAttributeUuid && <p className={styles.activeUuid}>{activePersonAttributeUuid}</p>}
|
|
67
54
|
<div className={styles.autocomplete}>
|
|
68
55
|
<Search
|
|
69
56
|
id={`search-input-${id}`}
|
|
@@ -74,27 +61,17 @@ export function PersonAttributeTypeSearchBox({
|
|
|
74
61
|
autoCapitalize="off"
|
|
75
62
|
aria-autocomplete="list"
|
|
76
63
|
role="combobox"
|
|
77
|
-
aria-label={t(
|
|
78
|
-
"searchPersonAttributeHelperText",
|
|
79
|
-
"Person attribute type name"
|
|
80
|
-
)}
|
|
64
|
+
aria-label={t('searchPersonAttributeHelperText', 'Person attribute type name')}
|
|
81
65
|
aria-controls={`searchbox-${id}`}
|
|
82
66
|
aria-expanded={searchResults.length > 0}
|
|
83
|
-
placeholder={t(
|
|
84
|
-
"searchPersonAttributeHelperText",
|
|
85
|
-
"Person attribute type name"
|
|
86
|
-
)}
|
|
67
|
+
placeholder={t('searchPersonAttributeHelperText', 'Person attribute type name')}
|
|
87
68
|
onChange={($event) => {
|
|
88
69
|
handleSearchTermChange($event.target.value);
|
|
89
70
|
}}
|
|
90
71
|
/>
|
|
91
72
|
|
|
92
73
|
{!!searchResults.length && (
|
|
93
|
-
<StructuredListWrapper
|
|
94
|
-
selection
|
|
95
|
-
className={styles.listbox}
|
|
96
|
-
id={`searchbox-${id}`}
|
|
97
|
-
>
|
|
74
|
+
<StructuredListWrapper selection className={styles.listbox} id={`searchbox-${id}`}>
|
|
98
75
|
{searchResults.map((personAttributeType: any) => (
|
|
99
76
|
<StructuredListRow
|
|
100
77
|
key={personAttributeType.uuid}
|
|
@@ -104,18 +81,14 @@ export function PersonAttributeTypeSearchBox({
|
|
|
104
81
|
}}
|
|
105
82
|
aria-selected="true"
|
|
106
83
|
>
|
|
107
|
-
<StructuredListCell className={styles.smallListCell}>
|
|
108
|
-
{personAttributeType.display}
|
|
109
|
-
</StructuredListCell>
|
|
84
|
+
<StructuredListCell className={styles.smallListCell}>{personAttributeType.display}</StructuredListCell>
|
|
110
85
|
</StructuredListRow>
|
|
111
86
|
))}
|
|
112
87
|
</StructuredListWrapper>
|
|
113
88
|
)}
|
|
114
89
|
|
|
115
90
|
{searchTerm && searchResults && !searchResults.length && (
|
|
116
|
-
<p className={styles.bodyShort01}>
|
|
117
|
-
{t("noPersonAttributeFoundText", "No matching results found")}
|
|
118
|
-
</p>
|
|
91
|
+
<p className={styles.bodyShort01}>{t('noPersonAttributeFoundText', 'No matching results found')}</p>
|
|
119
92
|
)}
|
|
120
93
|
</div>
|
|
121
94
|
</div>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
@use
|
|
2
|
-
@use
|
|
3
|
-
@import
|
|
1
|
+
@use '@carbon/styles/scss/spacing';
|
|
2
|
+
@use '@carbon/styles/scss/type';
|
|
3
|
+
@import '../../../implementer-tools.styles.scss';
|
|
4
4
|
|
|
5
5
|
.activeUuid {
|
|
6
|
-
@include type.type-style(
|
|
6
|
+
@include type.type-style('body-compact-01');
|
|
7
7
|
color: $ui-05;
|
|
8
8
|
margin-bottom: spacing.$spacing-03;
|
|
9
9
|
padding-bottom: spacing.$spacing-03;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
.autocomplete,
|
|
14
|
-
.autocomplete > [role=
|
|
14
|
+
.autocomplete > [role='combobox'] {
|
|
15
15
|
position: relative;
|
|
16
16
|
width: 20em;
|
|
17
17
|
}
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
.emptyResults {
|
|
32
|
-
@include type.type-style(
|
|
32
|
+
@include type.type-style('body-compact-01');
|
|
33
33
|
background-color: $ui-02;
|
|
34
34
|
color: $text-02;
|
|
35
35
|
min-height: 1rem;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import React, { useState } from
|
|
2
|
-
import uniqueId from
|
|
3
|
-
import { Checkbox, NumberInput, TextInput } from
|
|
4
|
-
import { Type } from
|
|
5
|
-
import { ConfigValueDescriptor } from
|
|
6
|
-
import { ValueType } from
|
|
7
|
-
import { ArrayEditor } from
|
|
8
|
-
import { ConceptSearchBox } from
|
|
9
|
-
import { ExtensionSlotAdd } from
|
|
10
|
-
import { ExtensionSlotRemove } from
|
|
11
|
-
import { ObjectEditor } from
|
|
12
|
-
import { ExtensionSlotOrder } from
|
|
13
|
-
import { PersonAttributeTypeSearchBox } from
|
|
14
|
-
import { PatientIdentifierTypeSearchBox } from
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import uniqueId from 'lodash-es/uniqueId';
|
|
3
|
+
import { Checkbox, NumberInput, TextInput } from '@carbon/react';
|
|
4
|
+
import { Type } from '@openmrs/esm-framework';
|
|
5
|
+
import { ConfigValueDescriptor } from '../editable-value.component';
|
|
6
|
+
import { ValueType } from '../value-editor';
|
|
7
|
+
import { ArrayEditor } from './array-editor';
|
|
8
|
+
import { ConceptSearchBox } from './concept-search';
|
|
9
|
+
import { ExtensionSlotAdd } from './extension-slot-add';
|
|
10
|
+
import { ExtensionSlotRemove } from './extension-slot-remove';
|
|
11
|
+
import { ObjectEditor } from './object-editor';
|
|
12
|
+
import { ExtensionSlotOrder } from './extension-slot-order';
|
|
13
|
+
import { PersonAttributeTypeSearchBox } from './person-attribute-search';
|
|
14
|
+
import { PatientIdentifierTypeSearchBox } from './patient-identifier-type-search';
|
|
15
15
|
|
|
16
16
|
export interface ValueEditorFieldProps {
|
|
17
17
|
element: ConfigValueDescriptor;
|
|
@@ -21,48 +21,26 @@ export interface ValueEditorFieldProps {
|
|
|
21
21
|
onChange: (value: any) => void;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export function ValueEditorField({
|
|
25
|
-
|
|
26
|
-
path,
|
|
27
|
-
valueType,
|
|
28
|
-
value,
|
|
29
|
-
onChange,
|
|
30
|
-
}: ValueEditorFieldProps) {
|
|
31
|
-
const [id] = useState(uniqueId("value-editor-"));
|
|
24
|
+
export function ValueEditorField({ element, path, valueType, value, onChange }: ValueEditorFieldProps) {
|
|
25
|
+
const [id] = useState(uniqueId('value-editor-'));
|
|
32
26
|
|
|
33
|
-
if (valueType ===
|
|
34
|
-
throw new Error(
|
|
35
|
-
"Programming error: ValueEditorField initialized for a 'remove' field, but no 'path' is available"
|
|
36
|
-
);
|
|
27
|
+
if (valueType === 'remove' && !path) {
|
|
28
|
+
throw new Error("Programming error: ValueEditorField initialized for a 'remove' field, but no 'path' is available");
|
|
37
29
|
}
|
|
38
30
|
|
|
39
31
|
return valueType === Type.Array ? (
|
|
40
32
|
<ArrayEditor element={element} valueArray={value} setValue={onChange} />
|
|
41
33
|
) : valueType === Type.Boolean ? (
|
|
42
|
-
<Checkbox
|
|
43
|
-
id={id}
|
|
44
|
-
checked={value}
|
|
45
|
-
hideLabel
|
|
46
|
-
labelText=""
|
|
47
|
-
onChange={(event, { checked, id }) => onChange(checked)}
|
|
48
|
-
/>
|
|
34
|
+
<Checkbox id={id} checked={value} hideLabel labelText="" onChange={(event, { checked, id }) => onChange(checked)} />
|
|
49
35
|
) : valueType === Type.ConceptUuid ? (
|
|
50
|
-
<ConceptSearchBox
|
|
51
|
-
value={value}
|
|
52
|
-
setConcept={(concept) => onChange(concept.uuid)}
|
|
53
|
-
/>
|
|
36
|
+
<ConceptSearchBox value={value} setConcept={(concept) => onChange(concept.uuid)} />
|
|
54
37
|
) : valueType === Type.PersonAttributeTypeUuid ? (
|
|
55
38
|
<PersonAttributeTypeSearchBox
|
|
56
39
|
value={value}
|
|
57
|
-
setPersonAttributeUuid={(personAttributeTypeUuid) =>
|
|
58
|
-
onChange(personAttributeTypeUuid)
|
|
59
|
-
}
|
|
40
|
+
setPersonAttributeUuid={(personAttributeTypeUuid) => onChange(personAttributeTypeUuid)}
|
|
60
41
|
/>
|
|
61
42
|
) : valueType === Type.PatientIdentifierTypeUuid ? (
|
|
62
|
-
<PatientIdentifierTypeSearchBox
|
|
63
|
-
value={value}
|
|
64
|
-
setPatientIdentifierTypeUuid={(uuid) => onChange(uuid)}
|
|
65
|
-
/>
|
|
43
|
+
<PatientIdentifierTypeSearchBox value={value} setPatientIdentifierTypeUuid={(uuid) => onChange(uuid)} />
|
|
66
44
|
) : valueType === Type.Number ? (
|
|
67
45
|
<NumberInput
|
|
68
46
|
id={id}
|
|
@@ -71,29 +49,24 @@ export function ValueEditorField({
|
|
|
71
49
|
hideSteppers
|
|
72
50
|
/>
|
|
73
51
|
) : valueType === Type.String || valueType === Type.UUID ? (
|
|
74
|
-
<TextInput
|
|
75
|
-
|
|
76
|
-
value={value}
|
|
77
|
-
labelText=""
|
|
78
|
-
onChange={(e) => onChange(e.target.value)}
|
|
79
|
-
/>
|
|
80
|
-
) : valueType === "add" ? (
|
|
52
|
+
<TextInput id={id} value={value} labelText="" onChange={(e) => onChange(e.target.value)} />
|
|
53
|
+
) : valueType === 'add' ? (
|
|
81
54
|
<ExtensionSlotAdd value={value ?? element._value} setValue={onChange} />
|
|
82
|
-
) : valueType ===
|
|
55
|
+
) : valueType === 'remove' && path ? (
|
|
83
56
|
<ExtensionSlotRemove
|
|
84
57
|
slotName={path[2]}
|
|
85
58
|
slotModuleName={path[0]}
|
|
86
59
|
value={value ?? element._value}
|
|
87
60
|
setValue={onChange}
|
|
88
61
|
/>
|
|
89
|
-
) : valueType ===
|
|
62
|
+
) : valueType === 'order' && path ? (
|
|
90
63
|
<ExtensionSlotOrder
|
|
91
64
|
slotName={path[2]}
|
|
92
65
|
slotModuleName={path[0]}
|
|
93
66
|
value={value ?? element._value}
|
|
94
67
|
setValue={onChange}
|
|
95
68
|
/>
|
|
96
|
-
) : valueType ===
|
|
69
|
+
) : valueType === 'configure' && path ? (
|
|
97
70
|
<>Todo</>
|
|
98
71
|
) : (
|
|
99
72
|
<ObjectEditor element={element} valueObject={value} setValue={onChange} />
|