@equinor/fusion-framework-dev-portal 8.0.3 → 9.0.0

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.
@@ -1,153 +0,0 @@
1
- import { useCallback } from 'react';
2
-
3
- import { useCurrentAppModules } from '@equinor/fusion-framework-react/app';
4
-
5
- import type {
6
- ContextItem,
7
- ContextModule,
8
- IContextProvider,
9
- } from '@equinor/fusion-framework-module-context';
10
- import { extractContextIdFromPath } from '@equinor/fusion-framework-module-context/utils';
11
-
12
- import type { NavigationModule } from '@equinor/fusion-framework-module-navigation';
13
-
14
- import { useObservableSubscription } from '@equinor/fusion-observable/react';
15
- import { EMPTY } from 'rxjs';
16
- import { useFrameworkModule } from '@equinor/fusion-framework-react';
17
-
18
- type CurrentAppModules = [ContextModule, NavigationModule];
19
-
20
- /**
21
- * Builds the navigation pathname when the context changes.
22
- *
23
- * If a context ID already exists in the current pathname (`pathContextId`),
24
- * it is replaced with the new context item's ID. Otherwise a new path
25
- * segment is appended. Falls back to the context provider's
26
- * `generatePathFromContext` when available.
27
- *
28
- * @param currentPathname - The current URL pathname.
29
- * @param item - The newly selected context item.
30
- * @param context - Optional context provider with a custom path generator.
31
- * @param pathContextId - Existing context ID found in the current URL, if any.
32
- * @returns The generated pathname string for navigation.
33
- */
34
- const generatePathname = (
35
- currentPathname: string,
36
- item: ContextItem,
37
- context?: IContextProvider,
38
- pathContextId?: string,
39
- ) => {
40
- // Replace an existing context id segment in the url when one is present
41
- if (pathContextId) {
42
- // context id exists in the url, replace it with the new context id
43
- const pathname =
44
- context?.generatePathFromContext?.(item, currentPathname) ??
45
- currentPathname.replace(pathContextId, item.id);
46
-
47
- console.debug(
48
- `🌍 Portal: context changed, navigating to app's context url:`,
49
- `found context id [${pathContextId}] in url, replacing with [${pathname}]`,
50
- );
51
-
52
- return pathname;
53
- }
54
- // could not find context id in the url, set the path to the new context id
55
- const pathname = context?.generatePathFromContext?.(item, currentPathname) ?? `/${item?.id}`;
56
-
57
- console.debug(
58
- `🌍 Portal: context changed, navigating to app's context url:`,
59
- `could not find context id in url, navigating to path [${pathname}]`,
60
- );
61
-
62
- return pathname;
63
- };
64
-
65
- /**
66
- * Observes the current application's context changes and synchronizes the URL.
67
- *
68
- * When the loaded app exposes both a context and navigation module, this hook
69
- * subscribes to `currentContext$`. On context change it updates the URL
70
- * pathname — either replacing an existing context ID segment or appending one.
71
- * When context is cleared, navigation resets to the root path.
72
- *
73
- * Uses the app's own navigation instance when available, falling back to the
74
- * portal-level navigation module.
75
- */
76
- export const useAppContextNavigation = () => {
77
- // use the framework navigation instance
78
- const navigation = useFrameworkModule<NavigationModule>('navigation');
79
-
80
- // use the current application modules
81
- const { modules } = useCurrentAppModules<CurrentAppModules>();
82
- // use the application context and navigation from the current application modules
83
- const { context, navigation: appNavigation } = modules ?? {};
84
-
85
- // subscribe to the context changes
86
- useObservableSubscription(
87
- // if the context is not available, use an empty observable
88
- context?.currentContext$ ?? EMPTY,
89
- // when the context changes, navigate to the new context
90
- useCallback(
91
- (item: ContextItem | undefined | null) => {
92
- // sanity check, if the item or navigation is undefined, early return
93
- if (item === undefined || navigation === undefined) {
94
- return;
95
- }
96
-
97
- // resolve the app base path (application base fragment of url)
98
- const currentPathname = appNavigation
99
- ? // if the app has its own navigation, use it to resolve the app base path
100
- appNavigation.path.pathname
101
- : // if the app does not have its own navigation, use the portal navigation to resolve the app base path
102
- navigation.path.pathname;
103
-
104
- console.debug(
105
- '🌍 Portal:',
106
- appNavigation
107
- ? 'App has its own navigation, using it to navigate.'
108
- : 'App does not have its own navigation, using portal navigation.',
109
- );
110
-
111
- /** context was cleared */
112
- if (item === null) {
113
- console.debug('🌍 Portal:', 'current context was cleared, navigating to root');
114
- // Prefer the app's own navigation instance when it exists
115
- if (appNavigation) {
116
- appNavigation.replace('/');
117
- } else {
118
- navigation.replace('/');
119
- }
120
- return;
121
- }
122
-
123
- const pathname = generatePathname(
124
- currentPathname,
125
- item,
126
- context,
127
- context?.extractContextIdFromPath?.(currentPathname) ??
128
- extractContextIdFromPath(currentPathname),
129
- );
130
-
131
- // always navigate via the portal navigation to trigger the synthetic pop() workaround,
132
- // ensuring app routers that listen only for POP actions detect the URL change
133
- if (appNavigation) {
134
- // resolve the full URL via the app navigation (includes app basename),
135
- // then hand it to the portal navigation which will not double-prefix when basename is empty
136
- const newUrl = appNavigation.createURL({ pathname });
137
- navigation.navigate(newUrl, { replace: true });
138
- } else {
139
- // pass the pathname directly so navigation.navigate does not re-run createURL
140
- // (which would duplicate the basename if one is configured)
141
- navigation.navigate({ pathname }, { replace: true });
142
- }
143
- },
144
- [
145
- // framework navigation instance, should not change
146
- navigation,
147
- // application navigation instance, may change when the application changes
148
- appNavigation,
149
- context,
150
- ],
151
- ),
152
- );
153
- };