@djangocfg/layouts 2.1.37 → 2.1.39
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/README.md +204 -18
- package/package.json +5 -5
- package/src/components/errors/index.ts +9 -0
- package/src/components/errors/types.ts +38 -0
- package/src/layouts/AppLayout/AppLayout.tsx +33 -45
- package/src/layouts/AppLayout/BaseApp.tsx +104 -33
- package/src/layouts/AuthLayout/AuthContext.tsx +7 -1
- package/src/layouts/AuthLayout/OAuthProviders.tsx +1 -10
- package/src/layouts/AuthLayout/OTPForm.tsx +1 -0
- package/src/layouts/PrivateLayout/PrivateLayout.tsx +1 -1
- package/src/layouts/PublicLayout/PublicLayout.tsx +1 -1
- package/src/layouts/PublicLayout/components/PublicMobileDrawer.tsx +1 -1
- package/src/layouts/PublicLayout/components/PublicNavigation.tsx +1 -1
- package/src/layouts/_components/UserMenu.tsx +1 -1
- package/src/layouts/index.ts +1 -1
- package/src/layouts/types/index.ts +47 -0
- package/src/layouts/types/layout.types.ts +61 -0
- package/src/layouts/types/providers.types.ts +65 -0
- package/src/layouts/types/ui.types.ts +103 -0
- package/src/snippets/Analytics/index.ts +1 -0
- package/src/snippets/Analytics/types.ts +10 -0
- package/src/snippets/PWAInstall/@docs/README.md +92 -0
- package/src/snippets/PWAInstall/README.md +185 -0
- package/src/snippets/{PWA → PWAInstall}/components/A2HSHint.tsx +85 -84
- package/src/snippets/PWAInstall/components/DesktopGuide.tsx +229 -0
- package/src/snippets/PWAInstall/context/InstallContext.tsx +102 -0
- package/src/snippets/{PWA → PWAInstall}/hooks/useInstallPrompt.ts +3 -0
- package/src/snippets/{PWA → PWAInstall}/index.ts +12 -31
- package/src/snippets/{PWA → PWAInstall}/types/components.ts +0 -6
- package/src/snippets/PWAInstall/types/config.ts +22 -0
- package/src/snippets/{PWA → PWAInstall}/types/index.ts +4 -4
- package/src/snippets/{PWA → PWAInstall}/utils/localStorage.ts +1 -23
- package/src/snippets/PushNotifications/@docs/README.md +191 -0
- package/src/snippets/PushNotifications/@docs/guides/django-integration.md +648 -0
- package/src/snippets/PushNotifications/@docs/guides/service-worker.md +467 -0
- package/src/snippets/PushNotifications/@docs/guides/vapid-setup.md +352 -0
- package/src/snippets/PushNotifications/README.md +328 -0
- package/src/snippets/{PWA → PushNotifications}/config.ts +2 -2
- package/src/snippets/PushNotifications/context/DjangoPushContext.tsx +190 -0
- package/src/snippets/{PWA → PushNotifications}/hooks/useDjangoPush.ts +63 -81
- package/src/snippets/{PWA → PushNotifications}/hooks/usePushNotifications.ts +12 -8
- package/src/snippets/PushNotifications/index.ts +87 -0
- package/src/snippets/PushNotifications/types/config.ts +28 -0
- package/src/snippets/PushNotifications/types/index.ts +9 -0
- package/src/snippets/PushNotifications/utils/localStorage.ts +60 -0
- package/src/snippets/PushNotifications/utils/logger.ts +149 -0
- package/src/snippets/PushNotifications/utils/platform.ts +151 -0
- package/src/snippets/index.ts +37 -12
- package/src/layouts/shared/index.ts +0 -21
- package/src/layouts/shared/types.ts +0 -247
- package/src/snippets/PWA/@refactoring/ARCHITECTURE_ANALYSIS.md +0 -1179
- package/src/snippets/PWA/@refactoring/EXECUTIVE_SUMMARY.md +0 -271
- package/src/snippets/PWA/@refactoring/README.md +0 -204
- package/src/snippets/PWA/@refactoring/REFACTORING_PROPOSALS.md +0 -1109
- package/src/snippets/PWA/@refactoring2/COMPARISON-WITH-NEXTJS.md +0 -718
- package/src/snippets/PWA/@refactoring2/P1-FIXES-COMPLETED.md +0 -188
- package/src/snippets/PWA/@refactoring2/POST-P0-ANALYSIS.md +0 -362
- package/src/snippets/PWA/@refactoring2/README.md +0 -85
- package/src/snippets/PWA/@refactoring2/RECOMMENDATIONS.md +0 -1321
- package/src/snippets/PWA/@refactoring2/REMAINING-ISSUES.md +0 -557
- package/src/snippets/PWA/README.md +0 -387
- package/src/snippets/PWA/context/DjangoPushContext.tsx +0 -105
- package/src/snippets/PWA/context/InstallContext.tsx +0 -118
- package/src/snippets/PWA/context/PushContext.tsx +0 -156
- /package/src/layouts/{shared → types}/README.md +0 -0
- /package/src/snippets/{PWA/@docs/research.md → PWAInstall/@docs/research/ios-android-install-flows.md} +0 -0
- /package/src/snippets/{PWA → PWAInstall}/components/IOSGuide.tsx +0 -0
- /package/src/snippets/{PWA → PWAInstall}/components/IOSGuideDrawer.tsx +0 -0
- /package/src/snippets/{PWA → PWAInstall}/components/IOSGuideModal.tsx +0 -0
- /package/src/snippets/{PWA → PWAInstall}/hooks/useIsPWA.ts +0 -0
- /package/src/snippets/{PWA → PWAInstall}/types/install.ts +0 -0
- /package/src/snippets/{PWA → PWAInstall}/types/platform.ts +0 -0
- /package/src/snippets/{PWA → PWAInstall}/utils/logger.ts +0 -0
- /package/src/snippets/{PWA → PWAInstall}/utils/platform.ts +0 -0
- /package/src/snippets/{PWA → PushNotifications}/components/PushPrompt.tsx +0 -0
- /package/src/snippets/{PWA → PushNotifications}/types/push.ts +0 -0
- /package/src/snippets/{PWA → PushNotifications}/utils/vapid.ts +0 -0
package/README.md
CHANGED
|
@@ -24,7 +24,17 @@ export default function RootLayout({ children }) {
|
|
|
24
24
|
return (
|
|
25
25
|
<html lang="en" suppressHydrationWarning>
|
|
26
26
|
<body>
|
|
27
|
-
<BaseApp
|
|
27
|
+
<BaseApp
|
|
28
|
+
theme={{ defaultTheme: 'dark' }}
|
|
29
|
+
analytics={{ googleTrackingId: 'G-XXXXXXXXXX' }}
|
|
30
|
+
centrifugo={{ enabled: true, url: process.env.NEXT_PUBLIC_CENTRIFUGO_URL }}
|
|
31
|
+
pwaInstall={{ enabled: true, showInstallHint: true }}
|
|
32
|
+
pushNotifications={{
|
|
33
|
+
enabled: true,
|
|
34
|
+
vapidPublicKey: process.env.NEXT_PUBLIC_VAPID_KEY || ''
|
|
35
|
+
}}
|
|
36
|
+
mcpChat={{ enabled: true, autoDetectEnvironment: true }}
|
|
37
|
+
>
|
|
28
38
|
{children}
|
|
29
39
|
</BaseApp>
|
|
30
40
|
</body>
|
|
@@ -34,12 +44,23 @@ export default function RootLayout({ children }) {
|
|
|
34
44
|
```
|
|
35
45
|
|
|
36
46
|
**Included providers:**
|
|
37
|
-
- ThemeProvider
|
|
38
|
-
- TooltipProvider
|
|
39
|
-
- SWRConfig
|
|
40
|
-
- AuthProvider (from `@djangocfg/api`)
|
|
41
|
-
-
|
|
42
|
-
-
|
|
47
|
+
- **ThemeProvider** - Light/dark/system theme management
|
|
48
|
+
- **TooltipProvider** - Tooltip positioning context
|
|
49
|
+
- **SWRConfig** - Data fetching configuration
|
|
50
|
+
- **AuthProvider** - Authentication context (from `@djangocfg/api`)
|
|
51
|
+
- **AnalyticsProvider** - Google Analytics (optional)
|
|
52
|
+
- **CentrifugoProvider** - WebSocket real-time (optional)
|
|
53
|
+
- **PwaProvider** - PWA installation (optional)
|
|
54
|
+
- **DjangoPushProvider** - Django web push integration with history (optional)
|
|
55
|
+
- **ErrorTrackingProvider** - Error handling and tracking
|
|
56
|
+
- **ErrorBoundary** - React error boundary
|
|
57
|
+
- **MCP Chat Widget** - AI chat assistant (optional)
|
|
58
|
+
|
|
59
|
+
**Global components:**
|
|
60
|
+
- **PageProgress** - NProgress bar for route changes
|
|
61
|
+
- **Toaster** - Toast notifications container
|
|
62
|
+
- **A2HSHint** - PWA install hint (if enabled)
|
|
63
|
+
- **PushPrompt** - Push notification prompt (if enabled)
|
|
43
64
|
|
|
44
65
|
> **Note:** Auth functionality is provided by `@djangocfg/api` package. See [@djangocfg/api documentation](../api/README.md) for auth usage.
|
|
45
66
|
|
|
@@ -51,6 +72,7 @@ Smart layout router built on BaseApp - automatically selects layout based on rou
|
|
|
51
72
|
import { AppLayout } from '@djangocfg/layouts';
|
|
52
73
|
import { PublicLayout } from './_layouts/PublicLayout';
|
|
53
74
|
import { PrivateLayout } from './_layouts/PrivateLayout';
|
|
75
|
+
import { AdminLayout } from './_layouts/AdminLayout';
|
|
54
76
|
|
|
55
77
|
// app/layout.tsx
|
|
56
78
|
export default function RootLayout({ children }) {
|
|
@@ -58,6 +80,16 @@ export default function RootLayout({ children }) {
|
|
|
58
80
|
<html lang="en" suppressHydrationWarning>
|
|
59
81
|
<body>
|
|
60
82
|
<AppLayout
|
|
83
|
+
// Provider configs (passed to BaseApp)
|
|
84
|
+
theme={{ defaultTheme: 'system' }}
|
|
85
|
+
analytics={{ googleTrackingId: 'G-XXXXXXXXXX' }}
|
|
86
|
+
pwaInstall={{ enabled: true }}
|
|
87
|
+
pushNotifications={{
|
|
88
|
+
enabled: true,
|
|
89
|
+
vapidPublicKey: process.env.NEXT_PUBLIC_VAPID_KEY || ''
|
|
90
|
+
}}
|
|
91
|
+
|
|
92
|
+
// Layout components
|
|
61
93
|
publicLayout={{
|
|
62
94
|
component: PublicLayout,
|
|
63
95
|
enabledPath: ['/', '/legal', '/contact']
|
|
@@ -66,7 +98,10 @@ export default function RootLayout({ children }) {
|
|
|
66
98
|
component: PrivateLayout,
|
|
67
99
|
enabledPath: ['/dashboard', '/profile']
|
|
68
100
|
}}
|
|
69
|
-
|
|
101
|
+
adminLayout={{
|
|
102
|
+
component: AdminLayout,
|
|
103
|
+
enabledPath: '/admin'
|
|
104
|
+
}}
|
|
70
105
|
>
|
|
71
106
|
{children}
|
|
72
107
|
</AppLayout>
|
|
@@ -185,14 +220,131 @@ Built-in tracking for:
|
|
|
185
220
|
- **OAuth events** - GitHub OAuth start, success, failure
|
|
186
221
|
- **Errors** - React ErrorBoundary errors
|
|
187
222
|
|
|
223
|
+
## PWA & Push Notifications
|
|
224
|
+
|
|
225
|
+
Progressive Web App features and Web Push notifications support.
|
|
226
|
+
|
|
227
|
+
### PWA Installation
|
|
228
|
+
|
|
229
|
+
Enable PWA installation prompts with `pwaInstall` config:
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
import { BaseApp } from '@djangocfg/layouts';
|
|
233
|
+
|
|
234
|
+
<BaseApp
|
|
235
|
+
pwaInstall={{
|
|
236
|
+
enabled: true,
|
|
237
|
+
showInstallHint: true, // Show A2HS hint
|
|
238
|
+
resetAfterDays: 3, // Re-show after dismissal
|
|
239
|
+
delayMs: 1000, // Delay before showing
|
|
240
|
+
logo: '/logo192.png', // PWA logo
|
|
241
|
+
}}
|
|
242
|
+
>
|
|
243
|
+
{children}
|
|
244
|
+
</BaseApp>
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Features:**
|
|
248
|
+
- **A2HSHint** - Platform-specific install hints (iOS Safari, Android Chrome, Desktop)
|
|
249
|
+
- **Auto-detection** - Detects if running as PWA
|
|
250
|
+
- **Dismissal tracking** - Respects user dismissal with localStorage
|
|
251
|
+
- **Custom timing** - Configurable delay and reset periods
|
|
252
|
+
|
|
253
|
+
### Push Notifications
|
|
254
|
+
|
|
255
|
+
Enable Web Push notifications with `pushNotifications` config:
|
|
256
|
+
|
|
257
|
+
```tsx
|
|
258
|
+
import { BaseApp } from '@djangocfg/layouts';
|
|
259
|
+
|
|
260
|
+
<BaseApp
|
|
261
|
+
pushNotifications={{
|
|
262
|
+
enabled: true,
|
|
263
|
+
vapidPublicKey: process.env.NEXT_PUBLIC_VAPID_KEY || '',
|
|
264
|
+
subscribeEndpoint: '/api/push/subscribe', // Backend subscription endpoint
|
|
265
|
+
requirePWA: true, // Only show if installed as PWA
|
|
266
|
+
autoSubscribe: false, // Auto-subscribe on install
|
|
267
|
+
delayMs: 5000, // Delay before showing prompt
|
|
268
|
+
resetAfterDays: 7, // Re-show after dismissal
|
|
269
|
+
}}
|
|
270
|
+
>
|
|
271
|
+
{children}
|
|
272
|
+
</BaseApp>
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**Features:**
|
|
276
|
+
- **PushPrompt** - Permission request prompt
|
|
277
|
+
- **VAPID authentication** - Secure push with VAPID keys
|
|
278
|
+
- **Subscription management** - Auto-subscribe and unsubscribe
|
|
279
|
+
- **PWA integration** - Can require PWA installation first
|
|
280
|
+
- **Custom timing** - Configurable delay and reset
|
|
281
|
+
|
|
282
|
+
### Usage
|
|
283
|
+
|
|
284
|
+
```tsx
|
|
285
|
+
import { usePwa, useDjangoPushContext } from '@djangocfg/layouts/snippets';
|
|
286
|
+
|
|
287
|
+
// PWA status
|
|
288
|
+
const { isPWA, isInstallable } = usePwa();
|
|
289
|
+
|
|
290
|
+
// Push notifications (Django integration)
|
|
291
|
+
const {
|
|
292
|
+
isSupported,
|
|
293
|
+
isSubscribed,
|
|
294
|
+
permission,
|
|
295
|
+
pushes,
|
|
296
|
+
subscribe,
|
|
297
|
+
unsubscribe,
|
|
298
|
+
sendPush,
|
|
299
|
+
clearPushes,
|
|
300
|
+
removePush,
|
|
301
|
+
} = useDjangoPushContext();
|
|
302
|
+
|
|
303
|
+
// Subscribe to push
|
|
304
|
+
await subscribe();
|
|
305
|
+
|
|
306
|
+
// Send test notification (via Django API)
|
|
307
|
+
await sendPush({
|
|
308
|
+
title: 'Hello!',
|
|
309
|
+
body: 'Test notification',
|
|
310
|
+
icon: '/icon.png',
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// Manage push history
|
|
314
|
+
clearPushes(); // Clear all
|
|
315
|
+
removePush(pushId); // Remove specific push
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### VAPID Keys Generation
|
|
319
|
+
|
|
320
|
+
Generate VAPID keys for push notifications:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
# Using web-push CLI
|
|
324
|
+
npx web-push generate-vapid-keys
|
|
325
|
+
|
|
326
|
+
# Or use openssl
|
|
327
|
+
openssl ecparam -name prime256v1 -genkey -noout -out vapid_private.pem
|
|
328
|
+
openssl ec -in vapid_private.pem -pubout -out vapid_public.pem
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Add keys to `.env.local`:
|
|
332
|
+
|
|
333
|
+
```env
|
|
334
|
+
NEXT_PUBLIC_VAPID_PUBLIC_KEY=your_public_key_here
|
|
335
|
+
VAPID_PRIVATE_KEY=your_private_key_here
|
|
336
|
+
```
|
|
337
|
+
|
|
188
338
|
## Snippets
|
|
189
339
|
|
|
190
|
-
Reusable UI components ready to use.
|
|
340
|
+
Reusable UI components and hooks ready to use.
|
|
191
341
|
|
|
192
342
|
```tsx
|
|
193
343
|
import {
|
|
194
344
|
Breadcrumbs,
|
|
195
345
|
AuthDialog,
|
|
346
|
+
usePwa,
|
|
347
|
+
useDjangoPushContext,
|
|
196
348
|
} from '@djangocfg/layouts/snippets';
|
|
197
349
|
```
|
|
198
350
|
|
|
@@ -201,6 +353,11 @@ import {
|
|
|
201
353
|
| `Breadcrumbs` | Navigation breadcrumbs with automatic path generation |
|
|
202
354
|
| `AuthDialog` | Auth modal (login/register) with event-based triggers |
|
|
203
355
|
| `AnalyticsProvider` | Analytics wrapper component |
|
|
356
|
+
| `usePwa` | PWA status hook (isPWA, isInstallable, etc.) |
|
|
357
|
+
| `useDjangoPushContext` | Django push notifications hook (subscribe, send, history) |
|
|
358
|
+
| `usePush` | Generic push hook (for non-Django apps) |
|
|
359
|
+
| `A2HSHint` | Add to Home Screen hint component |
|
|
360
|
+
| `PushPrompt` | Push notification permission prompt |
|
|
204
361
|
|
|
205
362
|
> **Extension Snippets:** Additional components are available in extension packages:
|
|
206
363
|
> - `@djangocfg/ext-leads` - ContactForm, ContactPage, ContactInfo
|
|
@@ -516,27 +673,56 @@ export default function DashboardPage() {
|
|
|
516
673
|
}
|
|
517
674
|
```
|
|
518
675
|
|
|
519
|
-
### Auth Page
|
|
676
|
+
### Auth Page (OTP Authentication)
|
|
520
677
|
|
|
521
678
|
```tsx
|
|
522
|
-
// app/auth/
|
|
679
|
+
// app/auth/page.tsx
|
|
680
|
+
'use client';
|
|
681
|
+
|
|
523
682
|
import { AuthLayout } from '@djangocfg/layouts';
|
|
524
|
-
import { LoginForm } from './_components/LoginForm';
|
|
525
683
|
|
|
526
|
-
export default function
|
|
684
|
+
export default function AuthPage() {
|
|
527
685
|
return (
|
|
528
686
|
<AuthLayout
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
687
|
+
sourceUrl="https://example.com"
|
|
688
|
+
supportUrl="/support"
|
|
689
|
+
termsUrl="/terms"
|
|
690
|
+
privacyUrl="/privacy"
|
|
691
|
+
enablePhoneAuth={false}
|
|
692
|
+
enableGithubAuth={true}
|
|
693
|
+
redirectUrl="/dashboard"
|
|
694
|
+
onOTPSuccess={() => {
|
|
695
|
+
console.log('OTP authentication successful');
|
|
696
|
+
}}
|
|
697
|
+
onOAuthSuccess={(user, isNewUser, provider) => {
|
|
698
|
+
console.log('OAuth success:', { user, isNewUser, provider });
|
|
699
|
+
}}
|
|
533
700
|
>
|
|
534
|
-
<
|
|
701
|
+
<div className="text-center mb-6">
|
|
702
|
+
<h2 className="text-2xl font-bold">Welcome to My App</h2>
|
|
703
|
+
<p className="text-muted-foreground mt-2">
|
|
704
|
+
Sign in with your email or phone
|
|
705
|
+
</p>
|
|
706
|
+
</div>
|
|
535
707
|
</AuthLayout>
|
|
536
708
|
);
|
|
537
709
|
}
|
|
538
710
|
```
|
|
539
711
|
|
|
712
|
+
**AuthLayout Props:**
|
|
713
|
+
| Prop | Type | Description |
|
|
714
|
+
|------|------|-------------|
|
|
715
|
+
| `sourceUrl` | `string` | Application URL for OTP emails |
|
|
716
|
+
| `redirectUrl` | `string` | URL to redirect after successful auth (default: `/dashboard`) |
|
|
717
|
+
| `enablePhoneAuth` | `boolean` | Enable phone number authentication |
|
|
718
|
+
| `enableGithubAuth` | `boolean` | Enable GitHub OAuth |
|
|
719
|
+
| `termsUrl` | `string` | Terms of service URL (shows checkbox if provided) |
|
|
720
|
+
| `privacyUrl` | `string` | Privacy policy URL |
|
|
721
|
+
| `supportUrl` | `string` | Support page URL |
|
|
722
|
+
| `onOTPSuccess` | `() => void` | Callback after successful OTP verification |
|
|
723
|
+
| `onOAuthSuccess` | `(user, isNewUser, provider) => void` | Callback after successful OAuth |
|
|
724
|
+
| `onError` | `(message: string) => void` | Error callback |
|
|
725
|
+
|
|
540
726
|
## License
|
|
541
727
|
|
|
542
728
|
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/layouts",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.39",
|
|
4
4
|
"description": "Simple, straightforward layout components for Next.js - import and use with props",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"layouts",
|
|
@@ -92,9 +92,9 @@
|
|
|
92
92
|
"check": "tsc --noEmit"
|
|
93
93
|
},
|
|
94
94
|
"peerDependencies": {
|
|
95
|
-
"@djangocfg/api": "^2.1.
|
|
96
|
-
"@djangocfg/centrifugo": "^2.1.
|
|
97
|
-
"@djangocfg/ui-nextjs": "^2.1.
|
|
95
|
+
"@djangocfg/api": "^2.1.39",
|
|
96
|
+
"@djangocfg/centrifugo": "^2.1.39",
|
|
97
|
+
"@djangocfg/ui-nextjs": "^2.1.39",
|
|
98
98
|
"@hookform/resolvers": "^5.2.0",
|
|
99
99
|
"consola": "^3.4.2",
|
|
100
100
|
"lucide-react": "^0.545.0",
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
"uuid": "^11.1.0"
|
|
115
115
|
},
|
|
116
116
|
"devDependencies": {
|
|
117
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
117
|
+
"@djangocfg/typescript-config": "^2.1.39",
|
|
118
118
|
"@types/node": "^24.7.2",
|
|
119
119
|
"@types/react": "^19.1.0",
|
|
120
120
|
"@types/react-dom": "^19.1.0",
|
|
@@ -8,3 +8,12 @@ export type { ErrorLayoutProps } from './ErrorLayout';
|
|
|
8
8
|
export { getErrorContent, ERROR_CODES } from './errorConfig';
|
|
9
9
|
export type { ErrorContent } from './errorConfig';
|
|
10
10
|
|
|
11
|
+
// Configuration types
|
|
12
|
+
export type {
|
|
13
|
+
ErrorBoundaryConfig,
|
|
14
|
+
ErrorTrackingConfig,
|
|
15
|
+
ValidationErrorConfig,
|
|
16
|
+
CORSErrorConfig,
|
|
17
|
+
NetworkErrorConfig,
|
|
18
|
+
} from './types';
|
|
19
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Handling Configuration Types
|
|
3
|
+
*
|
|
4
|
+
* Configuration types for ErrorTrackingProvider and ErrorBoundary
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { ErrorInfo } from 'react';
|
|
8
|
+
|
|
9
|
+
// Re-export ErrorTrackingConfig from ErrorsTracker
|
|
10
|
+
export type {
|
|
11
|
+
ErrorTrackingConfig,
|
|
12
|
+
ValidationErrorConfig,
|
|
13
|
+
CORSErrorConfig,
|
|
14
|
+
NetworkErrorConfig,
|
|
15
|
+
ErrorTypeConfig,
|
|
16
|
+
ErrorDetail,
|
|
17
|
+
ValidationErrorDetail,
|
|
18
|
+
CORSErrorDetail,
|
|
19
|
+
NetworkErrorDetail,
|
|
20
|
+
StoredError,
|
|
21
|
+
ErrorTrackingContextValue,
|
|
22
|
+
} from './ErrorsTracker/types';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Error Boundary Configuration
|
|
26
|
+
*
|
|
27
|
+
* Configuration for React ErrorBoundary component
|
|
28
|
+
*/
|
|
29
|
+
export interface ErrorBoundaryConfig {
|
|
30
|
+
/** Enable error boundary (default: true) */
|
|
31
|
+
enabled?: boolean;
|
|
32
|
+
|
|
33
|
+
/** Support email to display in error UI */
|
|
34
|
+
supportEmail?: string;
|
|
35
|
+
|
|
36
|
+
/** Custom error handler called when error is caught */
|
|
37
|
+
onError?: (error: Error, errorInfo: ErrorInfo) => void;
|
|
38
|
+
}
|
|
@@ -38,18 +38,19 @@
|
|
|
38
38
|
|
|
39
39
|
import React, { ReactNode, useMemo } from 'react';
|
|
40
40
|
import { usePathname } from 'next/navigation';
|
|
41
|
-
import { CentrifugoProvider } from '@djangocfg/centrifugo';
|
|
42
|
-
import { getCentrifugoAuthTokenRetrieve } from '@djangocfg/api';
|
|
43
|
-
import { AnalyticsProvider } from '../../snippets/Analytics';
|
|
44
41
|
import { Suspense, ClientOnly } from '../../components/core';
|
|
45
42
|
import { BaseApp } from './BaseApp';
|
|
46
43
|
import type {
|
|
47
44
|
ThemeConfig,
|
|
48
|
-
|
|
45
|
+
AnalyticsConfig,
|
|
46
|
+
CentrifugoConfig,
|
|
47
|
+
ErrorTrackingConfig,
|
|
49
48
|
ErrorBoundaryConfig,
|
|
50
49
|
SWRConfigOptions,
|
|
51
50
|
McpChatConfig,
|
|
52
|
-
|
|
51
|
+
PwaInstallConfig,
|
|
52
|
+
PushNotificationsConfig,
|
|
53
|
+
} from '../types';
|
|
53
54
|
import type { AuthConfig } from '@djangocfg/api/auth';
|
|
54
55
|
|
|
55
56
|
export type LayoutMode = 'public' | 'private' | 'admin';
|
|
@@ -114,19 +115,13 @@ export interface AppLayoutProps {
|
|
|
114
115
|
auth?: AuthConfig;
|
|
115
116
|
|
|
116
117
|
/** Analytics configuration */
|
|
117
|
-
analytics?:
|
|
118
|
-
googleTrackingId?: string;
|
|
119
|
-
};
|
|
118
|
+
analytics?: AnalyticsConfig;
|
|
120
119
|
|
|
121
120
|
/** Centrifugo configuration */
|
|
122
|
-
centrifugo?:
|
|
123
|
-
enabled?: boolean;
|
|
124
|
-
autoConnect?: boolean;
|
|
125
|
-
url?: string;
|
|
126
|
-
};
|
|
121
|
+
centrifugo?: CentrifugoConfig;
|
|
127
122
|
|
|
128
123
|
/** Error tracking configuration */
|
|
129
|
-
errorTracking?:
|
|
124
|
+
errorTracking?: ErrorTrackingConfig;
|
|
130
125
|
|
|
131
126
|
/** SWR configuration */
|
|
132
127
|
swr?: SWRConfigOptions;
|
|
@@ -136,6 +131,12 @@ export interface AppLayoutProps {
|
|
|
136
131
|
|
|
137
132
|
/** MCP Chat configuration */
|
|
138
133
|
mcpChat?: McpChatConfig;
|
|
134
|
+
|
|
135
|
+
/** PWA Install configuration */
|
|
136
|
+
pwaInstall?: PwaInstallConfig;
|
|
137
|
+
|
|
138
|
+
/** Push Notifications configuration */
|
|
139
|
+
pushNotifications?: PushNotificationsConfig;
|
|
139
140
|
}
|
|
140
141
|
|
|
141
142
|
/**
|
|
@@ -213,52 +214,39 @@ function AppLayoutContent({
|
|
|
213
214
|
}
|
|
214
215
|
};
|
|
215
216
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
// Wrap with providers (order matters!)
|
|
219
|
-
let content: ReactNode = layoutContent;
|
|
220
|
-
|
|
221
|
-
// Analytics Provider (if enabled)
|
|
222
|
-
if (analytics?.googleTrackingId) {
|
|
223
|
-
content = <AnalyticsProvider trackingId={analytics.googleTrackingId}>{content}</AnalyticsProvider>;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Centrifugo Provider (always wrap, but only enable if configured)
|
|
227
|
-
// This ensures useCentrifugo() hook works even when Centrifugo is disabled
|
|
228
|
-
const centrifugoUrl = centrifugo?.url || process.env.NEXT_PUBLIC_CENTRIFUGO_URL;
|
|
229
|
-
const centrifugoEnabled = centrifugo?.enabled !== false;
|
|
230
|
-
|
|
231
|
-
content = (
|
|
232
|
-
<CentrifugoProvider
|
|
233
|
-
enabled={centrifugoEnabled}
|
|
234
|
-
autoConnect={centrifugoEnabled && centrifugo?.autoConnect}
|
|
235
|
-
url={centrifugoUrl}
|
|
236
|
-
onTokenRefresh={async () => {
|
|
237
|
-
const response = await getCentrifugoAuthTokenRetrieve();
|
|
238
|
-
return response.token;
|
|
239
|
-
}}
|
|
240
|
-
>
|
|
241
|
-
{content}
|
|
242
|
-
</CentrifugoProvider>
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
return content;
|
|
217
|
+
// No providers here - all providers now in BaseApp
|
|
218
|
+
return renderLayout();
|
|
246
219
|
}
|
|
247
220
|
|
|
248
221
|
/**
|
|
249
222
|
* AppLayout - Main Component with All Providers
|
|
250
223
|
*/
|
|
251
224
|
export function AppLayout(props: AppLayoutProps) {
|
|
252
|
-
const {
|
|
225
|
+
const {
|
|
226
|
+
theme,
|
|
227
|
+
auth,
|
|
228
|
+
analytics,
|
|
229
|
+
centrifugo,
|
|
230
|
+
errorTracking,
|
|
231
|
+
errorBoundary,
|
|
232
|
+
swr,
|
|
233
|
+
mcpChat,
|
|
234
|
+
pwaInstall,
|
|
235
|
+
pushNotifications,
|
|
236
|
+
} = props;
|
|
253
237
|
|
|
254
238
|
return (
|
|
255
239
|
<BaseApp
|
|
256
240
|
theme={theme}
|
|
257
241
|
auth={auth}
|
|
242
|
+
analytics={analytics}
|
|
243
|
+
centrifugo={centrifugo}
|
|
258
244
|
errorTracking={errorTracking}
|
|
259
245
|
errorBoundary={errorBoundary}
|
|
260
246
|
swr={swr}
|
|
261
247
|
mcpChat={mcpChat}
|
|
248
|
+
pwaInstall={pwaInstall}
|
|
249
|
+
pushNotifications={pushNotifications}
|
|
262
250
|
>
|
|
263
251
|
<AppLayoutContent {...props} />
|
|
264
252
|
</BaseApp>
|