pull/1746/head
Yunus Emre Kalkan 6 years ago
commit f32ebc84cb

@ -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()
);

@ -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],
},
];
}

@ -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],
},
],
};
}
}

@ -1,4 +1,3 @@
export * from './lib/root-account.module';
export * from './lib/account.module';
export * from './lib/components';
export * from './lib/constants/routes';

@ -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<any>;
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);
}

@ -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,

@ -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<T = any> = (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<any>, public view: EmbeddedViewRef<AbpForContext>) {}
}
@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<any>;
private differ: IterableDiffer<any>;
private isShowEmptyRef: boolean;
get compareFn(): CompareFn {
return this.compareBy || compare;
}
get trackByFn(): TrackByFunction<any> {
return this.trackBy || ((index: number, item: any) => (item as any).id || index);
}
constructor(
private tempRef: TemplateRef<AbpForContext>,
private vcRef: ViewContainerRef,
private differs: IterableDiffers,
) {}
private iterateOverAppliedOperations(changes: IterableChanges<any>) {
const rw: RecordView[] = [];
changes.forEachOperation((record: IterableChangeRecord<any>, 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<AbpForContext>));
}
});
for (let i = 0, l = rw.length; i < l; i++) {
rw[i].view.context.$implicit = rw[i].record.item;
}
}
private iterateOverAttachedViews(changes: IterableChanges<any>) {
for (let i = 0, l = this.vcRef.length; i < l; i++) {
const viewRef = this.vcRef.get(i) as EmbeddedViewRef<AbpForContext>;
viewRef.context.index = i;
viewRef.context.count = l;
viewRef.context.list = this.items;
}
changes.forEachIdentityChange((record: IterableChangeRecord<any>) => {
const viewRef = this.vcRef.get(record.currentIndex) as EmbeddedViewRef<AbpForContext>;
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);
}
}
}

@ -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';

@ -2,4 +2,5 @@ export const enum eLayoutType {
account = 'account',
application = 'application',
empty = 'empty',
setting = 'setting',
}

@ -1,5 +1,5 @@
import { Config } from './config';
import { eLayoutType } from '../enums';
import { eLayoutType } from '../enums/common';
export namespace ABP {
export interface Root {

@ -1,11 +0,0 @@
import { ModuleWithProviders, NgModule } from '@angular/core';
@NgModule({})
export class RootFeatureManagementModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: RootFeatureManagementModule,
providers: [],
};
}
}

@ -1,3 +1,2 @@
export * from './lib/root-feature-management.module';
export * from './lib/feature-management.module';
export * from './lib/components';

@ -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 [];
}

@ -1,11 +0,0 @@
import { ModuleWithProviders, NgModule } from '@angular/core';
@NgModule({})
export class RootIdentityModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: RootIdentityModule,
providers: [],
};
}
}

@ -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';

@ -1,11 +0,0 @@
import { ModuleWithProviders, NgModule } from '@angular/core';
@NgModule({})
export class RootPermissionManagementModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: RootPermissionManagementModule,
providers: [],
};
}
}

@ -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';

@ -1 +0,0 @@
export * from './setting/setting.component';

@ -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);
}
}

@ -0,0 +1,59 @@
<div class="row entry-row">
<div class="col-auto">
<h1 class="content-header-title">{{ 'AbpSettingManagement::Settings' | abpLocalization }}</h1>
</div>
<!-- <div id="breadcrumb" class="col-md-auto pl-md-0">
<abp-breadcrumb></abp-breadcrumb>
</div> -->
<div class="col">
<div class="text-lg-right pt-2" id="AbpContentToolbar"></div>
</div>
</div>
<div id="SettingManagementWrapper">
<div class="card">
<div class="card-body">
<div *ngIf="!settingManagementService.settings.length" class="text-center">
<i class="fa fa-spinner fa-spin"></i>
</div>
<div class="row">
<div class="col-3">
<ul class="nav flex-column nav-pills" id="nav-tab" role="tablist">
<li
*abpFor="
let setting of settingManagementService.settings;
trackBy: trackByFn;
orderBy: 'order';
orderDir: 'ASC'
"
(click)="settingManagementService.setSelected(setting)"
class="nav-item"
[abpPermission]="setting.requiredPolicy"
>
<a
class="nav-link"
[id]="setting.name + '-tab'"
role="tab"
[class.active]="setting.name === settingManagementService.selected.name"
>{{ setting.name | abpLocalization }}</a
>
</li>
</ul>
</div>
<div class="col-9">
<div *ngIf="settingManagementService.settings.length" class="tab-content">
<div
class="tab-pane fade show active"
[id]="settingManagementService.selected.name + '-tab'"
role="tabpanel"
>
<h2>{{ settingManagementService.selected.name | abpLocalization }}</h2>
<hr class="my-4" />
<router-outlet></router-outlet>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -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<SettingTab> = (_, 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();
}
});
}
}

@ -1,51 +0,0 @@
<div class="row entry-row">
<div class="col-auto">
<h1 class="content-header-title">{{ 'AbpSettingManagement::Settings' | abpLocalization }}</h1>
</div>
<div id="breadcrumb" class="col-md-auto pl-md-0">
<abp-breadcrumb></abp-breadcrumb>
</div>
<div class="col">
<div class="text-lg-right pt-2" id="AbpContentToolbar"></div>
</div>
</div>
<div id="SettingManagementWrapper">
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-3">
<ul class="nav flex-column nav-pills" id="T515ccf3324254f41a4a9a6b34b0dae56" role="tablist">
<li
*ngFor="let setting of settings"
(click)="selected = setting"
class="nav-item"
[abpPermission]="setting.requiredPolicy"
>
<a
class="nav-link"
[id]="setting.name + '-tab'"
role="tab"
[class.active]="setting.name === selected.name"
>{{ setting.name | abpLocalization }}</a
>
</li>
</ul>
</div>
<div class="col-9">
<div class="tab-content">
<div class="tab-pane fade show active" [id]="selected.name + '-tab'" role="tabpanel">
<h2>{{ selected.name | abpLocalization }}</h2>
<hr class="my-4" />
<ng-container
*ngComponentOutlet="selected.component"
[abpPermission]="selected.requiredPolicy"
></ng-container>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -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];
}
}

@ -11,5 +11,4 @@ export const SETTING_MANAGEMENT_ROUTES = {
iconClass: 'fa fa-cog',
},
] as ABP.FullRoute[],
settings: [],
};

@ -1,11 +0,0 @@
import { ModuleWithProviders, NgModule } from '@angular/core';
@NgModule({})
export class RootSettingManagementModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: RootSettingManagementModule,
providers: [],
};
}
}

@ -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]));
}
}

@ -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: [] },
},
];

@ -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 {}

@ -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';

@ -1,11 +0,0 @@
import { ModuleWithProviders, NgModule } from '@angular/core';
@NgModule({})
export class RootTenantManagementModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: RootTenantManagementModule,
providers: [],
};
}
}

@ -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 [];
}

@ -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';

@ -1,8 +1,6 @@
import { Type } from '@angular/core';
export interface SettingTab {
name: string;
order: number;
component: Type<any>;
requiredPolicy?: string;
url?: string;
}

@ -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": {

@ -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 {}

Loading…
Cancel
Save