Skip to content

Commit

Permalink
App not hot updating with slot config changes
Browse files Browse the repository at this point in the history
  • Loading branch information
brandones committed Mar 15, 2022
1 parent a4c0d4e commit 29fc5c9
Show file tree
Hide file tree
Showing 17 changed files with 256 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import {
Config,
ConfigInternalStore,
configInternalStore,
getExtensionInternalStore,
implementerToolsConfigStore,
temporaryConfigStore,
useExtensionInternalStore,
useStore,
useStoreWithActions,
} from "@openmrs/esm-framework";
import {
Button,
Expand Down Expand Up @@ -89,13 +90,13 @@ export const Configuration: React.FC<ConfigurationProps> = () => {
toggleIsJsonModeEnabled,
isConfigToolbarOpen,
toggleIsToolbarOpen,
} = useStore(implementerToolsStore, actions);
const { devDefaultsAreOn, toggleDevDefaults } = useStore(
} = useStoreWithActions(implementerToolsStore, actions);
const { devDefaultsAreOn, toggleDevDefaults } = useStoreWithActions(
configInternalStore,
configActions
);
const { config } = useStore(implementerToolsConfigStore);
const extensionStore = useExtensionInternalStore();
const extensionStore = useStore(getExtensionInternalStore());
const tempConfigStore = useStore(temporaryConfigStore);
const [filterText, setFilterText] = useState("");
const tempConfig = tempConfigStore.config;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import React from "react";
import styles from "./styles.css";
import Close16 from "@carbon/icons-react/es/close/16";
import { useExtensionInternalStore, useStore } from "@openmrs/esm-framework";
import {
getExtensionInternalStore,
useStore,
useStoreWithActions,
} from "@openmrs/esm-framework";
import { Button } from "carbon-components-react";
import { Portal } from "./portal";
import { ExtensionOverlay } from "./extension-overlay.component";
import { ImplementerToolsStore, implementerToolsStore } from "../store";

export default function UiEditor() {
const { slots, extensions } = useExtensionInternalStore();
const { slots, extensions } = useStore(getExtensionInternalStore());
const { isOpen: implementerToolsIsOpen } = useStore(implementerToolsStore);

return (
Expand Down Expand Up @@ -66,7 +70,10 @@ const actions = {
};

export function ExitButton() {
const { toggleIsUIEditorEnabled } = useStore(implementerToolsStore, actions);
const { toggleIsUIEditorEnabled } = useStoreWithActions(
implementerToolsStore,
actions
);
return (
<Button
className={styles.exitButton}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
temporaryConfigStore,
} from "./state";
import { Type } from "../types";
import { getExtensionSlotConfigStore } from "..";
import { getExtensionSlotsConfigStore } from "..";

const mockConfigInternalStore =
configInternalStore as MockedStore<ConfigInternalStore>;
Expand Down Expand Up @@ -854,7 +854,8 @@ describe("extension slot config", () => {
},
},
});
const { config } = getExtensionSlotConfigStore("fooSlot").getState();
const { config } =
getExtensionSlotsConfigStore().getState().slots["fooSlot"];
expect(config).toStrictEqual({
add: ["bar", "baz"],
remove: ["zap"],
Expand Down Expand Up @@ -892,7 +893,8 @@ describe("extension slot config", () => {
},
});
await Config.getConfig("foo-module");
const { config } = getExtensionSlotConfigStore("fooSlot").getState();
const { config } =
getExtensionSlotsConfigStore().getState().slots["fooSlot"];
expect(config).toStrictEqual({ remove: ["bar"] });
});

Expand Down
18 changes: 13 additions & 5 deletions packages/framework/esm-config/src/module-config/module-config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { clone, reduce, mergeDeepRight } from "ramda";
import { clone, reduce, mergeDeepRight, equals } from "ramda";
import {
Config,
ConfigObject,
Expand All @@ -23,9 +23,9 @@ import {
configExtensionStore,
getConfigStore,
getExtensionConfigStore,
getExtensionSlotConfigStore,
implementerToolsConfigStore,
temporaryConfigStore,
getExtensionSlotsConfigStore,
} from "./state";
import type {} from "@openmrs/esm-globals";
import { TemporaryConfigStore } from "..";
Expand Down Expand Up @@ -125,9 +125,17 @@ function computeExtensionSlotConfigs(
tempState: TemporaryConfigStore
) {
const slotConfigs = getExtensionSlotConfigs(state, tempState);
for (let [slotName, config] of Object.entries(slotConfigs)) {
const slotStore = getExtensionSlotConfigStore(slotName);
slotStore.setState({ loaded: true, config });
const newSlotStoreEntries = Object.fromEntries(
Object.entries(slotConfigs).map(([slotName, config]) => [
slotName,
{ loaded: true, config },
])
);
const slotStore = getExtensionSlotsConfigStore();
const oldState = slotStore.getState();
const newState = { slots: { ...oldState.slots, ...newSlotStoreEntries } };
if (!equals(oldState, newState)) {
slotStore.setState(newState);
}
}

Expand Down
39 changes: 26 additions & 13 deletions packages/framework/esm-config/src/module-config/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,29 +141,42 @@ export function getConfigStore(moduleName: string) {
}

/**
* Configuration for a specific extension slot
* Configuration for all the specific extension slots
* @internal
*/
export interface ExtensionSlotConfigStore {
config: ExtensionSlotConfigObject;
loaded: boolean;
export interface ExtensionSlotsConfigStore {
slots: {
[slotName: string]: {
config: ExtensionSlotConfigObject;
loaded: boolean;
};
};
}

function initializeExtensionSlotConfigStore() {
return {
config: {},
loaded: false,
};
/** @internal */
export function getExtensionSlotsConfigStore() {
return getGlobalStore<ExtensionSlotsConfigStore>(`config-extension-slots`, {
slots: {},
});
}

/** @internal */
export function getExtensionSlotConfigStore(slotName: string) {
return getGlobalStore<ExtensionSlotConfigStore>(
`config-extension-slots-${slotName}`,
initializeExtensionSlotConfigStore()
export function getExtensionSlotConfig(slotName: string) {
return getExtensionSlotConfigFromStore(
getExtensionSlotsConfigStore().getState(),
slotName
);
}

/** @internal */
export function getExtensionSlotConfigFromStore(
state: ExtensionSlotsConfigStore,
slotName: string
) {
const slotConfig = state.slots[slotName];
return slotConfig ?? { loaded: false, config: {} };
}

/**
* A store for each mounted extension's config
* @internal
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const getExtensionSlotConfig = jest.fn().mockResolvedValue({});
export const getExtensionSlotConfigs = jest.fn().mockResolvedValue({});
56 changes: 46 additions & 10 deletions packages/framework/esm-extensions/src/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@

import {
ExtensionSlotConfigObject,
getExtensionSlotConfigStore,
ExtensionSlotsConfigStore,
getExtensionSlotConfig,
getExtensionSlotConfigFromStore,
getExtensionSlotsConfigStore,
} from "@openmrs/esm-config";
import isEqual from "lodash-es/isEqual";
import {
getExtensionInternalStore,
ExtensionSlotState,
Expand All @@ -30,16 +34,40 @@ const extensionInternalStore = getExtensionInternalStore();
const extensionStore = getExtensionStore();

// Keep the output store updated
extensionInternalStore.subscribe((internalStore) => {
function updateExtensionOutputStore(
internalState: ExtensionInternalStore,
extensionSlotConfigs: ExtensionSlotsConfigStore
) {
const slots: Record<string, ExtensionSlotState> = {};
for (let [slotName, slot] of Object.entries(internalStore.slots)) {
for (let [slotName, slot] of Object.entries(internalState.slots)) {
// Only include registered slots
if (slot.moduleName) {
// Only include registered slots
const assignedExtensions = getAssignedExtensions(slotName);
const { config } = getExtensionSlotConfigFromStore(
extensionSlotConfigs,
slot.name
);
const assignedExtensions = getAssignedExtensionsFromData(
slotName,
internalState,
config
);
slots[slotName] = { moduleName: slot.moduleName, assignedExtensions };
}
}
extensionStore.setState({ slots: slots });
if (!isEqual(extensionStore.getState().slots, slots)) {
extensionStore.setState({ slots });
}
}

extensionInternalStore.subscribe((internalStore) => {
updateExtensionOutputStore(
internalStore,
getExtensionSlotsConfigStore().getState()
);
});

getExtensionSlotsConfigStore().subscribe((slotConfigs) => {
updateExtensionOutputStore(extensionInternalStore.getState(), slotConfigs);
});

function createNewExtensionSlotInfo(
Expand Down Expand Up @@ -246,11 +274,11 @@ export function getConnectedExtensions(
);
}

export function getAssignedExtensions(
slotName: string
function getAssignedExtensionsFromData(
slotName: string,
internalState: ExtensionInternalStore,
config: ExtensionSlotConfigObject
): Array<AssignedExtension> {
const internalState = extensionInternalStore.getState();
const config = getExtensionSlotConfigStore(slotName).getState().config;
const attachedIds = internalState.slots[slotName].attachedIds;
const assignedIds = calculateAssignedIds(config, attachedIds);
const extensions: Array<AssignedExtension> = [];
Expand All @@ -269,6 +297,14 @@ export function getAssignedExtensions(
return extensions;
}

export function getAssignedExtensions(
slotName: string
): Array<AssignedExtension> {
const internalState = extensionInternalStore.getState();
const { config } = getExtensionSlotConfig(slotName);
return getAssignedExtensionsFromData(slotName, internalState, config);
}

function calculateAssignedIds(
config: ExtensionSlotConfigObject,
attachedIds: Array<string>
Expand Down
16 changes: 8 additions & 8 deletions packages/framework/esm-framework/docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -1801,7 +1801,7 @@ writing a module for a specific implementation.

#### Defined in

[packages/framework/esm-extensions/src/extensions.ts:126](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L126)
[packages/framework/esm-extensions/src/extensions.ts:131](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L131)

___

Expand Down Expand Up @@ -2093,7 +2093,7 @@ Avoid using this. Extension attachments should be considered declarative.

#### Defined in

[packages/framework/esm-extensions/src/extensions.ts:157](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L157)
[packages/framework/esm-extensions/src/extensions.ts:162](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L162)

___

Expand All @@ -2115,7 +2115,7 @@ Avoid using this. Extension attachments should be considered declarative.

#### Defined in

[packages/framework/esm-extensions/src/extensions.ts:181](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L181)
[packages/framework/esm-extensions/src/extensions.ts:186](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L186)

___

Expand Down Expand Up @@ -2247,7 +2247,7 @@ ___

#### Defined in

[packages/framework/esm-extensions/src/extensions.ts:249](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L249)
[packages/framework/esm-extensions/src/extensions.ts:277](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L277)

___

Expand Down Expand Up @@ -2371,7 +2371,7 @@ A list of extensions that should be rendered

#### Defined in

[packages/framework/esm-extensions/src/extensions.ts:239](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L239)
[packages/framework/esm-extensions/src/extensions.ts:244](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L244)

___

Expand Down Expand Up @@ -2438,7 +2438,7 @@ getExtensionNameFromId("baz")

#### Defined in

[packages/framework/esm-extensions/src/extensions.ts:70](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L70)
[packages/framework/esm-extensions/src/extensions.ts:75](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L75)

___

Expand All @@ -2458,7 +2458,7 @@ ___

#### Defined in

[packages/framework/esm-extensions/src/extensions.ts:83](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L83)
[packages/framework/esm-extensions/src/extensions.ts:88](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L88)

___

Expand All @@ -2479,7 +2479,7 @@ ___

#### Defined in

[packages/framework/esm-extensions/src/extensions.ts:75](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L75)
[packages/framework/esm-extensions/src/extensions.ts:80](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-extensions/src/extensions.ts#L80)

___

Expand Down
12 changes: 11 additions & 1 deletion packages/framework/esm-framework/mock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,17 @@ export const useExtensionInternalStore = createUseStore(

export const useExtensionStore = createUseStore(getExtensionStore());

export const useStore = (store: Store<any>, actions) => {
const defaultSelect = (x) => x;
export const useStore = (
store: Store<any>,
select = defaultSelect,
actions = {}
) => {
const state = select(store.getState());
return { ...state, ...actions };
};

export const useStoreWithActions = (store: Store<any>, actions) => {
const state = store.getState();
return { ...state, ...actions };
};
Expand Down
Loading

0 comments on commit 29fc5c9

Please sign in to comment.