aril 1.2.18 → 2.0.1-dev.1
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/boot/bridge/src/mfe-bridge.d.ts +42 -2
- package/boot/config/apps/index.d.ts +7 -1
- package/boot/config/apps/src/custom-reuse-outlet.component.d.ts +37 -0
- package/boot/config/apps/src/custom-route-reuse-strategy.class.d.ts +156 -0
- package/boot/config/apps/src/nav-link-context-menu.service.d.ts +33 -0
- package/boot/config/apps/src/nav-link.directive.d.ts +29 -0
- package/boot/config/apps/src/nav.service.d.ts +198 -0
- package/boot/config/apps/src/route-close.service.d.ts +9 -0
- package/boot/config/apps/src/safe-navigate.d.ts +17 -0
- package/boot/config/apps/src/tab-aware-url-serializer.d.ts +22 -0
- package/boot/config/plugins/src/getNgZone.d.ts +9 -1
- package/boot/mfe/src/app.component.d.ts +15 -4
- package/boot/mfe/src/isolated-location-strategy.d.ts +57 -0
- package/esm2022/boot/bridge/src/mfe-bridge.mjs +36 -5
- package/esm2022/boot/config/api/src/api.service.mjs +12 -3
- package/esm2022/boot/config/apps/index.mjs +8 -2
- package/esm2022/boot/config/apps/src/apps.service.mjs +14 -6
- package/esm2022/boot/config/apps/src/custom-reuse-outlet.component.mjs +207 -0
- package/esm2022/boot/config/apps/src/custom-route-reuse-strategy.class.mjs +540 -0
- package/esm2022/boot/config/apps/src/nav-link-context-menu.service.mjs +105 -0
- package/esm2022/boot/config/apps/src/nav-link.directive.mjs +45 -0
- package/esm2022/boot/config/apps/src/nav.service.mjs +675 -0
- package/esm2022/boot/config/apps/src/route-close.service.mjs +19 -0
- package/esm2022/boot/config/apps/src/safe-navigate.mjs +50 -0
- package/esm2022/boot/config/apps/src/tab-aware-url-serializer.mjs +50 -0
- package/esm2022/boot/config/plugins/src/getNgZone.mjs +13 -5
- package/esm2022/boot/host/src/app.component.mjs +1 -2
- package/esm2022/boot/host/src/bootstrap.mjs +22 -7
- package/esm2022/boot/mfe/src/app.component.mjs +143 -39
- package/esm2022/boot/mfe/src/bootstrap.mjs +197 -20
- package/esm2022/boot/mfe/src/isolated-location-strategy.mjs +142 -0
- package/esm2022/keycloak/src/auth.interceptor.mjs +17 -2
- package/esm2022/provider/src/prodiveHost.mjs +3 -5
- package/esm2022/provider/src/prodiveHostRouter.mjs +88 -9
- package/esm2022/theme/layout/app/expandableMenu/expandable-menu.component.mjs +81 -19
- package/esm2022/theme/layout/app/favorite-pages/favorite-pages-sidebar.component.mjs +6 -4
- package/esm2022/theme/layout/app/general-search/general-search.component.mjs +4 -4
- package/esm2022/theme/layout/app/history/history-sidebar.component.mjs +6 -4
- package/esm2022/theme/layout/app/layout/app.layout.component.mjs +422 -20
- package/esm2022/theme/layout/app/layout/mfe.layout.component.mjs +22 -35
- package/esm2022/theme/layout/app/site-map/site-map-sidebar.component.mjs +6 -4
- package/esm2022/theme/layout/app/static-sidebar/static-sidebar.component.mjs +85 -27
- package/esm2022/theme/layout/app/topbar/app.topbar.component.mjs +3 -3
- package/esm2022/theme/layout/service/breadcrumb-publisher.service.mjs +86 -0
- package/esm2022/theme/layout/service/tab-session.service.mjs +126 -0
- package/esm2022/ui-business/ref-value/src/ref-value.component.mjs +15 -7
- package/esm2022/util/sync-active-tab-route/src/sync-active-tab-route.directive.mjs +29 -9
- package/fesm2022/aril-app.component-s14ruALV.mjs +183 -0
- package/fesm2022/aril-app.component-s14ruALV.mjs.map +1 -0
- package/fesm2022/aril-boot-bridge.mjs +35 -4
- package/fesm2022/aril-boot-bridge.mjs.map +1 -1
- package/fesm2022/aril-boot-config-api.mjs +11 -2
- package/fesm2022/aril-boot-config-api.mjs.map +1 -1
- package/fesm2022/aril-boot-config-apps.mjs +1678 -10
- package/fesm2022/aril-boot-config-apps.mjs.map +1 -1
- package/fesm2022/aril-boot-config-plugins.mjs +12 -4
- package/fesm2022/aril-boot-config-plugins.mjs.map +1 -1
- package/fesm2022/aril-boot-host.mjs +21 -7
- package/fesm2022/aril-boot-host.mjs.map +1 -1
- package/fesm2022/aril-boot-mfe-app.component-a34GeuUv.mjs +183 -0
- package/fesm2022/aril-boot-mfe-app.component-a34GeuUv.mjs.map +1 -0
- package/fesm2022/aril-boot-mfe-aril-boot-mfe-KFO_X7yR.mjs +631 -0
- package/fesm2022/aril-boot-mfe-aril-boot-mfe-KFO_X7yR.mjs.map +1 -0
- package/fesm2022/aril-boot-mfe.mjs +5 -3
- package/fesm2022/aril-boot-mfe.mjs.map +1 -1
- package/fesm2022/aril-keycloak.mjs +16 -1
- package/fesm2022/aril-keycloak.mjs.map +1 -1
- package/fesm2022/aril-provider.mjs +90 -12
- package/fesm2022/aril-provider.mjs.map +1 -1
- package/fesm2022/aril-theme-layout.mjs +2628 -2017
- package/fesm2022/aril-theme-layout.mjs.map +1 -1
- package/fesm2022/aril-ui-business-ref-value.mjs +14 -6
- package/fesm2022/aril-ui-business-ref-value.mjs.map +1 -1
- package/fesm2022/aril-util-sync-active-tab-route.mjs +28 -8
- package/fesm2022/aril-util-sync-active-tab-route.mjs.map +1 -1
- package/fesm2022/aril.mjs +354 -25
- package/fesm2022/aril.mjs.map +1 -1
- package/keycloak/src/auth.interceptor.d.ts +7 -0
- package/package.json +222 -222
- package/provider/src/prodiveHost.d.ts +1 -0
- package/theme/layout/app/expandableMenu/expandable-menu.component.d.ts +21 -4
- package/theme/layout/app/expandableMenu/expandable-menu.component.html +19 -5
- package/theme/layout/app/expandableMenu/expandable-menu.component.ts +69 -9
- package/theme/layout/app/favorite-pages/favorite-pages-sidebar.component.html +1 -0
- package/theme/layout/app/favorite-pages/favorite-pages-sidebar.component.ts +3 -1
- package/theme/layout/app/general-search/general-search.component.html +2 -1
- package/theme/layout/app/general-search/general-search.component.ts +2 -2
- package/theme/layout/app/history/history-sidebar.component.html +3 -1
- package/theme/layout/app/history/history-sidebar.component.ts +3 -1
- package/theme/layout/app/layout/app.layout.component.d.ts +105 -5
- package/theme/layout/app/layout/app.layout.component.html +102 -1
- package/theme/layout/app/layout/app.layout.component.scss +372 -0
- package/theme/layout/app/layout/app.layout.component.ts +452 -13
- package/theme/layout/app/layout/mfe.layout.component.d.ts +1 -5
- package/theme/layout/app/layout/mfe.layout.component.ts +12 -38
- package/theme/layout/app/site-map/site-map-sidebar.component.html +1 -0
- package/theme/layout/app/site-map/site-map-sidebar.component.ts +3 -1
- package/theme/layout/app/static-sidebar/static-sidebar.component.d.ts +26 -5
- package/theme/layout/app/static-sidebar/static-sidebar.component.html +11 -5
- package/theme/layout/app/static-sidebar/static-sidebar.component.ts +68 -13
- package/theme/layout/app/topbar/app.topbar.component.html +0 -1
- package/theme/layout/app/topbar/app.topbar.component.scss +1 -1
- package/theme/layout/service/breadcrumb-publisher.service.d.ts +24 -0
- package/theme/layout/service/breadcrumb-publisher.service.ts +95 -0
- package/theme/layout/service/tab-session.service.d.ts +52 -0
- package/theme/layout/service/tab-session.service.ts +138 -0
- package/theme/styles/layout/_breadcrumb.scss +95 -0
- package/theme/styles/layout/_content.scss +2 -2
- package/ui-business/ref-value/src/ref-value.component.d.ts +4 -2
- package/util/sync-active-tab-route/src/sync-active-tab-route.directive.d.ts +15 -2
- package/boot/config/apps/src/reuse-strategy.d.ts +0 -4
- package/esm2022/boot/config/apps/src/reuse-strategy.mjs +0 -9
- package/esm2022/theme/layout/app/breadcrumb/app.breadcrumb.component.mjs +0 -107
- package/fesm2022/aril-app.component-wxP3y8dg.mjs +0 -81
- package/fesm2022/aril-app.component-wxP3y8dg.mjs.map +0 -1
- package/fesm2022/aril-boot-mfe-app.component-7IjAmjz0.mjs +0 -80
- package/fesm2022/aril-boot-mfe-app.component-7IjAmjz0.mjs.map +0 -1
- package/fesm2022/aril-boot-mfe-aril-boot-mfe-KXDpUyv7.mjs +0 -315
- package/fesm2022/aril-boot-mfe-aril-boot-mfe-KXDpUyv7.mjs.map +0 -1
- package/theme/layout/app/breadcrumb/app.breadcrumb.component.d.ts +0 -25
- package/theme/layout/app/breadcrumb/app.breadcrumb.component.html +0 -8
- package/theme/layout/app/breadcrumb/app.breadcrumb.component.ts +0 -127
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Location } from '@angular/common';
|
|
1
2
|
import { NgZone, Signal } from '@angular/core';
|
|
2
3
|
import type { Router } from '@angular/router';
|
|
3
4
|
import type { Apps, PluginMenuItem } from 'aril/boot/config/apps';
|
|
@@ -6,10 +7,13 @@ export interface RouteConfig {
|
|
|
6
7
|
content: string;
|
|
7
8
|
version: number;
|
|
8
9
|
}
|
|
10
|
+
export interface Breadcrumb {
|
|
11
|
+
label: string;
|
|
12
|
+
url?: string;
|
|
13
|
+
}
|
|
9
14
|
export interface LegacyWindowSlots {
|
|
10
15
|
activeHost?: Apps;
|
|
11
16
|
activeMF?: Apps;
|
|
12
|
-
isHostMode?: boolean;
|
|
13
17
|
hostMenuItems?: Signal<PluginMenuItem[]>;
|
|
14
18
|
pluginJson?: Record<string, unknown>;
|
|
15
19
|
routeConfigs?: RouteConfig[];
|
|
@@ -20,13 +24,49 @@ export interface LegacyWindowSlots {
|
|
|
20
24
|
export declare class MfeBridge {
|
|
21
25
|
readonly activeHost: import("@angular/core").WritableSignal<Apps | null>;
|
|
22
26
|
readonly activeMF: import("@angular/core").WritableSignal<Apps | null>;
|
|
23
|
-
readonly isHostMode: import("@angular/core").WritableSignal<boolean>;
|
|
24
27
|
readonly hostMenuItems: import("@angular/core").WritableSignal<PluginMenuItem[]>;
|
|
25
28
|
readonly pluginJson: import("@angular/core").WritableSignal<Record<string, unknown>>;
|
|
26
29
|
readonly routeConfigs: import("@angular/core").WritableSignal<RouteConfig[] | null>;
|
|
27
30
|
readonly pageTitle: import("@angular/core").WritableSignal<string>;
|
|
31
|
+
readonly breadcrumbs: import("@angular/core").WritableSignal<Breadcrumb[]>;
|
|
32
|
+
/**
|
|
33
|
+
* Bir MFE Router'ında olan son `NavigationEnd`'in URL'i ve **hangi tab'a ait olduğu**.
|
|
34
|
+
* MFE içi sayfa içi navigation'lar host Router'a yansımayabiliyor → `NavService` tab
|
|
35
|
+
* navLink'ini güncellemek için bu signal'ı izler.
|
|
36
|
+
*
|
|
37
|
+
* **Neden tabId taşıyor**: Birden fazla tab'ın MFE Router'ı async event tetikleyebilir
|
|
38
|
+
* (örn. hidden container'daki tab2 `?activeTab=1` replaceState yaparken). `activeTabId`'ye
|
|
39
|
+
* bakarak update yaparsak yanlış tab'ı kontamine ederiz. Mesajda kaynak tabId'yi taşıyıp
|
|
40
|
+
* `NavService.syncActiveTabNavLinkForTab(tabId, url)` ile spesifik tab'ı update ederiz.
|
|
41
|
+
*
|
|
42
|
+
* **Custom `equal`**: AppComponent her MFE NavigationEnd'de `set({tabId, url})` çağırır;
|
|
43
|
+
* yeni object reference olduğu için default reference-equality re-emit eder. Bu durumda
|
|
44
|
+
* aynı tab+url ile sürekli effect tetiklenir → tab navLink'i kullanıcının anasayfaya
|
|
45
|
+
* geçtiği gibi (host route'lar MFE NavigationEnd tetiklemez ama signal eski değerinde
|
|
46
|
+
* kalır) state değişikliklerini geri alır. Value-equality ile yalnızca gerçek URL
|
|
47
|
+
* değişikliklerinde tetiklensin.
|
|
48
|
+
*/
|
|
49
|
+
readonly activeMFEUrl: import("@angular/core").WritableSignal<{
|
|
50
|
+
tabId: string;
|
|
51
|
+
url: string;
|
|
52
|
+
title?: string | undefined;
|
|
53
|
+
} | null>;
|
|
54
|
+
/**
|
|
55
|
+
* Aktif tab'ın `tabId`'si — `NavService` tab değişimlerinde günceller.
|
|
56
|
+
* Plugin Router proxy'leri (`provideHostRouter`) bu signal'ı okuyup `navigate`/`navigateByUrl`
|
|
57
|
+
* çağrılarına `extras.state._tab` enjekte eder → plugin'lerin yaptığı tüm host
|
|
58
|
+
* navigation'ları otomatik tab-aware olur, Strategy doğru tab handle'ını korur.
|
|
59
|
+
*/
|
|
60
|
+
readonly activeTabId: import("@angular/core").WritableSignal<string>;
|
|
28
61
|
hostNgZone: NgZone | null;
|
|
29
62
|
hostRouter: Router | null;
|
|
63
|
+
/**
|
|
64
|
+
* Host (shell) `Location` servisi. Host modda MFE/plugin child injector'larından
|
|
65
|
+
* erişilemez (child Location izole `IsolatedLocationStrategy`'ye bağlı); browser
|
|
66
|
+
* adres çubuğuna `replaceState` ile yazmak isteyen directive'ler (örn. `?activeTab`
|
|
67
|
+
* senkronizasyonu) bunu kullanır. `hostRouter` ile aynı pattern.
|
|
68
|
+
*/
|
|
69
|
+
hostLocation: Location | null;
|
|
30
70
|
private mirrored;
|
|
31
71
|
mirrorToWindow(): void;
|
|
32
72
|
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
export * from './src/apps.service';
|
|
2
2
|
export * from './src/interfaces';
|
|
3
|
-
export * from './src/reuse-strategy';
|
|
3
|
+
export * from './src/custom-route-reuse-strategy.class';
|
|
4
|
+
export * from './src/route-close.service';
|
|
5
|
+
export * from './src/nav.service';
|
|
6
|
+
export * from './src/nav-link-context-menu.service';
|
|
7
|
+
export * from './src/nav-link.directive';
|
|
8
|
+
export * from './src/tab-aware-url-serializer';
|
|
9
|
+
export * from './src/safe-navigate';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { AfterContentInit, AfterViewInit, ElementRef, OnChanges, OnDestroy, OnInit } from '@angular/core';
|
|
2
|
+
import { ActivatedRoute } from '@angular/router';
|
|
3
|
+
import { LoadRemoteModuleOptions } from '@angular-architects/module-federation-runtime';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
export type WebComponentWrapperOptions = LoadRemoteModuleOptions & {
|
|
6
|
+
elementName: string;
|
|
7
|
+
};
|
|
8
|
+
export declare class ArilWebComponentWrapper implements OnInit, AfterContentInit, AfterViewInit, OnChanges, OnDestroy {
|
|
9
|
+
private route;
|
|
10
|
+
vc?: ElementRef;
|
|
11
|
+
options?: WebComponentWrapperOptions;
|
|
12
|
+
props?: {
|
|
13
|
+
[prop: string]: unknown;
|
|
14
|
+
};
|
|
15
|
+
events?: {
|
|
16
|
+
[event: string]: (event: Event) => void;
|
|
17
|
+
};
|
|
18
|
+
element?: HTMLElement;
|
|
19
|
+
private isDestroyed;
|
|
20
|
+
private registeredEvents;
|
|
21
|
+
private routeSub?;
|
|
22
|
+
needsRestore: boolean;
|
|
23
|
+
propsUpdated: boolean;
|
|
24
|
+
constructor(route: ActivatedRoute);
|
|
25
|
+
ngOnInit(): void;
|
|
26
|
+
ngOnChanges(): void;
|
|
27
|
+
private populateProps;
|
|
28
|
+
private setupEvents;
|
|
29
|
+
private teardownEvents;
|
|
30
|
+
private restoreElement;
|
|
31
|
+
private getHiddenContainer;
|
|
32
|
+
ngAfterContentInit(): Promise<void>;
|
|
33
|
+
ngAfterViewInit(): void;
|
|
34
|
+
ngOnDestroy(): void;
|
|
35
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ArilWebComponentWrapper, never>;
|
|
36
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ArilWebComponentWrapper, "mft-wc-wrapper", never, { "options": { "alias": "options"; "required": false; }; "props": { "alias": "props"; "required": false; }; "events": { "alias": "events"; "required": false; }; }, {}, never, never, false, never>;
|
|
37
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { OnDestroy } from '@angular/core';
|
|
2
|
+
import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router';
|
|
3
|
+
import { RouteCloseService } from './route-close.service';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
/**
|
|
6
|
+
* Tab-bazlı navigation için custom `RouteReuseStrategy`.
|
|
7
|
+
*
|
|
8
|
+
* ## Tab izolasyonu (`_tab` query param)
|
|
9
|
+
* `NavService` her tab'a unique `tabId` üretir ve URL'e `?_tab=<tabId>` query param
|
|
10
|
+
* ekler. Strategy bu param'ı route key'in parçası yapar:
|
|
11
|
+
* - Matcher (web component) route'lar: `mfe:${remoteName}:${tabId}`
|
|
12
|
+
* - Normal route'lar: `pathFromRoot` + tüm queryParams (zaten `_tab` dahil)
|
|
13
|
+
*
|
|
14
|
+
* Sonuç: aynı sayfanın iki tab'i `storedRoutes` üzerinde farklı slot'lara yazılır
|
|
15
|
+
* → bağımsız componentRef'ler, bağımsız state. `shouldReuseRoute` matcher karşılaştırması
|
|
16
|
+
* `tabId` farkını da dikkate alır — tab değişiminde fresh component oluşur.
|
|
17
|
+
*
|
|
18
|
+
* ## Mimari: iki bağımsız instance
|
|
19
|
+
* Bu strategy hem `aril/boot/host/src/bootstrap.ts`'te hem her MFE remote'unun
|
|
20
|
+
* `aril/boot/mfe/src/bootstrap.ts`'inde provider olarak veriliyor. Class
|
|
21
|
+
* `providedIn: 'root'` olduğu için **her root injector'da AYRI instance** yaşar.
|
|
22
|
+
* İki instance bağımsız `storedRoutes` map'i tutar ve birbirinden habersizdir:
|
|
23
|
+
*
|
|
24
|
+
* - **Host instance**: matcher route'ları yönetir; key `mfe:${remoteName}:${tabId}`.
|
|
25
|
+
* Tab kapanıp `mfe:wdm:abc123` silindiğinde effect remote'a ait `#0/wdm/...`
|
|
26
|
+
* prefix'li VE `_tab=abc123` içeren child key'leri de temizler.
|
|
27
|
+
* - **MFE instance** (her remote'un kendi içinde): normal route'lar için çalışır.
|
|
28
|
+
* Query params zaten `getRouteKey` çıktısına dahil olduğu için tab izolasyonu
|
|
29
|
+
* doğal olarak gelir — ek özel davranış gerekmez.
|
|
30
|
+
*
|
|
31
|
+
* ## Plugin custom element preservation
|
|
32
|
+
* `preserveCustomElementsInTree` detached view'daki `<md-search>` gibi custom
|
|
33
|
+
* element'leri hidden container'a taşır — element document'tan ayrılmaz, Angular
|
|
34
|
+
* Elements `disconnectedCallback` 10ms destroy timer'ı tetiklenmez, plugin
|
|
35
|
+
* componentRef'i ve dahili state'i (form input, search sonuçları) korunur.
|
|
36
|
+
*
|
|
37
|
+
* ## Bilinen sınırlamalar
|
|
38
|
+
* - `shouldDetach` matcher route'lar için tabId yokken false döner (tabsız orphan
|
|
39
|
+
* handle oluşmasın), diğer durumlarda `true` — tüm detached route'lar cache'lenir.
|
|
40
|
+
* Memory leak'i sınırlamak için `NavService` tab sayısını `MAX_TABS` ile kısıtlar
|
|
41
|
+
* ve son tab kapatıldığında effect remote'un tüm child key'lerini temizler. Yine de
|
|
42
|
+
* tab içinde açılan detail/edit gibi parametreli alt sayfaların handle'ları, parent
|
|
43
|
+
* tab kapanana kadar storedRoutes'ta kalır.
|
|
44
|
+
*/
|
|
45
|
+
export declare class CustomRouteReuseStrategy implements RouteReuseStrategy, OnDestroy {
|
|
46
|
+
routeCloseService: RouteCloseService;
|
|
47
|
+
storedRoutes: Record<string, DetachedRouteHandle>;
|
|
48
|
+
/**
|
|
49
|
+
* `(detachedTree as any).__arilPreservedCustomEls = [...]` runtime property
|
|
50
|
+
* eklemek yerine handle'ı key olarak kullanan bir WeakMap tutuyoruz —
|
|
51
|
+
* type-safe ve handle GC'ye uğradığında bellek otomatik temizlenir.
|
|
52
|
+
*/
|
|
53
|
+
private preservedCustomEls;
|
|
54
|
+
constructor();
|
|
55
|
+
/**
|
|
56
|
+
* Injector destroy edildiğinde — hibrit modda her tab'ın child `EnvironmentInjector`'ı tab
|
|
57
|
+
* kapanınca `destroy()` edilir; bu strategy `providedIn:'root'` olduğundan child injector'da
|
|
58
|
+
* (root-scope) materialize olmuş instance da yıkılır — `storedRoutes`'ta kalan TÜM detached
|
|
59
|
+
* handle'ları temizler. Aksi halde `preserveCustomElementsInTree` ile hidden container'a
|
|
60
|
+
* taşınmış plugin custom element'leri (örn. `<md-search>`) orphan kalır (memory leak): MFE
|
|
61
|
+
* internal route key'leri `_tab` taşımadığı için `aril:remote-cleanup` cross-injector temizliği
|
|
62
|
+
* onlara ulaşamaz. Injector-destroy bazlı bu süpürme garantili ve idempotenttir.
|
|
63
|
+
*/
|
|
64
|
+
ngOnDestroy(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Verilen key için direct + child cleanup uygular. Effect içinden ayrıştırılmış helper.
|
|
67
|
+
*/
|
|
68
|
+
private processCleanupKey;
|
|
69
|
+
/**
|
|
70
|
+
* `mfe:${remoteName}` veya `mfe:${remoteName}:${tabId}` formatındaki matcher key'i parse eder.
|
|
71
|
+
* tabId yoksa `null` döner (geriye dönük uyumluluk: legacy çağrılar tabId vermeyebilir).
|
|
72
|
+
*/
|
|
73
|
+
private parseMatcherKey;
|
|
74
|
+
/**
|
|
75
|
+
* Stored handle'ı tamamen temizle: hidden container'daki preserved element'leri (plugin
|
|
76
|
+
* custom element'leri + ArilWebComponentWrapper'ın `<app-xxx>` element'i) DOM'dan kaldır,
|
|
77
|
+
* sonra Angular `componentRef.destroy()` ile view tree'sini destroy et.
|
|
78
|
+
*
|
|
79
|
+
* `componentRef.destroy()` tek başına yeterli değil: Angular sadece view tree'sini bilir,
|
|
80
|
+
* bizim `preserveCustomElementsInTree` ve `preserveWebComponentElement` ile hidden
|
|
81
|
+
* container'a manuel taşınan element'lerden haberi yoktur → onlar orphan kalır.
|
|
82
|
+
*/
|
|
83
|
+
private cleanupStoredHandle;
|
|
84
|
+
/**
|
|
85
|
+
* Matcher (MFE) route'lar için tabId zorunlu. `getTabIdFromRoute` URL queryParams +
|
|
86
|
+
* history.state'i okur. Hiçbir kaynak tabId vermezse (ilk navigation interim'i) detach
|
|
87
|
+
* edilmez; `firstCheckForRoute` `_tab` ekleyip yeniden navigate edecek.
|
|
88
|
+
*/
|
|
89
|
+
shouldDetach(route: ActivatedRouteSnapshot): boolean;
|
|
90
|
+
store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void;
|
|
91
|
+
shouldAttach(route: ActivatedRouteSnapshot): boolean;
|
|
92
|
+
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null;
|
|
93
|
+
/**
|
|
94
|
+
* Web component element'ini hidden container'a taşır (state korunması için).
|
|
95
|
+
*
|
|
96
|
+
* Element'e `__arilPreserveDuringDetach` flag'i yazılır: `removeChild` + `appendChild`
|
|
97
|
+
* arasında MFE custom element'in `disconnectedCallback`'i tetikleniyor; flag oradaki
|
|
98
|
+
* destroy timer'ını **deterministic** şekilde bypass eder. Eskiden 50ms hardcoded timer
|
|
99
|
+
* yarış koşulu üretiyordu (yavaş cihazlarda Application istemsiz destroy oluyordu).
|
|
100
|
+
*/
|
|
101
|
+
private preserveWebComponentElement;
|
|
102
|
+
/**
|
|
103
|
+
* Web component element'ini hidden container'dan çıkar ve component view'a eklemeyi dene.
|
|
104
|
+
*
|
|
105
|
+
* `__arilPreserveDuringDetach` flag'i temizlenir — eğer bu retrieve sonrası element
|
|
106
|
+
* gerçek anlamda destroy edilirse `disconnectedCallback` flag yok kabul edip Application
|
|
107
|
+
* cleanup'ını yürütecek.
|
|
108
|
+
*/
|
|
109
|
+
private restoreWebComponentElement;
|
|
110
|
+
/**
|
|
111
|
+
* Global hidden container'ı oluşturur veya döndürür
|
|
112
|
+
*/
|
|
113
|
+
private getHiddenContainer;
|
|
114
|
+
/**
|
|
115
|
+
* Detached route view'ı içindeki plugin/MFE custom element'lerini (tag adında `-`
|
|
116
|
+
* bulunan ve `customElements`'a kayıtlı olanları) hidden container'a taşır ve
|
|
117
|
+
* yerlerine birer Comment placeholder bırakır. Element document'tan ayrılmaz,
|
|
118
|
+
* Angular Elements `disconnectedCallback` 10ms destroy timer'ı kanat çırpmaz —
|
|
119
|
+
* dolayısıyla plugin'in `ComponentRef` ve dahili state'i (form değerleri, search
|
|
120
|
+
* sonuçları vs.) sonraki retrieve'e kadar korunur.
|
|
121
|
+
*/
|
|
122
|
+
private preserveCustomElementsInTree;
|
|
123
|
+
/**
|
|
124
|
+
* preserveCustomElementsInTree ile taşınan custom element'leri orijinal
|
|
125
|
+
* placeholder'larının yerine geri koyar.
|
|
126
|
+
*/
|
|
127
|
+
private restoreCustomElementsInTree;
|
|
128
|
+
private isMatcherRoute;
|
|
129
|
+
private getRemoteName;
|
|
130
|
+
/**
|
|
131
|
+
* URL `?_tab=<tabId>` query param'ını oku — `NavService` her tab için unique değer üretir.
|
|
132
|
+
* `IsolatedLocationStrategy` sayesinde host Router'a tabsız navigation gelmez, sadece
|
|
133
|
+
* `tabState({_tab})`'lı tab tıklamaları gelir → `route.queryParams['_tab']` her zaman dolu.
|
|
134
|
+
*/
|
|
135
|
+
private getTabIdFromRoute;
|
|
136
|
+
/**
|
|
137
|
+
* Route key'ini oluşturur. Matcher (web component) route'lar için remoteName + tabId
|
|
138
|
+
* bazlı key kullanılır — aynı remote'un her tab'i ayrı MFE custom element instance'ına
|
|
139
|
+
* sahiptir (bağımsız state).
|
|
140
|
+
*
|
|
141
|
+
* Normal route'lar için `pathFromRoot` üzerinden tam yol üretilir, ardından query params
|
|
142
|
+
* eklenir (zaten `_tab` dahil) — nested boş-path (`path: ''`) child route'larının aynı `""`
|
|
143
|
+
* key'iyle çakışmasını engeller ve aynı path'in iki tab'i farklı key alır.
|
|
144
|
+
*/
|
|
145
|
+
private getRouteKey;
|
|
146
|
+
/**
|
|
147
|
+
* Query param'ları URL-safe şekilde serileştirir. `URLSearchParams` constructor'una
|
|
148
|
+
* doğrudan object verirsek array değerler `?ids=1,2,3` gibi tek key olarak yazılır;
|
|
149
|
+
* Angular Router'ın `?ids=1&ids=2&ids=3` davranışıyla uyumsuz olabilir. `append` ile
|
|
150
|
+
* her array elemanı ayrı entry olur ve null/undefined değerler atlanır.
|
|
151
|
+
*/
|
|
152
|
+
private serializeQueryParams;
|
|
153
|
+
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean;
|
|
154
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<CustomRouteReuseStrategy, never>;
|
|
155
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<CustomRouteReuseStrategy>;
|
|
156
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ContextMenu } from 'primeng/contextmenu';
|
|
2
|
+
import { NavItem } from './nav.service';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Tab navigasyonu yapan tüm linkli yapılar için ortak sağ-tık context menu servisi.
|
|
6
|
+
* Tek bir global PrimeNG `ContextMenu` instance'ı host shell (`AppLayoutComponent`)
|
|
7
|
+
* template'inde yaşar; her sayfa kendi `ContextMenu` enstantiate etmek yerine bu
|
|
8
|
+
* service üzerinden `open(event, navItem)` çağırır.
|
|
9
|
+
*
|
|
10
|
+
* Servis hangi link tıklandıysa onun `NavItem`'iyle menü modelini yeniden inşa eder
|
|
11
|
+
* ve `cm.show(event)` ile açar — tüm tüketiciler için tek source-of-truth.
|
|
12
|
+
*
|
|
13
|
+
* **Kayıt sözleşmesi**: shell mount olunca `register(cm)` çağırır. MFE'lerden gelen
|
|
14
|
+
* çağrılar global slot üzerinden host'a delege edilir.
|
|
15
|
+
*/
|
|
16
|
+
export declare class NavLinkContextMenuService {
|
|
17
|
+
private readonly navService;
|
|
18
|
+
private readonly translocoService;
|
|
19
|
+
private cm;
|
|
20
|
+
register(cm: ContextMenu): void;
|
|
21
|
+
open(event: MouseEvent, navItem: NavItem): void;
|
|
22
|
+
/**
|
|
23
|
+
* Programatik "yeni tab aç ve geç" — MFE component'lerinden çağrılır (eski
|
|
24
|
+
* `window.open('#'+url,'_blank')` yerine). Host instance'ta (`cm` set) doğrudan
|
|
25
|
+
* `NavService.openInNewTabAndFocus`'u çağırır; MFE instance'ında `__arilNavCommand`
|
|
26
|
+
* global slot'u üzerinden host'a delege eder. Host shell henüz mount olmadıysa
|
|
27
|
+
* (slot boş) sessizce no-op olur.
|
|
28
|
+
*/
|
|
29
|
+
openInNewTabAndFocus(navItem: NavItem): void;
|
|
30
|
+
private openLocal;
|
|
31
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NavLinkContextMenuService, never>;
|
|
32
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<NavLinkContextMenuService>;
|
|
33
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { NavItem } from './nav.service';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* Linkli her HTML elementine sağ-tık → tab context menüsü ekleyen directive.
|
|
5
|
+
*
|
|
6
|
+
* **Kullanım**: navLink/navName (ve opsiyonel icon) bilgisini object literal olarak verin:
|
|
7
|
+
* ```html
|
|
8
|
+
* <a [attr.href]="'#/' + path"
|
|
9
|
+
* [arilNavLink]="{ tabId: '', navLink: path, navName: 'Sayfa Adı', icon: 'pi pi-cog' }"
|
|
10
|
+
* (click)="...">
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Sağ tık → "Bu sekmede aç / Yeni sekmede aç / Yeni sekmede aç ve geç" menüsü açılır;
|
|
14
|
+
* komutlar `NavService` üzerinden ilgili tab eylemini tetikler. Ctrl+Click / Middle Click
|
|
15
|
+
* gibi mevcut shortcut'lar değişmez — bu menü onlara klavye/fare bilgisi olmayan
|
|
16
|
+
* kullanıcılar için keşfedilebilir bir alternatif.
|
|
17
|
+
*/
|
|
18
|
+
export declare class NavLinkDirective {
|
|
19
|
+
/**
|
|
20
|
+
* Optional çünkü site-map gibi conditional yapılarda template binding'i `node.routerLink ? {...} : null`
|
|
21
|
+
* şeklinde çalışıyor — required işaretlemek `null/undefined` durumunda TS hatası verir. Boş veya
|
|
22
|
+
* `navLink`'i olmayan navItem için `onContextMenu` no-op çalışır.
|
|
23
|
+
*/
|
|
24
|
+
navItem?: NavItem | null;
|
|
25
|
+
private readonly contextMenuService;
|
|
26
|
+
onContextMenu(event: MouseEvent): void;
|
|
27
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NavLinkDirective, never>;
|
|
28
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<NavLinkDirective, "[arilNavLink]", never, { "navItem": { "alias": "arilNavLink"; "required": false; }; }, {}, never, never, true, never>;
|
|
29
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { Router } from '@angular/router';
|
|
2
|
+
import { PluginMenuItem } from './interfaces';
|
|
3
|
+
import { RouteCloseService } from './route-close.service';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
/**
|
|
6
|
+
* `tabId` her tab'ı tekil kılan kimliktir; aynı `navLink` (path) altında birden fazla
|
|
7
|
+
* bağımsız tab açılabilmesini sağlar. NavService Router'a navigation yaparken URL'e
|
|
8
|
+
* `_tab=<tabId>` query param ekler ve `extras.state._tab` ile history state'e yazar.
|
|
9
|
+
* `TabAwareUrlSerializer` adres çubuğundan `_tab`'i strip eder; Router internal
|
|
10
|
+
* `queryParams` korunur → `CustomRouteReuseStrategy.getRouteKey` doğru tab key türetir.
|
|
11
|
+
*
|
|
12
|
+
* **Önemli**: `NavItem.navLink` HER ZAMAN CLEAN URL (no `_tab`). Hem display hem
|
|
13
|
+
* `activeRoute()` ile karşılaştırma için kullanılır. Tab kimliği `tabId` üzerinden
|
|
14
|
+
* yönetilir (`activeTabId` signal).
|
|
15
|
+
*/
|
|
16
|
+
export interface NavItem {
|
|
17
|
+
tabId: string;
|
|
18
|
+
navLink: string;
|
|
19
|
+
navName: string;
|
|
20
|
+
/**
|
|
21
|
+
* Menu item'dan gelen icon class'ı (örn. 'pi pi-bolt'). Verilmezse layout `getTabIcon`
|
|
22
|
+
* menu config'inden longest-prefix match ile lookup yapar; o da bulamazsa generic ikona düşer.
|
|
23
|
+
*/
|
|
24
|
+
icon?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Tab sabitleme — Chrome-vari pinning. Sabit tab'lar tab bar'ın **soluna** sıralanır,
|
|
27
|
+
* kompakt gösterilir (yalnız icon, başlık + close button gizli), `closeOthers`/`closeToRight`/
|
|
28
|
+
* `closeAll` çağrılarından korunur. Drag & drop'ta pinned ↔ normal sınırı geçilemez.
|
|
29
|
+
*/
|
|
30
|
+
pinned?: boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare class NavService {
|
|
33
|
+
router: Router;
|
|
34
|
+
routeCloseService: RouteCloseService;
|
|
35
|
+
private readonly messageService;
|
|
36
|
+
private readonly translocoService;
|
|
37
|
+
private readonly i18nReloadSub;
|
|
38
|
+
firstCheckForRoute: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Aynı anda açık olabilecek tab sayısı tavanı. Tab bar'ın UX'i ve `CustomRouteReuseStrategy`
|
|
41
|
+
* `storedRoutes` birikimi için üst sınır. Aşılırsa yeni navigasyon engellenir.
|
|
42
|
+
*/
|
|
43
|
+
private readonly MAX_TABS;
|
|
44
|
+
/** RFC4122 v4 UUID — collision-free, internal state taşımaz. */
|
|
45
|
+
private generateTabId;
|
|
46
|
+
/**
|
|
47
|
+
* Menu items'i NavService'ten almak için provider. `aril/boot/bridge`'i doğrudan import
|
|
48
|
+
* etmek ng-packagr'da `aril/boot/bridge → aril/boot/config/apps` döngüsü tetikliyordu
|
|
49
|
+
* (bridge `PluginMenuItem` type'ını import ediyor). Bunun yerine host shell
|
|
50
|
+
* (`AppLayoutComponent`) `setMenuItemsProvider(() => bridge.hostMenuItems())` ile bağlar.
|
|
51
|
+
* Provider yoksa label/icon resolve'u atlanır, URL segment fallback'i devreye girer.
|
|
52
|
+
*/
|
|
53
|
+
private menuItemsProvider;
|
|
54
|
+
setMenuItemsProvider(provider: () => PluginMenuItem[]): void;
|
|
55
|
+
/**
|
|
56
|
+
* Host shell anasayfa NavItem'ını sağlar — `AppLayoutComponent.homeNavItem` (menüdeki
|
|
57
|
+
* `root: true` öğesinden türetilir: navLink/navName/icon). Tüm tab'lar kapatıldığında
|
|
58
|
+
* liste boş kalmasın diye `openHomeTab` bunu kullanır; provider yoksa `/` + i18n fallback.
|
|
59
|
+
*/
|
|
60
|
+
private homeNavItemProvider;
|
|
61
|
+
setHomeNavItemProvider(provider: () => NavItem): void;
|
|
62
|
+
/**
|
|
63
|
+
* URL adres çubuğundan görülen aktif route — `TabAwareUrlSerializer` `_tab`'i strip
|
|
64
|
+
* ettiği için bu CLEAN URL'dir (ör. `/crm/address-management/search`). Tab navLink'leri
|
|
65
|
+
* de clean saklandığı için `r.navLink === activeRoute()` doğrudan karşılaştırılır.
|
|
66
|
+
*/
|
|
67
|
+
activeRoute: import("@angular/core").Signal<string | undefined>;
|
|
68
|
+
activeRoutes: import("@angular/core").WritableSignal<NavItem[]>;
|
|
69
|
+
/** History state'ten okunan aktif tab kimliği — `isActive(tab) = tab.tabId === activeTabId()`. */
|
|
70
|
+
activeTabId: import("@angular/core").WritableSignal<string>;
|
|
71
|
+
/**
|
|
72
|
+
* Chrome bookmark click davranışı: aktif tab'ın navLink/navName'i güncellenir,
|
|
73
|
+
* o tab'a navigate edilir. Yeni tab açılmaz. Mevcut tab'ın `tabId`'si KORUNUR —
|
|
74
|
+
* Router'a `?_tab=tabId` ile navigate edilir, history state'e yazılır; navLink
|
|
75
|
+
* storage'da CLEAN saklanır.
|
|
76
|
+
*/
|
|
77
|
+
navigateInCurrentTab(navItem: NavItem): void;
|
|
78
|
+
/**
|
|
79
|
+
* Arka planda yeni tab aç — aktif tab değişmez, navigate edilmez. `tabId` her zaman
|
|
80
|
+
* yeni üretilir (ya da caller verdiyse o kullanılır), exists check YOKTUR; aynı path
|
|
81
|
+
* birden fazla tab'da bağımsız yaşayabilir.
|
|
82
|
+
*/
|
|
83
|
+
openInBackgroundTab(navItem: NavItem): void;
|
|
84
|
+
/**
|
|
85
|
+
* Yeni tab aç ve o tab'a geç. Exists check YOK — aynı path'in iki ayrı tab'i kabul edilir;
|
|
86
|
+
* her tab kendi `tabId`'siyle ayrı componentRef instantiate eder.
|
|
87
|
+
*/
|
|
88
|
+
openInNewTabAndFocus(navItem: NavItem): void;
|
|
89
|
+
/** Programatik tab ekleme; activeRoute observable refresh path'i bunu kullanır. */
|
|
90
|
+
addToActiveRoutes(navItem: NavItem): void;
|
|
91
|
+
/**
|
|
92
|
+
* Aktif tab'ı `activeTabId` üzerinden bulur. Aynı `navLink`'in birden fazla tab'i
|
|
93
|
+
* olabileceği için navLink karşılaştırması ambiguous; tabId tek doğru kimlik.
|
|
94
|
+
*/
|
|
95
|
+
private findActiveTabIndex;
|
|
96
|
+
/** Tab limiti aşıldığında kullanıcıyı toast ile bilgilendirir. */
|
|
97
|
+
private notifyMaxTabsReached;
|
|
98
|
+
/** Anasayfa navLink'i — host menü root item'ından (yoksa '/'), clean format. */
|
|
99
|
+
private homeNavLink;
|
|
100
|
+
/** Verilen tab anasayfaya mı ait. */
|
|
101
|
+
private isHomeTab;
|
|
102
|
+
/**
|
|
103
|
+
* Anasayfa tab'ı açıp ona navigate eder — tab listesi HİÇ boş kalmamalı (en az 1 tab).
|
|
104
|
+
* NavItem host menü root item'ından gelir; yoksa `/` + i18n fallback ('tab.home', 'pi pi-home').
|
|
105
|
+
*/
|
|
106
|
+
private openHomeTab;
|
|
107
|
+
closeNavigation(navItem: NavItem): void;
|
|
108
|
+
/**
|
|
109
|
+
* Bir tab hariç diğer tüm tab'ları kapatır. Aktif tab kapatılanlardan ise `keepItem`'a geçer.
|
|
110
|
+
* **Sabit tab'lar korunur** (Chrome davranışı) — pinned olanlar her zaman açık kalır.
|
|
111
|
+
*/
|
|
112
|
+
closeOthers(keepItem: NavItem): void;
|
|
113
|
+
/**
|
|
114
|
+
* Verilen tab'ın sağındaki tüm tab'ları kapatır. **Sabit tab'lar korunur** —
|
|
115
|
+
* pinned bir tab sağda olsa bile kapatılmaz (Chrome davranışı).
|
|
116
|
+
*/
|
|
117
|
+
closeToRight(item: NavItem): void;
|
|
118
|
+
/**
|
|
119
|
+
* Sabit olmayan tüm tab'ları kapatır. **Sabit tab'lar korunur** — kullanıcı "Tümünü Kapat"
|
|
120
|
+
* isterse bile pinned tab'lar açık kalır (Chrome davranışı). Hiç pinned tab yoksa ana sayfaya
|
|
121
|
+
* navigate edilir.
|
|
122
|
+
*/
|
|
123
|
+
closeAll(): void;
|
|
124
|
+
/**
|
|
125
|
+
* Tab sabitleme toggle — Chrome-vari pinning. Pinned tab'lar tab bar'ın **soluna** taşınır
|
|
126
|
+
* (insertion sırasını koruyarak), kompakt görünür, `closeOthers`/`closeToRight`/`closeAll`
|
|
127
|
+
* çağrılarından korunur. Aynı pinned tıklanırsa sabitlemeyi kaldırır → normal alanın **sonuna**
|
|
128
|
+
* taşınır.
|
|
129
|
+
*/
|
|
130
|
+
togglePin(item: NavItem): void;
|
|
131
|
+
/** Sıradaki tab'a (circular) geçer. */
|
|
132
|
+
goToNextTab(): void;
|
|
133
|
+
/** Önceki tab'a (circular) geçer. */
|
|
134
|
+
goToPrevTab(): void;
|
|
135
|
+
/** Index'teki tab'a geçer (Alt+1..9 için 0-tabanlı index). */
|
|
136
|
+
goToTabByIndex(index: number): void;
|
|
137
|
+
/**
|
|
138
|
+
* Verilen tab'a navigate — UI'dan (tab tıklama) çağrılır. Router'a `_tab` ile URL ve
|
|
139
|
+
* `extras.state` ile tabId verir; UrlSerializer adres çubuğunu temiz tutar.
|
|
140
|
+
*/
|
|
141
|
+
navigateToTab(item: NavItem): void;
|
|
142
|
+
/**
|
|
143
|
+
* Belirli bir tab'ın `navLink`'ini ve (varsa) `navName`'ini günceller. **Kaynağa-bağlı**
|
|
144
|
+
* (per-tab) sync — caller hangi tab'ın URL'i olduğunu söyler, NavService aktif tab
|
|
145
|
+
* varsayımında bulunmaz. Hidden container'daki async MFE NavigationEnd'leri aktif tab'ın
|
|
146
|
+
* state'ini KONTAMİNE EDEMEZ.
|
|
147
|
+
*
|
|
148
|
+
* `title` parametresi MFE Router deepest route'unun `Route.title` veya `data.tabName`
|
|
149
|
+
* değerinden gelir → kullanıcı detail/edit gibi sub-sayfalara navigate olduğunda tab
|
|
150
|
+
* adı dinamik güncellenir. `title` undefined ise tab.navName değişmez (statik kalır).
|
|
151
|
+
*
|
|
152
|
+
* AppLayoutComponent effect'ten `bridge.activeMFEUrl` (`{tabId, url, title}`) ile çağrılır.
|
|
153
|
+
*/
|
|
154
|
+
syncActiveTabNavLinkForTab(tabId: string, rawUrl: string, title?: string): void;
|
|
155
|
+
/**
|
|
156
|
+
* Tab context-menu "Yinele" (Chrome "Duplicate"): mevcut tab'ın path'i kopyalanır, yeni bir
|
|
157
|
+
* `tabId` üretilir ve yeni tab oluşturulur. Strategy `_tab` query param'ını route key'in
|
|
158
|
+
* parçası yaptığı için yeni tab bağımsız `storedRoutes` slot'una yazılır → bağımsız
|
|
159
|
+
* componentRef + state. Mevcut tab korunur, kullanıcı her ikisinde de bağımsız çalışabilir.
|
|
160
|
+
*/
|
|
161
|
+
duplicateTab(item: NavItem): void;
|
|
162
|
+
reorderActiveRoutes(newRoutes: NavItem[]): void;
|
|
163
|
+
/**
|
|
164
|
+
* Menu config'inden navLink'e karşılık gelen item'i longest-prefix match ile bulup
|
|
165
|
+
* aktif dilde label + icon döner. Adres çubuğuna URL yapıştırarak deep link açıldığında
|
|
166
|
+
* tab'ın menüden açılan tab'la aynı görünüme sahip olmasını sağlar.
|
|
167
|
+
*
|
|
168
|
+
* Lookup `menuItemsProvider` üzerinden — host shell `setMenuItemsProvider` ile
|
|
169
|
+
* `bridge.hostMenuItems()`'a bağlar. Provider yoksa veya eşleşme yoksa `null` döner ve
|
|
170
|
+
* caller URL segment fallback'ine düşer.
|
|
171
|
+
*/
|
|
172
|
+
private resolveNavInfoFromMenu;
|
|
173
|
+
/**
|
|
174
|
+
* Menü/i18n yüklenince tab'ları (özellikle anasayfa) menüyle revize eder — refresh/ilk açılış
|
|
175
|
+
* path'inde tab fallback isim/iconla eklenmiş olabilir (menü veya çeviri o anda hazır değildi).
|
|
176
|
+
* Tetikleyiciler: `setMenuItemsProvider`/`setHomeNavItemProvider`, `translationLoadSuccess`
|
|
177
|
+
* event'i ve host shell menü signal'i değişimi (`AppLayoutComponent` effect). Public — host
|
|
178
|
+
* layout menü async yüklenince çağırır ki anasayfa adı `tab.home` fallback'inde takılmasın.
|
|
179
|
+
*/
|
|
180
|
+
reconcileTabsWithMenu(): void;
|
|
181
|
+
/**
|
|
182
|
+
* Menu ağacında verilen path için en spesifik (longest routerLink prefix) eşleşmeyi bulur.
|
|
183
|
+
* `mw/app-management/view-app` için hem `mw` hem `mw/app-management/view-app` eşleşse,
|
|
184
|
+
* daha uzun olan kazanır → leaf menu item'ın label/icon'u kullanılır.
|
|
185
|
+
*
|
|
186
|
+
* Path leading slash içerebilir (Router URL formatı), menu config routerLink'leri
|
|
187
|
+
* genelde leading slash'sız (`mw/meters`); ikisini normalize edip karşılaştırırız.
|
|
188
|
+
*/
|
|
189
|
+
private findMenuItemForRoute;
|
|
190
|
+
/**
|
|
191
|
+
* Bir tab'ın stored route handle'ını strategy'den temizler. Key formatı
|
|
192
|
+
* `mfe:${remoteName}:${tabId}` — strategy `processCleanupKey` matcher key'inden hem
|
|
193
|
+
* MFE custom element handle'ını hem o tab'a ait child route handle'larını düşürür.
|
|
194
|
+
*/
|
|
195
|
+
private cleanupTabHandle;
|
|
196
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NavService, never>;
|
|
197
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<NavService>;
|
|
198
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
export declare class RouteCloseService {
|
|
3
|
+
deleteRoute: import("@angular/core").WritableSignal<{
|
|
4
|
+
key: string | null;
|
|
5
|
+
}>;
|
|
6
|
+
deleteStoredRoute(key: string): void;
|
|
7
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<RouteCloseService, never>;
|
|
8
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<RouteCloseService>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NavigationBehaviorOptions, Router } from '@angular/router';
|
|
2
|
+
/**
|
|
3
|
+
* `Router.navigateByUrl` wrapper'ı — `AbortError`'ı caller için "navigation cancelled"
|
|
4
|
+
* sinyali olarak değerlendirip Promise'i `false` ile resolve eder.
|
|
5
|
+
*
|
|
6
|
+
* **Neden**: Angular Router pending bir navigation cycle aktifken yeni `navigateByUrl`
|
|
7
|
+
* çağrılırsa, eski cycle'ı **kasıtlı olarak iptal eder** ("son navigation kazanır" semantiği)
|
|
8
|
+
* ve eski Promise'ı `AbortError: Transition was skipped` ile reject eder. Bu hata değil,
|
|
9
|
+
* Router'ın akış kontrolüdür — eski navigation zaten anlamsız çünkü kullanıcı yeni bir
|
|
10
|
+
* hedefe yöneldi. Caller'ın bu rejection'ı silently handle etmesi BEKLENİR. Aksi halde
|
|
11
|
+
* "Uncaught (in promise) AbortError" console gürültüsü oluşur.
|
|
12
|
+
*
|
|
13
|
+
* Bu helper bütün NavService + MFE bootstrap relay + AppLayoutComponent çağrılarını
|
|
14
|
+
* tek noktadan tutarlı handle eder. Diğer hata türleri (`NavigationError`, runtime exception)
|
|
15
|
+
* normal şekilde reject edilir — gerçekten beklenmeyen sorunlar yutulmaz.
|
|
16
|
+
*/
|
|
17
|
+
export declare function safeNavigate(router: Router, url: string, extras?: NavigationBehaviorOptions): Promise<boolean>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { DefaultUrlSerializer, UrlTree } from '@angular/router';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* `_tab` query param'ını adres çubuğunda gizleyen `UrlSerializer`. Param Router'ın
|
|
5
|
+
* internal `UrlTree.queryParams`'ında korunur (parse imzasız, default davranış);
|
|
6
|
+
* sadece `serialize` çıktısı üzerinden — yani `Router.url`, `NavigationEnd.urlAfterRedirects`
|
|
7
|
+
* ve browser address bar — `_tab` strip edilir.
|
|
8
|
+
*
|
|
9
|
+
* **Sonuç**: `CustomRouteReuseStrategy.getRouteKey` `route.queryParams['_tab']`'ı
|
|
10
|
+
* normal şekilde okumaya devam eder (parse path'inde değişiklik yok), ama kullanıcının
|
|
11
|
+
* gördüğü URL temizdir.
|
|
12
|
+
*
|
|
13
|
+
* **NavService etkisi**: `activeRoute()` artık `_tab` taşımaz. Aktif tab tespiti
|
|
14
|
+
* `activeTabId` signal'i üzerinden yapılmalı (NavService bunu `window.history.state`'ten
|
|
15
|
+
* okur — `navigateByUrl(url, { state: { _tab } })` ile her navigation'da set edilir).
|
|
16
|
+
*/
|
|
17
|
+
export declare class TabAwareUrlSerializer extends DefaultUrlSerializer {
|
|
18
|
+
/** `parse` default davranışla bırakıldı — input URL'inde `_tab` varsa korunur (refresh deep link). */
|
|
19
|
+
serialize(tree: UrlTree): string;
|
|
20
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<TabAwareUrlSerializer, never>;
|
|
21
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<TabAwareUrlSerializer>;
|
|
22
|
+
}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { NgZone } from '@angular/core';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Host shell'in NgZone'unu MFE/plugin Application'a inject eder (paylaşımlı zone).
|
|
4
|
+
*
|
|
5
|
+
* `hostNgZone` host bootstrap'inde (`AppComponent` constructor'ında `inject(NgZone)`)
|
|
6
|
+
* set ediliyor. `getNgZone()` MFE/plugin bootstrap zamanında çağrılıyor → o anda
|
|
7
|
+
* `hostNgZone` set edilmiş olmalı. Set edilmemişse explicit error: silent `undefined`
|
|
8
|
+
* provider DI hatası "no provider for NgZone" gibi yanıltıcı bir mesajla patlardı.
|
|
9
|
+
*/
|
|
10
|
+
export declare const getNgZone: () => {
|
|
3
11
|
provide: typeof NgZone;
|
|
4
12
|
useValue: NgZone;
|
|
5
13
|
};
|
|
@@ -3,16 +3,27 @@ import { PrimeNGConfig } from 'primeng/api';
|
|
|
3
3
|
import { TranslocoService } from '@ngneat/transloco';
|
|
4
4
|
import { MfeBridge } from 'aril/boot/bridge';
|
|
5
5
|
import { LanguageCode } from 'aril/boot/config/translate';
|
|
6
|
-
import { AppMenuService } from 'aril/theme/layout';
|
|
7
6
|
import * as i0 from "@angular/core";
|
|
7
|
+
/**
|
|
8
|
+
* Tab izolasyonlu MFE app root.
|
|
9
|
+
*
|
|
10
|
+
* Her `<app-${appName}>` custom element instance'ı kendi `createApplication`'ını yarattığı için
|
|
11
|
+
* (bkz. `bootstrap.ts` `MFEAppElement`), `AppComponent` constructor'ı her tab için **bağımsız**
|
|
12
|
+
* çalışır — paylaşılan Injector/Router yok. Bu yüzden host Router subscription'ı her tab için
|
|
13
|
+
* ayrı kurulur ama "tab-id filter" ile **sadece o tab'a ait** `NavigationEnd`'leri MFE Router'a
|
|
14
|
+
* iletir; diğer tab'lerin navigation'ları ignore edilir.
|
|
15
|
+
*
|
|
16
|
+
* Tab kimliği `<app-${appName}>` element'inde `aril-tab-id` attribute olarak yazılır
|
|
17
|
+
* (`ArilWebComponentWrapper` route.queryParams._tab'ten okuyup set eder). Filter karşılaştırması:
|
|
18
|
+
* `window.history.state._tab === tabId` — `navigateToTab` `extras.state._tab` ile yazıyor.
|
|
19
|
+
*/
|
|
8
20
|
export declare class AppComponent {
|
|
9
21
|
private readonly router;
|
|
10
22
|
private readonly translocoService;
|
|
11
|
-
private readonly appMenuService;
|
|
12
23
|
private readonly primeNgConfig;
|
|
13
24
|
private readonly bridgeSvc;
|
|
14
|
-
|
|
15
|
-
|
|
25
|
+
private readonly elementRef;
|
|
26
|
+
constructor(router: Router, translocoService: TranslocoService, primeNgConfig: PrimeNGConfig, bridgeSvc: MfeBridge);
|
|
16
27
|
setLocale(lang: LanguageCode): void;
|
|
17
28
|
static ɵfac: i0.ɵɵFactoryDeclaration<AppComponent, never>;
|
|
18
29
|
static ɵcmp: i0.ɵɵComponentDeclaration<AppComponent, "ng-component", never, {}, {}, never, never, true, never>;
|