mirror of https://github.com/abpframework/abp.git
7 changed files with 202 additions and 358 deletions
@ -1,4 +1,7 @@ |
|||
export * from './account-layout/account-layout.component'; |
|||
export * from './application-layout/application-layout.component'; |
|||
export * from './empty-layout/empty-layout.component'; |
|||
export * from './logo/logo.component'; |
|||
export * from './nav-items/nav-items.component'; |
|||
export * from './routes/routes.component'; |
|||
export * from './validation-error/validation-error.component'; |
|||
|
|||
@ -0,0 +1,111 @@ |
|||
<ul class="navbar-nav"> |
|||
<ng-container |
|||
*ngFor="let route of visibleRoutes$ | async; trackBy: trackByFn" |
|||
[ngTemplateOutlet]="route?.children?.length ? dropdownLink : defaultLink" |
|||
[ngTemplateOutletContext]="{ $implicit: route }" |
|||
> |
|||
</ng-container> |
|||
|
|||
<ng-template #defaultLink let-route> |
|||
<li class="nav-item" *abpPermission="route.requiredPolicy"> |
|||
<a class="nav-link" [routerLink]="[route.url]" |
|||
><i *ngIf="route.iconClass" [ngClass]="route.iconClass"></i> |
|||
{{ route.name | abpLocalization }}</a |
|||
> |
|||
</li> |
|||
</ng-template> |
|||
|
|||
<ng-template #dropdownLink let-route> |
|||
<li |
|||
#navbarRootDropdown |
|||
*abpPermission="route.requiredPolicy" |
|||
[abpVisibility]="routeContainer" |
|||
class="nav-item dropdown" |
|||
display="static" |
|||
(click)=" |
|||
navbarRootDropdown.expand |
|||
? (navbarRootDropdown.expand = false) |
|||
: (navbarRootDropdown.expand = true) |
|||
" |
|||
> |
|||
<a |
|||
class="nav-link dropdown-toggle" |
|||
data-toggle="dropdown" |
|||
aria-haspopup="true" |
|||
aria-expanded="false" |
|||
href="javascript:void(0)" |
|||
> |
|||
<i *ngIf="route.iconClass" [ngClass]="route.iconClass"></i> |
|||
{{ route.name | abpLocalization }} |
|||
</a> |
|||
<div |
|||
#routeContainer |
|||
class="dropdown-menu border-0 shadow-sm" |
|||
(click)="$event.preventDefault(); $event.stopPropagation()" |
|||
[class.d-block]="smallScreen && navbarRootDropdown.expand" |
|||
> |
|||
<ng-template |
|||
#forTemplate |
|||
ngFor |
|||
[ngForOf]="route.children" |
|||
[ngForTrackBy]="trackByFn" |
|||
[ngForTemplate]="childWrapper" |
|||
></ng-template> |
|||
</div> |
|||
</li> |
|||
</ng-template> |
|||
|
|||
<ng-template #childWrapper let-child> |
|||
<ng-template |
|||
[ngTemplateOutlet]="child?.children?.length ? dropdownChild : defaultChild" |
|||
[ngTemplateOutletContext]="{ $implicit: child }" |
|||
></ng-template> |
|||
</ng-template> |
|||
|
|||
<ng-template #defaultChild let-child> |
|||
<div class="dropdown-submenu" *abpPermission="child.requiredPolicy"> |
|||
<a class="dropdown-item" [routerLink]="[child.url]"> |
|||
<i *ngIf="child.iconClass" [ngClass]="child.iconClass"></i> |
|||
{{ child.name | abpLocalization }}</a |
|||
> |
|||
</div> |
|||
</ng-template> |
|||
|
|||
<ng-template #dropdownChild let-child> |
|||
<div |
|||
[abpVisibility]="childrenContainer" |
|||
class="dropdown-submenu" |
|||
ngbDropdown |
|||
#dropdownSubmenu="ngbDropdown" |
|||
[display]="isDropdownChildDynamic ? 'dynamic' : 'static'" |
|||
placement="right-top" |
|||
[autoClose]="true" |
|||
*abpPermission="child.requiredPolicy" |
|||
(openChange)="openChange($event, childrenContainer)" |
|||
> |
|||
<div ngbDropdownToggle [class.dropdown-toggle]="false"> |
|||
<a |
|||
abpEllipsis="210px" |
|||
[abpEllipsisEnabled]="isDropdownChildDynamic" |
|||
role="button" |
|||
class="btn d-block text-left dropdown-toggle" |
|||
> |
|||
<i *ngIf="child.iconClass" [ngClass]="child.iconClass"></i> |
|||
{{ child.name | abpLocalization }} |
|||
</a> |
|||
</div> |
|||
<div |
|||
#childrenContainer |
|||
class="dropdown-menu border-0 shadow-sm" |
|||
[class.d-block]="smallScreen && dropdownSubmenu.isOpen()" |
|||
> |
|||
<ng-template |
|||
ngFor |
|||
[ngForOf]="child.children" |
|||
[ngForTrackBy]="trackByFn" |
|||
[ngForTemplate]="childWrapper" |
|||
></ng-template> |
|||
</div> |
|||
</div> |
|||
</ng-template> |
|||
</ul> |
|||
@ -0,0 +1,51 @@ |
|||
import { Component, OnInit, TrackByFunction, Input, Renderer2 } from '@angular/core'; |
|||
import { Observable } from 'rxjs'; |
|||
import { ABP, ConfigState } from '@abp/ng.core'; |
|||
import { map } from 'rxjs/operators'; |
|||
import { Select } from '@ngxs/store'; |
|||
|
|||
@Component({ |
|||
selector: 'abp-routes', |
|||
templateUrl: 'routes.component.html', |
|||
}) |
|||
export class RoutesComponent { |
|||
@Select(ConfigState.getOne('routes')) |
|||
routes$: Observable<ABP.FullRoute[]>; |
|||
|
|||
@Input() |
|||
smallScreen: boolean; |
|||
|
|||
@Input() |
|||
isDropdownChildDynamic: boolean; |
|||
|
|||
get visibleRoutes$(): Observable<ABP.FullRoute[]> { |
|||
return this.routes$.pipe(map(routes => getVisibleRoutes(routes))); |
|||
} |
|||
|
|||
trackByFn: TrackByFunction<ABP.FullRoute> = (_, item) => item.name; |
|||
|
|||
constructor(private renderer: Renderer2) {} |
|||
|
|||
openChange(event: boolean, childrenContainer: HTMLDivElement) { |
|||
if (!event) { |
|||
Object.keys(childrenContainer.style) |
|||
.filter(key => Number.isInteger(+key)) |
|||
.forEach(key => { |
|||
this.renderer.removeStyle(childrenContainer, childrenContainer.style[key]); |
|||
}); |
|||
this.renderer.removeStyle(childrenContainer, 'left'); |
|||
} |
|||
} |
|||
} |
|||
|
|||
function getVisibleRoutes(routes: ABP.FullRoute[]) { |
|||
return routes.reduce((acc, val) => { |
|||
if (val.invisible) return acc; |
|||
|
|||
if (val.children && val.children.length) { |
|||
val.children = getVisibleRoutes(val.children); |
|||
} |
|||
|
|||
return [...acc, val]; |
|||
}, []); |
|||
} |
|||
Loading…
Reference in new issue