diff --git a/.husky/pre-commit b/.husky/pre-commit index 5922bb35a..25b873980 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -3,6 +3,6 @@ set -e # die on error -npx lint-staged +yarn lint-staged yarn turbo extract-translations yarn turbo document --since main diff --git a/packages/apps/esm-primary-navigation-app/jest.config.js b/packages/apps/esm-primary-navigation-app/jest.config.js index ef2c0b2ad..a45ebe699 100644 --- a/packages/apps/esm-primary-navigation-app/jest.config.js +++ b/packages/apps/esm-primary-navigation-app/jest.config.js @@ -6,6 +6,7 @@ module.exports = { moduleNameMapper: { 'lodash-es': 'lodash', '@openmrs/esm-framework': '@openmrs/esm-framework/mock.tsx', + '@openmrs/esm-framework/src/internal': '@openmrs/esm-framework/mock.tsx', '\\.(s?css)$': 'identity-obj-proxy', 'react-i18next': '/__mocks__/react-i18next.mock.js', }, diff --git a/packages/apps/esm-primary-navigation-app/src/components/left-nav/index.tsx b/packages/apps/esm-primary-navigation-app/src/components/left-nav/left-nav.component.tsx similarity index 56% rename from packages/apps/esm-primary-navigation-app/src/components/left-nav/index.tsx rename to packages/apps/esm-primary-navigation-app/src/components/left-nav/left-nav.component.tsx index 0bb4e28db..1fb70799d 100644 --- a/packages/apps/esm-primary-navigation-app/src/components/left-nav/index.tsx +++ b/packages/apps/esm-primary-navigation-app/src/components/left-nav/left-nav.component.tsx @@ -1,15 +1,21 @@ /** @module @category UI */ import React from 'react'; -import { ExtensionSlot, useStore, leftNavStore } from '@openmrs/esm-framework/src/internal'; +import { ExtensionSlot, getActiveAppNames, useConnectedExtensions } from '@openmrs/esm-framework/src/internal'; import type { SideNavProps } from '@carbon/react'; import { SideNav } from '@carbon/react'; import styles from './left-nav.module.scss'; type LeftNavMenuProps = SideNavProps; +const basePath = window.getOpenmrsSpaBase(); +const defaultNavSlot = 'default-dashboard-slot'; + export const LeftNavMenu = React.forwardRef((props, ref) => { - const { slotName, basePath } = useStore(leftNavStore); const currentPath = window.location ?? { pathname: '' }; + const activePages = getActiveAppNames(); + const leftNavSlot = activePages && activePages.length === 1 ? `${activePages[0]}-dashboard-slot` : undefined; + const leftNavItems = useConnectedExtensions(leftNavSlot); + const slotName = leftNavSlot && leftNavItems.length > 0 ? leftNavSlot : defaultNavSlot; return ( diff --git a/packages/apps/esm-primary-navigation-app/src/components/navbar-header-panels/side-menu-panel.component.tsx b/packages/apps/esm-primary-navigation-app/src/components/navbar-header-panels/side-menu-panel.component.tsx index 7e31dc750..564b7f777 100644 --- a/packages/apps/esm-primary-navigation-app/src/components/navbar-header-panels/side-menu-panel.component.tsx +++ b/packages/apps/esm-primary-navigation-app/src/components/navbar-header-panels/side-menu-panel.component.tsx @@ -1,6 +1,6 @@ import React, { useEffect } from 'react'; import { useOnClickOutside } from '@openmrs/esm-framework'; -import { LeftNavMenu } from '../left-nav'; +import { LeftNavMenu } from '../left-nav/left-nav.component'; interface SideMenuPanelProps { expanded: boolean; diff --git a/packages/apps/esm-primary-navigation-app/src/components/navbar/navbar.component.tsx b/packages/apps/esm-primary-navigation-app/src/components/navbar/navbar.component.tsx index af507ef2d..d6d6a2d97 100644 --- a/packages/apps/esm-primary-navigation-app/src/components/navbar/navbar.component.tsx +++ b/packages/apps/esm-primary-navigation-app/src/components/navbar/navbar.component.tsx @@ -4,15 +4,14 @@ import classNames from 'classnames'; import { HeaderContainer, Header, HeaderMenuButton, HeaderGlobalBar, HeaderGlobalAction } from '@carbon/react'; import { Close, Switcher, UserAvatarFilledAlt } from '@carbon/react/icons'; import { - useLayoutType, ExtensionSlot, ConfigurableLink, - useSession, + getActiveAppNames, useConnectedExtensions, useConfig, useStore, } from '@openmrs/esm-framework'; -import { leftNavStore } from '@openmrs/esm-framework/src/internal'; +import { useTranslation } from 'react-i18next'; import { isDesktop } from '../../utils'; import AppMenuPanel from '../navbar-header-panels/app-menu-panel.component'; import Logo from '../logo/logo.component'; @@ -21,8 +20,7 @@ import OfflineBanner from '../offline-banner/offline-banner.component'; import UserMenuPanel from '../navbar-header-panels/user-menu-panel.component'; import SideMenuPanel from '../navbar-header-panels/side-menu-panel.component'; import styles from './navbar.scss'; -import { useTranslation } from 'react-i18next'; -import { LeftNavMenu } from '../left-nav'; +import { LeftNavMenu } from '../left-nav/left-nav.component'; const HeaderItems: React.FC = () => { const { t } = useTranslation(); @@ -30,8 +28,10 @@ const HeaderItems: React.FC = () => { const [activeHeaderPanel, setActiveHeaderPanel] = useState(null); const layout = useLayoutType(); const appMenuItems = useConnectedExtensions('app-menu-slot'); - const { slotName: leftNavSlot } = useStore(leftNavStore); + const activePages = getActiveAppNames(); + const leftNavSlot = activePages && activePages.length > 0 ? `${activePages[0]}-dashboard-slot` : undefined; const leftNavItems = useConnectedExtensions(leftNavSlot); + const defaultNavItems = useConnectedExtensions('default-dashboard-slot'); const userMenuItems = useConnectedExtensions('user-panel-slot'); const isActivePanel = useCallback((panelName: string) => activeHeaderPanel === panelName, [activeHeaderPanel]); @@ -46,15 +46,21 @@ const HeaderItems: React.FC = () => { [], ); - const showLeftNav = useMemo(() => isDesktop(layout) && leftNavItems.length > 0, [leftNavItems.length, layout]); - const showHamburger = useMemo(() => !isDesktop(layout) && leftNavItems.length > 0, [leftNavItems.length, layout]); + const showLeftNav = useMemo( + () => isDesktop(layout) && (leftNavItems.length > 0 || defaultNavItems.length > 0), + [leftNavItems.length, defaultNavItems.length, layout], + ); + const showHamburgerMenu = useMemo( + () => !isDesktop(layout) && (leftNavItems.length > 0 || defaultNavItems.length > 0), + [leftNavItems.length, defaultNavItems.length, layout], + ); const showAppMenu = useMemo(() => appMenuItems.length > 0, [appMenuItems.length]); const showUserMenu = useMemo(() => userMenuItems.length > 0, [userMenuItems.length]); return ( <>
- {showHamburger && ( + {showHamburgerMenu && ( { /> )} -
+
@@ -117,7 +123,7 @@ const HeaderItems: React.FC = () => { )} - {showHamburger && } + {showHamburgerMenu && } {showAppMenu && } {showUserMenu && } diff --git a/packages/framework/esm-extensions/src/store.ts b/packages/framework/esm-extensions/src/store.ts index 9b7955eab..93b951168 100644 --- a/packages/framework/esm-extensions/src/store.ts +++ b/packages/framework/esm-extensions/src/store.ts @@ -1,9 +1,9 @@ /** @module @category Extension */ import isEqual from 'lodash-es/isEqual'; import type { ConfigExtensionStoreElement, ConfigObject, ExtensionSlotConfigObject } from '@openmrs/esm-config'; +import { type Loadable } from '@openmrs/esm-globals'; import { configExtensionStore } from '@openmrs/esm-config'; import { createGlobalStore, getGlobalStore } from '@openmrs/esm-state'; -import type { LifeCycles } from 'single-spa'; export interface ExtensionMeta { [_: string]: any; @@ -11,7 +11,7 @@ export interface ExtensionMeta { export interface ExtensionRegistration { name: string; - load(): Promise<{ default?: LifeCycles } & LifeCycles>; + load: Loadable; moduleName: string; meta: ExtensionMeta; order?: number; diff --git a/packages/framework/esm-framework/docs/API.md b/packages/framework/esm-framework/docs/API.md index 4119830ea..2de4eaa7d 100644 --- a/packages/framework/esm-framework/docs/API.md +++ b/packages/framework/esm-framework/docs/API.md @@ -164,6 +164,11 @@ - [syncOfflinePatientData](API.md#syncofflinepatientdata) - [useConnectivity](API.md#useconnectivity) +### Other Functions + +- [setLeftNav](API.md#setleftnav) +- [unsetLeftNav](API.md#unsetleftnav) + ### Store Functions - [createGlobalStore](API.md#createglobalstore) @@ -187,7 +192,6 @@ - [PatientBannerToggleContactDetailsButton](API.md#patientbannertogglecontactdetailsbutton) - [PatientPhoto](API.md#patientphoto) - [isDesktop](API.md#isdesktop) -- [setLeftNav](API.md#setleftnav) - [showActionableNotification](API.md#showactionablenotification) - [showModal](API.md#showmodal) - [showNotification](API.md#shownotification) @@ -197,7 +201,6 @@ - [subscribeNotificationShown](API.md#subscribenotificationshown) - [subscribeSnackbarShown](API.md#subscribesnackbarshown) - [subscribeToastShown](API.md#subscribetoastshown) -- [unsetLeftNav](API.md#unsetleftnav) - [useBodyScrollLock](API.md#usebodyscrolllock) - [useLayoutType](API.md#uselayouttype) - [useOnClickOutside](API.md#useonclickoutside) @@ -455,6 +458,19 @@ ___ ## Other Type Aliases +### ComponentOrLoadable + +Ƭ **ComponentOrLoadable**: { `component`: `string` } \| { `component?`: `never` } + +Internal shared type for various *Definitions that either take a named component or a function to load the +component. + +#### Defined in + +[packages/framework/esm-globals/src/types.ts:175](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L175) + +___ + ### ConfigValue Ƭ **ConfigValue**: `string` \| `number` \| `boolean` \| `void` \| `any`[] \| `object` @@ -467,25 +483,49 @@ ___ ### ExtensionDefinition -Ƭ **ExtensionDefinition**: { `featureFlag?`: `string` ; `meta?`: { `[k: string]`: `unknown`; } ; `name`: `string` ; `offline?`: `boolean` ; `online?`: `boolean` ; `order?`: `number` ; `privileges?`: `string` \| `string`[] ; `slot?`: `string` ; `slots?`: `string`[] } & { `component`: `string` } \| { `component?`: `never` } +Ƭ **ExtensionDefinition**: { `featureFlag?`: `string` ; `meta?`: { `[k: string]`: `unknown`; } ; `name`: `string` ; `offline?`: `boolean` ; `online?`: `boolean` ; `order?`: `number` ; `privileges?`: `string` \| `string`[] ; `slot?`: `string` ; `slots?`: `string`[] } & [`ComponentOrLoadable`](API.md#componentorloadable) A definition of an extension as extracted from an app's routes.json #### Defined in -[packages/framework/esm-globals/src/types.ts:172](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L172) +[packages/framework/esm-globals/src/types.ts:200](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L200) + +___ + +### Loadable + +Ƭ **Loadable**<`LoadResult`\>: () => `Promise`<`LifeCycles`<`LoadResult`\> & { `default`: `LifeCycles`<`LoadResult`\> }\> + +#### Type parameters + +| Name | Type | +| :------ | :------ | +| `LoadResult` | {} | + +#### Type declaration + +▸ (): `Promise`<`LifeCycles`<`LoadResult`\> & { `default`: `LifeCycles`<`LoadResult`\> }\> + +##### Returns + +`Promise`<`LifeCycles`<`LoadResult`\> & { `default`: `LifeCycles`<`LoadResult`\> }\> + +#### Defined in + +[packages/framework/esm-globals/src/types.ts:169](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L169) ___ ### ModalDefinition -Ƭ **ModalDefinition**: { `name`: `string` } & { `component`: `string` } \| { `component?`: `never` } +Ƭ **ModalDefinition**: { `name`: `string` } & [`ComponentOrLoadable`](API.md#componentorloadable) A definition of a modal as extracted from an app's routes.json #### Defined in -[packages/framework/esm-globals/src/types.ts:237](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L237) +[packages/framework/esm-globals/src/types.ts:244](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L244) ___ @@ -498,7 +538,7 @@ Basically, this is the same as the app routes, with each routes definition keyed #### Defined in -[packages/framework/esm-globals/src/types.ts:348](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L348) +[packages/framework/esm-globals/src/types.ts:313](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L313) ___ @@ -613,13 +653,13 @@ ___ ### WorkspaceDefinition -Ƭ **WorkspaceDefinition**: { `canHide?`: `boolean` ; `canMaximize?`: `boolean` ; `name`: `string` ; `preferredWindowSize?`: [`WorkspaceWindowState`](API.md#workspacewindowstate) ; `title`: `string` ; `type`: `string` ; `width?`: ``"narrow"`` \| ``"wider"`` } & { `component`: `string` } \| { `component?`: `never` } +Ƭ **WorkspaceDefinition**: { `canHide?`: `boolean` ; `canMaximize?`: `boolean` ; `name`: `string` ; `preferredWindowSize?`: [`WorkspaceWindowState`](API.md#workspacewindowstate) ; `title`: `string` ; `type`: `string` ; `width?`: ``"narrow"`` \| ``"wider"`` } & [`ComponentOrLoadable`](API.md#componentorloadable) A definition of a workspace as extracted from an app's routes.json #### Defined in -[packages/framework/esm-globals/src/types.ts:271](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L271) +[packages/framework/esm-globals/src/types.ts:257](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L257) ___ @@ -629,7 +669,7 @@ ___ #### Defined in -[packages/framework/esm-globals/src/types.ts:266](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L266) +[packages/framework/esm-globals/src/types.ts:252](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L252) ___ @@ -997,16 +1037,6 @@ ___ ## UI Variables -### LeftNavMenu - -• `Const` **LeftNavMenu**: `ForwardRefExoticComponent`<`SideNavProps` & `RefAttributes`<`HTMLElement`\>\> - -#### Defined in - -[packages/framework/esm-styleguide/src/left-nav/index.tsx:31](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/left-nav/index.tsx#L31) - -___ - ### ResponsiveWrapper • `Const` **ResponsiveWrapper**: `React.FC`<[`ResponsiveWrapperProps`](interfaces/ResponsiveWrapperProps.md)\> @@ -4237,6 +4267,40 @@ ___ ___ +## Other Functions + +### setLeftNav + +▸ **setLeftNav**(): `void` + +**`deprecated`** + +#### Returns + +`void` + +#### Defined in + +[packages/framework/esm-pages/src/pages.ts:73](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-pages/src/pages.ts#L73) + +___ + +### unsetLeftNav + +▸ **unsetLeftNav**(): `void` + +**`deprecated`** + +#### Returns + +`void` + +#### Defined in + +[packages/framework/esm-pages/src/pages.ts:76](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-pages/src/pages.ts#L76) + +___ + ## Store Functions ### createGlobalStore @@ -4541,7 +4605,7 @@ invalid key to this function will result in a type error. | Name | Type | Description | | :------ | :------ | :------ | -| `key` | ``"error"`` \| ``"change"`` \| ``"close"`` \| ``"other"`` \| ``"actions"`` \| ``"address"`` \| ``"cancel"`` \| ``"confirm"`` \| ``"contactDetails"`` \| ``"errorCopy"`` \| ``"female"`` \| ``"hideDetails"`` \| ``"loading"`` \| ``"male"`` \| ``"patientLists"`` \| ``"relationships"`` \| ``"seeMoreLists"`` \| ``"showDetails"`` \| ``"unknown"`` \| ``"closeAllOpenedWorkspaces"`` \| ``"closingAllWorkspacesPromptBody"`` \| ``"closingAllWorkspacesPromptTitle"`` \| ``"discard"`` \| ``"openAnyway"`` \| ``"unsavedChangesInOpenedWorkspace"`` \| ``"unsavedChangesInWorkspace"`` \| ``"unsavedChangesTitleText"`` \| ``"address1"`` \| ``"address2"`` \| ``"city"`` \| ``"cityVillage"`` \| ``"country"`` \| ``"countyDistrict"`` \| ``"postalCode"`` \| ``"state"`` \| ``"stateProvince"`` | - | +| `key` | ``"error"`` \| ``"change"`` \| ``"close"`` \| ``"other"`` \| ``"actions"`` \| ``"address"`` \| ``"cancel"`` \| ``"confirm"`` \| ``"contactDetails"`` \| ``"errorCopy"`` \| ``"female"`` \| ``"hideDetails"`` \| ``"loading"`` \| ``"male"`` \| ``"patientLists"`` \| ``"relationships"`` \| ``"seeMoreLists"`` \| ``"showDetails"`` \| ``"unknown"`` \| ``"closeAllOpenedWorkspaces"`` \| ``"closingAllWorkspacesPromptBody"`` \| ``"closingAllWorkspacesPromptTitle"`` \| ``"discard"`` \| ``"hide"`` \| ``"maximize"`` \| ``"minimize"`` \| ``"openAnyway"`` \| ``"unsavedChangesInOpenedWorkspace"`` \| ``"unsavedChangesInWorkspace"`` \| ``"unsavedChangesTitleText"`` \| ``"workspaceHeader"`` \| ``"address1"`` \| ``"address2"`` \| ``"city"`` \| ``"cityVillage"`` \| ``"country"`` \| ``"countyDistrict"`` \| ``"postalCode"`` \| ``"state"`` \| ``"stateProvince"`` | - | | `defaultText?` | `string` | - | | `options?` | `object` | Object passed to the i18next `t` function. See https://www.i18next.com/translation-function/essentials#overview-options for more information. `ns` and `defaultValue` are already set and may not be used. | @@ -4740,26 +4804,6 @@ ___ ___ -### setLeftNav - -▸ **setLeftNav**(`__namedParameters`): `void` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `__namedParameters` | `Object` | - -#### Returns - -`void` - -#### Defined in - -[packages/framework/esm-styleguide/src/left-nav/index.tsx:19](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/left-nav/index.tsx#L19) - -___ - ### showActionableNotification ▸ **showActionableNotification**(`notification`): `void` @@ -4987,26 +5031,6 @@ ___ ___ -### unsetLeftNav - -▸ **unsetLeftNav**(`name`): `void` - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `name` | `any` | - -#### Returns - -`void` - -#### Defined in - -[packages/framework/esm-styleguide/src/left-nav/index.tsx:23](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/left-nav/index.tsx#L23) - -___ - ### useBodyScrollLock ▸ **useBodyScrollLock**(`active`): `void` @@ -5604,7 +5628,7 @@ For the patient chart, this is `workspace-header-patient-chart-slot`. #### Defined in -[packages/framework/esm-styleguide/src/workspaces/window/workspace-window.component.tsx:48](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/window/workspace-window.component.tsx#L48) +[packages/framework/esm-styleguide/src/workspaces/window/workspace-window.component.tsx:55](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/window/workspace-window.component.tsx#L55) ___ diff --git a/packages/framework/esm-framework/docs/interfaces/ExtensionRegistration.md b/packages/framework/esm-framework/docs/interfaces/ExtensionRegistration.md index a5a8829cd..3b80b67de 100644 --- a/packages/framework/esm-framework/docs/interfaces/ExtensionRegistration.md +++ b/packages/framework/esm-framework/docs/interfaces/ExtensionRegistration.md @@ -7,6 +7,7 @@ ### Extension Properties - [featureFlag](ExtensionRegistration.md#featureflag) +- [load](ExtensionRegistration.md#load) - [meta](ExtensionRegistration.md#meta) - [moduleName](ExtensionRegistration.md#modulename) - [name](ExtensionRegistration.md#name) @@ -15,10 +16,6 @@ - [order](ExtensionRegistration.md#order) - [privileges](ExtensionRegistration.md#privileges) -### Methods - -- [load](ExtensionRegistration.md#load) - ## Extension Properties ### featureFlag @@ -31,6 +28,16 @@ ___ +### load + +• **load**: [`Loadable`](../API.md#loadable)<{}\> + +#### Defined in + +[packages/framework/esm-extensions/src/store.ts:14](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-extensions/src/store.ts#L14) + +___ + ### meta • **meta**: [`ExtensionMeta`](ExtensionMeta.md) @@ -98,17 +105,3 @@ ___ #### Defined in [packages/framework/esm-extensions/src/store.ts:20](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-extensions/src/store.ts#L20) - -## Methods - -### load - -▸ **load**(): `Promise`<{ `default?`: `LifeCycles`<{}\> } & `LifeCycles`<{}\>\> - -#### Returns - -`Promise`<{ `default?`: `LifeCycles`<{}\> } & `LifeCycles`<{}\>\> - -#### Defined in - -[packages/framework/esm-extensions/src/store.ts:14](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-extensions/src/store.ts#L14) diff --git a/packages/framework/esm-framework/docs/interfaces/LeftNavStore.md b/packages/framework/esm-framework/docs/interfaces/LeftNavStore.md deleted file mode 100644 index 725090fe9..000000000 --- a/packages/framework/esm-framework/docs/interfaces/LeftNavStore.md +++ /dev/null @@ -1,30 +0,0 @@ -[@openmrs/esm-framework](../API.md) / LeftNavStore - -# Interface: LeftNavStore - -## Table of contents - -### Properties - -- [basePath](LeftNavStore.md#basepath) -- [slotName](LeftNavStore.md#slotname) - -## Properties - -### basePath - -• **basePath**: `string` - -#### Defined in - -[packages/framework/esm-state/src/left-nav-state.ts:5](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-state/src/left-nav-state.ts#L5) - -___ - -### slotName - -• **slotName**: ``null`` \| `string` - -#### Defined in - -[packages/framework/esm-state/src/left-nav-state.ts:4](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-state/src/left-nav-state.ts#L4) diff --git a/packages/framework/esm-framework/docs/interfaces/OpenmrsAppRoutes.md b/packages/framework/esm-framework/docs/interfaces/OpenmrsAppRoutes.md index eb3f6d5cc..de17763fe 100644 --- a/packages/framework/esm-framework/docs/interfaces/OpenmrsAppRoutes.md +++ b/packages/framework/esm-framework/docs/interfaces/OpenmrsAppRoutes.md @@ -25,7 +25,7 @@ A list of backend modules necessary for this frontend module and the correspondi #### Defined in -[packages/framework/esm-globals/src/types.ts:325](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L325) +[packages/framework/esm-globals/src/types.ts:290](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L290) ___ @@ -37,7 +37,7 @@ An array of all extensions supported by this frontend module. Extensions can be #### Defined in -[packages/framework/esm-globals/src/types.ts:333](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L333) +[packages/framework/esm-globals/src/types.ts:298](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L298) ___ @@ -49,7 +49,7 @@ An array of all modals supported by this frontend module. Modals can be launched #### Defined in -[packages/framework/esm-globals/src/types.ts:337](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L337) +[packages/framework/esm-globals/src/types.ts:302](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L302) ___ @@ -61,7 +61,7 @@ An array of all pages supported by this frontend module. Pages are automatically #### Defined in -[packages/framework/esm-globals/src/types.ts:329](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L329) +[packages/framework/esm-globals/src/types.ts:294](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L294) ___ @@ -73,7 +73,7 @@ The version of this frontend module. #### Defined in -[packages/framework/esm-globals/src/types.ts:321](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L321) +[packages/framework/esm-globals/src/types.ts:286](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L286) ___ @@ -85,4 +85,4 @@ An array of all workspaces supported by this frontend module. Workspaces can be #### Defined in -[packages/framework/esm-globals/src/types.ts:341](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L341) +[packages/framework/esm-globals/src/types.ts:306](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L306) diff --git a/packages/framework/esm-framework/docs/interfaces/ResourceLoader.md b/packages/framework/esm-framework/docs/interfaces/ResourceLoader.md index 3c22e7c15..865d64ddb 100644 --- a/packages/framework/esm-framework/docs/interfaces/ResourceLoader.md +++ b/packages/framework/esm-framework/docs/interfaces/ResourceLoader.md @@ -20,4 +20,4 @@ #### Defined in -[packages/framework/esm-globals/src/types.ts:351](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L351) +[packages/framework/esm-globals/src/types.ts:316](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-globals/src/types.ts#L316) diff --git a/packages/framework/esm-framework/docs/interfaces/WorkspaceWindowProps.md b/packages/framework/esm-framework/docs/interfaces/WorkspaceWindowProps.md index e8749289c..aa8a85732 100644 --- a/packages/framework/esm-framework/docs/interfaces/WorkspaceWindowProps.md +++ b/packages/framework/esm-framework/docs/interfaces/WorkspaceWindowProps.md @@ -17,7 +17,7 @@ #### Defined in -[packages/framework/esm-styleguide/src/workspaces/window/workspace-window.component.tsx:16](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/window/workspace-window.component.tsx#L16) +[packages/framework/esm-styleguide/src/workspaces/window/workspace-window.component.tsx:23](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/window/workspace-window.component.tsx#L23) ___ @@ -27,4 +27,4 @@ ___ #### Defined in -[packages/framework/esm-styleguide/src/workspaces/window/workspace-window.component.tsx:15](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/window/workspace-window.component.tsx#L15) +[packages/framework/esm-styleguide/src/workspaces/window/workspace-window.component.tsx:22](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/workspaces/window/workspace-window.component.tsx#L22) diff --git a/packages/framework/esm-framework/jest.config.js b/packages/framework/esm-framework/jest.config.js index 7243b3f05..4983e9995 100644 --- a/packages/framework/esm-framework/jest.config.js +++ b/packages/framework/esm-framework/jest.config.js @@ -6,6 +6,7 @@ module.exports = { '\\.(s?css)$': 'identity-obj-proxy', '\\.(svg)$': '/__mocks__/fileMock.js', 'lodash-es/(.*)': 'lodash/$1', + '^lodash-es$': 'lodash', // See https://jestjs.io/docs/upgrading-to-jest28#packagejson-exports // which links to https://github.com/microsoft/accessibility-insights-web/pull/5421#issuecomment-1109168149 '^dexie$': require.resolve('dexie'), diff --git a/packages/framework/esm-framework/mock.tsx b/packages/framework/esm-framework/mock.tsx index f5c365ed2..0817368bb 100644 --- a/packages/framework/esm-framework/mock.tsx +++ b/packages/framework/esm-framework/mock.tsx @@ -47,6 +47,9 @@ export const goBackInHistory = jest.fn(); /* esm-offline */ export const useConnectivity = jest.fn().mockReturnValue(true); +/* esm-pages */ +export const getActiveAppNames = jest.fn().mockReturnValue([]); + /* esm-styleguide */ export const showNotification = jest.fn(); export const showActionableNotification = jest.fn(); @@ -54,8 +57,6 @@ export const showToast = jest.fn(); export const showSnackbar = jest.fn(); export const showModal = jest.fn(); -export const setLeftNav = jest.fn(); -export const unsetLeftNav = jest.fn(); export const ResponsiveWrapper = jest.fn(({ children }) => <>{children}); export const OpenmrsDatePicker = jest.fn(() =>
OpenMRS DatePicker
); export const ErrorState = jest.fn(() =>
Error State
); diff --git a/packages/framework/esm-framework/package.json b/packages/framework/esm-framework/package.json index 98ea25223..73faa4aec 100644 --- a/packages/framework/esm-framework/package.json +++ b/packages/framework/esm-framework/package.json @@ -46,6 +46,7 @@ "@openmrs/esm-globals": "workspace:*", "@openmrs/esm-navigation": "workspace:*", "@openmrs/esm-offline": "workspace:*", + "@openmrs/esm-pages": "workspace:*", "@openmrs/esm-react-utils": "workspace:*", "@openmrs/esm-routes": "workspace:*", "@openmrs/esm-state": "workspace:*", diff --git a/packages/framework/esm-framework/src/index.ts b/packages/framework/esm-framework/src/index.ts index 1cf52ee85..5f2d98f27 100644 --- a/packages/framework/esm-framework/src/index.ts +++ b/packages/framework/esm-framework/src/index.ts @@ -7,6 +7,7 @@ export * from '@openmrs/esm-feature-flags/src/public'; export * from '@openmrs/esm-globals/src/public'; export * from '@openmrs/esm-navigation/src/public'; export * from '@openmrs/esm-offline/src/public'; +export * from '@openmrs/esm-pages/src/public'; export * from '@openmrs/esm-react-utils/src/public'; export * from '@openmrs/esm-state/src/public'; export * from '@openmrs/esm-styleguide/src/public'; diff --git a/packages/framework/esm-framework/src/internal.ts b/packages/framework/esm-framework/src/internal.ts index f2ddc2a73..860f2bdfd 100644 --- a/packages/framework/esm-framework/src/internal.ts +++ b/packages/framework/esm-framework/src/internal.ts @@ -7,6 +7,7 @@ export * from '@openmrs/esm-feature-flags'; export * from '@openmrs/esm-globals'; export * from '@openmrs/esm-navigation'; export * from '@openmrs/esm-offline'; +export * from '@openmrs/esm-pages'; export * from '@openmrs/esm-react-utils'; export * from '@openmrs/esm-routes'; export * from '@openmrs/esm-state'; diff --git a/packages/framework/esm-globals/src/types.ts b/packages/framework/esm-globals/src/types.ts index a6b313329..0f71d7be1 100644 --- a/packages/framework/esm-globals/src/types.ts +++ b/packages/framework/esm-globals/src/types.ts @@ -166,6 +166,34 @@ export type PageDefinition = { */ export type RegisteredPageDefinition = Omit & AppComponent & { order: number }; +export type Loadable = () => Promise & { default: LifeCycles }>; + +/** + * Internal shared type for various *Definitions that either take a named component or a function to load the + * component. + */ +export type ComponentOrLoadable = + | { + /** + * The name of the component exported by this frontend module. + */ + component: string; + /** + * @internal + */ + load?: never; + } + | { + /** + * The name of the component exported by this frontend module. + */ + component?: never; + /** + * @internal + */ + load: Loadable; + }; + /** * A definition of an extension as extracted from an app's routes.json */ @@ -208,28 +236,7 @@ export type ExtensionDefinition = { meta?: { [k: string]: unknown; }; -} & ( - | { - /** - * The name of the component exported by this frontend module. - */ - component: string; - /** - * @internal - */ - load?: never; - } - | { - /** - * The name of the component exported by this frontend module. - */ - component?: never; - /** - * @internal - */ - load: () => Promise<{ default?: LifeCycles } & LifeCycles>; - } -); +} & ComponentOrLoadable; /** * A definition of a modal as extracted from an app's routes.json @@ -239,28 +246,7 @@ export type ModalDefinition = { * The name of this modal. This is used to launch the modal. */ name: string; -} & ( - | { - /** - * The name of the component exported by this frontend module. - */ - component: string; - /** - * @internal - */ - load?: never; - } - | { - /** - * The name of the component exported by this frontend module. - */ - component?: never; - /** - * @internal - */ - load: () => Promise<{ default?: LifeCycles } & LifeCycles>; - } -); +} & ComponentOrLoadable; /* The possible states a workspace window can be opened in. */ export type WorkspaceWindowState = 'maximized' | 'hidden' | 'normal'; @@ -288,28 +274,7 @@ export type WorkspaceDefinition = { canMaximize?: boolean; width?: 'narrow' | 'wider'; preferredWindowSize?: WorkspaceWindowState; -} & ( - | { - /** - * The name of the component exported by this frontend module. - */ - component: string; - /** - * @internal - */ - load?: never; - } - | { - /** - * The name of the component exported by this frontend module. - */ - component?: never; - /** - * @internal - */ - load: () => Promise<{ default?: LifeCycles } & LifeCycles>; - } -); +} & ComponentOrLoadable; /** * This interface describes the format of the routes provided by an app diff --git a/packages/framework/esm-pages/README.md b/packages/framework/esm-pages/README.md new file mode 100644 index 000000000..0c6fbd6fb --- /dev/null +++ b/packages/framework/esm-pages/README.md @@ -0,0 +1,4 @@ +# openmrs-esm-dynamic-loading + +openmrs-esm-dynamic-loading provides functions for dynamically loading JS files using Webpack Module Federation +dynamic remotes. diff --git a/packages/framework/esm-pages/jest.config.js b/packages/framework/esm-pages/jest.config.js new file mode 100644 index 000000000..52484b6fd --- /dev/null +++ b/packages/framework/esm-pages/jest.config.js @@ -0,0 +1,9 @@ +module.exports = { + transform: { + '^.+\\.tsx?$': ['@swc/jest'], + }, + testEnvironment: 'jsdom', + testEnvironmentOptions: { + url: 'http://localhost/', + }, +}; diff --git a/packages/framework/esm-pages/package.json b/packages/framework/esm-pages/package.json new file mode 100644 index 000000000..beab6cda2 --- /dev/null +++ b/packages/framework/esm-pages/package.json @@ -0,0 +1,51 @@ +{ + "name": "@openmrs/esm-pages", + "version": "5.5.0", + "license": "MPL-2.0", + "description": "Manages pages within the OpenMRS application", + "browser": "dist/openmrs-esm-pages.js", + "main": "src/index.ts", + "source": true, + "sideEffects": false, + "scripts": { + "test": "cross-env TZ=UTC jest --config jest.config.js --verbose false --passWithNoTests --color", + "test:watch": "cross-env TZ=UTC jest --watch --config jest.config.js --color", + "build": "webpack --mode=production", + "build:development": "webpack --mode development", + "analyze": "webpack --mode=production --env analyze=true", + "typescript": "tsc", + "lint": "eslint src --ext ts,tsx" + }, + "keywords": [ + "openmrs", + "microfrontends" + ], + "directories": { + "lib": "dist", + "src": "src" + }, + "browserslist": [ + "extends browserslist-config-openmrs" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/openmrs/openmrs-esm-core.git" + }, + "bugs": { + "url": "https://github.com/openmrs/openmrs-esm-core/issues" + }, + "homepage": "https://github.com/openmrs/openmrs-esm-core#readme", + "publishConfig": { + "access": "public" + }, + "peerDependencies": { + "@openmrs/esm-globals": "5.x", + "@openmrs/esm-state": "5.x", + "single-spa": "6.x" + }, + "devDependencies": { + "@openmrs/esm-globals": "workspace:*", + "@openmrs/esm-state": "workspace:*", + "single-spa": "^6.0.1" + } +} diff --git a/packages/framework/esm-pages/src/index.ts b/packages/framework/esm-pages/src/index.ts new file mode 100644 index 000000000..23c7929ac --- /dev/null +++ b/packages/framework/esm-pages/src/index.ts @@ -0,0 +1 @@ +export * from './pages'; diff --git a/packages/framework/esm-pages/src/pages.ts b/packages/framework/esm-pages/src/pages.ts new file mode 100644 index 000000000..2fbb29c58 --- /dev/null +++ b/packages/framework/esm-pages/src/pages.ts @@ -0,0 +1,76 @@ +import { type RegisteredPageDefinition, type Loadable } from '@openmrs/esm-globals'; +import { createGlobalStore } from '@openmrs/esm-state'; +import { type LifeCycles, getMountedApps, registerApplication } from 'single-spa'; +import { omit, uniq } from 'lodash-es'; + +/** Internal store of registered pages */ +interface PageRegistry { + /** Pages indexed by name */ + pages: Record; +} + +const pageRegistryStore = createGlobalStore('pageRegistry', { + pages: {}, +}); + +export type PageRegistration = RegisteredPageDefinition & { + activityFn: (location: Location) => boolean; + load: () => Promise; +}; + +/** @internal */ +export function getPageRegistration(appName: string, order: number): RegisteredPageDefinition | undefined { + return pageRegistryStore.getState().pages[`${appName}-${order}`]; +} + +/** @internal */ +export function getActiveAppNames(includeUtilityPages: boolean = false): Array { + let mountedPages = getMountedApps(); + if (!includeUtilityPages) { + mountedPages = mountedPages.filter( + (page) => + !page.includes('devtools') && + !page.includes('implementer-tools-app') && + !page.includes('primary-navigation-app'), + ); + } + + return uniq(mountedPages.filter((page) => page.includes('-page-')).map((page) => page.split('-page-', 1)[0])); +} + +/** @internal */ +export function getActivePageRegistrations(includeUtilityPages: boolean = false): Array { + let mountedPages = getMountedApps(); + if (!includeUtilityPages) { + mountedPages = mountedPages.filter( + (page) => + !page.includes('devtools') && + !page.includes('implementer-tools-app') && + !page.includes('primary-navigation-app'), + ); + } + + const pageRegistrations = pageRegistryStore.getState().pages; + return mountedPages + .filter((page) => page.includes('-page-')) + .map((page) => { + const [appName, order] = page.split('-page-', 1); + return pageRegistrations[`${appName}-${order}`]; + }) + .filter((page) => typeof page !== 'undefined' && page !== null); +} + +/** @internal */ +export function registerPage(pageDefinition: PageRegistration) { + pageRegistryStore.setState((state) => { + state[`${pageDefinition.appName}-${pageDefinition.order}`] = omit(pageDefinition, 'load', 'activityFn'); + return state; + }); + registerApplication(pageDefinition.appName, pageDefinition.load, pageDefinition.activityFn); +} + +/** @deprecated */ +export function setLeftNav() {} + +/** @deprecated */ +export function unsetLeftNav() {} diff --git a/packages/framework/esm-pages/src/public.ts b/packages/framework/esm-pages/src/public.ts new file mode 100644 index 000000000..8b8d5dde2 --- /dev/null +++ b/packages/framework/esm-pages/src/public.ts @@ -0,0 +1 @@ +export { setLeftNav, unsetLeftNav } from './pages'; diff --git a/packages/framework/esm-pages/tsconfig.json b/packages/framework/esm-pages/tsconfig.json new file mode 100644 index 000000000..a0a20d3ed --- /dev/null +++ b/packages/framework/esm-pages/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "module": "esnext", + "target": "es2015", + "allowSyntheticDefaultImports": true, + "jsx": "react", + "strictNullChecks": true, + "moduleResolution": "node", + "declaration": true, + "declarationDir": "dist", + "emitDeclarationOnly": true, + "lib": [ + "dom", + "es5", + "scripthost", + "es2015", + "es2015.promise", + "es2016.array.include", + "es2018", + "esnext" + ] + }, + "include": ["src/**/*"] +} diff --git a/packages/framework/esm-pages/webpack.config.js b/packages/framework/esm-pages/webpack.config.js new file mode 100644 index 000000000..cd09fcbe2 --- /dev/null +++ b/packages/framework/esm-pages/webpack.config.js @@ -0,0 +1,42 @@ +const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); +const { resolve, basename } = require('path'); +const { CleanWebpackPlugin } = require('clean-webpack-plugin'); +const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); + +const { browser, peerDependencies } = require('./package.json'); + +module.exports = (env) => ({ + entry: [resolve(__dirname, 'src/index.ts')], + output: { + filename: basename(browser), + path: resolve(__dirname, 'dist'), + library: { type: 'system' }, + }, + devtool: 'source-map', + module: { + rules: [ + { + test: /\.m?(js|ts|tsx)$/, + exclude: /node_modules/, + use: 'swc-loader', + }, + ], + }, + externals: Object.keys(peerDependencies || {}), + resolve: { + extensions: ['.ts', '.js', '.tsx', '.jsx'], + }, + plugins: [ + new CleanWebpackPlugin(), + new ForkTsCheckerWebpackPlugin(), + new BundleAnalyzerPlugin({ + analyzerMode: env && env.analyze ? 'static' : 'disabled', + }), + ], + devServer: { + disableHostCheck: true, + headers: { + 'Access-Control-Allow-Origin': '*', + }, + }, +}); diff --git a/packages/framework/esm-state/src/index.ts b/packages/framework/esm-state/src/index.ts index 5ce71fe5a..da8854349 100644 --- a/packages/framework/esm-state/src/index.ts +++ b/packages/framework/esm-state/src/index.ts @@ -1,2 +1 @@ export * from './state'; -export * from './left-nav-state'; diff --git a/packages/framework/esm-state/src/left-nav-state.ts b/packages/framework/esm-state/src/left-nav-state.ts deleted file mode 100644 index 665e15351..000000000 --- a/packages/framework/esm-state/src/left-nav-state.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { createGlobalStore } from './state'; - -export interface LeftNavStore { - slotName: string | null; - basePath: string; -} - -/** - * @internal - */ -export const leftNavStore = createGlobalStore('left-nav', { - slotName: null, - basePath: window.spaBase, -}); - -export function setLeftNav({ name, basePath }) { - leftNavStore.setState({ slotName: name, basePath }); -} - -export function unsetLeftNav(name) { - if (leftNavStore.getState().slotName == name) { - leftNavStore.setState({ slotName: null }); - } -} diff --git a/packages/framework/esm-state/src/public.ts b/packages/framework/esm-state/src/public.ts index e344b9916..aefca141b 100644 --- a/packages/framework/esm-state/src/public.ts +++ b/packages/framework/esm-state/src/public.ts @@ -1,2 +1 @@ export { createGlobalStore, getGlobalStore, subscribeTo } from './state'; -export { type LeftNavStore, setLeftNav, unsetLeftNav } from './left-nav-state'; diff --git a/packages/framework/esm-styleguide/jest.config.js b/packages/framework/esm-styleguide/jest.config.js index d9ccab3b4..bcd3b1a1a 100644 --- a/packages/framework/esm-styleguide/jest.config.js +++ b/packages/framework/esm-styleguide/jest.config.js @@ -7,10 +7,12 @@ module.exports = { '\\.(s?css)$': 'identity-obj-proxy', '^@carbon/icons-react/es/(.*)$': '@carbon/icons-react/lib/$1', '^@carbon/charts': 'identity-obj-proxy', + '@openmrs/esm-framework': '@openmrs/esm-framework/mock', '@openmrs/esm-react-utils': '@openmrs/esm-react-utils/mock', '@openmrs/esm-translations': '@openmrs/esm-translations/mock', '^lodash-es/(.*)$': 'lodash/$1', - dexie: require.resolve('dexie'), + '^lodash-es$': 'lodash', + dexie: 'dexie', }, collectCoverageFrom: [ '**/src/**/*.component.tsx', diff --git a/packages/framework/esm-styleguide/src/modals/registry.ts b/packages/framework/esm-styleguide/src/modals/registry.ts index 24c09d6f2..e20e5a15a 100644 --- a/packages/framework/esm-styleguide/src/modals/registry.ts +++ b/packages/framework/esm-styleguide/src/modals/registry.ts @@ -1,11 +1,11 @@ import { getExtensionRegistration } from '@openmrs/esm-extensions'; +import { type Loadable } from '@openmrs/esm-globals'; import { createGlobalStore } from '@openmrs/esm-state'; -import type { LifeCycles } from 'single-spa'; /** @internal */ export interface ModalRegistration { name: string; - load(): Promise<{ default?: LifeCycles } & LifeCycles>; + load: Loadable; moduleName: string; } diff --git a/packages/framework/esm-styleguide/src/workspaces/workspaces.ts b/packages/framework/esm-styleguide/src/workspaces/workspaces.ts index 0a8a957e0..4984c1c87 100644 --- a/packages/framework/esm-styleguide/src/workspaces/workspaces.ts +++ b/packages/framework/esm-styleguide/src/workspaces/workspaces.ts @@ -1,9 +1,10 @@ /** @module @category Workspace */ import { useMemo } from 'react'; -import type { LifeCycles } from 'single-spa'; import _i18n from 'i18next'; import { type ExtensionRegistration, + type Loadable, + getExtensionRegistration, getGlobalStore, navigate, translateFrom, @@ -11,8 +12,7 @@ import { useStore, getCoreTranslation, type WorkspaceWindowState, -} from '@openmrs/esm-framework'; -import { getExtensionRegistration } from '@openmrs/esm-extensions'; +} from '@openmrs/esm-framework/src/internal'; import { type CloseWorkspaceOptions } from './types'; export interface Prompt { @@ -41,7 +41,7 @@ export interface WorkspaceRegistration { canMaximize: boolean; width: 'narrow' | 'wider'; preferredWindowSize: WorkspaceWindowState; - load: () => Promise<{ default?: LifeCycles } & LifeCycles>; + load: Loadable; moduleName: string; } @@ -69,7 +69,7 @@ export interface RegisterWorkspaceOptions { canMaximize?: boolean; width?: 'narrow' | 'wider'; preferredWindowSize?: WorkspaceWindowState; - load: () => Promise<{ default?: LifeCycles } & LifeCycles>; + load: Loadable; moduleName: string; } diff --git a/packages/shell/esm-app-shell/src/apps.ts b/packages/shell/esm-app-shell/src/apps.ts index 7d63dd81b..40237d4c3 100644 --- a/packages/shell/esm-app-shell/src/apps.ts +++ b/packages/shell/esm-app-shell/src/apps.ts @@ -1,17 +1,18 @@ -import { type ActivityFn, type LifeCycles, pathToActiveWhen, registerApplication } from 'single-spa'; +import { type ActivityFn, type LifeCycles, pathToActiveWhen } from 'single-spa'; import { - type RegisteredPageDefinition, type ExtensionDefinition, + type Loadable, type OpenmrsAppRoutes, + type RegisteredPageDefinition, type RouteDefinition, - type ExtensionRegistration, type ModalDefinition, type WorkspaceDefinition, attach, - registerExtension, importDynamic, + registerExtension, registerModal, registerModuleWithConfigSystem, + registerPage, registerWorkspace, } from '@openmrs/esm-framework/src/internal'; import { emptyLifecycle, routeRegex } from './helpers'; @@ -229,6 +230,7 @@ export function finishRegisteringAllApps() { } const index = appIndices.get(page.appName); + page.order = index; const name = `${page.appName}-page-${index}`; const div = document.createElement('div'); div.id = `single-spa-application:${name}`; @@ -273,7 +275,14 @@ To fix this, ensure that you define the "component" field inside the page defini const activityFn = wrapPageActivityFn(getActivityFn(route), page); const loader = getLoader(page.appName, page.component); - registerApplication(appName, loader, activityFn); + if (loader) { + registerPage({ + ...page, + appName: appName, + activityFn, + load: loader, + }); + } } /** @@ -312,7 +321,7 @@ To fix this, ensure that you define a 'component' field inside the extension def return; } - let loader: ExtensionRegistration['load'] | undefined = undefined; + let loader: Loadable | undefined = undefined; if (extension.component) { loader = getLoader(appName, extension.component); } else if (extension.load) { @@ -372,7 +381,7 @@ To fix this, ensure that you define a 'component' field inside the modal definit return; } - let loader: ExtensionRegistration['load'] | undefined = undefined; + let loader: Loadable | undefined = undefined; if (modal.component) { loader = getLoader(appName, modal.component); } else if (modal.load) { @@ -431,7 +440,7 @@ To fix this, ensure that you define a 'component' field inside the workspace def return; } - let loader: ExtensionRegistration['load'] | undefined = undefined; + let loader: Loadable | undefined = undefined; if (workspace.component) { loader = getLoader(appName, workspace.component); } else if (workspace.load) { diff --git a/yarn.lock b/yarn.lock index 548734d32..2fcb8546c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3131,6 +3131,7 @@ __metadata: "@openmrs/esm-globals": "workspace:*" "@openmrs/esm-navigation": "workspace:*" "@openmrs/esm-offline": "workspace:*" + "@openmrs/esm-pages": "workspace:*" "@openmrs/esm-react-utils": "workspace:*" "@openmrs/esm-routes": "workspace:*" "@openmrs/esm-state": "workspace:*" @@ -3279,6 +3280,20 @@ __metadata: languageName: unknown linkType: soft +"@openmrs/esm-pages@workspace:*, @openmrs/esm-pages@workspace:packages/framework/esm-pages": + version: 0.0.0-use.local + resolution: "@openmrs/esm-pages@workspace:packages/framework/esm-pages" + dependencies: + "@openmrs/esm-globals": "workspace:*" + "@openmrs/esm-state": "workspace:*" + single-spa: "npm:^6.0.1" + peerDependencies: + "@openmrs/esm-globals": 5.x + "@openmrs/esm-state": 5.x + single-spa: 6.x + languageName: unknown + linkType: soft + "@openmrs/esm-primary-navigation-app@workspace:packages/apps/esm-primary-navigation-app": version: 0.0.0-use.local resolution: "@openmrs/esm-primary-navigation-app@workspace:packages/apps/esm-primary-navigation-app"