@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.
Files changed (65) hide show
  1. package/README.md +1 -9
  2. package/__mocks__/react-i18next.js +54 -0
  3. package/{.babelrc → babel.config.json} +2 -1
  4. package/dist/266.openmrs-esm-implementer-tools-app.js +3 -0
  5. package/dist/266.openmrs-esm-implementer-tools-app.js.LICENSE.txt +8 -0
  6. package/dist/266.openmrs-esm-implementer-tools-app.js.map +1 -0
  7. package/dist/319.openmrs-esm-implementer-tools-app.js +1 -0
  8. package/dist/472.openmrs-esm-implementer-tools-app.js +2 -0
  9. package/dist/472.openmrs-esm-implementer-tools-app.js.map +1 -0
  10. package/dist/574.openmrs-esm-implementer-tools-app.js +1 -0
  11. package/dist/728.openmrs-esm-implementer-tools-app.js +2 -0
  12. package/dist/728.openmrs-esm-implementer-tools-app.js.map +1 -0
  13. package/dist/965.openmrs-esm-implementer-tools-app.js +3 -0
  14. package/dist/965.openmrs-esm-implementer-tools-app.js.LICENSE.txt +5 -0
  15. package/dist/965.openmrs-esm-implementer-tools-app.js.map +1 -0
  16. package/dist/openmrs-esm-implementer-tools-app.js +1 -1
  17. package/dist/openmrs-esm-implementer-tools-app.js.buildmanifest.json +170 -0
  18. package/dist/openmrs-esm-implementer-tools-app.js.map +1 -1
  19. package/jest.config.js +1 -2
  20. package/package.json +13 -20
  21. package/src/backend-dependencies/backend-dependencies.component.tsx +97 -0
  22. package/src/backend-dependencies/openmrs-backend-dependencies.ts +113 -93
  23. package/src/backend-dependencies/useBackendDependencies.ts +16 -0
  24. package/src/config-edit-button/config-edit-button.component.tsx +3 -1
  25. package/src/configuration/config-tree-for-module.component.tsx +1 -1
  26. package/src/configuration/config-tree.component.tsx +2 -9
  27. package/src/configuration/configuration.component.tsx +101 -31
  28. package/src/configuration/configuration.test.tsx +6 -6
  29. package/src/configuration/description.component.tsx +3 -1
  30. package/src/configuration/display-value.tsx +4 -4
  31. package/src/configuration/editable-value.component.tsx +5 -2
  32. package/src/configuration/extension-slots-config-tree.tsx +10 -14
  33. package/src/configuration/layout/subtree.component.tsx +1 -1
  34. package/src/configuration/layout/tree-container.component.tsx +1 -1
  35. package/src/configuration/value-editor.tsx +1 -1
  36. package/src/configuration/value-editors/array-editor.tsx +3 -3
  37. package/src/configuration/value-editors/extension-slot-add.tsx +1 -1
  38. package/src/configuration/value-editors/extension-slot-order.tsx +0 -4
  39. package/src/configuration/value-editors/extension-slot-remove.tsx +19 -7
  40. package/src/configuration/value-editors/object-editor.tsx +3 -3
  41. package/src/configuration/value-editors/value-editor-field.tsx +1 -3
  42. package/src/implementer-tools.button.tsx +33 -0
  43. package/src/implementer-tools.component.tsx +45 -81
  44. package/src/implementer-tools.styles.css +5 -9
  45. package/src/index.ts +35 -9
  46. package/src/popup/popup.component.tsx +11 -27
  47. package/src/popup/popup.styles.css +1 -1
  48. package/src/store.ts +27 -32
  49. package/src/ui-editor/extension-overlay.component.tsx +1 -1
  50. package/src/ui-editor/styles.css +7 -0
  51. package/src/ui-editor/ui-editor.tsx +49 -21
  52. package/translations/en.json +12 -0
  53. package/translations/es.json +13 -0
  54. package/tsconfig.json +1 -0
  55. package/webpack.config.js +1 -66
  56. package/__mocks__/openmrs-esm-framework.mock.tsx +0 -142
  57. package/dist/1.openmrs-esm-implementer-tools-app.js +0 -15
  58. package/dist/1.openmrs-esm-implementer-tools-app.js.map +0 -1
  59. package/dist/2.openmrs-esm-implementer-tools-app.js +0 -2
  60. package/dist/2.openmrs-esm-implementer-tools-app.js.map +0 -1
  61. package/src/backend-dependencies/backend-dependecies.component.tsx +0 -106
  62. package/src/backend-dependencies/backend-dependencies-style.css +0 -4
  63. package/src/backend-dependencies/helpers/backend-dependecies-helper.test.ts +0 -127
  64. package/src/backend-dependencies/helpers/backend-dependecies-helper.ts +0 -70
  65. 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
- useStore,
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
- config: { [key: string]: any };
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
- config,
37
+ extensionsConfig,
37
38
  moduleName,
38
39
  }: ExtensionSlotsConfigTreeProps) {
39
- const { extensionIdBySlotByModule } = useStore(implementerToolsStore);
40
-
41
- const extensionSlotNames = Object.keys(
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
- config={config?.[slotName]}
44
+ key={slotName}
45
+ config={extensionsConfig?.[slotName]}
50
46
  path={[moduleName, "extensions", slotName]}
51
47
  />
52
48
  ))}
@@ -4,7 +4,7 @@ import {
4
4
  StructuredListCell,
5
5
  StructuredListRow,
6
6
  StructuredListWrapper,
7
- } from "carbon-components-react/es/components/StructuredList";
7
+ } from "carbon-components-react";
8
8
  import styles from "./layout.styles.css";
9
9
 
10
10
  export interface SubtreeProps {
@@ -2,7 +2,7 @@ import React, { ReactNode } from "react";
2
2
  import {
3
3
  StructuredListBody,
4
4
  StructuredListWrapper,
5
- } from "carbon-components-react/es/components/StructuredList";
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/es/components/Button";
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/es/components/StructuredList";
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/es/components/MultiSelect";
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/es/components/MultiSelect";
3
- import { useStore } from "@openmrs/esm-framework";
4
- import { implementerToolsStore } from "../../store";
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 { extensionIdBySlotByModule } = useStore(implementerToolsStore);
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={extensionIdBySlotByModule[slotModuleName][
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
- } from "carbon-components-react/es/components/StructuredList";
8
- import { Tile } from "carbon-components-react/es/components/Tile";
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/es/components/Checkbox";
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 styles from "./implementer-tools.styles.css";
3
+ import { NotificationActionButton } from "carbon-components-react";
5
4
  import {
6
- checkModules,
7
- MissingBackendModules,
8
- } from "./backend-dependencies/openmrs-backend-dependencies";
9
- import { NotificationActionButton } from "carbon-components-react/es/components/Notification";
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 { implementerToolsStore } from "./store";
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 [hasAlert, setHasAlert] = useState(false);
23
- const [visibleTabIndex, setVisibleTabIndex] = useState(0);
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
- checkModules().then(
41
- ({
42
- modulesWithMissingBackendModules,
43
- modulesWithWrongBackendModulesVersion,
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
- if (
56
- !(
57
- modulesWithMissingBackendModules.length ||
58
- modulesWithWrongBackendModulesVersion.length
59
- )
60
- )
61
- return;
62
-
63
- const showModuleDiagnostics = () => {
64
- setVisibleTabIndex(1);
65
- if (!isOpen) {
66
- togglePopup();
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
- setHasAlert={setHasAlert}
94
- modulesWithMissingBackendModules={modulesWithMissingBackendModules}
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
- z-index: 100000;
3
- background-color: var(--omrs-color-interaction-minus-two);
4
- height: 40px !important;
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
- .triggerButtonAlert {
13
- background-color: var(--omrs-color-danger);
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
- lifecycle: getAsyncLifecycle(
6
- () => import("./implementer-tools.component"),
15
+ pages: [
16
+ {
17
+ route: () => true,
18
+ load: getAsyncLifecycle(
19
+ () => import("./implementer-tools.component"),
20
+ options
21
+ ),
22
+ },
23
+ ],
24
+ extensions: [
7
25
  {
8
- featureName: "Implementer Tools",
9
- moduleName: "@openmrs/esm-implementer-tools-app",
10
- }
11
- ),
12
- activate: () => true,
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 = () => Promise.resolve();
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, useEffect } from "react";
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-dependecies.component";
9
- import { MissingBackendModules } from "../backend-dependencies/openmrs-backend-dependencies";
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
- setHasAlert(value: boolean): void;
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 [configHasAlert, setConfigHasAlert] = useState(false);
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 setHasAlert={setConfigHasAlert} />
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, extensionStore } from "@openmrs/esm-framework";
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> = createGlobalStore(
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
- extensionIdBySlotByModule: {},
30
- }
30
+ });
31
+
32
+ export const setHasAlert = implementerToolsStore.action(
33
+ (state, value: boolean) => ({
34
+ ...state,
35
+ hasAlert: value,
36
+ })
31
37
  );
32
38
 
33
- /* Set up subscriptions for module-slot-extension cache.
34
- * This cache exists so that implementer tools doesn't "forget" about
35
- * slots & extensions that are no longer mounted.
36
- */
39
+ export const togglePopup = implementerToolsStore.action((state) => ({
40
+ ...state,
41
+ isOpen: !state.isOpen,
42
+ }));
37
43
 
38
- extensionStore.subscribe((state) => {
39
- const newValue = {};
40
- for (let [slotName, slot] of Object.entries(state.slots)) {
41
- for (let [moduleName, instance] of Object.entries(slot.instances)) {
42
- if (!newValue[moduleName]) {
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);
@@ -6,7 +6,7 @@ export interface ExtensionOverlayProps {
6
6
  extensionName: string;
7
7
  slotModuleName: string;
8
8
  slotName: string;
9
- domElement: HTMLElement;
9
+ domElement: HTMLElement | null;
10
10
  }
11
11
 
12
12
  export function ExtensionOverlay({
@@ -53,3 +53,10 @@
53
53
  top: 0;
54
54
  left: 0;
55
55
  }
56
+
57
+ .exitButton {
58
+ position: fixed !important;
59
+ bottom: 0;
60
+ right: 0;
61
+ z-index: 999999;
62
+ }