import React, { useEffect } from 'react';
import { subscribeOpenmrsEvent } from '@openmrs/esm-emr-api';
import classNames from 'classnames';
import { createRoot } from 'react-dom/client';
import { ActionMenu } from './action-menu2/action-menu2.component';
import { closeWorkspaceGroup2, useWorkspace2Store } from './workspace2';
import { shouldCloseOnUrlChange } from './scope-utils';
import ActiveWorkspaceWindow from './active-workspace-window.component';
import styles from './workspace-windows-and-menu.module.scss';
export function renderWorkspaceWindowsAndMenu(target: HTMLElement | null) {
if (target) {
const root = createRoot(target);
root.render();
}
}
/**
* This component renders the workspace action menu of a workspace group
* and all the active workspace windows within that group.
*/
function WorkspaceWindowsAndMenu() {
const { openedGroup, openedWindows, registeredGroupsByName, registeredWindowsByName } = useWorkspace2Store();
useEffect(() => {
const unsubscribe = subscribeOpenmrsEvent('before-page-changed', (pageChangedEvent) => {
const { newPage, cancelNavigation, oldUrl, newUrl } = pageChangedEvent;
if (!openedGroup) {
return;
}
// Always close on app change - this takes precedence as a safety boundary
if (newPage) {
cancelNavigation(closeWorkspaceGroup2().then((isClosed) => !isClosed));
return;
}
const group = registeredGroupsByName[openedGroup.groupName];
const scopePattern = group?.scopePattern;
// No scopePattern means no additional scope-based closing (original behavior)
if (!scopePattern) {
return;
}
if (process.env.NODE_ENV !== 'production' && !scopePattern.startsWith('^')) {
console.warn(
`Workspace group "${openedGroup.groupName}" has a scopePattern without a start anchor (^). ` +
`This may cause unexpected behavior. Pattern: "${scopePattern}"`,
);
}
if (shouldCloseOnUrlChange(scopePattern, oldUrl, newUrl)) {
// Prompt to close the workspaces
// should only cancel navigation if the user cancels the prompt
cancelNavigation(closeWorkspaceGroup2().then((isClosed) => !isClosed));
}
});
return unsubscribe;
}, [openedGroup, registeredGroupsByName]);
if (!openedGroup) {
return null;
}
const group = registeredGroupsByName[openedGroup.groupName];
const hasMaximizedWindow = openedWindows.some((window) => window.maximized);
const { name: groupName } = group;
const windowsWithIcons = Object.values(registeredWindowsByName)
.filter((window): window is Required => window.group === groupName && window.icon !== undefined)
.sort((a, b) => (a.order ?? Number.MAX_VALUE) - (b.order ?? Number.MAX_VALUE));
const showActionMenu = windowsWithIcons.length > 0;
return (