@openmrs/esm-implementer-tools-app 3.1.10-pre.97 → 3.1.12-pre.599
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/README.md +1 -9
- package/__mocks__/react-i18next.js +54 -0
- package/{.babelrc → babel.config.json} +2 -1
- package/dist/266.openmrs-esm-implementer-tools-app.js +3 -0
- package/dist/266.openmrs-esm-implementer-tools-app.js.LICENSE.txt +8 -0
- package/dist/266.openmrs-esm-implementer-tools-app.js.map +1 -0
- package/dist/319.openmrs-esm-implementer-tools-app.js +1 -0
- package/dist/472.openmrs-esm-implementer-tools-app.js +2 -0
- package/dist/472.openmrs-esm-implementer-tools-app.js.map +1 -0
- package/dist/574.openmrs-esm-implementer-tools-app.js +1 -0
- package/dist/728.openmrs-esm-implementer-tools-app.js +2 -0
- package/dist/728.openmrs-esm-implementer-tools-app.js.map +1 -0
- package/dist/965.openmrs-esm-implementer-tools-app.js +3 -0
- package/dist/965.openmrs-esm-implementer-tools-app.js.LICENSE.txt +5 -0
- package/dist/965.openmrs-esm-implementer-tools-app.js.map +1 -0
- package/dist/openmrs-esm-implementer-tools-app.js +1 -1
- package/dist/openmrs-esm-implementer-tools-app.js.buildmanifest.json +170 -0
- package/dist/openmrs-esm-implementer-tools-app.js.map +1 -1
- package/jest.config.js +1 -2
- package/package.json +13 -20
- package/src/backend-dependencies/backend-dependencies.component.tsx +97 -0
- package/src/backend-dependencies/openmrs-backend-dependencies.ts +113 -93
- package/src/backend-dependencies/useBackendDependencies.ts +16 -0
- package/src/config-edit-button/config-edit-button.component.tsx +3 -1
- package/src/configuration/config-tree-for-module.component.tsx +1 -1
- package/src/configuration/config-tree.component.tsx +2 -9
- package/src/configuration/configuration.component.tsx +101 -31
- package/src/configuration/configuration.test.tsx +6 -6
- package/src/configuration/description.component.tsx +3 -1
- package/src/configuration/display-value.tsx +4 -4
- package/src/configuration/editable-value.component.tsx +5 -2
- package/src/configuration/extension-slots-config-tree.tsx +10 -14
- package/src/configuration/layout/subtree.component.tsx +1 -1
- package/src/configuration/layout/tree-container.component.tsx +1 -1
- package/src/configuration/value-editor.tsx +1 -1
- package/src/configuration/value-editors/array-editor.tsx +3 -3
- package/src/configuration/value-editors/extension-slot-add.tsx +1 -1
- package/src/configuration/value-editors/extension-slot-order.tsx +0 -4
- package/src/configuration/value-editors/extension-slot-remove.tsx +19 -7
- package/src/configuration/value-editors/object-editor.tsx +3 -3
- package/src/configuration/value-editors/value-editor-field.tsx +1 -3
- package/src/implementer-tools.button.tsx +33 -0
- package/src/implementer-tools.component.tsx +45 -81
- package/src/implementer-tools.styles.css +5 -9
- package/src/index.ts +35 -9
- package/src/popup/popup.component.tsx +11 -27
- package/src/popup/popup.styles.css +1 -1
- package/src/store.ts +27 -32
- package/src/ui-editor/extension-overlay.component.tsx +1 -1
- package/src/ui-editor/styles.css +7 -0
- package/src/ui-editor/ui-editor.tsx +49 -21
- package/translations/en.json +12 -0
- package/translations/es.json +13 -0
- package/tsconfig.json +1 -0
- package/webpack.config.js +1 -66
- package/__mocks__/openmrs-esm-framework.mock.tsx +0 -142
- package/dist/1.openmrs-esm-implementer-tools-app.js +0 -15
- package/dist/1.openmrs-esm-implementer-tools-app.js.map +0 -1
- package/dist/2.openmrs-esm-implementer-tools-app.js +0 -2
- package/dist/2.openmrs-esm-implementer-tools-app.js.map +0 -1
- package/src/backend-dependencies/backend-dependecies.component.tsx +0 -106
- package/src/backend-dependencies/backend-dependencies-style.css +0 -4
- package/src/backend-dependencies/helpers/backend-dependecies-helper.test.ts +0 -127
- package/src/backend-dependencies/helpers/backend-dependecies-helper.ts +0 -70
- package/src/set-public-path.ts +0 -3
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import React, { useEffect, useState } from "react";
|
|
1
|
+
import React, { useEffect, useMemo, useState } from "react";
|
|
2
2
|
import EditableValue from "./editable-value.component";
|
|
3
3
|
import isEqual from "lodash-es/isEqual";
|
|
4
4
|
import {
|
|
5
5
|
extensionStore,
|
|
6
6
|
ExtensionSlotConfigureValueObject,
|
|
7
|
-
|
|
7
|
+
useExtensionStore,
|
|
8
|
+
ExtensionStore,
|
|
8
9
|
} from "@openmrs/esm-framework";
|
|
9
10
|
import { ExtensionConfigureTree } from "./extension-configure-tree";
|
|
10
11
|
import { Subtree } from "./layout/subtree.component";
|
|
11
12
|
import { implementerToolsStore } from "../store";
|
|
12
13
|
|
|
13
14
|
interface ExtensionSlotsConfigTreeProps {
|
|
14
|
-
|
|
15
|
+
extensionsConfig: { [key: string]: any };
|
|
15
16
|
moduleName: string;
|
|
16
17
|
}
|
|
17
18
|
|
|
@@ -33,20 +34,15 @@ interface ExtensionConfigureDescriptor {
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
export function ExtensionSlotsConfigTree({
|
|
36
|
-
|
|
37
|
+
extensionsConfig,
|
|
37
38
|
moduleName,
|
|
38
39
|
}: ExtensionSlotsConfigTreeProps) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
extensionIdBySlotByModule[moduleName] || {}
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
return extensionSlotNames.length ? (
|
|
46
|
-
<Subtree label={"extension slots"} leaf={false}>
|
|
47
|
-
{extensionSlotNames.map((slotName) => (
|
|
40
|
+
return extensionsConfig && Object.keys(extensionsConfig).length ? (
|
|
41
|
+
<Subtree label="extension slots" leaf={false}>
|
|
42
|
+
{Object.keys(extensionsConfig).map((slotName) => (
|
|
48
43
|
<ExtensionSlotConfigTree
|
|
49
|
-
|
|
44
|
+
key={slotName}
|
|
45
|
+
config={extensionsConfig?.[slotName]}
|
|
50
46
|
path={[moduleName, "extensions", slotName]}
|
|
51
47
|
/>
|
|
52
48
|
))}
|
|
@@ -2,7 +2,7 @@ import React, { ReactNode } from "react";
|
|
|
2
2
|
import {
|
|
3
3
|
StructuredListBody,
|
|
4
4
|
StructuredListWrapper,
|
|
5
|
-
} from "carbon-components-react
|
|
5
|
+
} from "carbon-components-react";
|
|
6
6
|
import styles from "./layout.styles.css";
|
|
7
7
|
|
|
8
8
|
export interface TreeContainerProps {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useState, useRef } from "react";
|
|
2
2
|
import Close16 from "@carbon/icons-react/es/close/16";
|
|
3
3
|
import Save16 from "@carbon/icons-react/es/save/16";
|
|
4
|
-
import Button from "carbon-components-react
|
|
4
|
+
import { Button } from "carbon-components-react";
|
|
5
5
|
import { Type } from "@openmrs/esm-framework";
|
|
6
6
|
import { ConfigValueDescriptor } from "./editable-value.component";
|
|
7
7
|
import { ValueEditorField } from "./value-editors/value-editor-field";
|
|
@@ -3,16 +3,16 @@ import cloneDeep from "lodash-es/cloneDeep";
|
|
|
3
3
|
import uniqueId from "lodash-es/uniqueId";
|
|
4
4
|
import Add16 from "@carbon/icons-react/es/add/16";
|
|
5
5
|
import TrashCan16 from "@carbon/icons-react/es/trash-can/16";
|
|
6
|
-
import Button from "carbon-components-react/es/components/Button";
|
|
7
6
|
import styles from "./array-editor.styles.css";
|
|
8
7
|
import { Type } from "@openmrs/esm-framework";
|
|
9
|
-
import { Tile } from "carbon-components-react/es/components/Tile";
|
|
10
8
|
import {
|
|
9
|
+
Button,
|
|
10
|
+
Tile,
|
|
11
11
|
StructuredListBody,
|
|
12
12
|
StructuredListCell,
|
|
13
13
|
StructuredListRow,
|
|
14
14
|
StructuredListWrapper,
|
|
15
|
-
} from "carbon-components-react
|
|
15
|
+
} from "carbon-components-react";
|
|
16
16
|
import { ValueEditorField } from "./value-editor-field";
|
|
17
17
|
import { ConfigValueDescriptor } from "../editable-value.component";
|
|
18
18
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useState, useEffect } from "react";
|
|
2
|
-
import MultiSelect from "carbon-components-react
|
|
2
|
+
import { MultiSelect } from "carbon-components-react";
|
|
3
3
|
import { ExtensionStore, extensionStore } from "@openmrs/esm-framework";
|
|
4
4
|
|
|
5
5
|
export function ExtensionSlotAdd({ value, setValue }) {
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { useStore } from "@openmrs/esm-framework";
|
|
3
|
-
import { implementerToolsStore } from "../../store";
|
|
4
2
|
|
|
5
3
|
export function ExtensionSlotOrder({
|
|
6
4
|
slotName,
|
|
@@ -8,7 +6,5 @@ export function ExtensionSlotOrder({
|
|
|
8
6
|
value,
|
|
9
7
|
setValue,
|
|
10
8
|
}) {
|
|
11
|
-
const { extensionIdBySlotByModule } = useStore(implementerToolsStore);
|
|
12
|
-
|
|
13
9
|
return <div>Todo: compose array with extension lookup</div>;
|
|
14
10
|
}
|
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import MultiSelect from "carbon-components-react
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import { MultiSelect } from "carbon-components-react";
|
|
3
|
+
import {
|
|
4
|
+
ExtensionStore,
|
|
5
|
+
getAssignedIds,
|
|
6
|
+
useExtensionStore,
|
|
7
|
+
} from "@openmrs/esm-framework";
|
|
8
|
+
|
|
9
|
+
function getExtensionIds(
|
|
10
|
+
store: ExtensionStore,
|
|
11
|
+
moduleName: string,
|
|
12
|
+
slotName: string
|
|
13
|
+
) {
|
|
14
|
+
const slot = store.slots[slotName];
|
|
15
|
+
const instance = slot.instances[moduleName];
|
|
16
|
+
return getAssignedIds(instance, slot.attachedIds);
|
|
17
|
+
}
|
|
5
18
|
|
|
6
19
|
export function ExtensionSlotRemove({
|
|
7
20
|
slotName,
|
|
@@ -9,14 +22,13 @@ export function ExtensionSlotRemove({
|
|
|
9
22
|
value,
|
|
10
23
|
setValue,
|
|
11
24
|
}) {
|
|
12
|
-
const
|
|
25
|
+
const store = useExtensionStore();
|
|
26
|
+
const assignedIds = getExtensionIds(store, slotModuleName, slotName);
|
|
13
27
|
|
|
14
28
|
return (
|
|
15
29
|
<MultiSelect.Filterable
|
|
16
30
|
id={`add-select`}
|
|
17
|
-
items={
|
|
18
|
-
slotName
|
|
19
|
-
].map((name) => ({ id: name, label: name }))}
|
|
31
|
+
items={assignedIds.map((id) => ({ id, label: id }))}
|
|
20
32
|
placeholder="Select extensions"
|
|
21
33
|
onChange={(value) => setValue(value.selectedItems.map((v) => v.id))}
|
|
22
34
|
initialSelectedItems={value}
|
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
StructuredListCell,
|
|
5
5
|
StructuredListRow,
|
|
6
6
|
StructuredListWrapper,
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
Tile,
|
|
8
|
+
} from "carbon-components-react";
|
|
9
9
|
import { ValueEditorField } from "./value-editor-field";
|
|
10
10
|
import { ConfigValueDescriptor } from "../editable-value.component";
|
|
11
11
|
import { Type } from "@openmrs/esm-framework";
|
|
@@ -29,7 +29,7 @@ export function ObjectEditor({
|
|
|
29
29
|
<StructuredListBody>
|
|
30
30
|
{Object.entries(element).map(([key, schema]) =>
|
|
31
31
|
!key.startsWith("_") ? (
|
|
32
|
-
<StructuredListRow>
|
|
32
|
+
<StructuredListRow key={key}>
|
|
33
33
|
<StructuredListCell>
|
|
34
34
|
<ValueEditorField
|
|
35
35
|
element={{ _value: key, _source: element._source }}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import React, { useState } from "react";
|
|
2
2
|
import uniqueId from "lodash-es/uniqueId";
|
|
3
|
-
import Checkbox from "carbon-components-react
|
|
4
|
-
import NumberInput from "carbon-components-react/es/components/NumberInput";
|
|
5
|
-
import TextInput from "carbon-components-react/es/components/TextInput";
|
|
3
|
+
import { Checkbox, NumberInput, TextInput } from "carbon-components-react";
|
|
6
4
|
import { Type } from "@openmrs/esm-framework";
|
|
7
5
|
import { ConfigValueDescriptor } from "../editable-value.component";
|
|
8
6
|
import { ValueType } from "../value-editor";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import Close20 from "@carbon/icons-react/es/close/20";
|
|
4
|
+
import Tools20 from "@carbon/icons-react/es/tools/20";
|
|
5
|
+
import { HeaderGlobalAction } from "carbon-components-react";
|
|
6
|
+
import { UserHasAccess, useStore } from "@openmrs/esm-framework";
|
|
7
|
+
import { implementerToolsStore, togglePopup } from "./store";
|
|
8
|
+
import styles from "./implementer-tools.styles.css";
|
|
9
|
+
|
|
10
|
+
const ImplementerToolsButton: React.FC = () => {
|
|
11
|
+
const { t } = useTranslation();
|
|
12
|
+
const { isOpen } = useStore(implementerToolsStore);
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<UserHasAccess privilege="coreapps.systemAdministration">
|
|
16
|
+
<HeaderGlobalAction
|
|
17
|
+
aria-label={t("implementerTools", "Implementer Tools")}
|
|
18
|
+
aria-labelledby="Implementer Tools"
|
|
19
|
+
className={styles.toolStyles}
|
|
20
|
+
name="ImplementerToolsIcon"
|
|
21
|
+
onClick={togglePopup}
|
|
22
|
+
>
|
|
23
|
+
{isOpen ? (
|
|
24
|
+
<Close20 />
|
|
25
|
+
) : (
|
|
26
|
+
<Tools20 className={styles.popupTriggerButton} />
|
|
27
|
+
)}
|
|
28
|
+
</HeaderGlobalAction>
|
|
29
|
+
</UserHasAccess>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default ImplementerToolsButton;
|
|
@@ -1,104 +1,68 @@
|
|
|
1
1
|
import React, { useState, useEffect } from "react";
|
|
2
|
-
import { UserHasAccess, showToast, useStore } from "@openmrs/esm-framework";
|
|
3
2
|
import Popup from "./popup/popup.component";
|
|
4
|
-
import
|
|
3
|
+
import { NotificationActionButton } from "carbon-components-react";
|
|
5
4
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
showNotification,
|
|
6
|
+
UserHasAccess,
|
|
7
|
+
useStore,
|
|
8
|
+
} from "@openmrs/esm-framework";
|
|
9
|
+
import {
|
|
10
|
+
implementerToolsStore,
|
|
11
|
+
showModuleDiagnostics,
|
|
12
|
+
togglePopup,
|
|
13
|
+
} from "./store";
|
|
10
14
|
import { UiEditor } from "./ui-editor/ui-editor";
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
export default function ImplementerTools() {
|
|
14
|
-
return (
|
|
15
|
-
<UserHasAccess privilege="coreapps.systemAdministration">
|
|
16
|
-
<PopupHandler />
|
|
17
|
-
</UserHasAccess>
|
|
18
|
-
);
|
|
19
|
-
}
|
|
15
|
+
import { useBackendDependencies } from "./backend-dependencies/useBackendDependencies";
|
|
16
|
+
import { hasInvalidDependencies } from "./backend-dependencies/openmrs-backend-dependencies";
|
|
20
17
|
|
|
21
18
|
function PopupHandler() {
|
|
22
|
-
const
|
|
23
|
-
const [
|
|
24
|
-
const [
|
|
25
|
-
modulesWithMissingBackendModules,
|
|
26
|
-
setModulesWithMissingBackendModules,
|
|
27
|
-
] = useState<Array<MissingBackendModules>>([]);
|
|
28
|
-
const [
|
|
29
|
-
modulesWithWrongBackendModulesVersion,
|
|
30
|
-
setModulesWithWrongBackendModulesVersion,
|
|
31
|
-
] = useState<Array<MissingBackendModules>>([]);
|
|
32
|
-
const { isOpen, isUIEditorEnabled } = useStore(implementerToolsStore);
|
|
19
|
+
const frontendModules = useBackendDependencies();
|
|
20
|
+
const [shouldShowNotification, setShouldShowNotification] = useState(false);
|
|
33
21
|
|
|
34
|
-
function togglePopup() {
|
|
35
|
-
implementerToolsStore.setState({ isOpen: !isOpen });
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// loading missing modules
|
|
39
22
|
useEffect(() => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}) => {
|
|
45
|
-
setModulesWithMissingBackendModules(modulesWithMissingBackendModules);
|
|
46
|
-
setModulesWithWrongBackendModulesVersion(
|
|
47
|
-
modulesWithWrongBackendModulesVersion
|
|
48
|
-
);
|
|
49
|
-
}
|
|
23
|
+
// displaying toast if modules are missing
|
|
24
|
+
setShouldShowNotification(
|
|
25
|
+
(alreadyShowing) =>
|
|
26
|
+
alreadyShowing || hasInvalidDependencies(frontendModules)
|
|
50
27
|
);
|
|
51
|
-
}, []);
|
|
28
|
+
}, [frontendModules]);
|
|
52
29
|
|
|
53
|
-
// displaying toast if modules are missing
|
|
54
30
|
useEffect(() => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return false;
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
showToast({
|
|
72
|
-
description: "Found modules with unresolved backend dependencies.",
|
|
73
|
-
action: (
|
|
74
|
-
<NotificationActionButton onClick={showModuleDiagnostics}>
|
|
75
|
-
View
|
|
76
|
-
</NotificationActionButton>
|
|
77
|
-
),
|
|
78
|
-
kind: "error",
|
|
79
|
-
});
|
|
80
|
-
}, [modulesWithMissingBackendModules, modulesWithWrongBackendModulesVersion]);
|
|
31
|
+
// only show notification max. 1 time
|
|
32
|
+
if (shouldShowNotification) {
|
|
33
|
+
showNotification({
|
|
34
|
+
description: "Found modules with unresolved backend dependencies.",
|
|
35
|
+
action: (
|
|
36
|
+
<NotificationActionButton onClick={showModuleDiagnostics}>
|
|
37
|
+
View
|
|
38
|
+
</NotificationActionButton>
|
|
39
|
+
),
|
|
40
|
+
kind: "error",
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}, [shouldShowNotification]);
|
|
81
44
|
|
|
45
|
+
const { isOpen, isUIEditorEnabled, openTabIndex } = useStore(
|
|
46
|
+
implementerToolsStore
|
|
47
|
+
);
|
|
82
48
|
return (
|
|
83
49
|
<>
|
|
84
|
-
<button
|
|
85
|
-
onClick={togglePopup}
|
|
86
|
-
className={`${styles.popupTriggerButton} ${
|
|
87
|
-
hasAlert ? styles.triggerButtonAlert : ""
|
|
88
|
-
}`}
|
|
89
|
-
/>
|
|
90
50
|
{isOpen ? (
|
|
91
51
|
<Popup
|
|
92
52
|
close={togglePopup}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
modulesWithWrongBackendModulesVersion={
|
|
96
|
-
modulesWithWrongBackendModulesVersion
|
|
97
|
-
}
|
|
98
|
-
visibleTabIndex={visibleTabIndex}
|
|
53
|
+
frontendModules={frontendModules}
|
|
54
|
+
visibleTabIndex={openTabIndex}
|
|
99
55
|
/>
|
|
100
56
|
) : null}
|
|
101
57
|
{isUIEditorEnabled ? <UiEditor /> : null}
|
|
102
58
|
</>
|
|
103
59
|
);
|
|
104
60
|
}
|
|
61
|
+
|
|
62
|
+
export default function ImplementerTools() {
|
|
63
|
+
return (
|
|
64
|
+
<UserHasAccess privilege="coreapps.systemAdministration">
|
|
65
|
+
<PopupHandler />
|
|
66
|
+
</UserHasAccess>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
.popupTriggerButton {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
width: 40px !important;
|
|
6
|
-
bottom: 10px;
|
|
7
|
-
right: 8px;
|
|
8
|
-
position: fixed;
|
|
2
|
+
height: 25px !important;
|
|
3
|
+
width: 25px !important;
|
|
4
|
+
position: relative;
|
|
9
5
|
border-radius: 2px;
|
|
10
6
|
}
|
|
11
7
|
|
|
12
|
-
.
|
|
13
|
-
background-color:
|
|
8
|
+
.toolStyles {
|
|
9
|
+
background-color: transparent;
|
|
14
10
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,20 +1,46 @@
|
|
|
1
1
|
import { getAsyncLifecycle } from "@openmrs/esm-framework";
|
|
2
2
|
|
|
3
|
+
const frontendDependencies = {
|
|
4
|
+
"@openmrs/esm-framework": process.env.FRAMEWORK_VERSION,
|
|
5
|
+
};
|
|
6
|
+
|
|
3
7
|
function setupOpenMRS() {
|
|
8
|
+
const moduleName = "@openmrs/esm-implementer-tools-app";
|
|
9
|
+
const options = {
|
|
10
|
+
featureName: "Implementer Tools",
|
|
11
|
+
moduleName,
|
|
12
|
+
};
|
|
13
|
+
|
|
4
14
|
return {
|
|
5
|
-
|
|
6
|
-
|
|
15
|
+
pages: [
|
|
16
|
+
{
|
|
17
|
+
route: () => true,
|
|
18
|
+
load: getAsyncLifecycle(
|
|
19
|
+
() => import("./implementer-tools.component"),
|
|
20
|
+
options
|
|
21
|
+
),
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
extensions: [
|
|
7
25
|
{
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
26
|
+
id: "implementer-tools-button",
|
|
27
|
+
slot: "top-nav-actions-slot",
|
|
28
|
+
load: getAsyncLifecycle(
|
|
29
|
+
() => import("./implementer-tools.button"),
|
|
30
|
+
options
|
|
31
|
+
),
|
|
32
|
+
},
|
|
33
|
+
],
|
|
13
34
|
};
|
|
14
35
|
}
|
|
15
36
|
|
|
16
|
-
const importTranslation =
|
|
37
|
+
const importTranslation = require.context(
|
|
38
|
+
"../translations",
|
|
39
|
+
false,
|
|
40
|
+
/.json$/,
|
|
41
|
+
"lazy"
|
|
42
|
+
);
|
|
17
43
|
|
|
18
|
-
export { setupOpenMRS, importTranslation };
|
|
44
|
+
export { setupOpenMRS, importTranslation, frontendDependencies };
|
|
19
45
|
|
|
20
46
|
export { default as ConfigEditButton } from "./config-edit-button/config-edit-button.component";
|
|
@@ -1,30 +1,22 @@
|
|
|
1
|
-
import React, { useState
|
|
1
|
+
import React, { useState } from "react";
|
|
2
2
|
import Close16 from "@carbon/icons-react/es/close/16";
|
|
3
|
-
import Button from "carbon-components-react/es/components/Button";
|
|
4
|
-
import ContentSwitcher from "carbon-components-react/es/components/ContentSwitcher";
|
|
5
|
-
import Switch from "carbon-components-react/es/components/Switch";
|
|
6
3
|
import styles from "./popup.styles.css";
|
|
4
|
+
import { Button, ContentSwitcher, Switch } from "carbon-components-react";
|
|
5
|
+
import { useTranslation } from "react-i18next";
|
|
7
6
|
import { Configuration } from "../configuration/configuration.component";
|
|
8
|
-
import { ModuleDiagnostics } from "../backend-dependencies/backend-
|
|
9
|
-
import {
|
|
7
|
+
import { ModuleDiagnostics } from "../backend-dependencies/backend-dependencies.component";
|
|
8
|
+
import { FrontendModule } from "../backend-dependencies/openmrs-backend-dependencies";
|
|
10
9
|
|
|
11
10
|
interface DevToolsPopupProps {
|
|
12
11
|
close(): void;
|
|
13
|
-
|
|
14
|
-
modulesWithMissingBackendModules: Array<MissingBackendModules>;
|
|
15
|
-
modulesWithWrongBackendModulesVersion: Array<MissingBackendModules>;
|
|
12
|
+
frontendModules: Array<FrontendModule>;
|
|
16
13
|
visibleTabIndex?: number;
|
|
17
14
|
}
|
|
18
15
|
|
|
19
16
|
export default function Popup(props: DevToolsPopupProps) {
|
|
20
|
-
const
|
|
21
|
-
const [diagnosticsHasAlert, setDiagnosticsHasAlert] = useState(false);
|
|
17
|
+
const { t } = useTranslation();
|
|
22
18
|
const [activeTab, setActiveTab] = useState(0);
|
|
23
19
|
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
props.setHasAlert(configHasAlert || diagnosticsHasAlert);
|
|
26
|
-
}, [diagnosticsHasAlert, configHasAlert]);
|
|
27
|
-
|
|
28
20
|
return (
|
|
29
21
|
<div className={styles.popup}>
|
|
30
22
|
<div className={styles.topBar}>
|
|
@@ -36,13 +28,13 @@ export default function Popup(props: DevToolsPopupProps) {
|
|
|
36
28
|
>
|
|
37
29
|
<Switch
|
|
38
30
|
name="configuration-tab"
|
|
39
|
-
text="Configuration"
|
|
31
|
+
text={t("configuration", "Configuration")}
|
|
40
32
|
onClick={() => {}}
|
|
41
33
|
onKeyDown={() => {}}
|
|
42
34
|
/>
|
|
43
35
|
<Switch
|
|
44
36
|
name="backend-modules-tab"
|
|
45
|
-
text="Backend Modules"
|
|
37
|
+
text={t("backendModules", "Backend Modules")}
|
|
46
38
|
onClick={() => {}}
|
|
47
39
|
onKeyDown={() => {}}
|
|
48
40
|
/>
|
|
@@ -61,17 +53,9 @@ export default function Popup(props: DevToolsPopupProps) {
|
|
|
61
53
|
</div>
|
|
62
54
|
<div className={styles.content}>
|
|
63
55
|
{activeTab == 0 ? (
|
|
64
|
-
<Configuration
|
|
56
|
+
<Configuration />
|
|
65
57
|
) : (
|
|
66
|
-
<ModuleDiagnostics
|
|
67
|
-
setHasAlert={setDiagnosticsHasAlert}
|
|
68
|
-
modulesWithMissingBackendModules={
|
|
69
|
-
props.modulesWithMissingBackendModules
|
|
70
|
-
}
|
|
71
|
-
modulesWithWrongBackendModulesVersion={
|
|
72
|
-
props.modulesWithWrongBackendModulesVersion
|
|
73
|
-
}
|
|
74
|
-
/>
|
|
58
|
+
<ModuleDiagnostics frontendModules={props.frontendModules} />
|
|
75
59
|
)}
|
|
76
60
|
</div>
|
|
77
61
|
</div>
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
justify-content: space-between;
|
|
14
14
|
align-items: flex-start;
|
|
15
15
|
box-sizing: border-box;
|
|
16
|
-
font-family: sans serif;
|
|
17
16
|
overflow-y: auto;
|
|
18
17
|
}
|
|
19
18
|
|
|
@@ -34,6 +33,7 @@
|
|
|
34
33
|
justify-content: space-between;
|
|
35
34
|
border-bottom: 1px solid #a0a0a0;
|
|
36
35
|
z-index: 2;
|
|
36
|
+
background: #e0e0e0;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
.closeButton {
|
package/src/store.ts
CHANGED
|
@@ -1,63 +1,58 @@
|
|
|
1
|
-
import { createGlobalStore
|
|
1
|
+
import { createGlobalStore } from "@openmrs/esm-framework";
|
|
2
2
|
import { Store } from "unistore";
|
|
3
|
-
import merge from "lodash-es/merge";
|
|
4
3
|
|
|
5
4
|
export interface ImplementerToolsStore {
|
|
6
5
|
activeItemDescription?: ActiveItemDescription;
|
|
7
|
-
configPathBeingEdited: null | string
|
|
6
|
+
configPathBeingEdited: null | Array<string>;
|
|
8
7
|
isOpen: boolean;
|
|
8
|
+
hasAlert: boolean;
|
|
9
|
+
openTabIndex: number;
|
|
9
10
|
isConfigToolbarOpen: boolean;
|
|
10
11
|
isUIEditorEnabled: boolean;
|
|
11
|
-
extensionIdBySlotByModule: Record<string, Record<string, Array<string>>>;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export interface ActiveItemDescription {
|
|
15
|
-
path: string
|
|
15
|
+
path: Array<string>;
|
|
16
16
|
description?: string;
|
|
17
|
-
value?: string | string
|
|
17
|
+
value?: string | Array<string>;
|
|
18
18
|
source?: string;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export const implementerToolsStore: Store<ImplementerToolsStore> =
|
|
22
|
-
"implementer-tools",
|
|
23
|
-
{
|
|
21
|
+
export const implementerToolsStore: Store<ImplementerToolsStore> =
|
|
22
|
+
createGlobalStore("implementer-tools", {
|
|
24
23
|
activeItemDescription: undefined,
|
|
25
24
|
configPathBeingEdited: null,
|
|
26
25
|
isOpen: getIsImplementerToolsOpen(),
|
|
26
|
+
hasAlert: false,
|
|
27
|
+
openTabIndex: 0,
|
|
27
28
|
isConfigToolbarOpen: getIsConfigToolbarOpen(),
|
|
28
29
|
isUIEditorEnabled: getIsUIEditorEnabled(),
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export const setHasAlert = implementerToolsStore.action(
|
|
33
|
+
(state, value: boolean) => ({
|
|
34
|
+
...state,
|
|
35
|
+
hasAlert: value,
|
|
36
|
+
})
|
|
31
37
|
);
|
|
32
38
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
export const togglePopup = implementerToolsStore.action((state) => ({
|
|
40
|
+
...state,
|
|
41
|
+
isOpen: !state.isOpen,
|
|
42
|
+
}));
|
|
37
43
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
newValue[moduleName] = {};
|
|
44
|
-
}
|
|
45
|
-
newValue[moduleName][slotName] = instance.assignedIds;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
implementerToolsStore.setState({
|
|
49
|
-
extensionIdBySlotByModule: merge(
|
|
50
|
-
implementerToolsStore.getState().extensionIdBySlotByModule,
|
|
51
|
-
newValue
|
|
52
|
-
),
|
|
53
|
-
});
|
|
54
|
-
});
|
|
44
|
+
export const showModuleDiagnostics = implementerToolsStore.action((state) => ({
|
|
45
|
+
...state,
|
|
46
|
+
isOpen: true,
|
|
47
|
+
openTabIndex: 1,
|
|
48
|
+
}));
|
|
55
49
|
|
|
56
50
|
/* Set up localStorage-serialized state elements */
|
|
57
51
|
|
|
58
52
|
let lastValueOfIsOpen = getIsImplementerToolsOpen();
|
|
59
53
|
let lastValueOfConfigToolbarOpen = getIsConfigToolbarOpen();
|
|
60
54
|
let lastValueOfIsUiEditorEnabled = getIsUIEditorEnabled();
|
|
55
|
+
|
|
61
56
|
implementerToolsStore.subscribe((state) => {
|
|
62
57
|
if (state.isOpen != lastValueOfIsOpen) {
|
|
63
58
|
setIsImplementerToolsOpen(state.isOpen);
|