@djangocfg/layouts 1.2.19 → 1.2.21
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.
- package/package.json +5 -5
- package/src/auth/context/AuthContext.tsx +12 -1
- package/src/layouts/AppLayout/AppLayout.tsx +13 -0
- package/src/layouts/AppLayout/components/PackageVersions/packageVersions.config.ts +8 -8
- package/src/layouts/AppLayout/layouts/AdminLayout/AdminLayout.tsx +43 -2
- package/src/layouts/AppLayout/layouts/AdminLayout/components/ParentSync.tsx +20 -71
- package/src/layouts/AppLayout/layouts/AdminLayout/hooks/useApp.ts +33 -90
- package/src/layouts/AppLayout/layouts/PrivateLayout/components/DashboardHeader.tsx +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/layouts",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.21",
|
|
4
4
|
"description": "Layout system and components for Unrealon applications",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "DjangoCFG",
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
"check": "tsc --noEmit"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@djangocfg/api": "^1.2.
|
|
57
|
-
"@djangocfg/og-image": "^1.2.
|
|
58
|
-
"@djangocfg/ui": "^1.2.
|
|
56
|
+
"@djangocfg/api": "^1.2.21",
|
|
57
|
+
"@djangocfg/og-image": "^1.2.21",
|
|
58
|
+
"@djangocfg/ui": "^1.2.21",
|
|
59
59
|
"@hookform/resolvers": "^5.2.0",
|
|
60
60
|
"consola": "^3.4.2",
|
|
61
61
|
"lucide-react": "^0.468.0",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"vidstack": "0.6.15"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
|
-
"@djangocfg/typescript-config": "^1.2.
|
|
79
|
+
"@djangocfg/typescript-config": "^1.2.21",
|
|
80
80
|
"@types/node": "^24.7.2",
|
|
81
81
|
"@types/react": "19.2.2",
|
|
82
82
|
"@types/react-dom": "19.2.1",
|
|
@@ -93,25 +93,36 @@ const AuthProviderInternal: React.FC<AuthProviderProps> = ({ children, config })
|
|
|
93
93
|
|
|
94
94
|
// Simple profile loading without retry - now uses AccountsContext
|
|
95
95
|
const loadCurrentProfile = useCallback(async (): Promise<void> => {
|
|
96
|
+
// console.log('[AuthContext] loadCurrentProfile called');
|
|
96
97
|
try {
|
|
97
98
|
// Ensure API clients are properly initialized with current token
|
|
98
|
-
|
|
99
|
+
const isAuth = api.isAuthenticated();
|
|
100
|
+
const token = api.getToken();
|
|
101
|
+
// console.log('[AuthContext] isAuthenticated:', isAuth, 'token:', token ? token.substring(0, 20) + '...' : 'null');
|
|
102
|
+
|
|
103
|
+
if (!isAuth) {
|
|
104
|
+
console.warn('[AuthContext] No valid authentication token, throwing error');
|
|
99
105
|
throw new Error('No valid authentication token');
|
|
100
106
|
}
|
|
101
107
|
|
|
108
|
+
// console.log('[AuthContext] Refreshing profile from AccountsContext...');
|
|
102
109
|
// Refresh profile from AccountsContext
|
|
103
110
|
const refreshedProfile = await accounts.refreshProfile();
|
|
104
111
|
|
|
105
112
|
if (refreshedProfile) {
|
|
113
|
+
// console.log('[AuthContext] Profile loaded successfully:', refreshedProfile.id, 'is_staff:', refreshedProfile.is_staff, 'is_superuser:', refreshedProfile.is_superuser);
|
|
106
114
|
authLogger.info('Profile loaded successfully:', refreshedProfile.id);
|
|
107
115
|
} else {
|
|
116
|
+
console.warn('[AuthContext] Profile refresh returned undefined - but keeping tokens');
|
|
108
117
|
authLogger.warn('Profile refresh returned undefined - but keeping tokens');
|
|
109
118
|
}
|
|
110
119
|
|
|
111
120
|
// Always mark as initialized if we have valid tokens
|
|
112
121
|
// Don't clear tokens just because profile fetch failed
|
|
113
122
|
setInitialized(true);
|
|
123
|
+
// console.log('[AuthContext] loadCurrentProfile completed, initialized=true');
|
|
114
124
|
} catch (error) {
|
|
125
|
+
console.error('[AuthContext] Failed to load profile:', error);
|
|
115
126
|
authLogger.error('Failed to load profile:', error);
|
|
116
127
|
// Use global error handler first, fallback to clearing state
|
|
117
128
|
if (!handleGlobalAuthError(error, 'loadCurrentProfile')) {
|
|
@@ -110,6 +110,19 @@ function LayoutRouter({
|
|
|
110
110
|
// Admin routes: Always show loading during SSR and initial client render
|
|
111
111
|
// This prevents hydration mismatch when isAuthenticated differs between server/client
|
|
112
112
|
if (isAdminRoute && !forceLayout) {
|
|
113
|
+
// In embedded mode (iframe), render AdminLayout immediately to receive postMessage
|
|
114
|
+
const isEmbedded = typeof window !== 'undefined' && window !== window.parent;
|
|
115
|
+
|
|
116
|
+
if (isEmbedded) {
|
|
117
|
+
// Skip loading checks - AdminLayout will handle auth via postMessage
|
|
118
|
+
return (
|
|
119
|
+
<AdminLayout enableParentSync={true}>
|
|
120
|
+
{children}
|
|
121
|
+
</AdminLayout>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Standalone mode: show loading during initialization
|
|
113
126
|
if (!isMounted || isLoading) {
|
|
114
127
|
return (
|
|
115
128
|
<div className="min-h-screen flex items-center justify-center">
|
|
@@ -16,36 +16,36 @@ export interface PackageInfo {
|
|
|
16
16
|
/**
|
|
17
17
|
* Package versions registry
|
|
18
18
|
* Auto-synced from package.json files
|
|
19
|
-
* Last updated: 2025-11-
|
|
19
|
+
* Last updated: 2025-11-02T11:45:27.117Z
|
|
20
20
|
*/
|
|
21
21
|
const PACKAGE_VERSIONS: PackageInfo[] = [
|
|
22
22
|
{
|
|
23
23
|
"name": "@djangocfg/ui",
|
|
24
|
-
"version": "1.2.
|
|
24
|
+
"version": "1.2.21"
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
"name": "@djangocfg/api",
|
|
28
|
-
"version": "1.2.
|
|
28
|
+
"version": "1.2.21"
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"name": "@djangocfg/layouts",
|
|
32
|
-
"version": "1.2.
|
|
32
|
+
"version": "1.2.21"
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"name": "@djangocfg/markdown",
|
|
36
|
-
"version": "1.2.
|
|
36
|
+
"version": "1.2.21"
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
"name": "@djangocfg/og-image",
|
|
40
|
-
"version": "1.2.
|
|
40
|
+
"version": "1.2.21"
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
"name": "@djangocfg/eslint-config",
|
|
44
|
-
"version": "1.2.
|
|
44
|
+
"version": "1.2.21"
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
"name": "@djangocfg/typescript-config",
|
|
48
|
-
"version": "1.2.
|
|
48
|
+
"version": "1.2.21"
|
|
49
49
|
}
|
|
50
50
|
];
|
|
51
51
|
|
|
@@ -82,27 +82,68 @@ export function AdminLayout({
|
|
|
82
82
|
config,
|
|
83
83
|
enableParentSync = true
|
|
84
84
|
}: AdminLayoutProps) {
|
|
85
|
-
const
|
|
85
|
+
const [isMounted, setIsMounted] = React.useState(false);
|
|
86
|
+
const { user, isLoading, loadCurrentProfile } = useAuth();
|
|
87
|
+
// console.log('[AdminLayout] Rendering with user:', user, 'isLoading:', isLoading);
|
|
88
|
+
|
|
89
|
+
// Track mount state to prevent hydration mismatch
|
|
90
|
+
React.useEffect(() => {
|
|
91
|
+
setIsMounted(true);
|
|
92
|
+
}, []);
|
|
86
93
|
|
|
87
94
|
// useCfgApp hook is called here to initialize iframe communication
|
|
88
95
|
// Automatically sets tokens in API client when received from parent
|
|
89
96
|
const { isEmbedded } = useCfgApp({
|
|
90
|
-
onAuthTokenReceived: (authToken, refreshToken) => {
|
|
97
|
+
onAuthTokenReceived: async (authToken, refreshToken) => {
|
|
98
|
+
// console.log('[AdminLayout] onAuthTokenReceived called');
|
|
99
|
+
// console.log('[AdminLayout] authToken:', authToken.substring(0, 20) + '...', 'refreshToken:', refreshToken ? refreshToken.substring(0, 20) + '...' : 'null');
|
|
100
|
+
|
|
91
101
|
// Always set tokens in API client
|
|
92
102
|
api.setToken(authToken, refreshToken);
|
|
103
|
+
// console.log('[AdminLayout] Tokens set in API client');
|
|
104
|
+
|
|
105
|
+
// Load user profile after setting tokens
|
|
106
|
+
// console.log('[AdminLayout] Loading user profile...');
|
|
107
|
+
await loadCurrentProfile();
|
|
108
|
+
// console.log('[AdminLayout] User profile loaded');
|
|
93
109
|
|
|
94
110
|
// Call custom handler if provided
|
|
95
111
|
if (config?.onAuthTokenReceived) {
|
|
112
|
+
// console.log('[AdminLayout] Calling custom onAuthTokenReceived handler');
|
|
96
113
|
config.onAuthTokenReceived(authToken, refreshToken);
|
|
97
114
|
}
|
|
98
115
|
}
|
|
99
116
|
});
|
|
100
117
|
|
|
118
|
+
// console.log('[AdminLayout] isEmbedded:', isEmbedded);
|
|
119
|
+
|
|
120
|
+
// During SSR and initial render, show loading to prevent hydration mismatch
|
|
121
|
+
if (!isMounted) {
|
|
122
|
+
return (
|
|
123
|
+
<div className="min-h-screen flex items-center justify-center bg-background">
|
|
124
|
+
<div className="text-muted-foreground">Loading admin panel...</div>
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Show loading while auth is initializing (waiting for tokens from parent or profile loading)
|
|
130
|
+
if (isLoading) {
|
|
131
|
+
// console.log('[AdminLayout] Showing loading state - isLoading:', isLoading);
|
|
132
|
+
return (
|
|
133
|
+
<div className="min-h-screen flex items-center justify-center bg-background">
|
|
134
|
+
<div className="text-muted-foreground">Loading admin panel...</div>
|
|
135
|
+
</div>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
101
139
|
// Check if user has staff or superuser privileges
|
|
102
140
|
const hasAdminAccess = user?.is_staff || user?.is_superuser;
|
|
141
|
+
// console.log('[AdminLayout] user:', user, 'hasAdminAccess:', hasAdminAccess, 'is_staff:', user?.is_staff, 'is_superuser:', user?.is_superuser);
|
|
103
142
|
|
|
104
143
|
// Only render AdminLayout features for staff/superuser
|
|
105
144
|
if (!hasAdminAccess) {
|
|
145
|
+
console.warn('[AdminLayout] Access denied - user does not have admin access');
|
|
146
|
+
// console.log('[AdminLayout] User details:', JSON.stringify(user, null, 2));
|
|
106
147
|
return (
|
|
107
148
|
<div className="min-h-screen flex items-center justify-center bg-background">
|
|
108
149
|
<div className="text-center space-y-4 p-8">
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
'use client';
|
|
10
10
|
|
|
11
11
|
import { useEffect, useState } from 'react';
|
|
12
|
+
import { useRouter } from 'next/router';
|
|
12
13
|
import { useAuth } from '../../../../../auth';
|
|
13
14
|
import { useThemeContext } from '@djangocfg/ui';
|
|
14
15
|
import { useCfgApp } from '../hooks/useApp';
|
|
@@ -47,15 +48,20 @@ export function ParentSync() {
|
|
|
47
48
|
* Separated to avoid SSR issues during static export
|
|
48
49
|
*/
|
|
49
50
|
function ParentSyncClient() {
|
|
51
|
+
const router = useRouter();
|
|
50
52
|
const auth = useAuth();
|
|
51
53
|
const { setTheme } = useThemeContext();
|
|
52
54
|
const { isEmbedded, isMounted, parentTheme } = useCfgApp();
|
|
53
55
|
|
|
54
56
|
// 1. Sync theme from parent → iframe
|
|
55
57
|
useEffect(() => {
|
|
58
|
+
// console.log('[ParentSync] Theme sync effect triggered - isEmbedded:', isEmbedded, 'parentTheme:', parentTheme);
|
|
56
59
|
if (isEmbedded && parentTheme) {
|
|
57
|
-
// console.log('[ParentSync]
|
|
60
|
+
// console.log('[ParentSync] Syncing theme from parent:', parentTheme);
|
|
58
61
|
setTheme(parentTheme);
|
|
62
|
+
// console.log('[ParentSync] setTheme called with:', parentTheme);
|
|
63
|
+
} else {
|
|
64
|
+
// console.log('[ParentSync] Skipping theme sync - isEmbedded:', isEmbedded, 'parentTheme:', parentTheme);
|
|
59
65
|
}
|
|
60
66
|
}, [isEmbedded, parentTheme, setTheme]);
|
|
61
67
|
|
|
@@ -89,94 +95,37 @@ function ParentSyncClient() {
|
|
|
89
95
|
}
|
|
90
96
|
}, [auth.isAuthenticated, auth.isLoading, auth.user, isEmbedded, isMounted]);
|
|
91
97
|
|
|
92
|
-
// 3.
|
|
98
|
+
// 3. iframe-resize removed - was causing log spam
|
|
99
|
+
|
|
100
|
+
// 4. Send navigation events to parent (for "Open in New Window" button)
|
|
93
101
|
useEffect(() => {
|
|
94
102
|
// Only send if embedded and mounted
|
|
95
103
|
if (!isEmbedded || !isMounted) {
|
|
96
104
|
return;
|
|
97
105
|
}
|
|
98
106
|
|
|
99
|
-
|
|
100
|
-
const sendHeight = () => {
|
|
101
|
-
const height = document.documentElement.scrollHeight;
|
|
102
|
-
// console.log('[ParentSync] 📏 Sending height to parent:', height);
|
|
103
|
-
|
|
107
|
+
const handleRouteChange = (url: string) => {
|
|
104
108
|
try {
|
|
105
109
|
window.parent.postMessage({
|
|
106
|
-
type: 'iframe-
|
|
107
|
-
data: {
|
|
110
|
+
type: 'iframe-navigation',
|
|
111
|
+
data: { path: url }
|
|
108
112
|
}, '*');
|
|
109
113
|
} catch (e) {
|
|
110
|
-
console.error('[ParentSync]
|
|
114
|
+
console.error('[ParentSync] Failed to send navigation event:', e);
|
|
111
115
|
}
|
|
112
116
|
};
|
|
113
117
|
|
|
114
|
-
//
|
|
115
|
-
|
|
118
|
+
// Listen to Next.js router events
|
|
119
|
+
router.events.on('routeChangeComplete', handleRouteChange);
|
|
116
120
|
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
sendHeight();
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
// Observe body element for size changes
|
|
123
|
-
resizeObserver.observe(document.body);
|
|
121
|
+
// Send initial route
|
|
122
|
+
handleRouteChange(router.asPath);
|
|
124
123
|
|
|
125
124
|
// Cleanup
|
|
126
125
|
return () => {
|
|
127
|
-
|
|
126
|
+
router.events.off('routeChangeComplete', handleRouteChange);
|
|
128
127
|
};
|
|
129
|
-
}, [isEmbedded, isMounted]);
|
|
130
|
-
|
|
131
|
-
// 4. Send navigation events to parent (for "Open in New Window" button)
|
|
132
|
-
useEffect(() => {
|
|
133
|
-
// Only send if embedded and mounted
|
|
134
|
-
if (!isEmbedded || !isMounted) {
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Import Next.js router dynamically
|
|
139
|
-
import('next/router').then(({ default: Router }) => {
|
|
140
|
-
const handleRouteChange = (url: string) => {
|
|
141
|
-
// console.log('[ParentSync] 🔗 Route changed:', url);
|
|
142
|
-
|
|
143
|
-
try {
|
|
144
|
-
window.parent.postMessage({
|
|
145
|
-
type: 'iframe-navigation',
|
|
146
|
-
data: { path: url }
|
|
147
|
-
}, '*');
|
|
148
|
-
} catch (e) {
|
|
149
|
-
console.error('[ParentSync] ❌ Failed to send navigation event:', e);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Also send height update after route change
|
|
153
|
-
setTimeout(() => {
|
|
154
|
-
const height = document.documentElement.scrollHeight;
|
|
155
|
-
try {
|
|
156
|
-
window.parent.postMessage({
|
|
157
|
-
type: 'iframe-resize',
|
|
158
|
-
data: { height }
|
|
159
|
-
}, '*');
|
|
160
|
-
} catch (e) {
|
|
161
|
-
console.error('[ParentSync] ❌ Failed to send height:', e);
|
|
162
|
-
}
|
|
163
|
-
}, 100);
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
// Listen to Next.js router events
|
|
167
|
-
Router.events.on('routeChangeComplete', handleRouteChange);
|
|
168
|
-
|
|
169
|
-
// Send initial route
|
|
170
|
-
handleRouteChange(Router.asPath);
|
|
171
|
-
|
|
172
|
-
// Cleanup
|
|
173
|
-
return () => {
|
|
174
|
-
Router.events.off('routeChangeComplete', handleRouteChange);
|
|
175
|
-
};
|
|
176
|
-
}).catch(err => {
|
|
177
|
-
console.warn('[ParentSync] Failed to load next/router:', err);
|
|
178
|
-
});
|
|
179
|
-
}, [isEmbedded, isMounted]);
|
|
128
|
+
}, [isEmbedded, isMounted, router]);
|
|
180
129
|
|
|
181
130
|
// This component doesn't render anything
|
|
182
131
|
return null;
|
|
@@ -94,13 +94,10 @@ export function useCfgApp(options?: UseCfgAppOptions): UseCfgAppReturn {
|
|
|
94
94
|
const [parentThemeMode, setParentThemeMode] = useState<string | null>(null);
|
|
95
95
|
|
|
96
96
|
useEffect(() => {
|
|
97
|
-
// Debug logging (uncomment for debugging)
|
|
98
|
-
// console.log('[useCfgApp] Hook initializing...');
|
|
99
97
|
setIsMounted(true);
|
|
100
98
|
|
|
101
99
|
// Check if running in iframe
|
|
102
100
|
const inIframe = window.self !== window.top;
|
|
103
|
-
// console.log('[useCfgApp] Iframe detection:', { inIframe });
|
|
104
101
|
setIsEmbedded(inIframe);
|
|
105
102
|
|
|
106
103
|
// Check if running as standalone PWA
|
|
@@ -109,138 +106,84 @@ export function useCfgApp(options?: UseCfgAppOptions): UseCfgAppReturn {
|
|
|
109
106
|
|
|
110
107
|
// Get referrer if embedded
|
|
111
108
|
if (inIframe && document.referrer) {
|
|
112
|
-
// console.log('[useCfgApp] Referrer:', document.referrer);
|
|
113
109
|
setReferrer(document.referrer);
|
|
114
110
|
}
|
|
115
111
|
|
|
116
|
-
// Setup resize observer and interval for iframe height updates
|
|
117
|
-
let resizeObserver: ResizeObserver | null = null;
|
|
118
|
-
let checkHeightInterval: NodeJS.Timeout | null = null;
|
|
119
|
-
|
|
120
|
-
// Notify parent window that iframe is ready
|
|
121
|
-
if (inIframe) {
|
|
122
|
-
try {
|
|
123
|
-
// console.log('[useCfgApp] Sending iframe-ready message to parent');
|
|
124
|
-
window.parent.postMessage({
|
|
125
|
-
type: 'iframe-ready',
|
|
126
|
-
data: {
|
|
127
|
-
url: window.location.href,
|
|
128
|
-
referrer: document.referrer
|
|
129
|
-
}
|
|
130
|
-
}, '*'); // Use '*' or specific origin for security
|
|
131
|
-
// console.log('[useCfgApp] iframe-ready message sent');
|
|
132
|
-
} catch (e) {
|
|
133
|
-
console.error('[useCfgApp] Failed to notify parent:', e);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Send current content height (both increases and decreases)
|
|
137
|
-
const sendHeight = () => {
|
|
138
|
-
try {
|
|
139
|
-
// Use body.scrollHeight to avoid iframe height feedback loop
|
|
140
|
-
// document.documentElement.scrollHeight includes iframe's own height!
|
|
141
|
-
const bodyScrollHeight = document.body.scrollHeight;
|
|
142
|
-
const bodyOffsetHeight = document.body.offsetHeight;
|
|
143
|
-
const height = Math.max(bodyScrollHeight, bodyOffsetHeight);
|
|
144
|
-
|
|
145
|
-
window.parent.postMessage({
|
|
146
|
-
type: 'iframe-resize',
|
|
147
|
-
data: { height }
|
|
148
|
-
}, '*');
|
|
149
|
-
} catch (e) {
|
|
150
|
-
console.error('[useCfgApp] Failed to send height:', e);
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
// Send height immediately after mount
|
|
155
|
-
setTimeout(sendHeight, 100);
|
|
156
|
-
|
|
157
|
-
// Watch for content size changes using ResizeObserver
|
|
158
|
-
resizeObserver = new ResizeObserver(() => {
|
|
159
|
-
sendHeight();
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
// Observe document body for size changes
|
|
163
|
-
resizeObserver.observe(document.body);
|
|
164
|
-
|
|
165
|
-
// Also observe on route changes and after data loads
|
|
166
|
-
checkHeightInterval = setInterval(sendHeight, 1000);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
112
|
// Listen for messages from parent window
|
|
170
113
|
const handleMessage = (event: MessageEvent) => {
|
|
171
|
-
// console.log('[useCfgApp]
|
|
114
|
+
// console.log('[useCfgApp] RAW message event:', {
|
|
172
115
|
// origin: event.origin,
|
|
173
|
-
//
|
|
174
|
-
//
|
|
116
|
+
// source: event.source === window.parent ? 'parent' : 'other',
|
|
117
|
+
// dataType: typeof event.data,
|
|
118
|
+
// data: event.data
|
|
175
119
|
// });
|
|
176
120
|
|
|
177
|
-
// Verify origin for security (optional - adjust for your needs)
|
|
178
|
-
// if (event.origin !== window.location.origin) return;
|
|
179
|
-
|
|
180
121
|
const { type, data } = event.data || {};
|
|
122
|
+
// console.log('[useCfgApp] Received message:', type, data);
|
|
181
123
|
|
|
182
124
|
switch (type) {
|
|
183
125
|
case 'parent-auth':
|
|
184
|
-
// console.log('[useCfgApp]
|
|
126
|
+
// console.log('[useCfgApp] parent-auth message received');
|
|
185
127
|
// Receive authentication tokens from parent
|
|
186
128
|
if (data?.authToken && options?.onAuthTokenReceived) {
|
|
129
|
+
// console.log('[useCfgApp] Auth tokens found, calling onAuthTokenReceived callback');
|
|
130
|
+
// console.log('[useCfgApp] authToken:', data.authToken.substring(0, 20) + '...', 'refreshToken:', data.refreshToken ? data.refreshToken.substring(0, 20) + '...' : 'null');
|
|
187
131
|
try {
|
|
188
|
-
// console.log('[useCfgApp] Calling onAuthTokenReceived');
|
|
189
132
|
options.onAuthTokenReceived(data.authToken, data.refreshToken);
|
|
190
|
-
// console.log('[useCfgApp]
|
|
133
|
+
// console.log('[useCfgApp] onAuthTokenReceived callback completed successfully');
|
|
191
134
|
} catch (e) {
|
|
192
135
|
console.error('[useCfgApp] Failed to process auth tokens:', e);
|
|
193
136
|
}
|
|
137
|
+
} else {
|
|
138
|
+
console.warn('[useCfgApp] parent-auth message received but authToken or callback missing:', { hasToken: !!data?.authToken, hasCallback: !!options?.onAuthTokenReceived });
|
|
194
139
|
}
|
|
195
140
|
break;
|
|
196
141
|
|
|
197
142
|
case 'parent-theme':
|
|
198
|
-
// console.log('[useCfgApp]
|
|
143
|
+
// console.log('[useCfgApp] parent-theme message received:', data?.theme);
|
|
199
144
|
// Receive theme from parent
|
|
200
145
|
if (data?.theme) {
|
|
201
146
|
try {
|
|
202
|
-
// console.log('[useCfgApp] Setting theme:', {
|
|
203
|
-
// theme: data.theme,
|
|
204
|
-
// themeMode: data.themeMode
|
|
205
|
-
// });
|
|
206
147
|
setParentTheme(data.theme);
|
|
207
148
|
if (data.themeMode) {
|
|
208
149
|
setParentThemeMode(data.themeMode);
|
|
209
150
|
}
|
|
210
|
-
// console.log('[useCfgApp] Theme
|
|
151
|
+
// console.log('[useCfgApp] Theme set successfully:', data.theme);
|
|
211
152
|
} catch (e) {
|
|
212
153
|
console.error('[useCfgApp] Failed to process theme:', e);
|
|
213
154
|
}
|
|
214
155
|
}
|
|
215
156
|
break;
|
|
216
157
|
|
|
217
|
-
case 'parent-resize':
|
|
218
|
-
// Handle parent window resize (optional)
|
|
219
|
-
// console.log('[useCfgApp] Parent resized:', data);
|
|
220
|
-
break;
|
|
221
|
-
|
|
222
158
|
default:
|
|
223
|
-
// if (type) {
|
|
224
|
-
// console.log('[useCfgApp] Unknown message type:', type);
|
|
225
|
-
// }
|
|
226
159
|
break;
|
|
227
160
|
}
|
|
228
161
|
};
|
|
229
162
|
|
|
230
|
-
// console.log('[useCfgApp] Adding message event listener');
|
|
231
163
|
window.addEventListener('message', handleMessage);
|
|
164
|
+
// console.log('[useCfgApp] Message listener registered, isEmbedded:', inIframe);
|
|
165
|
+
|
|
166
|
+
// Send iframe-ready since listener is registered
|
|
167
|
+
if (inIframe) {
|
|
168
|
+
try {
|
|
169
|
+
// console.log('[useCfgApp] Sending iframe-ready message to parent');
|
|
170
|
+
window.parent.postMessage({
|
|
171
|
+
type: 'iframe-ready',
|
|
172
|
+
data: {
|
|
173
|
+
url: window.location.href,
|
|
174
|
+
referrer: document.referrer
|
|
175
|
+
}
|
|
176
|
+
}, '*');
|
|
177
|
+
// console.log('[useCfgApp] iframe-ready message sent');
|
|
178
|
+
} catch (e) {
|
|
179
|
+
console.error('[useCfgApp] Failed to notify parent about ready state:', e);
|
|
180
|
+
}
|
|
181
|
+
} else {
|
|
182
|
+
// console.log('[useCfgApp] Not in iframe, skipping iframe-ready message');
|
|
183
|
+
}
|
|
232
184
|
|
|
233
185
|
return () => {
|
|
234
|
-
// console.log('[useCfgApp] Cleaning up message event listener');
|
|
235
186
|
window.removeEventListener('message', handleMessage);
|
|
236
|
-
|
|
237
|
-
// Cleanup resize observer and interval
|
|
238
|
-
if (resizeObserver) {
|
|
239
|
-
resizeObserver.disconnect();
|
|
240
|
-
}
|
|
241
|
-
if (checkHeightInterval) {
|
|
242
|
-
clearInterval(checkHeightInterval);
|
|
243
|
-
}
|
|
244
187
|
};
|
|
245
188
|
}, [options]);
|
|
246
189
|
|
|
@@ -47,7 +47,7 @@ export function DashboardHeader({ isAdmin = false }: DashboardHeaderProps) {
|
|
|
47
47
|
|
|
48
48
|
// Notification handler - TODO: implement notification system
|
|
49
49
|
const handleNotificationClick = () => {
|
|
50
|
-
console.log('Notifications clicked');
|
|
50
|
+
// console.log('Notifications clicked');
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
return (
|