Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 52 additions & 14 deletions frontend/src/components/DynamicPageRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { defaultPageService } from '../services/defaultPageService';
import { usePageState } from '../contexts/PageStateContext';
import { useModuleState } from '../contexts/ModuleStateContext';
import { pageContextService } from '../services/PageContextService';
import { clearPageCache } from '../utils/clearPageCache';

// Declare global interface for backward compatibility
declare global {
Expand Down Expand Up @@ -96,22 +97,50 @@ function useUnifiedPageLoader(options: {

// Helper function to convert a layout item
const convertLayoutItem = (item: any) => {
const moduleId = ('moduleUniqueId' in item) ? item.moduleUniqueId : item.i;
let pluginId = ('pluginId' in item) ? item.pluginId :
(legacyPage.modules?.[moduleId]?.pluginId);
// The layout item key is a unique instance id; use it to look up the module definition
const layoutKey = ('moduleUniqueId' in item) ? item.moduleUniqueId : item.i;
const moduleDef = legacyPage.modules?.[layoutKey];

// If no direct pluginId, try to extract from moduleId
if (!pluginId && moduleId) {
pluginId = extractPluginIdFromModuleId(moduleId);
// console.log(`[DynamicPageRenderer] Extracted pluginId '${pluginId}' from moduleId '${moduleId}'`);
}
// Check if item has args property (new format from database)
const hasArgs = item.args && typeof item.args === 'object';

// Skip items without a valid pluginId to prevent infinite loops
// Prefer pluginId from item directly, then from args, then from module definition
let pluginId = item.pluginId || (hasArgs ? item.pluginId : undefined) || moduleDef?.pluginId;
if (!pluginId && layoutKey) {
pluginId = extractPluginIdFromModuleId(layoutKey) || undefined as any;
}
if (!pluginId || pluginId === 'unknown') {
console.warn(`[DynamicPageRenderer] Skipping layout item with missing pluginId:`, { item, moduleId, pluginId });
console.warn(`[DynamicPageRenderer] Skipping layout item with missing pluginId:`, { item, layoutKey, pluginId });
return null;
}

// Extract moduleId from args if available, otherwise use module definition or layout key
let baseModuleId;
if (hasArgs && item.args.moduleId) {
baseModuleId = item.args.moduleId;
console.log('[DynamicPageRenderer] Using moduleId from args:', baseModuleId);
} else {
baseModuleId = moduleDef?.moduleId || moduleDef?.moduleName || layoutKey;
console.log('[DynamicPageRenderer] Using moduleId from moduleDef or layoutKey:', baseModuleId);
}

// Merge config from module definition and args
// IMPORTANT: Include moduleId in config for LayoutEngine to use
const config = {
...(moduleDef?.config || {}),
...(hasArgs ? item.args : {}),
moduleId: baseModuleId // Ensure moduleId is in config
};

console.log('[DynamicPageRenderer] Converted layout item:', {
itemId: item.i,
pluginId,
moduleId: baseModuleId,
hasArgs,
args: item.args,
config
});

return {
i: item.i,
x: item.x,
Expand All @@ -125,9 +154,9 @@ function useUnifiedPageLoader(options: {
static: ('static' in item) ? item.static : false,
isDraggable: ('isDraggable' in item) ? item.isDraggable !== false : true,
isResizable: ('isResizable' in item) ? item.isResizable !== false : true,
moduleId,
moduleId: baseModuleId,
pluginId,
config: legacyPage.modules?.[moduleId]?.config || {},
config,
};
};

Expand All @@ -145,9 +174,11 @@ function useUnifiedPageLoader(options: {
// Convert modules to unified format
const modules: ModuleConfig[] = [];
if (legacyPage.modules) {
Object.entries(legacyPage.modules).forEach(([moduleId, moduleDefinition]) => {
Object.entries(legacyPage.modules).forEach(([layoutKey, moduleDefinition]) => {
// Prefer the plugin's declared module id or name for unified ids
const unifiedModuleId = moduleDefinition.moduleId || moduleDefinition.moduleName || layoutKey;
modules.push({
id: moduleId,
id: unifiedModuleId,
pluginId: moduleDefinition.pluginId,
type: 'component',
...moduleDefinition.config,
Expand Down Expand Up @@ -187,6 +218,13 @@ function useUnifiedPageLoader(options: {

const cacheKey = getCacheKey();

// TEMPORARY: Clear cache for AI Chat page to ensure fresh data
if (route === 'ai-chat-1756310855' || location.pathname.includes('ai-chat')) {
clearPageCache('0c8f4dc670a4409c87030c3000779e14');
clearPageCache('ai-chat');
console.log('[DynamicPageRenderer] Cleared cache for AI Chat page');
}

// Check cache first
const cachedPage = getCachedPage(cacheKey);
if (cachedPage) {
Expand Down
8 changes: 1 addition & 7 deletions frontend/src/components/DynamicPluginRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,7 @@ export class DynamicPluginRenderer extends React.Component<

const Component = module.component;

console.log(`[DynamicPluginRenderer] Rendering component for ${module.name}:`, {
hasComponent: !!Component,
componentType: typeof Component,
componentName: Component?.name,
isFunction: typeof Component === 'function',
moduleProps: Object.keys(module.props || {})
});


if (!Component) {
console.error(`[DynamicPluginRenderer] No component found for module ${module.name}`);
Expand Down
9 changes: 1 addition & 8 deletions frontend/src/components/PluginModuleRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -766,14 +766,7 @@ export const PluginModuleRenderer: React.FC<PluginModuleRendererProps> = ({
);
}

console.log(`[PluginModuleRenderer] Rendering module for ${pluginId}:`, {
moduleId: module.id,
moduleName: module.name,
hasComponent: !!module.component,
componentType: typeof module.component,
componentName: module.component?.name,
propsKeys: Object.keys(module.props || {})
});


return (
<ComponentErrorBoundary>
Expand Down
52 changes: 27 additions & 25 deletions frontend/src/components/dashboard/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,28 +40,23 @@ const Header = ({ onToggleSidebar, rightContent, sidebarOpen }: HeaderProps) =>
const [pageTitle, setPageTitle] = useState<string>('');
const [isStudioPage, setIsStudioPage] = useState<boolean>(false);

// Determine if the current URL is a studio page
const isCurrentPathStudioPage = location.pathname.startsWith('/plugin-studio') ||
location.pathname.startsWith('/pages/');
// Determine if the current URL is a page that should show title
// This includes studio pages, regular pages, and any page that sets a title
const shouldShowPageTitle = location.pathname.startsWith('/plugin-studio') ||
location.pathname.startsWith('/pages/') ||
location.pathname.startsWith('/page/') ||
// Also show for any page that has set a title
Boolean(window.currentPageTitle);

// Effect to reset state when location changes
useEffect(() => {
if (!isCurrentPathStudioPage) {
setPageTitle('');
setIsStudioPage(false);
window.currentPageTitle = undefined;
window.isStudioPage = false;
console.log('Header - Reset state because not on a studio page');
}
}, [location.pathname, isCurrentPathStudioPage]);
// Reset the page title when navigating away from pages
// But don't immediately clear it - let the new page set its title
console.log('Header - Location changed to:', location.pathname);
}, [location.pathname]);

// Effect to check the global variables periodically
useEffect(() => {
// Only check for updates if we're on a studio page
if (!isCurrentPathStudioPage) {
return;
}

// Initial check
if (window.currentPageTitle) {
setPageTitle(window.currentPageTitle);
Expand All @@ -73,14 +68,20 @@ const Header = ({ onToggleSidebar, rightContent, sidebarOpen }: HeaderProps) =>
console.log('Header - Initial global variables:', {
currentPageTitle: window.currentPageTitle,
isStudioPage: window.isStudioPage,
isCurrentPathStudioPage
pathname: location.pathname
});

// Set up an interval to check for changes
const intervalId = setInterval(() => {
if (window.currentPageTitle && window.currentPageTitle !== pageTitle) {
console.log('Header - Updating page title from global:', window.currentPageTitle);
setPageTitle(window.currentPageTitle);
// Update page title if it has changed
if (window.currentPageTitle !== pageTitle) {
if (window.currentPageTitle) {
console.log('Header - Updating page title from global:', window.currentPageTitle);
setPageTitle(window.currentPageTitle);
} else {
// Clear the title if it's been unset
setPageTitle('');
}
}

if (window.isStudioPage !== undefined && window.isStudioPage !== isStudioPage) {
Expand All @@ -91,7 +92,7 @@ const Header = ({ onToggleSidebar, rightContent, sidebarOpen }: HeaderProps) =>

// Clean up the interval when the component unmounts
return () => clearInterval(intervalId);
}, [pageTitle, isStudioPage, isCurrentPathStudioPage]);
}, [pageTitle, isStudioPage, location.pathname]);

const handleMenu = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
Expand Down Expand Up @@ -156,8 +157,8 @@ const Header = ({ onToggleSidebar, rightContent, sidebarOpen }: HeaderProps) =>
{sidebarOpen ? <MenuOpenIcon /> : <MenuIcon />}
</IconButton>

{/* Display page title for studio pages */}
{isStudioPage && isCurrentPathStudioPage ? (
{/* Display page title when available */}
{pageTitle ? (
<Typography
variant="h6"
sx={{
Expand All @@ -166,10 +167,11 @@ const Header = ({ onToggleSidebar, rightContent, sidebarOpen }: HeaderProps) =>
alignItems: 'center',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
whiteSpace: 'nowrap',
maxWidth: '400px'
}}
>
{pageTitle || 'No Title Available'}
{pageTitle}
</Typography>
) : null}
</Box>
Expand Down
Loading