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
|
@@ -7,11 +7,9 @@ import { Subscription } from 'rxjs';
|
|
|
7
7
|
import { PluginMenuItem } from 'aril/boot/config/apps';
|
|
8
8
|
import { TranslateJsonPipe } from 'aril/util/pipes';
|
|
9
9
|
import { LayoutService } from '../../service/app.layout.service';
|
|
10
|
-
import { AppMenuService } from '../../service/app.menu.service';
|
|
11
10
|
import * as i0 from "@angular/core";
|
|
12
11
|
export declare class ExpandableMenuComponent implements OnInit, OnDestroy {
|
|
13
12
|
private translateJsonPipe;
|
|
14
|
-
private menuService;
|
|
15
13
|
private router;
|
|
16
14
|
private keycloak;
|
|
17
15
|
private translocoService;
|
|
@@ -50,7 +48,8 @@ export declare class ExpandableMenuComponent implements OnInit, OnDestroy {
|
|
|
50
48
|
private readonly MAX_LENGTH;
|
|
51
49
|
actionLoadingItems: Set<string>;
|
|
52
50
|
private actionSubscription;
|
|
53
|
-
|
|
51
|
+
private readonly navService;
|
|
52
|
+
constructor(translateJsonPipe: TranslateJsonPipe, router: Router, keycloak: KeycloakService, translocoService: TranslocoService, layoutService: LayoutService, http: HttpClient);
|
|
54
53
|
get selectedMainItem(): number | null;
|
|
55
54
|
get secondarySidebarExpanded(): boolean;
|
|
56
55
|
isTextTruncated(label: any, lang: string | null, menuType?: 'main' | 'secondary' | 'tertiary' | 'nested'): boolean;
|
|
@@ -61,18 +60,36 @@ export declare class ExpandableMenuComponent implements OnInit, OnDestroy {
|
|
|
61
60
|
updateMenuFromRootKey(index: number): void;
|
|
62
61
|
updateMenuItems(): void;
|
|
63
62
|
getMenuItems(): PluginMenuItem[];
|
|
64
|
-
selectMainItem(index: number, item: PluginMenuItem): void;
|
|
63
|
+
selectMainItem(event: MouseEvent, index: number, item: PluginMenuItem): void;
|
|
65
64
|
toggleSecondarySidebar(): void;
|
|
66
65
|
isMobile(): boolean;
|
|
67
66
|
onResize(): void;
|
|
68
67
|
updateActiveMenuFromCurrentRoute(): void;
|
|
69
68
|
isHaveSelectedChildItem(item: PluginMenuItem): boolean;
|
|
70
69
|
getLocalText(text: any): string;
|
|
70
|
+
/**
|
|
71
|
+
* Hash strategy için routerLink'i `#`-prefix'li href'e çevirir. routerLink config'te
|
|
72
|
+
* leading slash içerebilir (örn. anasayfa için `'/'`); naive `'#/' + routerLink`
|
|
73
|
+
* concatenation `#//` üretirdi — sağ tık "linki kopyala" UX'inde bu çirkin görünür.
|
|
74
|
+
*/
|
|
75
|
+
getHashHref(routerLink: string | undefined | null): string;
|
|
71
76
|
getActionItemKey(item: PluginMenuItem): string;
|
|
72
77
|
isActionLoading(item: PluginMenuItem): boolean;
|
|
73
78
|
onActionItemClick(item: PluginMenuItem, event?: Event): void;
|
|
74
79
|
private buildSuccessRoute;
|
|
75
80
|
private getValueByPath;
|
|
81
|
+
/**
|
|
82
|
+
* Chrome-like menü click davranışı (secondary/tertiary/nested seviyeleri için):
|
|
83
|
+
* - Normal click → aktif tab'da navigate
|
|
84
|
+
* - Ctrl/Cmd + Click → arka planda yeni tab
|
|
85
|
+
* - Ctrl/Cmd + Shift + Click → ön planda yeni tab
|
|
86
|
+
*/
|
|
87
|
+
onMenuClick(event: MouseEvent, item: PluginMenuItem): void;
|
|
88
|
+
/** Middle click (button 1) → arka planda yeni tab. */
|
|
89
|
+
onMenuAuxClick(event: MouseEvent, item: PluginMenuItem): void;
|
|
90
|
+
/** Middle click default scroll davranışını engelle. */
|
|
91
|
+
onMenuMousedown(event: MouseEvent): void;
|
|
92
|
+
private dispatchNavigation;
|
|
76
93
|
toggleSidebar(): void;
|
|
77
94
|
static ɵfac: i0.ɵɵFactoryDeclaration<ExpandableMenuComponent, never>;
|
|
78
95
|
static ɵcmp: i0.ɵɵComponentDeclaration<ExpandableMenuComponent, "app-expandable-menu", never, {}, {}, never, never, true, never>;
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
@if(!item.separator){
|
|
8
8
|
<li
|
|
9
9
|
[ngClass]="{'active': isActiveRoute(item) || isHaveSelectedChildItem(item)}"
|
|
10
|
-
(click)="selectMainItem(i, item)"
|
|
10
|
+
(click)="selectMainItem($event, i, item)"
|
|
11
|
+
(auxclick)="onMenuAuxClick($event, item)"
|
|
12
|
+
(mousedown)="onMenuMousedown($event)"
|
|
11
13
|
[pTooltip]="(item.label && activeLang() ? item.label[activeLang()!] || '' : '')"
|
|
12
14
|
tooltipPosition="right">
|
|
13
15
|
<div class="main-menu-item">
|
|
@@ -55,7 +57,11 @@
|
|
|
55
57
|
} @else {
|
|
56
58
|
<!-- Regular menu item -->
|
|
57
59
|
<li class="secondary-menu-item" [ngClass]="{'active': isActiveRoute(subItem)}">
|
|
58
|
-
<a [
|
|
60
|
+
<a [attr.href]="subItem.routerLink ? getHashHref(subItem.routerLink) : null"
|
|
61
|
+
[arilNavLink]="{ tabId: '', navLink: subItem.routerLink || '', navName: getLocalText(subItem.label), icon: subItem.icon }"
|
|
62
|
+
(click)="onMenuClick($event, subItem)"
|
|
63
|
+
(auxclick)="onMenuAuxClick($event, subItem)"
|
|
64
|
+
(mousedown)="onMenuMousedown($event)"
|
|
59
65
|
class="secondary-menu-link"
|
|
60
66
|
[pTooltip]="!isMobile() && isTextTruncated(subItem.label, activeLang(), 'secondary') ? (subItem.label && activeLang() ? subItem.label[activeLang()!] || '' : '') : ''"
|
|
61
67
|
tooltipPosition="right">
|
|
@@ -82,7 +88,11 @@
|
|
|
82
88
|
</li>
|
|
83
89
|
} @else {
|
|
84
90
|
<li class="tertiary-menu-item" [ngClass]="{'active': isActiveRoute(childItem)}">
|
|
85
|
-
<a [
|
|
91
|
+
<a [attr.href]="childItem.routerLink ? getHashHref(childItem.routerLink) : null"
|
|
92
|
+
[arilNavLink]="{ tabId: '', navLink: childItem.routerLink || '', navName: getLocalText(childItem.label), icon: childItem.icon }"
|
|
93
|
+
(click)="onMenuClick($event, childItem)"
|
|
94
|
+
(auxclick)="onMenuAuxClick($event, childItem)"
|
|
95
|
+
(mousedown)="onMenuMousedown($event)"
|
|
86
96
|
class="tertiary-menu-link"
|
|
87
97
|
[pTooltip]="!isMobile() && isTextTruncated(childItem.label, activeLang(), 'tertiary') ? (childItem.label && activeLang() ? childItem.label[activeLang()!] || '' : '') : ''"
|
|
88
98
|
tooltipPosition="right">
|
|
@@ -106,10 +116,14 @@
|
|
|
106
116
|
</a>
|
|
107
117
|
</li>
|
|
108
118
|
} @else {
|
|
109
|
-
<li
|
|
119
|
+
<li
|
|
110
120
|
class="nested-menu-item"
|
|
111
121
|
[ngClass]="{'active': isActiveRoute(nestedItem)}">
|
|
112
|
-
<a [
|
|
122
|
+
<a [attr.href]="nestedItem.routerLink ? getHashHref(nestedItem.routerLink) : null"
|
|
123
|
+
[arilNavLink]="{ tabId: '', navLink: nestedItem.routerLink || '', navName: getLocalText(nestedItem.label), icon: nestedItem.icon }"
|
|
124
|
+
(click)="onMenuClick($event, nestedItem)"
|
|
125
|
+
(auxclick)="onMenuAuxClick($event, nestedItem)"
|
|
126
|
+
(mousedown)="onMenuMousedown($event)"
|
|
113
127
|
class="nested-menu-link"
|
|
114
128
|
[pTooltip]="!isMobile() && isTextTruncated(nestedItem.label, activeLang(), 'nested') ? (nestedItem.label && activeLang() ? nestedItem.label[activeLang()!] || '' : '') : ''"
|
|
115
129
|
tooltipPosition="right">
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { NgClass } from '@angular/common';
|
|
2
2
|
import { HttpClient } from '@angular/common/http';
|
|
3
|
-
import { Component, HostListener, OnDestroy, OnInit, Signal } from '@angular/core';
|
|
3
|
+
import { Component, HostListener, OnDestroy, OnInit, Signal, inject } from '@angular/core';
|
|
4
4
|
import { toSignal } from '@angular/core/rxjs-interop';
|
|
5
|
-
import { NavigationEnd, Router
|
|
5
|
+
import { NavigationEnd, Router } from '@angular/router';
|
|
6
6
|
|
|
7
7
|
import { TooltipModule } from 'primeng/tooltip';
|
|
8
8
|
|
|
@@ -11,16 +11,15 @@ import { KeycloakService } from 'keycloak-angular';
|
|
|
11
11
|
import { Subscription, filter } from 'rxjs';
|
|
12
12
|
|
|
13
13
|
import { bridge } from 'aril/boot/bridge';
|
|
14
|
-
import { PluginMenuItem } from 'aril/boot/config/apps';
|
|
14
|
+
import { NavItem, NavLinkDirective, NavService, PluginMenuItem } from 'aril/boot/config/apps';
|
|
15
15
|
import { TranslateJsonPipe } from 'aril/util/pipes';
|
|
16
16
|
|
|
17
17
|
import { LayoutService } from '../../service/app.layout.service';
|
|
18
|
-
import { AppMenuService } from '../../service/app.menu.service';
|
|
19
18
|
|
|
20
19
|
@Component({
|
|
21
20
|
standalone: true,
|
|
22
21
|
selector: 'app-expandable-menu',
|
|
23
|
-
imports: [
|
|
22
|
+
imports: [NgClass, TooltipModule, NavLinkDirective],
|
|
24
23
|
templateUrl: 'expandable-menu.component.html',
|
|
25
24
|
providers: [TranslateJsonPipe]
|
|
26
25
|
})
|
|
@@ -73,10 +72,10 @@ export class ExpandableMenuComponent implements OnInit, OnDestroy {
|
|
|
73
72
|
|
|
74
73
|
actionLoadingItems = new Set<string>();
|
|
75
74
|
private actionSubscription: Subscription | null = null;
|
|
75
|
+
private readonly navService = inject(NavService);
|
|
76
76
|
|
|
77
77
|
constructor(
|
|
78
78
|
private translateJsonPipe: TranslateJsonPipe,
|
|
79
|
-
private menuService: AppMenuService,
|
|
80
79
|
private router: Router,
|
|
81
80
|
private keycloak: KeycloakService,
|
|
82
81
|
private translocoService: TranslocoService,
|
|
@@ -195,14 +194,14 @@ export class ExpandableMenuComponent implements OnInit, OnDestroy {
|
|
|
195
194
|
}
|
|
196
195
|
|
|
197
196
|
updateMenuItems(): void {
|
|
198
|
-
this.cachedMenuItems = bridge.
|
|
197
|
+
this.cachedMenuItems = bridge.hostMenuItems();
|
|
199
198
|
}
|
|
200
199
|
|
|
201
200
|
getMenuItems(): PluginMenuItem[] {
|
|
202
201
|
return this.cachedMenuItems;
|
|
203
202
|
}
|
|
204
203
|
|
|
205
|
-
selectMainItem(index: number, item: PluginMenuItem): void {
|
|
204
|
+
selectMainItem(event: MouseEvent, index: number, item: PluginMenuItem): void {
|
|
206
205
|
// Handle action items at top level
|
|
207
206
|
if (item.action && (!item.items || item.items.length === 0)) {
|
|
208
207
|
this.onActionItemClick(item);
|
|
@@ -213,7 +212,12 @@ export class ExpandableMenuComponent implements OnInit, OnDestroy {
|
|
|
213
212
|
this.layoutService.setSecondarySidebarExpanded(false);
|
|
214
213
|
this.layoutService.setSelectedMainItem(index);
|
|
215
214
|
this.selectedMainMenuItem = item;
|
|
216
|
-
this.
|
|
215
|
+
this.dispatchNavigation(event, {
|
|
216
|
+
tabId: '',
|
|
217
|
+
navLink: item.routerLink,
|
|
218
|
+
navName: this.getLocalText(item.label),
|
|
219
|
+
icon: item.icon
|
|
220
|
+
});
|
|
217
221
|
return;
|
|
218
222
|
}
|
|
219
223
|
|
|
@@ -296,6 +300,16 @@ export class ExpandableMenuComponent implements OnInit, OnDestroy {
|
|
|
296
300
|
return this.translateJsonPipe.transform(text);
|
|
297
301
|
}
|
|
298
302
|
|
|
303
|
+
/**
|
|
304
|
+
* Hash strategy için routerLink'i `#`-prefix'li href'e çevirir. routerLink config'te
|
|
305
|
+
* leading slash içerebilir (örn. anasayfa için `'/'`); naive `'#/' + routerLink`
|
|
306
|
+
* concatenation `#//` üretirdi — sağ tık "linki kopyala" UX'inde bu çirkin görünür.
|
|
307
|
+
*/
|
|
308
|
+
getHashHref(routerLink: string | undefined | null): string {
|
|
309
|
+
if (!routerLink) return '#';
|
|
310
|
+
return routerLink.startsWith('/') ? '#' + routerLink : '#/' + routerLink;
|
|
311
|
+
}
|
|
312
|
+
|
|
299
313
|
getActionItemKey(item: PluginMenuItem): string {
|
|
300
314
|
return item.action?.url + '|' + item.action?.successRoute;
|
|
301
315
|
}
|
|
@@ -362,6 +376,52 @@ export class ExpandableMenuComponent implements OnInit, OnDestroy {
|
|
|
362
376
|
}, obj);
|
|
363
377
|
}
|
|
364
378
|
|
|
379
|
+
/**
|
|
380
|
+
* Chrome-like menü click davranışı (secondary/tertiary/nested seviyeleri için):
|
|
381
|
+
* - Normal click → aktif tab'da navigate
|
|
382
|
+
* - Ctrl/Cmd + Click → arka planda yeni tab
|
|
383
|
+
* - Ctrl/Cmd + Shift + Click → ön planda yeni tab
|
|
384
|
+
*/
|
|
385
|
+
onMenuClick(event: MouseEvent, item: PluginMenuItem): void {
|
|
386
|
+
if (!item.routerLink) return;
|
|
387
|
+
event.preventDefault();
|
|
388
|
+
this.dispatchNavigation(event, {
|
|
389
|
+
tabId: '',
|
|
390
|
+
navLink: item.routerLink,
|
|
391
|
+
navName: this.getLocalText(item.label),
|
|
392
|
+
icon: item.icon
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/** Middle click (button 1) → arka planda yeni tab. */
|
|
397
|
+
onMenuAuxClick(event: MouseEvent, item: PluginMenuItem): void {
|
|
398
|
+
if (event.button !== 1 || !item.routerLink) return;
|
|
399
|
+
event.preventDefault();
|
|
400
|
+
this.navService.openInBackgroundTab({
|
|
401
|
+
tabId: '',
|
|
402
|
+
navLink: item.routerLink,
|
|
403
|
+
navName: this.getLocalText(item.label),
|
|
404
|
+
icon: item.icon
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/** Middle click default scroll davranışını engelle. */
|
|
409
|
+
onMenuMousedown(event: MouseEvent): void {
|
|
410
|
+
if (event.button === 1) event.preventDefault();
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
private dispatchNavigation(event: MouseEvent, navItem: NavItem): void {
|
|
414
|
+
if (event.ctrlKey || event.metaKey) {
|
|
415
|
+
if (event.shiftKey) {
|
|
416
|
+
this.navService.openInNewTabAndFocus(navItem);
|
|
417
|
+
} else {
|
|
418
|
+
this.navService.openInBackgroundTab(navItem);
|
|
419
|
+
}
|
|
420
|
+
} else {
|
|
421
|
+
this.navService.navigateInCurrentTab(navItem);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
365
425
|
toggleSidebar() {
|
|
366
426
|
// Eğer seçili bir ana menü öğesi varsa ve alt menüleri varsa toggle yapabiliriz
|
|
367
427
|
if (this.selectedMainMenuItem && this.selectedMainMenuItem.items && this.selectedMainMenuItem.items.length > 0) {
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
<div
|
|
52
52
|
class="favorite-item"
|
|
53
53
|
[class.default-item]="favorite.id < 0"
|
|
54
|
+
[arilNavLink]="{ tabId: '', navLink: favorite.url, navName: favorite.label }"
|
|
54
55
|
(click)="navigateToFavorite(favorite)"
|
|
55
56
|
[pTooltip]="getFullUrl(favorite.url)"
|
|
56
57
|
tooltipPosition="top">
|
|
@@ -13,6 +13,7 @@ import { TooltipModule } from 'primeng/tooltip';
|
|
|
13
13
|
import { TranslocoModule, TranslocoService } from '@ngneat/transloco';
|
|
14
14
|
import { Subject, switchMap } from 'rxjs';
|
|
15
15
|
|
|
16
|
+
import { NavLinkDirective } from 'aril/boot/config/apps';
|
|
16
17
|
import { ButtonComponent } from 'aril/ui/button';
|
|
17
18
|
|
|
18
19
|
import { LayoutService } from '../../service/app.layout.service';
|
|
@@ -34,7 +35,8 @@ import { solidIcons } from 'aril/util/lib';
|
|
|
34
35
|
ButtonComponent,
|
|
35
36
|
TranslocoModule,
|
|
36
37
|
TooltipModule,
|
|
37
|
-
FontAwesomeModule
|
|
38
|
+
FontAwesomeModule,
|
|
39
|
+
NavLinkDirective
|
|
38
40
|
],
|
|
39
41
|
templateUrl: './favorite-pages-sidebar.component.html',
|
|
40
42
|
styleUrls: ['./favorite-pages-sidebar.component.scss'],
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
</div>
|
|
30
30
|
</ng-template>
|
|
31
31
|
<ng-template let-result pTemplate="item">
|
|
32
|
-
<div class="flex items-center gap-2"
|
|
32
|
+
<div class="flex items-center gap-2"
|
|
33
|
+
[arilNavLink]="result.url ? { tabId: '', navLink: result.url, navName: result.title } : null">
|
|
33
34
|
<div class="result-icon">
|
|
34
35
|
<i class="pi {{ result.icon }}"></i>
|
|
35
36
|
</div>
|
|
@@ -11,7 +11,7 @@ import { of, startWith, Subject } from 'rxjs';
|
|
|
11
11
|
import { catchError, filter, map, switchMap } from 'rxjs/operators';
|
|
12
12
|
|
|
13
13
|
import { bridge } from 'aril/boot/bridge';
|
|
14
|
-
import { Apps } from 'aril/boot/config/apps';
|
|
14
|
+
import { Apps, NavLinkDirective } from 'aril/boot/config/apps';
|
|
15
15
|
|
|
16
16
|
import { SearchService } from '../../service/search.service';
|
|
17
17
|
import { getPresentableData } from './helpers';
|
|
@@ -20,7 +20,7 @@ import { CacheSearchRequestDTO, DefaultSearchAggregateAssetAggregate, Presentabl
|
|
|
20
20
|
@Component({
|
|
21
21
|
selector: 'app-general-search',
|
|
22
22
|
standalone: true,
|
|
23
|
-
imports: [CommonModule, FormsModule, TranslocoModule, AutoCompleteModule],
|
|
23
|
+
imports: [CommonModule, FormsModule, TranslocoModule, AutoCompleteModule, NavLinkDirective],
|
|
24
24
|
templateUrl: './general-search.component.html',
|
|
25
25
|
styleUrls: ['./general-search.component.scss']
|
|
26
26
|
})
|
|
@@ -41,7 +41,9 @@
|
|
|
41
41
|
<p-scrollPanel [style]="{ width: '100%', height: '100%' }">
|
|
42
42
|
<div class="history-items">
|
|
43
43
|
@for (item of filteredHistory(); track trackByItemId($index, item)) {
|
|
44
|
-
<div class="history-item"
|
|
44
|
+
<div class="history-item"
|
|
45
|
+
[arilNavLink]="{ tabId: '', navLink: item.url, navName: getLocalizedTitle(item) }"
|
|
46
|
+
(click)="navigateToItem(item)">
|
|
45
47
|
<div class="item-content">
|
|
46
48
|
<div class="item-header">
|
|
47
49
|
<div class="item-title">
|
|
@@ -13,6 +13,7 @@ import { TooltipModule } from 'primeng/tooltip';
|
|
|
13
13
|
import { TranslocoModule, TranslocoService } from '@ngneat/transloco';
|
|
14
14
|
import { Subject, takeUntil } from 'rxjs';
|
|
15
15
|
|
|
16
|
+
import { NavLinkDirective } from 'aril/boot/config/apps';
|
|
16
17
|
import { ButtonComponent } from 'aril/ui/button';
|
|
17
18
|
import { TextComponent } from 'aril/ui/text';
|
|
18
19
|
|
|
@@ -36,7 +37,8 @@ import { solidIcons } from 'aril/util/lib';
|
|
|
36
37
|
BadgeModule,
|
|
37
38
|
TranslocoModule,
|
|
38
39
|
TextComponent,
|
|
39
|
-
FontAwesomeModule
|
|
40
|
+
FontAwesomeModule,
|
|
41
|
+
NavLinkDirective
|
|
40
42
|
],
|
|
41
43
|
templateUrl: './history-sidebar.component.html',
|
|
42
44
|
styleUrls: ['./history-sidebar.component.scss'],
|
|
@@ -1,24 +1,124 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CdkDragDrop } from '@angular/cdk/drag-drop';
|
|
2
|
+
import { AfterViewInit, ElementRef, OnDestroy, Renderer2 } from '@angular/core';
|
|
2
3
|
import { Router } from '@angular/router';
|
|
4
|
+
import { MenuItem } from 'primeng/api';
|
|
5
|
+
import { ContextMenu } from 'primeng/contextmenu';
|
|
3
6
|
import { Subscription } from 'rxjs';
|
|
7
|
+
import { NavItem, NavService } from 'aril/boot/config/apps';
|
|
8
|
+
import { TranslateJsonPipe } from 'aril/util/pipes';
|
|
4
9
|
import { LayoutService } from '../../service/app.layout.service';
|
|
5
10
|
import { AppMenuService } from '../../service/app.menu.service';
|
|
6
|
-
import { AppTopbarComponent } from '../topbar/app.topbar.component';
|
|
7
11
|
import { ExpandableMenuComponent } from '../expandableMenu/expandable-menu.component';
|
|
8
12
|
import { StaticSidebarComponent } from '../static-sidebar/static-sidebar.component';
|
|
13
|
+
import { AppTopbarComponent } from '../topbar/app.topbar.component';
|
|
9
14
|
import * as i0 from "@angular/core";
|
|
10
|
-
export declare class AppLayoutComponent implements OnDestroy {
|
|
11
|
-
private menuService;
|
|
15
|
+
export declare class AppLayoutComponent implements OnDestroy, AfterViewInit {
|
|
16
|
+
private readonly menuService;
|
|
12
17
|
layoutService: LayoutService;
|
|
13
18
|
renderer: Renderer2;
|
|
14
19
|
router: Router;
|
|
20
|
+
private readonly translateJsonPipe;
|
|
15
21
|
overlayMenuOpenSubscription: Subscription;
|
|
16
22
|
menuOutsideClickListener: any;
|
|
17
23
|
menuScrollListener: any;
|
|
18
24
|
expandableMenuComponent: ExpandableMenuComponent;
|
|
19
25
|
staticSidebarComponent: StaticSidebarComponent;
|
|
20
26
|
appTopbar: AppTopbarComponent;
|
|
21
|
-
|
|
27
|
+
tabsContainer?: ElementRef<HTMLDivElement>;
|
|
28
|
+
tabContextMenu?: ContextMenu;
|
|
29
|
+
navLinkContextMenu?: ContextMenu;
|
|
30
|
+
navService: NavService;
|
|
31
|
+
private readonly translocoService;
|
|
32
|
+
private readonly navLinkContextMenuService;
|
|
33
|
+
private readonly tabSession;
|
|
34
|
+
tabContextMenuItems: MenuItem[];
|
|
35
|
+
/** Tab bar yatay scroll konum/genişlik durumu. Chevron butonlarının görünürlüğünü kontrol eder. */
|
|
36
|
+
canScrollLeft: import("@angular/core").WritableSignal<boolean>;
|
|
37
|
+
canScrollRight: import("@angular/core").WritableSignal<boolean>;
|
|
38
|
+
/**
|
|
39
|
+
* Breadcrumb segmentleri — `bridge.breadcrumbs()` üzerinden okunur.
|
|
40
|
+
* Source-of-truth aktif MFE'de çalışan `BreadcrumbPublisherService`'tir;
|
|
41
|
+
* MFE her NavigationEnd'de kendi route ağacından zinciri çıkarıp bridge'e yazar.
|
|
42
|
+
* Shell yalnızca presenter — başa "Anasayfa" item'ı ekleyip son item'ı aktif işaretler.
|
|
43
|
+
*/
|
|
44
|
+
breadcrumbItems: import("@angular/core").Signal<(MenuItem & {
|
|
45
|
+
active?: boolean | undefined;
|
|
46
|
+
isHome?: boolean | undefined;
|
|
47
|
+
})[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Aktif olmayan breadcrumb segmentine tıklama → mevcut tab'ı parent route ile günceller.
|
|
50
|
+
* `<a [routerLink]>` directive'i `href`'i Router'ın location strategy'sine göre
|
|
51
|
+
* (hash/path) doğru formatlar — sağ tık "linki kopyala" davranışı çalışır.
|
|
52
|
+
* Default Router navigate'ini `preventDefault()` ile durdurup `navigateInCurrentTab`
|
|
53
|
+
* üzerinden ilerletiyoruz; böylece yeni sekme açılmaz.
|
|
54
|
+
*/
|
|
55
|
+
onBreadcrumbClick(event: MouseEvent, item: {
|
|
56
|
+
label?: string;
|
|
57
|
+
url?: string;
|
|
58
|
+
}): void;
|
|
59
|
+
/**
|
|
60
|
+
* Home icon → root menu item (`apps.service.ts:51`'de tanımlı `{ root: true, routerLink: '/' }`).
|
|
61
|
+
* Tek source-of-truth — etiket çevirisi `TranslateJsonPipe` ile aktif dilden okunur.
|
|
62
|
+
* Mevcut tab güncellenir, yeni sekme açılmaz.
|
|
63
|
+
*/
|
|
64
|
+
onHomeClick(event: MouseEvent): void;
|
|
65
|
+
/**
|
|
66
|
+
* Anasayfa için NavItem — breadcrumb home ikonunun hem `(click)` handler'ı hem
|
|
67
|
+
* `[arilNavLink]` context menu directive'i tarafından paylaşılır.
|
|
68
|
+
*/
|
|
69
|
+
readonly homeNavItem: import("@angular/core").Signal<NavItem>;
|
|
70
|
+
/**
|
|
71
|
+
* Tab icon resolution sırası:
|
|
72
|
+
* 1. NavItem.icon (sidebar click'inden iletilmişse — en doğru)
|
|
73
|
+
* 2. Menu config'inde navLink'i en uzun prefix olarak match eden item.icon
|
|
74
|
+
* 3. Generic fallback (`pi pi-file`)
|
|
75
|
+
*
|
|
76
|
+
* Best-match için longest-prefix kullanılır: `wdm/meters/123` için hem `wdm` hem
|
|
77
|
+
* `wdm/meters` match'lerse, daha spesifik `wdm/meters` kazanır. Böylece deep link
|
|
78
|
+
* refresh'inde (NavService.firstCheckForRoute path'inde icon set edilemediği zaman)
|
|
79
|
+
* doğru remote/section ikonu otomatik bulunur.
|
|
80
|
+
*/
|
|
81
|
+
getTabIcon(item: NavItem): string;
|
|
82
|
+
private findIconForRoute;
|
|
83
|
+
drop(event: CdkDragDrop<any[]>): void;
|
|
84
|
+
isActive(item: NavItem): boolean;
|
|
85
|
+
closeTab(event: Event, item: NavItem): void;
|
|
86
|
+
/** Tab sol-click → o tab'a geç. NavService Router'a `?_tab` URL'i ve history state'i verir. */
|
|
87
|
+
onTabClick(event: MouseEvent, item: NavItem): void;
|
|
88
|
+
/** Middle click (button 1) → tab kapat (Chrome standardı). Sabit tab'lar kapatılmaz. */
|
|
89
|
+
onTabAuxClick(event: MouseEvent, item: NavItem): void;
|
|
90
|
+
/** Middle click default scroll davranışını engelle. */
|
|
91
|
+
onTabMousedown(event: MouseEvent): void;
|
|
92
|
+
/**
|
|
93
|
+
* Tab right-click → context menu. Sabit tab'larda "Kapat" disabled; pin/unpin item'ı
|
|
94
|
+
* Chrome'daki gibi en üstte yer alır. `closeOthers`/`closeToRight`/`closeAll` zaten
|
|
95
|
+
* NavService seviyesinde pinned'i koruyor — UI'da ekstra disabled gerekmez.
|
|
96
|
+
*/
|
|
97
|
+
onTabContextMenu(event: MouseEvent, item: NavItem): void;
|
|
98
|
+
private isLastTab;
|
|
99
|
+
/**
|
|
100
|
+
* Tek kalan tab anasayfaysa true → kapatma (✕) butonu gizlenir (NavService de kapatmayı
|
|
101
|
+
* reddeder). "Her zaman en az 1 tab açık" kuralının UI tarafı.
|
|
102
|
+
*/
|
|
103
|
+
isLastHomeTab(item: NavItem): boolean;
|
|
104
|
+
/** "+" butonu → ana sayfaya navigate (yeni tab varsa onu aç, yoksa eklenir). */
|
|
105
|
+
onAddTab(): void;
|
|
106
|
+
scrollTabsLeft(): void;
|
|
107
|
+
scrollTabsRight(): void;
|
|
108
|
+
private updateScrollState;
|
|
109
|
+
/**
|
|
110
|
+
* Klavye kısayolları (Chrome paritesi):
|
|
111
|
+
* - `Alt+W` → aktif tab kapat (Ctrl+W browser-reserved)
|
|
112
|
+
* - `Ctrl+Tab` / `Ctrl+Shift+Tab` → sonraki/önceki tab (denemeli — bazı tarayıcılar override etmez)
|
|
113
|
+
* - `Ctrl+PageDown` / `Ctrl+PageUp` → sonraki/önceki tab (yedek)
|
|
114
|
+
* - `Alt+1..9` → ilgili index'teki tab (Ctrl+1..9 browser-reserved)
|
|
115
|
+
* - `Ctrl+Shift+T` veya `Alt+Shift+T` → son kapatılan tab'ı geri aç
|
|
116
|
+
*/
|
|
117
|
+
onDocumentKeydown(event: KeyboardEvent): void;
|
|
118
|
+
private isTypingInInput;
|
|
119
|
+
ngAfterViewInit(): void;
|
|
120
|
+
private resizeObserver;
|
|
121
|
+
constructor(menuService: AppMenuService, layoutService: LayoutService, renderer: Renderer2, router: Router, translateJsonPipe: TranslateJsonPipe);
|
|
22
122
|
blockBodyScroll(): void;
|
|
23
123
|
unblockBodyScroll(): void;
|
|
24
124
|
private isElementInside;
|
|
@@ -7,7 +7,108 @@
|
|
|
7
7
|
<div class="layout-content-wrapper">
|
|
8
8
|
<app-topbar />
|
|
9
9
|
<div class="layout-content">
|
|
10
|
-
<
|
|
10
|
+
<p-breadcrumb styleClass="breadcrumb-strip" [model]="breadcrumbItems()">
|
|
11
|
+
<ng-template pTemplate="item" let-item>
|
|
12
|
+
@if (item.isHome) {
|
|
13
|
+
<a class="breadcrumb-home"
|
|
14
|
+
[routerLink]="'/'"
|
|
15
|
+
[arilNavLink]="homeNavItem()"
|
|
16
|
+
(click)="onHomeClick($event)"
|
|
17
|
+
[attr.aria-label]="'breadcrumb.home' | transloco">
|
|
18
|
+
<i class="pi pi-home" aria-hidden="true"></i>
|
|
19
|
+
</a>
|
|
20
|
+
} @else if (item.active || !item.url) {
|
|
21
|
+
<span class="breadcrumb-item active">{{ item.label }}</span>
|
|
22
|
+
} @else {
|
|
23
|
+
<a
|
|
24
|
+
class="breadcrumb-item breadcrumb-link"
|
|
25
|
+
[routerLink]="item.url"
|
|
26
|
+
[arilNavLink]="{ tabId: '', navLink: item.url, navName: item.label }"
|
|
27
|
+
(click)="onBreadcrumbClick($event, item)">
|
|
28
|
+
{{ item.label }}
|
|
29
|
+
</a>
|
|
30
|
+
}
|
|
31
|
+
</ng-template>
|
|
32
|
+
<ng-template pTemplate="separator">
|
|
33
|
+
<i class="breadcrumb-sep pi pi-angle-right text-base" aria-hidden="true"></i>
|
|
34
|
+
</ng-template>
|
|
35
|
+
</p-breadcrumb>
|
|
36
|
+
<div class="tabs-bar">
|
|
37
|
+
@if (canScrollLeft()) {
|
|
38
|
+
<button
|
|
39
|
+
type="button"
|
|
40
|
+
class="tabs-scroll-btn tabs-scroll-left"
|
|
41
|
+
(click)="scrollTabsLeft()"
|
|
42
|
+
[pTooltip]="'tab.scrollLeft' | transloco"
|
|
43
|
+
tooltipPosition="bottom"
|
|
44
|
+
[attr.aria-label]="'tab.scrollLeft' | transloco">
|
|
45
|
+
<i class="pi pi-chevron-left"></i>
|
|
46
|
+
</button>
|
|
47
|
+
}
|
|
48
|
+
<div
|
|
49
|
+
#tabsContainer
|
|
50
|
+
class="tabs-container"
|
|
51
|
+
cdkDropList
|
|
52
|
+
cdkDropListOrientation="horizontal"
|
|
53
|
+
(cdkDropListDropped)="drop($event)">
|
|
54
|
+
@for (item of navService.activeRoutes(); track item.tabId; let i = $index) {
|
|
55
|
+
<div
|
|
56
|
+
class="tab-item"
|
|
57
|
+
cdkDrag
|
|
58
|
+
[class.active]="isActive(item)"
|
|
59
|
+
[class.pinned]="item.pinned"
|
|
60
|
+
[pTooltip]="item.navName"
|
|
61
|
+
tooltipPosition="bottom"
|
|
62
|
+
[tooltipDisabled]="isActive(item) && !item.pinned"
|
|
63
|
+
[showDelay]="500"
|
|
64
|
+
(click)="onTabClick($event, item)"
|
|
65
|
+
(auxclick)="onTabAuxClick($event, item)"
|
|
66
|
+
(mousedown)="onTabMousedown($event)"
|
|
67
|
+
(contextmenu)="onTabContextMenu($event, item)">
|
|
68
|
+
<i class="tab-icon" [ngClass]="getTabIcon(item)"></i>
|
|
69
|
+
@if (!item.pinned) {
|
|
70
|
+
<span class="tab-title">{{ item.navName }}</span>
|
|
71
|
+
@if (!isLastHomeTab(item)) {
|
|
72
|
+
<button
|
|
73
|
+
type="button"
|
|
74
|
+
class="tab-close-btn"
|
|
75
|
+
(click)="closeTab($event, item)"
|
|
76
|
+
[attr.aria-label]="'tab.close' | transloco">
|
|
77
|
+
<i class="pi pi-times"></i>
|
|
78
|
+
</button>
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
</div>
|
|
82
|
+
}
|
|
83
|
+
</div>
|
|
84
|
+
@if (canScrollRight()) {
|
|
85
|
+
<button
|
|
86
|
+
type="button"
|
|
87
|
+
class="tabs-scroll-btn tabs-scroll-right"
|
|
88
|
+
(click)="scrollTabsRight()"
|
|
89
|
+
[pTooltip]="'tab.scrollRight' | transloco"
|
|
90
|
+
tooltipPosition="bottom"
|
|
91
|
+
[attr.aria-label]="'tab.scrollRight' | transloco">
|
|
92
|
+
<i class="pi pi-chevron-right"></i>
|
|
93
|
+
</button>
|
|
94
|
+
}
|
|
95
|
+
<button
|
|
96
|
+
type="button"
|
|
97
|
+
class="tabs-add-btn"
|
|
98
|
+
(click)="onAddTab()"
|
|
99
|
+
[pTooltip]="'tab.newTab' | transloco"
|
|
100
|
+
tooltipPosition="bottom"
|
|
101
|
+
[attr.aria-label]="'tab.newTab' | transloco">
|
|
102
|
+
<i class="pi pi-plus"></i>
|
|
103
|
+
</button>
|
|
104
|
+
</div>
|
|
105
|
+
<p-contextMenu #tabContextMenu [model]="tabContextMenuItems" appendTo="body"></p-contextMenu>
|
|
106
|
+
<!-- Global nav-link context menu: tüm linkli yapılarda `[arilNavLink]` directive'i bu instance'ı paylaşır. -->
|
|
107
|
+
<p-contextMenu #navLinkContextMenu [model]="[]" appendTo="body"></p-contextMenu>
|
|
108
|
+
|
|
109
|
+
<div class="layout-page">
|
|
110
|
+
<router-outlet />
|
|
111
|
+
</div>
|
|
11
112
|
</div>
|
|
12
113
|
</div>
|
|
13
114
|
<app-profilemenu />
|