mirror of https://github.com/abpframework/abp.git
25 changed files with 269 additions and 51 deletions
@ -0,0 +1,7 @@ |
|||||
|
{ |
||||
|
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", |
||||
|
"dest": "../../../dist/components/page", |
||||
|
"lib": { |
||||
|
"entryFile": "src/public-api.ts" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,77 @@ |
|||||
|
import { |
||||
|
Directive, |
||||
|
TemplateRef, |
||||
|
ViewContainerRef, |
||||
|
Input, |
||||
|
InjectionToken, |
||||
|
Optional, |
||||
|
Inject, |
||||
|
OnInit, |
||||
|
OnDestroy, |
||||
|
Injector, |
||||
|
OnChanges, |
||||
|
SimpleChanges, |
||||
|
SimpleChange, |
||||
|
} from '@angular/core'; |
||||
|
|
||||
|
export interface PageRenderStrategy { |
||||
|
shouldRender(type: string); |
||||
|
onInit?(type: string, injector: Injector, context?: any); |
||||
|
onDestroy?(type: string, injector?: Injector, context?: any); |
||||
|
onContextUpdate?(change: SimpleChange); |
||||
|
} |
||||
|
|
||||
|
export const PAGE_RENDER_STRATEGY = new InjectionToken<PageRenderStrategy>('PAGE_RENDER_STRATEGY'); |
||||
|
|
||||
|
@Directive({ selector: '[abpPagePart]' }) |
||||
|
export class PagePartDirective implements OnInit, OnDestroy, OnChanges { |
||||
|
hasRendered = false; |
||||
|
type: string; |
||||
|
|
||||
|
@Input() set abpPagePart(type: string) { |
||||
|
this.type = type; |
||||
|
const shouldRender = this.shouldRender(type); |
||||
|
|
||||
|
if (shouldRender && !this.hasRendered) { |
||||
|
this.viewContainer.createEmbeddedView(this.templateRef); |
||||
|
this.hasRendered = true; |
||||
|
} else if (!shouldRender && this.hasRendered) { |
||||
|
this.viewContainer.clear(); |
||||
|
this.hasRendered = false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Input('abpPagePartContext') context: any; |
||||
|
|
||||
|
constructor( |
||||
|
private templateRef: TemplateRef<any>, |
||||
|
private viewContainer: ViewContainerRef, |
||||
|
@Optional() @Inject(PAGE_RENDER_STRATEGY) private renderLogic: PageRenderStrategy, |
||||
|
private injector: Injector, |
||||
|
) {} |
||||
|
|
||||
|
ngOnChanges({ context }: SimpleChanges): void { |
||||
|
if (this.renderLogic?.onContextUpdate) { |
||||
|
this.renderLogic.onContextUpdate(context); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
ngOnInit() { |
||||
|
if (this.renderLogic?.onInit) { |
||||
|
this.renderLogic.onInit(this.type, this.injector, this.context); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
ngOnDestroy() { |
||||
|
if (this.renderLogic?.onDestroy) { |
||||
|
this.renderLogic.onDestroy(this.type, this.injector, this.context); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
shouldRender(type: string) { |
||||
|
if (this.renderLogic) { |
||||
|
return this.renderLogic.shouldRender(type); |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
import { Component, ViewEncapsulation } from '@angular/core'; |
||||
|
|
||||
|
export enum PageParts { |
||||
|
title = 'PageTitleContainerComponent', |
||||
|
breadcrumb = 'PageBreadcrumbContainerComponent', |
||||
|
toolbar = 'PageToolbarContainerComponent', |
||||
|
} |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'abp-page-title-container', |
||||
|
template: ` |
||||
|
<ng-content></ng-content> |
||||
|
`,
|
||||
|
encapsulation: ViewEncapsulation.None, |
||||
|
}) |
||||
|
export class PageTitleContainerComponent {} |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'abp-page-breadcrumb-container', |
||||
|
template: ` |
||||
|
<ng-content></ng-content> |
||||
|
`,
|
||||
|
encapsulation: ViewEncapsulation.None, |
||||
|
}) |
||||
|
export class PageBreadcrumbContainerComponent {} |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'abp-page-toolbar-container', |
||||
|
template: ` |
||||
|
<ng-content></ng-content> |
||||
|
`,
|
||||
|
encapsulation: ViewEncapsulation.None, |
||||
|
}) |
||||
|
export class PageToolbarContainerComponent {} |
||||
@ -0,0 +1,41 @@ |
|||||
|
<div class="row entry-row"> |
||||
|
<ng-container *ngIf="titleVisible"> |
||||
|
<ng-container *ngIf="customTitle; else defaultTitleTemplate"> |
||||
|
<ng-content select="abp-page-title-container"></ng-content> |
||||
|
</ng-container> |
||||
|
</ng-container> |
||||
|
|
||||
|
<ng-container *ngIf="breadcrumbVisible"> |
||||
|
<ng-container *ngIf="customBreadcrumb; else defaultBreadcrumbTemplate"> |
||||
|
<ng-content select="abp-page-breadcrumb-container"></ng-content> |
||||
|
</ng-container> |
||||
|
</ng-container> |
||||
|
|
||||
|
<ng-container *ngIf="toolbarVisible"> |
||||
|
<ng-container *ngIf="customToolbar; else defaultPageToolbarTemplate"> |
||||
|
<ng-content select="abp-page-toolbar-container"></ng-content> |
||||
|
</ng-container> |
||||
|
</ng-container> |
||||
|
</div> |
||||
|
|
||||
|
<ng-content></ng-content> |
||||
|
|
||||
|
<ng-template #defaultTitleTemplate> |
||||
|
<div class="col-auto" *abpPagePart="pageParts.title"> |
||||
|
<h1 class="content-header-title"> |
||||
|
{{ title }} |
||||
|
</h1> |
||||
|
</div> |
||||
|
</ng-template> |
||||
|
|
||||
|
<ng-template #defaultBreadcrumbTemplate> |
||||
|
<div class="col-lg-auto pl-lg-0" *abpPagePart="pageParts.breadcrumb"> |
||||
|
<abp-breadcrumb></abp-breadcrumb> |
||||
|
</div> |
||||
|
</ng-template> |
||||
|
|
||||
|
<ng-template #defaultPageToolbarTemplate> |
||||
|
<div class="col" *abpPagePart="pageParts.toolbar; context: record"> |
||||
|
<abp-page-toolbar [record]="record"></abp-page-toolbar> |
||||
|
</div> |
||||
|
</ng-template> |
||||
@ -0,0 +1,32 @@ |
|||||
|
import { Component, Input, ViewEncapsulation, ContentChild } from '@angular/core'; |
||||
|
import { |
||||
|
PageTitleContainerComponent, |
||||
|
PageBreadcrumbContainerComponent, |
||||
|
PageToolbarContainerComponent, |
||||
|
PageParts, |
||||
|
} from './page-parts.component'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'abp-page', |
||||
|
templateUrl: './page.component.html', |
||||
|
encapsulation: ViewEncapsulation.None, |
||||
|
}) |
||||
|
export class PageComponent { |
||||
|
@Input() title: string; |
||||
|
@Input() record: any; |
||||
|
|
||||
|
@Input() titleVisible = true; |
||||
|
@Input() breadcrumbVisible = true; |
||||
|
@Input() toolbarVisible = true; |
||||
|
|
||||
|
pageParts = { |
||||
|
title: PageParts.title, |
||||
|
breadcrumb: PageParts.breadcrumb, |
||||
|
toolbar: PageParts.toolbar, |
||||
|
}; |
||||
|
|
||||
|
@ContentChild(PageTitleContainerComponent) customTitle: PageTitleContainerComponent; |
||||
|
@ContentChild(PageBreadcrumbContainerComponent) |
||||
|
customBreadcrumb: PageBreadcrumbContainerComponent; |
||||
|
@ContentChild(PageToolbarContainerComponent) customToolbar: PageToolbarContainerComponent; |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
import { NgModule } from '@angular/core'; |
||||
|
import { CommonModule } from '@angular/common'; |
||||
|
import { UiExtensionsModule } from '@abp/ng.theme.shared/extensions'; |
||||
|
import { ThemeSharedModule } from '@abp/ng.theme.shared'; |
||||
|
import { CoreModule } from '@abp/ng.core'; |
||||
|
import { PageComponent } from './page.component'; |
||||
|
import { |
||||
|
PageTitleContainerComponent, |
||||
|
PageBreadcrumbContainerComponent, |
||||
|
PageToolbarContainerComponent, |
||||
|
} from './page-parts.component'; |
||||
|
import { PagePartDirective } from './page-part.directive'; |
||||
|
|
||||
|
const exportedDeclarations = [ |
||||
|
PageComponent, |
||||
|
PageTitleContainerComponent, |
||||
|
PageBreadcrumbContainerComponent, |
||||
|
PageToolbarContainerComponent, |
||||
|
PagePartDirective, |
||||
|
]; |
||||
|
|
||||
|
@NgModule({ |
||||
|
declarations: [...exportedDeclarations], |
||||
|
imports: [CommonModule, UiExtensionsModule, CoreModule, ThemeSharedModule], |
||||
|
exports: [...exportedDeclarations], |
||||
|
}) |
||||
|
export class PageModule {} |
||||
@ -0,0 +1,4 @@ |
|||||
|
export * from './page.module'; |
||||
|
export * from './page-part.directive'; |
||||
|
export * from './page-parts.component'; |
||||
|
export * from './page.component'; |
||||
@ -1,46 +1,36 @@ |
|||||
<div class="row entry-row"> |
<abp-page [title]="'AbpSettingManagement::Settings' | abpLocalization" [toolbarVisible]="false"> |
||||
<div class="col-auto"> |
<div id="SettingManagementWrapper"> |
||||
<h1 class="content-header-title">{{ 'AbpSettingManagement::Settings' | abpLocalization }}</h1> |
<div class="card"> |
||||
</div> |
<div class="card-body"> |
||||
<div id="breadcrumb" class="col-lg-auto pl-lg-0"> |
<div class="row"> |
||||
<abp-breadcrumb></abp-breadcrumb> |
<div class="col-12 col-md-3"> |
||||
</div> |
<ul class="nav flex-column nav-pills" id="nav-tab" role="tablist"> |
||||
<div class="col"> |
<ng-container *abpFor="let setting of settings; trackBy: trackByFn"> |
||||
<div class="text-lg-right pt-2" id="AbpContentToolbar"></div> |
<li |
||||
</div> |
(click)="selected = setting" |
||||
</div> |
class="nav-item pointer" |
||||
|
*abpPermission="setting.requiredPolicy" |
||||
<div id="SettingManagementWrapper"> |
|
||||
<div class="card"> |
|
||||
<div class="card-body"> |
|
||||
<div class="row"> |
|
||||
<div class="col-12 col-md-3"> |
|
||||
<ul class="nav flex-column nav-pills" id="nav-tab" role="tablist"> |
|
||||
<ng-container *abpFor="let setting of settings; trackBy: trackByFn"> |
|
||||
<li |
|
||||
(click)="selected = setting" |
|
||||
class="nav-item pointer" |
|
||||
*abpPermission="setting.requiredPolicy" |
|
||||
> |
|
||||
<a |
|
||||
class="nav-link" |
|
||||
[id]="setting.name + '-tab'" |
|
||||
role="tab" |
|
||||
[class.active]="setting.name === selected.name" |
|
||||
>{{ setting.name | abpLocalization }}</a |
|
||||
> |
> |
||||
</li> |
<a |
||||
</ng-container> |
class="nav-link" |
||||
</ul> |
[id]="setting.name + '-tab'" |
||||
</div> |
role="tab" |
||||
<div class="col-12 col-md-9"> |
[class.active]="setting.name === selected.name" |
||||
<div *ngIf="settings.length" class="tab-content"> |
>{{ setting.name | abpLocalization }}</a |
||||
<div class="tab-pane fade show active" [id]="selected.name + '-tab'" role="tabpanel"> |
> |
||||
<ng-container *ngComponentOutlet="selected.component"></ng-container> |
</li> |
||||
|
</ng-container> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<div class="col-12 col-md-9"> |
||||
|
<div *ngIf="settings.length" class="tab-content"> |
||||
|
<div class="tab-pane fade show active" [id]="selected.name + '-tab'" role="tabpanel"> |
||||
|
<ng-container *ngComponentOutlet="selected.component"></ng-container> |
||||
|
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
</abp-page> |
||||
|
|||||
Loading…
Reference in new issue