diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs index 030f474c96..5efbc358f0 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs @@ -38,7 +38,7 @@ namespace Volo.Abp.Cli.Commands if (password.IsNullOrWhiteSpace()) { throw new CliUsageException( - "Password name is missing!" + + "Password is missing!" + Environment.NewLine + Environment.NewLine + GetUsageInfo() ); diff --git a/npm/ng-packs/packages/account/src/lib/account.module.ts b/npm/ng-packs/packages/account/src/lib/account.module.ts index fbfe6a7226..8a790a21c1 100644 --- a/npm/ng-packs/packages/account/src/lib/account.module.ts +++ b/npm/ng-packs/packages/account/src/lib/account.module.ts @@ -1,6 +1,6 @@ import { CoreModule } from '@abp/ng.core'; import { ThemeSharedModule } from '@abp/ng.theme.shared'; -import { NgModule } from '@angular/core'; +import { NgModule, Provider } from '@angular/core'; import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; import { NgxValidateCoreModule } from '@ngx-validate/core'; import { TableModule } from 'primeng/table'; @@ -8,6 +8,8 @@ import { AccountRoutingModule } from './account-routing.module'; import { LoginComponent } from './components/login/login.component'; import { RegisterComponent } from './components/register/register.component'; import { TenantBoxComponent } from './components/tenant-box/tenant-box.component'; +import { Options } from './models/options'; +import { ACCOUNT_OPTIONS, optionsFactory } from './tokens/options.token'; @NgModule({ declarations: [LoginComponent, RegisterComponent, TenantBoxComponent], @@ -15,3 +17,14 @@ import { TenantBoxComponent } from './components/tenant-box/tenant-box.component exports: [], }) export class AccountModule {} + +export function AccountProviders(options = {} as Options): Provider[] { + return [ + { provide: ACCOUNT_OPTIONS, useValue: options }, + { + provide: 'ACCOUNT_OPTIONS', + useFactory: optionsFactory, + deps: [ACCOUNT_OPTIONS], + }, + ]; +} diff --git a/npm/ng-packs/packages/account/src/lib/root-account.module.ts b/npm/ng-packs/packages/account/src/lib/root-account.module.ts deleted file mode 100644 index beca480223..0000000000 --- a/npm/ng-packs/packages/account/src/lib/root-account.module.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ModuleWithProviders, NgModule } from '@angular/core'; -import { Options } from './models/options'; -import { ACCOUNT_OPTIONS, optionsFactory } from './tokens/options.token'; - -@NgModule({}) -export class RootAccountModule { - static forRoot(options = {} as Options): ModuleWithProviders { - return { - ngModule: RootAccountModule, - providers: [ - { provide: ACCOUNT_OPTIONS, useValue: options }, - { - provide: 'ACCOUNT_OPTIONS', - useFactory: optionsFactory, - deps: [ACCOUNT_OPTIONS], - }, - ], - }; - } -} diff --git a/npm/ng-packs/packages/account/src/public-api.ts b/npm/ng-packs/packages/account/src/public-api.ts index d75f7155f1..0e845f0768 100644 --- a/npm/ng-packs/packages/account/src/public-api.ts +++ b/npm/ng-packs/packages/account/src/public-api.ts @@ -1,4 +1,3 @@ -export * from './lib/root-account.module'; export * from './lib/account.module'; export * from './lib/components'; export * from './lib/constants/routes'; diff --git a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts index 517e1974ad..d89d486c57 100644 --- a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts +++ b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts @@ -1,12 +1,13 @@ -import { Component, OnDestroy, Type } from '@angular/core'; -import { NavigationEnd, Router, UrlSegment } from '@angular/router'; +import { Component, Input, OnDestroy, Type } from '@angular/core'; +import { ActivatedRoute, NavigationEnd, Router, UrlSegment } from '@angular/router'; import { Select, Store } from '@ngxs/store'; import { Observable } from 'rxjs'; -import { eLayoutType } from '../enums'; -import { ABP, Config } from '../models'; -import { ConfigState } from '../states'; -import { takeUntilDestroy } from '../utils'; import snq from 'snq'; +import { eLayoutType } from '../enums/common'; +import { Config } from '../models/config'; +import { ABP } from '../models/common'; +import { ConfigState } from '../states/config.state'; +import { takeUntilDestroy } from '../utils/rxjs-utils'; @Component({ selector: 'abp-dynamic-layout', @@ -23,16 +24,23 @@ export class DynamicLayoutComponent implements OnDestroy { layout: Type; - constructor(private router: Router, private store: Store) { + constructor(private router: Router, private route: ActivatedRoute, private store: Store) { + const { + requirements: { layouts }, + routes, + } = this.store.selectSnapshot(ConfigState.getAll); + + if ((this.route.snapshot.data || {}).layout) { + this.layout = layouts + .filter(l => !!l) + .find(l => snq(() => l.type.toLowerCase().indexOf(this.route.snapshot.data.layout), -1) > -1); + } + this.router.events.pipe(takeUntilDestroy(this)).subscribe(event => { if (event instanceof NavigationEnd) { const { segments } = this.router.parseUrl(event.url).root.children.primary; - const { - requirements: { layouts }, - routes, - } = this.store.selectSnapshot(ConfigState.getAll); - const layout = findLayout(segments, routes); + const layout = (this.route.snapshot.data || {}).layout || findLayout(segments, routes); this.layout = layouts.filter(l => !!l).find(l => snq(() => l.type.toLowerCase().indexOf(layout), -1) > -1); } diff --git a/npm/ng-packs/packages/core/src/lib/core.module.ts b/npm/ng-packs/packages/core/src/lib/core.module.ts index 6e801ffd83..c9c6ce9761 100644 --- a/npm/ng-packs/packages/core/src/lib/core.module.ts +++ b/npm/ng-packs/packages/core/src/lib/core.module.ts @@ -24,6 +24,7 @@ import { ProfileState } from './states/profile.state'; import { SessionState } from './states/session.state'; import { getInitialData, localeInitializer } from './utils/initial-utils'; import { ConfigPlugin, NGXS_CONFIG_PLUGIN_OPTIONS } from './plugins/config/config.plugin'; +import { ForDirective } from './directives/for.directive'; @NgModule({ imports: [ @@ -41,6 +42,7 @@ import { ConfigPlugin, NGXS_CONFIG_PLUGIN_OPTIONS } from './plugins/config/confi DynamicLayoutComponent, AutofocusDirective, EllipsisDirective, + ForDirective, FormSubmitDirective, LocalizationPipe, PermissionDirective, @@ -58,6 +60,7 @@ import { ConfigPlugin, NGXS_CONFIG_PLUGIN_OPTIONS } from './plugins/config/confi DynamicLayoutComponent, AutofocusDirective, EllipsisDirective, + ForDirective, FormSubmitDirective, LocalizationPipe, PermissionDirective, diff --git a/npm/ng-packs/packages/core/src/lib/directives/for.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/for.directive.ts new file mode 100644 index 0000000000..24769b325d --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/directives/for.directive.ts @@ -0,0 +1,174 @@ +import { + Directive, + EmbeddedViewRef, + Input, + IterableChangeRecord, + IterableChanges, + IterableDiffer, + IterableDiffers, + OnChanges, + TemplateRef, + TrackByFunction, + ViewContainerRef, +} from '@angular/core'; +import compare from 'just-compare'; + +export type CompareFn = (value: T, comparison: T) => boolean; + +class AbpForContext { + constructor(public $implicit: any, public index: number, public count: number, public list: any[]) {} +} + +class RecordView { + constructor(public record: IterableChangeRecord, public view: EmbeddedViewRef) {} +} + +@Directive({ + selector: '[abpFor]', +}) +export class ForDirective implements OnChanges { + @Input('abpForOf') + items: any[]; + + @Input('abpForOrderBy') + orderBy: string; + + @Input('abpForOrderDir') + orderDir: 'ASC' | 'DESC'; + + @Input('abpForFilterBy') + filterBy: string; + + @Input('abpForFilterVal') + filterVal: any; + + @Input('abpForTrackBy') + trackBy; + + @Input('abpForCompareBy') + compareBy: CompareFn; + + @Input('abpForEmptyRef') + emptyRef: TemplateRef; + + private differ: IterableDiffer; + + private isShowEmptyRef: boolean; + + get compareFn(): CompareFn { + return this.compareBy || compare; + } + + get trackByFn(): TrackByFunction { + return this.trackBy || ((index: number, item: any) => (item as any).id || index); + } + + constructor( + private tempRef: TemplateRef, + private vcRef: ViewContainerRef, + private differs: IterableDiffers, + ) {} + + private iterateOverAppliedOperations(changes: IterableChanges) { + const rw: RecordView[] = []; + + changes.forEachOperation((record: IterableChangeRecord, previousIndex: number, currentIndex: number) => { + if (record.previousIndex == null) { + const view = this.vcRef.createEmbeddedView( + this.tempRef, + new AbpForContext(null, -1, -1, this.items), + currentIndex, + ); + + rw.push(new RecordView(record, view)); + } else if (currentIndex == null) { + this.vcRef.remove(previousIndex); + } else { + const view = this.vcRef.get(previousIndex); + this.vcRef.move(view, currentIndex); + + rw.push(new RecordView(record, view as EmbeddedViewRef)); + } + }); + + for (let i = 0, l = rw.length; i < l; i++) { + rw[i].view.context.$implicit = rw[i].record.item; + } + } + + private iterateOverAttachedViews(changes: IterableChanges) { + for (let i = 0, l = this.vcRef.length; i < l; i++) { + const viewRef = this.vcRef.get(i) as EmbeddedViewRef; + viewRef.context.index = i; + viewRef.context.count = l; + viewRef.context.list = this.items; + } + + changes.forEachIdentityChange((record: IterableChangeRecord) => { + const viewRef = this.vcRef.get(record.currentIndex) as EmbeddedViewRef; + viewRef.context.$implicit = record.item; + }); + } + + private projectItems(items: any[]): void { + if (!items.length && this.emptyRef) { + this.vcRef.createEmbeddedView(this.emptyRef).rootNodes; + this.isShowEmptyRef = true; + + return; + } + + if (this.emptyRef && this.isShowEmptyRef) { + this.vcRef.clear(); + this.isShowEmptyRef = false; + } + + if (!this.differ && items) { + this.differ = this.differs.find(items).create(this.trackByFn); + } + + if (this.differ) { + const changes = this.differ.diff(items); + + if (changes) { + this.iterateOverAppliedOperations(changes); + this.iterateOverAttachedViews(changes); + } + } + } + + private sortItems(items: any[]) { + if (this.orderBy) { + items.sort((a, b) => (a[this.orderBy] > b[this.orderBy] ? 1 : a[this.orderBy] < b[this.orderBy] ? -1 : 0)); + } else { + items.sort(); + } + } + + ngOnChanges() { + let items = [...this.items] as any[]; + if (!Array.isArray(items)) return; + + const compareFn = this.compareFn; + + if (typeof this.filterBy !== 'undefined') { + items = items.filter(item => compareFn(item[this.filterBy], this.filterVal)); + } + + switch (this.orderDir) { + case 'ASC': + this.sortItems(items); + this.projectItems(items); + break; + + case 'DESC': + this.sortItems(items); + items.reverse(); + this.projectItems(items); + break; + + default: + this.projectItems(items); + } + } +} diff --git a/npm/ng-packs/packages/core/src/lib/directives/index.ts b/npm/ng-packs/packages/core/src/lib/directives/index.ts index 336b6ff5ab..7edf1b5f76 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/index.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/index.ts @@ -1,5 +1,6 @@ export * from './autofocus.directive'; export * from './ellipsis.directive'; +export * from './for.directive'; export * from './form-submit.directive'; export * from './permission.directive'; export * from './visibility.directive'; diff --git a/npm/ng-packs/packages/core/src/lib/enums/common.ts b/npm/ng-packs/packages/core/src/lib/enums/common.ts index 08ddf05b6d..3b953b8ac7 100644 --- a/npm/ng-packs/packages/core/src/lib/enums/common.ts +++ b/npm/ng-packs/packages/core/src/lib/enums/common.ts @@ -2,4 +2,5 @@ export const enum eLayoutType { account = 'account', application = 'application', empty = 'empty', + setting = 'setting', } diff --git a/npm/ng-packs/packages/core/src/lib/models/common.ts b/npm/ng-packs/packages/core/src/lib/models/common.ts index 502363a323..a5089760f0 100644 --- a/npm/ng-packs/packages/core/src/lib/models/common.ts +++ b/npm/ng-packs/packages/core/src/lib/models/common.ts @@ -1,5 +1,5 @@ import { Config } from './config'; -import { eLayoutType } from '../enums'; +import { eLayoutType } from '../enums/common'; export namespace ABP { export interface Root { diff --git a/npm/ng-packs/packages/feature-management/src/lib/root-feature-management.module.ts b/npm/ng-packs/packages/feature-management/src/lib/root-feature-management.module.ts deleted file mode 100644 index cb60351a07..0000000000 --- a/npm/ng-packs/packages/feature-management/src/lib/root-feature-management.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ModuleWithProviders, NgModule } from '@angular/core'; - -@NgModule({}) -export class RootFeatureManagementModule { - static forRoot(): ModuleWithProviders { - return { - ngModule: RootFeatureManagementModule, - providers: [], - }; - } -} diff --git a/npm/ng-packs/packages/feature-management/src/public-api.ts b/npm/ng-packs/packages/feature-management/src/public-api.ts index a13bb6c526..047ac00914 100644 --- a/npm/ng-packs/packages/feature-management/src/public-api.ts +++ b/npm/ng-packs/packages/feature-management/src/public-api.ts @@ -1,3 +1,2 @@ -export * from './lib/root-feature-management.module'; export * from './lib/feature-management.module'; export * from './lib/components'; diff --git a/npm/ng-packs/packages/identity/src/lib/identity.module.ts b/npm/ng-packs/packages/identity/src/lib/identity.module.ts index 7ae218a5f3..d94ba410d9 100644 --- a/npm/ng-packs/packages/identity/src/lib/identity.module.ts +++ b/npm/ng-packs/packages/identity/src/lib/identity.module.ts @@ -1,5 +1,5 @@ import { CoreModule } from '@abp/ng.core'; -import { NgModule } from '@angular/core'; +import { NgModule, Provider } from '@angular/core'; import { NgxsModule } from '@ngxs/store'; import { RolesComponent } from './components/roles/roles.component'; import { IdentityRoutingModule } from './identity-routing.module'; @@ -26,3 +26,7 @@ import { NgxValidateCoreModule } from '@ngx-validate/core'; ], }) export class IdentityModule {} + +export function IdentityProviders(): Provider[] { + return []; +} diff --git a/npm/ng-packs/packages/identity/src/lib/root-identity.module.ts b/npm/ng-packs/packages/identity/src/lib/root-identity.module.ts deleted file mode 100644 index c5cc5efaaa..0000000000 --- a/npm/ng-packs/packages/identity/src/lib/root-identity.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ModuleWithProviders, NgModule } from '@angular/core'; - -@NgModule({}) -export class RootIdentityModule { - static forRoot(): ModuleWithProviders { - return { - ngModule: RootIdentityModule, - providers: [], - }; - } -} diff --git a/npm/ng-packs/packages/identity/src/public-api.ts b/npm/ng-packs/packages/identity/src/public-api.ts index e3de2483e4..be547b1c34 100644 --- a/npm/ng-packs/packages/identity/src/public-api.ts +++ b/npm/ng-packs/packages/identity/src/public-api.ts @@ -2,7 +2,6 @@ * Public API Surface of identity */ -export * from './lib/root-identity.module'; export * from './lib/identity.module'; export * from './lib/actions/identity.actions'; export * from './lib/components/roles/roles.component'; diff --git a/npm/ng-packs/packages/permission-management/src/lib/root-permission-management.module.ts b/npm/ng-packs/packages/permission-management/src/lib/root-permission-management.module.ts deleted file mode 100644 index a61fbc6b64..0000000000 --- a/npm/ng-packs/packages/permission-management/src/lib/root-permission-management.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ModuleWithProviders, NgModule } from '@angular/core'; - -@NgModule({}) -export class RootPermissionManagementModule { - static forRoot(): ModuleWithProviders { - return { - ngModule: RootPermissionManagementModule, - providers: [], - }; - } -} diff --git a/npm/ng-packs/packages/permission-management/src/public-api.ts b/npm/ng-packs/packages/permission-management/src/public-api.ts index bf45b06676..3182363f25 100644 --- a/npm/ng-packs/packages/permission-management/src/public-api.ts +++ b/npm/ng-packs/packages/permission-management/src/public-api.ts @@ -2,7 +2,6 @@ * Public API Surface of permission-management */ -export * from './lib/root-permission-management.module'; export * from './lib/permission-management.module'; export * from './lib/actions'; export * from './lib/components'; diff --git a/npm/ng-packs/packages/setting-management/src/lib/components/index.ts b/npm/ng-packs/packages/setting-management/src/lib/components/index.ts deleted file mode 100644 index 4f59d5c056..0000000000 --- a/npm/ng-packs/packages/setting-management/src/lib/components/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './setting/setting.component'; diff --git a/npm/ng-packs/packages/setting-management/src/lib/components/services/initial.service.ts b/npm/ng-packs/packages/setting-management/src/lib/components/services/initial.service.ts deleted file mode 100644 index 44f289a362..0000000000 --- a/npm/ng-packs/packages/setting-management/src/lib/components/services/initial.service.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { SettingTab } from '@abp/ng.theme.shared'; -import { Injectable, OnInit } from '@angular/core'; -import { Router } from '@angular/router'; -import snq from 'snq'; - -@Injectable() -export class InitialService { - public settings: SettingTab[]; - - constructor(private router: Router) { - this.settings = this.router.config - .map(route => snq(() => route.data.routes.settings)) - .filter(settings => settings && settings.length) - .reduce((acc, val) => [...acc, ...val], []) - .sort((a, b) => a.order - b.order); - } -} diff --git a/npm/ng-packs/packages/setting-management/src/lib/components/setting-layout.component.html b/npm/ng-packs/packages/setting-management/src/lib/components/setting-layout.component.html new file mode 100644 index 0000000000..8465f75e65 --- /dev/null +++ b/npm/ng-packs/packages/setting-management/src/lib/components/setting-layout.component.html @@ -0,0 +1,59 @@ +
+
+

{{ 'AbpSettingManagement::Settings' | abpLocalization }}

+
+ +
+
+
+
+ +
+
+
+
+ +
+
+ +
+
+
+

{{ settingManagementService.selected.name | abpLocalization }}

+
+ +
+
+
+
+
+
+
diff --git a/npm/ng-packs/packages/setting-management/src/lib/components/setting-layout.component.ts b/npm/ng-packs/packages/setting-management/src/lib/components/setting-layout.component.ts new file mode 100644 index 0000000000..3096a2104b --- /dev/null +++ b/npm/ng-packs/packages/setting-management/src/lib/components/setting-layout.component.ts @@ -0,0 +1,37 @@ +import { eLayoutType } from '@abp/ng.core'; +import { SettingTab } from '@abp/ng.theme.shared'; +import { Component, TrackByFunction } from '@angular/core'; +import { Router } from '@angular/router'; +import { timer } from 'rxjs'; +import { SettingManagementService } from '../services/setting-management.service'; + +@Component({ + selector: 'abp-setting-layout', + templateUrl: './setting-layout.component.html', +}) +export class SettingLayoutComponent { + // required for dynamic component + static type = eLayoutType.setting; + + trackByFn: TrackByFunction = (_, item) => item.name; + + constructor(public settingManagementService: SettingManagementService, private router: Router) { + if ( + settingManagementService.selected && + this.router.url !== settingManagementService.selected.url && + settingManagementService.settings.length + ) { + settingManagementService.setSelected(settingManagementService.settings[0]); + } + } + + ngOnDestroy() {} + + ngAfterViewInit() { + timer(250).subscribe(() => { + if (!this.settingManagementService.settings.length) { + this.settingManagementService.setSettings(); + } + }); + } +} diff --git a/npm/ng-packs/packages/setting-management/src/lib/components/setting/setting.component.html b/npm/ng-packs/packages/setting-management/src/lib/components/setting/setting.component.html deleted file mode 100644 index 6397e17a1f..0000000000 --- a/npm/ng-packs/packages/setting-management/src/lib/components/setting/setting.component.html +++ /dev/null @@ -1,51 +0,0 @@ -
-
-

{{ 'AbpSettingManagement::Settings' | abpLocalization }}

-
- -
-
-
-
- -
-
-
-
- -
-
-
-

{{ selected.name | abpLocalization }}

-
- - -
-
-
-
-
-
-
diff --git a/npm/ng-packs/packages/setting-management/src/lib/components/setting/setting.component.ts b/npm/ng-packs/packages/setting-management/src/lib/components/setting/setting.component.ts deleted file mode 100644 index 645f7e2c2c..0000000000 --- a/npm/ng-packs/packages/setting-management/src/lib/components/setting/setting.component.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { SettingTab, fade } from '@abp/ng.theme.shared'; -import { InitialService } from '../services/initial.service'; - -@Component({ - selector: 'abp-setting', - templateUrl: './setting.component.html', -}) -export class SettingComponent implements OnInit { - settings: SettingTab[]; - - selected = {} as SettingTab; - - constructor(private initialService: InitialService) {} - - ngOnInit() { - this.settings = this.initialService.settings; - this.selected = this.settings[0]; - } -} diff --git a/npm/ng-packs/packages/setting-management/src/lib/constants/routes.ts b/npm/ng-packs/packages/setting-management/src/lib/constants/routes.ts index 067f8e9c02..3f47c95eb7 100644 --- a/npm/ng-packs/packages/setting-management/src/lib/constants/routes.ts +++ b/npm/ng-packs/packages/setting-management/src/lib/constants/routes.ts @@ -11,5 +11,4 @@ export const SETTING_MANAGEMENT_ROUTES = { iconClass: 'fa fa-cog', }, ] as ABP.FullRoute[], - settings: [], }; diff --git a/npm/ng-packs/packages/setting-management/src/lib/root-setting-management.module.ts b/npm/ng-packs/packages/setting-management/src/lib/root-setting-management.module.ts deleted file mode 100644 index 120d9fc444..0000000000 --- a/npm/ng-packs/packages/setting-management/src/lib/root-setting-management.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ModuleWithProviders, NgModule } from '@angular/core'; - -@NgModule({}) -export class RootSettingManagementModule { - static forRoot(): ModuleWithProviders { - return { - ngModule: RootSettingManagementModule, - providers: [], - }; - } -} diff --git a/npm/ng-packs/packages/setting-management/src/lib/services/setting-management.service.ts b/npm/ng-packs/packages/setting-management/src/lib/services/setting-management.service.ts new file mode 100644 index 0000000000..141ce3a03d --- /dev/null +++ b/npm/ng-packs/packages/setting-management/src/lib/services/setting-management.service.ts @@ -0,0 +1,53 @@ +import { SettingTab } from '@abp/ng.theme.shared'; +import { Injectable } from '@angular/core'; +import { Router, RouteConfigLoadEnd, NavigationEnd } from '@angular/router'; +import { Navigate } from '@ngxs/router-plugin'; +import { Store } from '@ngxs/store'; +import { filter } from 'rxjs/operators'; +import { takeUntilDestroy } from '@abp/ng.core'; +import { Subscription, timer } from 'rxjs'; + +@Injectable({ providedIn: 'root' }) +export class SettingManagementService { + settings: SettingTab[] = []; + + selected = {} as SettingTab; + + constructor(private router: Router, private store: Store) { + let timeout: Subscription; + this.router.events + .pipe( + filter(event => event instanceof RouteConfigLoadEnd), + takeUntilDestroy(this), + ) + .subscribe(event => { + if (timeout) timeout.unsubscribe(); + timeout = timer(150).subscribe(() => { + this.setSettings(); + }); + }); + } + + ngOnDestroy() {} + + setSettings() { + setTimeout(() => { + const route = this.router.config.find(r => r.path === 'setting-management'); + this.settings = route.data.settings.sort((a, b) => a.order - b.order); + this.checkSelected(); + }, 0); + } + + checkSelected() { + this.selected = this.settings.find(setting => setting.url === this.router.url) || ({} as SettingTab); + + if (!this.selected.name && this.settings.length) { + this.setSelected(this.settings[0]); + } + } + + setSelected(selected: SettingTab) { + this.selected = selected; + this.store.dispatch(new Navigate([selected.url])); + } +} diff --git a/npm/ng-packs/packages/setting-management/src/lib/setting-management-routing.module.ts b/npm/ng-packs/packages/setting-management/src/lib/setting-management-routing.module.ts index dcafc14f41..e401df16de 100644 --- a/npm/ng-packs/packages/setting-management/src/lib/setting-management-routing.module.ts +++ b/npm/ng-packs/packages/setting-management/src/lib/setting-management-routing.module.ts @@ -1,13 +1,15 @@ import { DynamicLayoutComponent } from '@abp/ng.core'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -import { SettingComponent } from './components/setting/setting.component'; +import { SETTING_MANAGEMENT_ROUTES } from './constants/routes'; +import { SettingLayoutComponent } from './components/setting-layout.component'; const routes: Routes = [ { - path: '', + path: 'setting-management', component: DynamicLayoutComponent, - children: [{ path: '', component: SettingComponent }], + children: [{ path: '', component: SettingLayoutComponent }], + data: { routes: SETTING_MANAGEMENT_ROUTES, settings: [] }, }, ]; diff --git a/npm/ng-packs/packages/setting-management/src/lib/setting-management.module.ts b/npm/ng-packs/packages/setting-management/src/lib/setting-management.module.ts index 6c0918788c..b3959e6650 100644 --- a/npm/ng-packs/packages/setting-management/src/lib/setting-management.module.ts +++ b/npm/ng-packs/packages/setting-management/src/lib/setting-management.module.ts @@ -1,15 +1,14 @@ -import { CoreModule, noop } from '@abp/ng.core'; -import { NgModule, ModuleWithProviders, APP_INITIALIZER, Self } from '@angular/core'; -import { SettingComponent } from './components/setting/setting.component'; -import { SettingManagementRoutingModule } from './setting-management-routing.module'; +import { CoreModule } from '@abp/ng.core'; import { ThemeSharedModule } from '@abp/ng.theme.shared'; -import { InitialService } from './components/services/initial.service'; +import { NgModule } from '@angular/core'; +import { SettingLayoutComponent } from './components/setting-layout.component'; +import { SettingManagementRoutingModule } from './setting-management-routing.module'; + +export const SETTING_LAYOUT = SettingLayoutComponent; @NgModule({ - declarations: [SettingComponent], + declarations: [SETTING_LAYOUT], imports: [SettingManagementRoutingModule, CoreModule, ThemeSharedModule], - providers: [InitialService], + entryComponents: [SETTING_LAYOUT], }) -export class SettingManagementModule { - constructor(@Self() initialService: InitialService) {} -} +export class SettingManagementModule {} diff --git a/npm/ng-packs/packages/setting-management/src/public-api.ts b/npm/ng-packs/packages/setting-management/src/public-api.ts index 6ef085fc8e..5343d9e457 100644 --- a/npm/ng-packs/packages/setting-management/src/public-api.ts +++ b/npm/ng-packs/packages/setting-management/src/public-api.ts @@ -1,4 +1,3 @@ -export * from './lib/root-setting-management.module'; export * from './lib/setting-management.module'; -export * from './lib/components'; export * from './lib/constants'; +export * from './lib/components/setting-layout.component'; diff --git a/npm/ng-packs/packages/tenant-management/src/lib/root-tenant-management.module.ts b/npm/ng-packs/packages/tenant-management/src/lib/root-tenant-management.module.ts deleted file mode 100644 index a147f2a36a..0000000000 --- a/npm/ng-packs/packages/tenant-management/src/lib/root-tenant-management.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ModuleWithProviders, NgModule } from '@angular/core'; - -@NgModule({}) -export class RootTenantManagementModule { - static forRoot(): ModuleWithProviders { - return { - ngModule: RootTenantManagementModule, - providers: [], - }; - } -} diff --git a/npm/ng-packs/packages/tenant-management/src/lib/tenant-management.module.ts b/npm/ng-packs/packages/tenant-management/src/lib/tenant-management.module.ts index feb7303167..f8a258da3b 100644 --- a/npm/ng-packs/packages/tenant-management/src/lib/tenant-management.module.ts +++ b/npm/ng-packs/packages/tenant-management/src/lib/tenant-management.module.ts @@ -1,6 +1,6 @@ import { CoreModule } from '@abp/ng.core'; import { ThemeSharedModule } from '@abp/ng.theme.shared'; -import { NgModule } from '@angular/core'; +import { NgModule, Provider } from '@angular/core'; import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; import { NgxsModule } from '@ngxs/store'; import { TableModule } from 'primeng/table'; @@ -24,3 +24,7 @@ import { NgxValidateCoreModule } from '@ngx-validate/core'; ], }) export class TenantManagementModule {} + +export function TenantManagementProviders(): Provider[] { + return []; +} diff --git a/npm/ng-packs/packages/tenant-management/src/public-api.ts b/npm/ng-packs/packages/tenant-management/src/public-api.ts index 6b2ae2d388..9bae9a9edb 100644 --- a/npm/ng-packs/packages/tenant-management/src/public-api.ts +++ b/npm/ng-packs/packages/tenant-management/src/public-api.ts @@ -1,4 +1,3 @@ -export * from './lib/root-tenant-management.module'; export * from './lib/tenant-management.module'; export * from './lib/actions'; export * from './lib/components'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/models/setting-management.ts b/npm/ng-packs/packages/theme-shared/src/lib/models/setting-management.ts index 68bd0335a5..1b8c36412e 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/models/setting-management.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/models/setting-management.ts @@ -1,8 +1,6 @@ -import { Type } from '@angular/core'; - export interface SettingTab { name: string; order: number; - component: Type; requiredPolicy?: string; + url?: string; } diff --git a/npm/ng-packs/tsconfig.json b/npm/ng-packs/tsconfig.json index 9c996dd271..d503c81439 100644 --- a/npm/ng-packs/tsconfig.json +++ b/npm/ng-packs/tsconfig.json @@ -11,8 +11,13 @@ "moduleResolution": "node", "importHelpers": true, "target": "es2015", - "typeRoots": ["node_modules/@types"], - "lib": ["es2018", "dom"], + "typeRoots": [ + "node_modules/@types" + ], + "lib": [ + "es2018", + "dom" + ], "paths": {} }, "angularCompilerOptions": { diff --git a/templates/app/angular/src/app/app.module.ts b/templates/app/angular/src/app/app.module.ts index 86b2d1b7be..7e942b2648 100644 --- a/templates/app/angular/src/app/app.module.ts +++ b/templates/app/angular/src/app/app.module.ts @@ -11,9 +11,9 @@ import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { SharedModule } from './shared/shared.module'; import { ThemeSharedModule } from '@abp/ng.theme.shared'; -import { RootAccountModule } from '@abp/ng.account'; -import { RootIdentityModule } from '@abp/ng.identity'; -import { RootTenantManagementModule } from '@abp/ng.tenant-management'; +import { AccountProviders } from '@abp/ng.account'; +import { IdentityProviders } from '@abp/ng.identity'; +import { TenantManagementProviders } from '@abp/ng.tenant-management'; @NgModule({ declarations: [AppComponent], @@ -29,15 +29,12 @@ import { RootTenantManagementModule } from '@abp/ng.tenant-management'; layouts: LAYOUTS, }, }), - RootAccountModule.forRoot({ redirectUrl: '/' }), - RootIdentityModule.forRoot(), - RootTenantManagementModule.forRoot(), OAuthModule.forRoot(), NgxsModule.forRoot([]), NgxsReduxDevtoolsPluginModule.forRoot({ disabled: environment.production }), ], - providers: [], + providers: [...AccountProviders({ redirectUrl: '/' }), ...IdentityProviders(), ...TenantManagementProviders()], bootstrap: [AppComponent], }) export class AppModule {}