@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 from
|
|
2
|
-
import { StructuredListCell, StructuredListRow } from
|
|
3
|
-
import styles from
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StructuredListCell, StructuredListRow } from '@carbon/react';
|
|
3
|
+
import styles from './display-value.scss';
|
|
4
4
|
|
|
5
5
|
export interface DisplayValueProps {
|
|
6
6
|
value: any;
|
|
@@ -11,34 +11,30 @@ export function DisplayValue({ value }: DisplayValueProps) {
|
|
|
11
11
|
return (
|
|
12
12
|
<div>
|
|
13
13
|
{Array.isArray(value)
|
|
14
|
-
? typeof value[0] ===
|
|
14
|
+
? typeof value[0] === 'object'
|
|
15
15
|
? value.map((v, i) => (
|
|
16
16
|
<StructuredListRow key={`${v}-${i}`}>
|
|
17
|
+
<StructuredListCell className={styles.smallListCell}>{i + 1}</StructuredListCell>
|
|
17
18
|
<StructuredListCell className={styles.smallListCell}>
|
|
18
|
-
{
|
|
19
|
+
<DisplayValue value={v} />
|
|
19
20
|
</StructuredListCell>
|
|
21
|
+
</StructuredListRow>
|
|
22
|
+
))
|
|
23
|
+
: `[ ${value.join(', ')} ]`
|
|
24
|
+
: typeof value === 'object' && value !== null
|
|
25
|
+
? Object.entries(value).map(([k, v], i) => (
|
|
26
|
+
<StructuredListRow key={`${k}-${i}`}>
|
|
27
|
+
<StructuredListCell className={styles.smallListCell}>{k}</StructuredListCell>
|
|
20
28
|
<StructuredListCell className={styles.smallListCell}>
|
|
21
29
|
<DisplayValue value={v} />
|
|
22
30
|
</StructuredListCell>
|
|
23
31
|
</StructuredListRow>
|
|
24
32
|
))
|
|
25
|
-
:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
{k}
|
|
31
|
-
</StructuredListCell>
|
|
32
|
-
<StructuredListCell className={styles.smallListCell}>
|
|
33
|
-
<DisplayValue value={v} />
|
|
34
|
-
</StructuredListCell>
|
|
35
|
-
</StructuredListRow>
|
|
36
|
-
))
|
|
37
|
-
: typeof value === "string" || typeof value === "number"
|
|
38
|
-
? value
|
|
39
|
-
: value == null
|
|
40
|
-
? "none"
|
|
41
|
-
: JSON.stringify(value)}
|
|
33
|
+
: typeof value === 'string' || typeof value === 'number'
|
|
34
|
+
? value
|
|
35
|
+
: value == null
|
|
36
|
+
? 'none'
|
|
37
|
+
: JSON.stringify(value)}
|
|
42
38
|
</div>
|
|
43
39
|
);
|
|
44
40
|
}
|
|
@@ -1,21 +1,15 @@
|
|
|
1
|
-
import React, { useState, useEffect, useRef } from
|
|
2
|
-
import isEqual from
|
|
3
|
-
import unset from
|
|
4
|
-
import cloneDeep from
|
|
5
|
-
import styles from
|
|
6
|
-
import { Button } from
|
|
7
|
-
import { Edit, Reset } from
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
temporaryConfigStore,
|
|
14
|
-
} from "@openmrs/esm-framework/src/internal";
|
|
15
|
-
import { ValueEditor, CustomValueType } from "./value-editor";
|
|
16
|
-
import { implementerToolsStore, ImplementerToolsStore } from "../../store";
|
|
17
|
-
import { DisplayValue } from "./display-value";
|
|
18
|
-
import { useTranslation } from "react-i18next";
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
2
|
+
import isEqual from 'lodash-es/isEqual';
|
|
3
|
+
import unset from 'lodash-es/unset';
|
|
4
|
+
import cloneDeep from 'lodash-es/cloneDeep';
|
|
5
|
+
import styles from './editable-value.styles.scss';
|
|
6
|
+
import { Button } from '@carbon/react';
|
|
7
|
+
import { Edit, Reset } from '@carbon/react/icons';
|
|
8
|
+
import { ConfigValue, Validator, Type, Config, temporaryConfigStore } from '@openmrs/esm-framework/src/internal';
|
|
9
|
+
import { ValueEditor, CustomValueType } from './value-editor';
|
|
10
|
+
import { implementerToolsStore, ImplementerToolsStore } from '../../store';
|
|
11
|
+
import { DisplayValue } from './display-value';
|
|
12
|
+
import { useTranslation } from 'react-i18next';
|
|
19
13
|
|
|
20
14
|
export interface EditableValueProps {
|
|
21
15
|
path: Array<string>;
|
|
@@ -33,11 +27,7 @@ export interface ConfigValueDescriptor {
|
|
|
33
27
|
_type?: Type;
|
|
34
28
|
}
|
|
35
29
|
|
|
36
|
-
export default function EditableValue({
|
|
37
|
-
path,
|
|
38
|
-
element,
|
|
39
|
-
customType,
|
|
40
|
-
}: EditableValueProps) {
|
|
30
|
+
export default function EditableValue({ path, element, customType }: EditableValueProps) {
|
|
41
31
|
const [valueString, setValueString] = useState<string>();
|
|
42
32
|
const [editing, setEditing] = useState(false);
|
|
43
33
|
const [error, setError] = useState<string | null>(null);
|
|
@@ -58,10 +48,7 @@ export default function EditableValue({
|
|
|
58
48
|
|
|
59
49
|
useEffect(() => {
|
|
60
50
|
const update = (state: ImplementerToolsStore) => {
|
|
61
|
-
if (
|
|
62
|
-
state.configPathBeingEdited &&
|
|
63
|
-
isEqual(state.configPathBeingEdited, path)
|
|
64
|
-
) {
|
|
51
|
+
if (state.configPathBeingEdited && isEqual(state.configPathBeingEdited, path)) {
|
|
65
52
|
focusOnConfigPathBeingEdited();
|
|
66
53
|
}
|
|
67
54
|
};
|
|
@@ -100,11 +87,7 @@ export default function EditableValue({
|
|
|
100
87
|
handleSave={(val) => {
|
|
101
88
|
try {
|
|
102
89
|
const result = JSON.parse(val);
|
|
103
|
-
const tempConfigUpdate = set(
|
|
104
|
-
cloneDeep(temporaryConfigStore.getState()),
|
|
105
|
-
["config", ...path],
|
|
106
|
-
result
|
|
107
|
-
);
|
|
90
|
+
const tempConfigUpdate = set(cloneDeep(temporaryConfigStore.getState()), ['config', ...path], result);
|
|
108
91
|
temporaryConfigStore.setState(tempConfigUpdate);
|
|
109
92
|
setValueString(val);
|
|
110
93
|
closeEditor();
|
|
@@ -121,29 +104,21 @@ export default function EditableValue({
|
|
|
121
104
|
<Button
|
|
122
105
|
kind="ghost"
|
|
123
106
|
size="sm"
|
|
124
|
-
iconDescription={t(
|
|
107
|
+
iconDescription={t('editValueButtonText', 'Edit')}
|
|
125
108
|
onClick={() => setEditing(true)}
|
|
126
109
|
ref={activeConfigRef}
|
|
127
110
|
renderIcon={(props) => <Edit size={16} {...props} />}
|
|
128
111
|
hasIconOnly
|
|
129
112
|
/>
|
|
130
|
-
{element._source ==
|
|
113
|
+
{element._source == 'temporary config' ? (
|
|
131
114
|
<Button
|
|
132
115
|
renderIcon={(props) => <Reset size={16} {...props} />}
|
|
133
116
|
size="sm"
|
|
134
117
|
kind="ghost"
|
|
135
|
-
iconDescription={t(
|
|
136
|
-
"resetToDefaultValueButtonText",
|
|
137
|
-
"Reset to default"
|
|
138
|
-
)}
|
|
118
|
+
iconDescription={t('resetToDefaultValueButtonText', 'Reset to default')}
|
|
139
119
|
hasIconOnly
|
|
140
120
|
onClick={() => {
|
|
141
|
-
temporaryConfigStore.setState(
|
|
142
|
-
unset(temporaryConfigStore.getState(), [
|
|
143
|
-
"config",
|
|
144
|
-
...path,
|
|
145
|
-
]) as any
|
|
146
|
-
);
|
|
121
|
+
temporaryConfigStore.setState(unset(temporaryConfigStore.getState(), ['config', ...path]) as any);
|
|
147
122
|
}}
|
|
148
123
|
/>
|
|
149
124
|
) : null}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import EditableValue from
|
|
3
|
-
import { ExtensionSlotConfigureValueObject } from
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import EditableValue from './editable-value.component';
|
|
3
|
+
import { ExtensionSlotConfigureValueObject } from '@openmrs/esm-framework';
|
|
4
4
|
|
|
5
5
|
export interface ExtensionConfigureTreeProps {
|
|
6
6
|
moduleName: string;
|
|
@@ -8,18 +8,14 @@ export interface ExtensionConfigureTreeProps {
|
|
|
8
8
|
config?: ExtensionSlotConfigureValueObject;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export function ExtensionConfigureTree({
|
|
12
|
-
moduleName,
|
|
13
|
-
slotName,
|
|
14
|
-
config,
|
|
15
|
-
}: ExtensionConfigureTreeProps) {
|
|
11
|
+
export function ExtensionConfigureTree({ moduleName, slotName, config }: ExtensionConfigureTreeProps) {
|
|
16
12
|
return (
|
|
17
13
|
<EditableValue
|
|
18
|
-
path={[moduleName, slotName,
|
|
14
|
+
path={[moduleName, slotName, 'configure']}
|
|
19
15
|
element={
|
|
20
16
|
config && Object.keys(config).length
|
|
21
|
-
? { _value: config, _source:
|
|
22
|
-
: { _value: undefined, _source:
|
|
17
|
+
? { _value: config, _source: '', _default: {} }
|
|
18
|
+
: { _value: undefined, _source: 'default', _default: {} }
|
|
23
19
|
}
|
|
24
20
|
customType="configure"
|
|
25
21
|
/>
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import EditableValue from
|
|
3
|
-
import isEqual from
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} from
|
|
8
|
-
import { ExtensionConfigureTree } from "./extension-configure-tree";
|
|
9
|
-
import { Subtree } from "./layout/subtree.component";
|
|
10
|
-
import { implementerToolsStore } from "../../store";
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import EditableValue from './editable-value.component';
|
|
3
|
+
import isEqual from 'lodash-es/isEqual';
|
|
4
|
+
import { ExtensionSlotConfigureValueObject, useAssignedExtensions } from '@openmrs/esm-framework';
|
|
5
|
+
import { ExtensionConfigureTree } from './extension-configure-tree';
|
|
6
|
+
import { Subtree } from './layout/subtree.component';
|
|
7
|
+
import { implementerToolsStore } from '../../store';
|
|
11
8
|
|
|
12
9
|
interface ExtensionSlotsConfigTreeProps {
|
|
13
10
|
extensionsConfig: { [key: string]: any };
|
|
@@ -31,17 +28,14 @@ interface ExtensionConfigureDescriptor {
|
|
|
31
28
|
_source: string;
|
|
32
29
|
}
|
|
33
30
|
|
|
34
|
-
export function ExtensionSlotsConfigTree({
|
|
35
|
-
extensionsConfig,
|
|
36
|
-
moduleName,
|
|
37
|
-
}: ExtensionSlotsConfigTreeProps) {
|
|
31
|
+
export function ExtensionSlotsConfigTree({ extensionsConfig, moduleName }: ExtensionSlotsConfigTreeProps) {
|
|
38
32
|
return extensionsConfig && Object.keys(extensionsConfig).length ? (
|
|
39
33
|
<Subtree label="extension slots" leaf={false}>
|
|
40
34
|
{Object.keys(extensionsConfig).map((slotName) => (
|
|
41
35
|
<ExtensionSlotConfigTree
|
|
42
36
|
key={slotName}
|
|
43
37
|
config={extensionsConfig?.[slotName]}
|
|
44
|
-
path={[moduleName,
|
|
38
|
+
path={[moduleName, 'extensionSlots', slotName]}
|
|
45
39
|
/>
|
|
46
40
|
))}
|
|
47
41
|
</Subtree>
|
|
@@ -69,23 +63,17 @@ function ExtensionSlotConfigTree({ config, path }: ExtensionSlotConfigProps) {
|
|
|
69
63
|
}
|
|
70
64
|
}
|
|
71
65
|
|
|
72
|
-
function setActiveItemDescriptionOnMouseEnter(
|
|
73
|
-
moduleName,
|
|
74
|
-
slotName,
|
|
75
|
-
key,
|
|
76
|
-
value
|
|
77
|
-
) {
|
|
66
|
+
function setActiveItemDescriptionOnMouseEnter(moduleName, slotName, key, value) {
|
|
78
67
|
if (!implementerToolsStore.getState().configPathBeingEdited) {
|
|
79
68
|
implementerToolsStore.setState({
|
|
80
69
|
activeItemDescription: {
|
|
81
70
|
path: [moduleName, slotName, key],
|
|
82
71
|
source: value?._source,
|
|
83
72
|
description: {
|
|
84
|
-
add:
|
|
85
|
-
remove:
|
|
86
|
-
order:
|
|
87
|
-
configure:
|
|
88
|
-
"Pass a configuration object directly to one of the extensions in this slot.",
|
|
73
|
+
add: 'Add an extension to this slot.',
|
|
74
|
+
remove: 'Remove an extension from this slot.',
|
|
75
|
+
order: 'Reorder the extensions in this slot.',
|
|
76
|
+
configure: 'Pass a configuration object directly to one of the extensions in this slot.',
|
|
89
77
|
}[key],
|
|
90
78
|
value: JSON.stringify(value?._value),
|
|
91
79
|
},
|
|
@@ -95,10 +83,7 @@ function ExtensionSlotConfigTree({ config, path }: ExtensionSlotConfigProps) {
|
|
|
95
83
|
|
|
96
84
|
function removeActiveItemDescriptionOnMouseLeave(thisPath) {
|
|
97
85
|
const state = implementerToolsStore.getState();
|
|
98
|
-
if (
|
|
99
|
-
isEqual(state.activeItemDescription?.path, thisPath) &&
|
|
100
|
-
!isEqual(state.configPathBeingEdited, thisPath)
|
|
101
|
-
) {
|
|
86
|
+
if (isEqual(state.activeItemDescription?.path, thisPath) && !isEqual(state.configPathBeingEdited, thisPath)) {
|
|
102
87
|
implementerToolsStore.setState({ activeItemDescription: undefined });
|
|
103
88
|
}
|
|
104
89
|
}
|
|
@@ -107,43 +92,26 @@ function ExtensionSlotConfigTree({ config, path }: ExtensionSlotConfigProps) {
|
|
|
107
92
|
<Subtree
|
|
108
93
|
label={slotName}
|
|
109
94
|
leaf={false}
|
|
110
|
-
onMouseEnter={() =>
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
onMouseLeave={() =>
|
|
114
|
-
removeActiveItemDescriptionOnMouseLeave([moduleName, slotName])
|
|
115
|
-
}
|
|
95
|
+
onMouseEnter={() => setActiveExtensionSlotOnMouseEnter(moduleName, slotName)}
|
|
96
|
+
onMouseLeave={() => removeActiveItemDescriptionOnMouseLeave([moduleName, slotName])}
|
|
116
97
|
>
|
|
117
|
-
{([
|
|
98
|
+
{(['add', 'remove', 'order', 'configure'] as const).map((key) => (
|
|
118
99
|
<Subtree
|
|
119
100
|
label={key}
|
|
120
|
-
key={path.join(
|
|
101
|
+
key={path.join('.') + key}
|
|
121
102
|
leaf={true}
|
|
122
|
-
onMouseEnter={() =>
|
|
123
|
-
|
|
124
|
-
moduleName,
|
|
125
|
-
slotName,
|
|
126
|
-
key,
|
|
127
|
-
config?.[key]
|
|
128
|
-
)
|
|
129
|
-
}
|
|
130
|
-
onMouseLeave={() =>
|
|
131
|
-
removeActiveItemDescriptionOnMouseLeave([moduleName, slotName, key])
|
|
132
|
-
}
|
|
103
|
+
onMouseEnter={() => setActiveItemDescriptionOnMouseEnter(moduleName, slotName, key, config?.[key])}
|
|
104
|
+
onMouseLeave={() => removeActiveItemDescriptionOnMouseLeave([moduleName, slotName, key])}
|
|
133
105
|
>
|
|
134
|
-
{key ===
|
|
135
|
-
<ExtensionConfigureTree
|
|
136
|
-
moduleName={moduleName}
|
|
137
|
-
slotName={slotName}
|
|
138
|
-
config={config?.configure?._value}
|
|
139
|
-
/>
|
|
106
|
+
{key === 'configure' ? (
|
|
107
|
+
<ExtensionConfigureTree moduleName={moduleName} slotName={slotName} config={config?.configure?._value} />
|
|
140
108
|
) : (
|
|
141
109
|
<EditableValue
|
|
142
110
|
path={path.concat([key])}
|
|
143
111
|
element={
|
|
144
112
|
config?.[key] ?? {
|
|
145
113
|
_value: undefined,
|
|
146
|
-
_source:
|
|
114
|
+
_source: 'default',
|
|
147
115
|
_default: [],
|
|
148
116
|
}
|
|
149
117
|
}
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
StructuredListCell,
|
|
5
|
-
StructuredListRow,
|
|
6
|
-
StructuredListWrapper,
|
|
7
|
-
} from "@carbon/react";
|
|
8
|
-
import styles from "./layout.styles.css";
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StructuredListBody, StructuredListCell, StructuredListRow, StructuredListWrapper } from '@carbon/react';
|
|
3
|
+
import styles from './layout.styles.css';
|
|
9
4
|
|
|
10
5
|
export interface SubtreeProps {
|
|
11
6
|
leaf: boolean;
|
|
@@ -15,34 +10,16 @@ export interface SubtreeProps {
|
|
|
15
10
|
onMouseLeave?: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
|
16
11
|
}
|
|
17
12
|
|
|
18
|
-
export function Subtree({
|
|
19
|
-
leaf,
|
|
20
|
-
label,
|
|
21
|
-
children,
|
|
22
|
-
onMouseEnter,
|
|
23
|
-
onMouseLeave,
|
|
24
|
-
}: SubtreeProps) {
|
|
13
|
+
export function Subtree({ leaf, label, children, onMouseEnter, onMouseLeave }: SubtreeProps) {
|
|
25
14
|
return leaf ? (
|
|
26
|
-
<StructuredListRow
|
|
27
|
-
className={styles.
|
|
28
|
-
onMouseEnter={onMouseEnter}
|
|
29
|
-
onMouseLeave={onMouseLeave}
|
|
30
|
-
>
|
|
31
|
-
<StructuredListCell className={styles.labelCell}>
|
|
32
|
-
{label}
|
|
33
|
-
</StructuredListCell>
|
|
15
|
+
<StructuredListRow className={styles.structuredListRow} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
|
|
16
|
+
<StructuredListCell className={styles.labelCell}>{label}</StructuredListCell>
|
|
34
17
|
<StructuredListCell>{children}</StructuredListCell>
|
|
35
18
|
</StructuredListRow>
|
|
36
19
|
) : (
|
|
37
20
|
<>
|
|
38
|
-
<StructuredListRow
|
|
39
|
-
className={styles.
|
|
40
|
-
onMouseEnter={onMouseEnter}
|
|
41
|
-
onMouseLeave={onMouseLeave}
|
|
42
|
-
>
|
|
43
|
-
<StructuredListCell className={styles.labelCell}>
|
|
44
|
-
{label}
|
|
45
|
-
</StructuredListCell>
|
|
21
|
+
<StructuredListRow className={styles.structuredListRow} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
|
|
22
|
+
<StructuredListCell className={styles.labelCell}>{label}</StructuredListCell>
|
|
46
23
|
<StructuredListCell />
|
|
47
24
|
</StructuredListRow>
|
|
48
25
|
<StructuredListRow className={styles.structuredListRow}>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React, { ReactNode } from
|
|
2
|
-
import { StructuredListBody, StructuredListWrapper } from
|
|
3
|
-
import styles from
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { StructuredListBody, StructuredListWrapper } from '@carbon/react';
|
|
3
|
+
import styles from './layout.styles.css';
|
|
4
4
|
|
|
5
5
|
export interface TreeContainerProps {
|
|
6
6
|
children: ReactNode;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import React, { useEffect, useState, useRef } from
|
|
2
|
-
import { useTranslation } from
|
|
3
|
-
import { Button } from
|
|
4
|
-
import { Close, Save } from
|
|
5
|
-
import { Type } from
|
|
6
|
-
import { ConfigValueDescriptor } from
|
|
7
|
-
import { ValueEditorField } from
|
|
8
|
-
import styles from
|
|
1
|
+
import React, { useEffect, useState, useRef } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { Button } from '@carbon/react';
|
|
4
|
+
import { Close, Save } from '@carbon/react/icons';
|
|
5
|
+
import { Type } from '@openmrs/esm-framework';
|
|
6
|
+
import { ConfigValueDescriptor } from './editable-value.component';
|
|
7
|
+
import { ValueEditorField } from './value-editors/value-editor-field';
|
|
8
|
+
import styles from './value-editor.scss';
|
|
9
9
|
|
|
10
|
-
export type CustomValueType =
|
|
10
|
+
export type CustomValueType = 'add' | 'remove' | 'order' | 'configure';
|
|
11
11
|
|
|
12
12
|
export type ValueType = CustomValueType | Type;
|
|
13
13
|
|
|
@@ -19,13 +19,7 @@ interface ValueEditorProps {
|
|
|
19
19
|
handleClose: () => void;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
export function ValueEditor({
|
|
23
|
-
element,
|
|
24
|
-
customType,
|
|
25
|
-
path,
|
|
26
|
-
handleSave,
|
|
27
|
-
handleClose,
|
|
28
|
-
}: ValueEditorProps) {
|
|
22
|
+
export function ValueEditor({ element, customType, path, handleSave, handleClose }: ValueEditorProps) {
|
|
29
23
|
const ref = useRef<HTMLDivElement>(null);
|
|
30
24
|
const [tmpValue, setTmpValue] = useState(element._value);
|
|
31
25
|
const { t } = useTranslation();
|
|
@@ -34,42 +28,32 @@ export function ValueEditor({
|
|
|
34
28
|
|
|
35
29
|
useEffect(() => {
|
|
36
30
|
const keyListener = (e: KeyboardEvent) => {
|
|
37
|
-
if (e.key ===
|
|
31
|
+
if (e.key === 'Escape') {
|
|
38
32
|
handleClose();
|
|
39
|
-
} else if (e.key ===
|
|
33
|
+
} else if (e.key === 'Enter') {
|
|
40
34
|
handleSave(JSON.stringify(tmpValue));
|
|
41
35
|
}
|
|
42
36
|
};
|
|
43
37
|
|
|
44
|
-
document.addEventListener(
|
|
38
|
+
document.addEventListener('keyup', keyListener);
|
|
45
39
|
return () => {
|
|
46
|
-
document.removeEventListener(
|
|
40
|
+
document.removeEventListener('keyup', keyListener);
|
|
47
41
|
};
|
|
48
42
|
}, [handleSave, handleClose, tmpValue]);
|
|
49
43
|
|
|
50
44
|
return (
|
|
51
|
-
<div ref={ref} style={{ display:
|
|
52
|
-
<ValueEditorField
|
|
53
|
-
element={element}
|
|
54
|
-
path={path}
|
|
55
|
-
value={tmpValue}
|
|
56
|
-
onChange={setTmpValue}
|
|
57
|
-
valueType={valueType}
|
|
58
|
-
/>
|
|
45
|
+
<div ref={ref} style={{ display: 'inherit' }}>
|
|
46
|
+
<ValueEditorField element={element} path={path} value={tmpValue} onChange={setTmpValue} valueType={valueType} />
|
|
59
47
|
<div className={styles.valueEditorButtons}>
|
|
60
48
|
<Button
|
|
61
49
|
renderIcon={(props) => <Save {...props} size={16} />}
|
|
62
50
|
kind="primary"
|
|
63
51
|
onClick={() => handleSave(JSON.stringify(tmpValue))}
|
|
64
52
|
>
|
|
65
|
-
{t(
|
|
53
|
+
{t('saveValueButtonText', 'Save')}
|
|
66
54
|
</Button>
|
|
67
|
-
<Button
|
|
68
|
-
|
|
69
|
-
kind="secondary"
|
|
70
|
-
onClick={handleClose}
|
|
71
|
-
>
|
|
72
|
-
{t("cancelButtonText", "Cancel")}
|
|
55
|
+
<Button renderIcon={(props) => <Close {...props} size={16} />} kind="secondary" onClick={handleClose}>
|
|
56
|
+
{t('cancelButtonText', 'Cancel')}
|
|
73
57
|
</Button>
|
|
74
58
|
</div>
|
|
75
59
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import React, { useMemo } from
|
|
2
|
-
import cloneDeep from
|
|
3
|
-
import uniqueId from
|
|
4
|
-
import { Type } from
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import cloneDeep from 'lodash-es/cloneDeep';
|
|
3
|
+
import uniqueId from 'lodash-es/uniqueId';
|
|
4
|
+
import { Type } from '@openmrs/esm-framework';
|
|
5
5
|
import {
|
|
6
6
|
Button,
|
|
7
7
|
Tile,
|
|
@@ -9,11 +9,11 @@ import {
|
|
|
9
9
|
StructuredListCell,
|
|
10
10
|
StructuredListRow,
|
|
11
11
|
StructuredListWrapper,
|
|
12
|
-
} from
|
|
13
|
-
import { Add, TrashCan } from
|
|
14
|
-
import { ValueEditorField } from
|
|
15
|
-
import { ConfigValueDescriptor } from
|
|
16
|
-
import styles from
|
|
12
|
+
} from '@carbon/react';
|
|
13
|
+
import { Add, TrashCan } from '@carbon/react/icons';
|
|
14
|
+
import { ValueEditorField } from './value-editor-field';
|
|
15
|
+
import { ConfigValueDescriptor } from '../editable-value.component';
|
|
16
|
+
import styles from './array-editor.styles.css';
|
|
17
17
|
|
|
18
18
|
interface ArrayEditorProps {
|
|
19
19
|
element: ConfigValueDescriptor;
|
|
@@ -21,12 +21,8 @@ interface ArrayEditorProps {
|
|
|
21
21
|
setValue: (value: Array<any>) => void;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export function ArrayEditor({
|
|
25
|
-
|
|
26
|
-
valueArray,
|
|
27
|
-
setValue,
|
|
28
|
-
}: ArrayEditorProps) {
|
|
29
|
-
const arrayKey = useMemo(() => uniqueId("array-editor-"), []);
|
|
24
|
+
export function ArrayEditor({ element, valueArray, setValue }: ArrayEditorProps) {
|
|
25
|
+
const arrayKey = useMemo(() => uniqueId('array-editor-'), []);
|
|
30
26
|
return (
|
|
31
27
|
<Tile className={styles.arrayEditor}>
|
|
32
28
|
<StructuredListWrapper>
|
|
@@ -74,10 +70,7 @@ export function ArrayEditor({
|
|
|
74
70
|
hasIconOnly
|
|
75
71
|
onClick={() => {
|
|
76
72
|
const newValueArray = cloneDeep(valueArray);
|
|
77
|
-
const newValue =
|
|
78
|
-
(element._elements?._type ?? Type.Object) == Type.Object
|
|
79
|
-
? {}
|
|
80
|
-
: null;
|
|
73
|
+
const newValue = (element._elements?._type ?? Type.Object) == Type.Object ? {} : null;
|
|
81
74
|
newValueArray.push(newValue);
|
|
82
75
|
setValue(newValueArray);
|
|
83
76
|
}}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import useSWR from
|
|
2
|
-
import { openmrsFetch } from
|
|
1
|
+
import useSWR from 'swr';
|
|
2
|
+
import { openmrsFetch } from '@openmrs/esm-framework';
|
|
3
3
|
|
|
4
4
|
export type Concept = {
|
|
5
5
|
answers: Array<ConceptAnswer>;
|
|
@@ -22,7 +22,7 @@ export function useConceptLookup(query: string) {
|
|
|
22
22
|
|
|
23
23
|
const { data, error } = useSWR<{ data: { results: Array<Concept> } }, Error>(
|
|
24
24
|
query ? conceptLookupUrl : null,
|
|
25
|
-
openmrsFetch
|
|
25
|
+
openmrsFetch,
|
|
26
26
|
);
|
|
27
27
|
|
|
28
28
|
return {
|
|
@@ -35,10 +35,7 @@ export function useConceptLookup(query: string) {
|
|
|
35
35
|
export function useGetConceptByUuid(conceptUuid: string) {
|
|
36
36
|
const fetchConceptUrl = `/ws/rest/v1/concept/${conceptUuid}`;
|
|
37
37
|
|
|
38
|
-
const { data, error } = useSWR<{ data: Concept }, Error>(
|
|
39
|
-
conceptUuid ? fetchConceptUrl : null,
|
|
40
|
-
openmrsFetch
|
|
41
|
-
);
|
|
38
|
+
const { data, error } = useSWR<{ data: Concept }, Error>(conceptUuid ? fetchConceptUrl : null, openmrsFetch);
|
|
42
39
|
|
|
43
40
|
return {
|
|
44
41
|
concept: data?.data ?? null,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
@use
|
|
2
|
-
@use
|
|
3
|
-
@import
|
|
1
|
+
@use '@carbon/styles/scss/type';
|
|
2
|
+
@use '@carbon/styles/scss/spacing';
|
|
3
|
+
@import '../../implementer-tools.styles.scss';
|
|
4
4
|
|
|
5
5
|
.activeConceptUuid {
|
|
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,13 +11,13 @@
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
.autocomplete,
|
|
14
|
-
.autocomplete > [role=
|
|
14
|
+
.autocomplete > [role='combobox'] {
|
|
15
15
|
display: flex;
|
|
16
16
|
position: relative;
|
|
17
17
|
width: 20em;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
.autocomplete [role=
|
|
20
|
+
.autocomplete [role='listbox'] {
|
|
21
21
|
margin: 0;
|
|
22
22
|
padding: 0;
|
|
23
23
|
display: flex;
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
color: #000;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
.autocomplete [role=
|
|
39
|
+
.autocomplete [role='option']:hover {
|
|
40
40
|
background-color: #38a169;
|
|
41
41
|
border-color: #38a169;
|
|
42
42
|
color: #f7fafc;
|