Merge pull request #1584 from abpframework/refactor/general

Refactor/general
pull/1588/head
Yasin Aydın 6 years ago committed by GitHub
commit f8a6569ff3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -53,7 +53,12 @@ export class LoginComponent {
this.store.dispatch(new Navigate([redirectUrl]));
}),
catchError(err => {
this.toasterService.error(snq(() => err.error.error_description, 'An error occured.'), 'Error');
this.toasterService.error(
snq(() => err.error.error_description) ||
snq(() => err.error.error.message, 'AbpAccount::DefaultErrorMessage'),
'Error',
{ life: 7000 },
);
return throwError(err);
}),
finalize(() => (this.inProgress = false)),

@ -8,7 +8,7 @@
<div class="form-group">
<label for="input-user-name">{{ 'AbpAccount::UserName' | abpLocalization }}</label
><span> * </span
><input autofocus type="text" id="input-user-name" class="form-control" formControlName="username" autofocus/>
><input autofocus type="text" id="input-user-name" class="form-control" formControlName="username" />
</div>
<div class="form-group">
<label for="input-email-address">{{ 'AbpAccount::EmailAddress' | abpLocalization }}</label

@ -1,13 +1,11 @@
import { ToasterService } from '@abp/ng.theme.shared';
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { validatePassword } from '@ngx-validate/core';
import { throwError } from 'rxjs';
import { catchError, finalize, take } from 'rxjs/operators';
import snq from 'snq';
import { RegisterRequest } from '../../models';
import { AccountService } from '../../services/account.service';
const { maxLength, minLength, required, email } = Validators;
@Component({
@ -22,10 +20,7 @@ export class RegisterComponent {
constructor(private fb: FormBuilder, private accountService: AccountService, private toasterService: ToasterService) {
this.form = this.fb.group({
username: ['', [required, maxLength(255)]],
password: [
'',
[required, maxLength(32), minLength(6), validatePassword(['small', 'capital', 'number', 'special'])],
],
password: ['', [required, maxLength(32)]],
email: ['', [required, email]],
});
}
@ -47,7 +42,12 @@ export class RegisterComponent {
.pipe(
take(1),
catchError(err => {
this.toasterService.error(snq(() => err.error.error_description, 'An error occured.'), 'Error');
this.toasterService.error(
snq(() => err.error.error_description) ||
snq(() => err.error.error.message, 'AbpAccount::DefaultErrorMessage'),
'Error',
{ life: 7000 },
);
return throwError(err);
}),
finalize(() => (this.inProgress = false)),

@ -31,6 +31,7 @@ export namespace ABP {
parentName?: string;
path: string;
requiredPolicy?: string;
iconClass?: string;
}
export interface FullRoute extends Route {

@ -47,7 +47,9 @@ function transformRoutes(routes: Routes = [], wrappers: ABP.FullRoute[] = []): a
routes
.filter(route => (route.data || {}).routes && (route.component || route.loadChildren))
.forEach(route => {
const abpPackage = abpRoutes.find(abp => abp.path.toLowerCase() === route.path.toLowerCase());
const abpPackage = abpRoutes.find(
abp => abp.path.toLowerCase() === route.path.toLowerCase() && snq(() => route.data.routes.length, false),
);
const { length } = transformed;
if (abpPackage) {

@ -28,13 +28,13 @@ export class ProfileService {
return this.rest.request<Profile.Response, Profile.Response>(request);
}
changePassword(body: Profile.ChangePasswordRequest): Observable<null> {
changePassword(body: Profile.ChangePasswordRequest, throwErr: boolean = false): Observable<null> {
const request: Rest.Request<Profile.ChangePasswordRequest> = {
method: 'POST',
url: '/api/identity/my-profile/changePassword',
url: '/api/identity/my-profile/change-password',
body,
};
return this.rest.request<Profile.ChangePasswordRequest, null>(request);
return this.rest.request<Profile.ChangePasswordRequest, null>(request, { throwErr });
}
}

@ -40,6 +40,6 @@ export class ProfileState {
@Action(ProfileChangePassword)
changePassword(_, { payload }: ProfileChangePassword) {
return this.profileService.changePassword(payload);
return this.profileService.changePassword(payload, true);
}
}

@ -7,7 +7,7 @@ export function organizeRoutes(
parentName: string = null,
): ABP.FullRoute[] {
const filter = route => {
if (route.children) {
if (route.children && route.children.length) {
route.children = organizeRoutes(route.children, wrappers, parentNameArr, route.name);
}
@ -34,20 +34,18 @@ export function organizeRoutes(
}
export function setChildRoute(routes: ABP.FullRoute[], parentNameArr: ABP.FullRoute[]): ABP.FullRoute[] {
return routes
.map(route => {
if (route.children && route.children.length) {
route.children = setChildRoute(route.children, parentNameArr);
}
return routes.map(route => {
if (route.children && route.children.length) {
route.children = setChildRoute(route.children, parentNameArr);
}
const foundedChildren = parentNameArr.filter(parent => parent.parentName === route.name);
if (foundedChildren && foundedChildren.length) {
route.children = [...(route.children || []), ...foundedChildren];
}
const foundedChildren = parentNameArr.filter(parent => parent.parentName === route.name);
if (foundedChildren && foundedChildren.length) {
route.children = [...(route.children || []), ...foundedChildren];
}
return route;
})
.filter(route => route.path || (route.children && route.children.length));
return route;
});
}
export function sortRoutes(routes: ABP.FullRoute[] = []): ABP.FullRoute[] {

@ -2,7 +2,6 @@ import { ABP } from '@abp/ng.core';
import { ConfirmationService, Toaster } from '@abp/ng.theme.shared';
import { Component, OnInit, TemplateRef, TrackByFunction, ViewChild } from '@angular/core';
import { AbstractControl, FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { validatePassword } from '@ngx-validate/core';
import { Select, Store } from '@ngxs/store';
import { combineLatest, Observable, Subject } from 'rxjs';
import { debounceTime, filter, map, pluck, take } from 'rxjs/operators';
@ -72,15 +71,7 @@ export class UsersComponent implements OnInit {
this.roles = this.store.selectSnapshot(IdentityState.getRoles);
this.form = this.fb.group({
password: [
'',
[
Validators.required,
Validators.maxLength(32),
Validators.minLength(6),
validatePassword(['small', 'capital', 'number', 'special']),
],
],
password: ['', [Validators.required, Validators.maxLength(32)]],
userName: [this.selected.userName || '', [Validators.required, Validators.maxLength(256)]],
email: [this.selected.email || '', [Validators.required, Validators.email, Validators.maxLength(256)]],
name: [this.selected.name || '', [Validators.maxLength(64)]],

@ -8,11 +8,12 @@ export const IDENTITY_ROUTES = [
wrapper: true,
},
{
name: 'Identity',
name: 'Identity Management',
path: 'identity',
order: 1,
parentName: 'Administration',
layout: eLayoutType.application,
iconClass: 'fa fa-id-card-o',
children: [
{ path: 'roles', name: 'Roles', order: 2, requiredPolicy: 'AbpIdentity.Roles' },
{ path: 'users', name: 'Users', order: 1, requiredPolicy: 'AbpIdentity.Users' },

@ -6,6 +6,7 @@ export const TENANT_MANAGEMENT_ROUTES = [
path: 'tenant-management',
parentName: 'Administration',
layout: eLayoutType.application,
iconClass: 'fa fa-users',
children: [
{
path: 'tenants',

@ -1,4 +1,5 @@
import { ProfileChangePassword } from '@abp/ng.core';
import { ToasterService } from '@abp/ng.theme.shared';
import {
Component,
EventEmitter,
@ -11,8 +12,9 @@ import {
ViewChild,
} from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { comparePasswords, validatePassword } from '@ngx-validate/core';
import { comparePasswords } from '@ngx-validate/core';
import { Store } from '@ngxs/store';
import snq from 'snq';
const { minLength, required } = Validators;
@ -41,14 +43,14 @@ export class ChangePasswordComponent implements OnInit, OnChanges {
form: FormGroup;
constructor(private fb: FormBuilder, private store: Store) {}
constructor(private fb: FormBuilder, private store: Store, private toasterService: ToasterService) {}
ngOnInit(): void {
this.form = this.fb.group(
{
password: ['', [required, minLength(6), validatePassword(['small', 'capital', 'number', 'special'])]],
newPassword: ['', [required, minLength(6), validatePassword(['small', 'capital', 'number', 'special'])]],
repeatNewPassword: ['', [required, minLength(6), validatePassword(['small', 'capital', 'number', 'special'])]],
password: ['', required],
newPassword: ['', required],
repeatNewPassword: ['', required],
},
{
validators: [comparePasswords(['newPassword', 'repeatNewPassword'])],
@ -66,8 +68,16 @@ export class ChangePasswordComponent implements OnInit, OnChanges {
newPassword: this.form.get('newPassword').value,
}),
)
.subscribe(() => {
this.visible = false;
.subscribe({
next: () => {
this.visible = false;
this.form.reset();
},
error: err => {
this.toasterService.error(snq(() => err.error.error.message, 'AbpAccount::DefaultErrorMessage'), 'Error', {
life: 7000,
});
},
});
}

@ -46,7 +46,10 @@
<ng-template #defaultChild let-child>
<div class="dropdown-submenu" [abpPermission]="child.requiredPolicy">
<a class="dropdown-item py-2 px-2" [routerLink]="[child.url]">{{ child.name | abpLocalization }}</a>
<a class="dropdown-item py-2 px-2" [routerLink]="[child.url]">
<i *ngIf="child.iconClass" [ngClass]="child.iconClass"></i>
{{ child.name | abpLocalization }}</a
>
</div>
</ng-template>
@ -61,11 +64,12 @@
>
<div ngbDropdownToggle [class.dropdown-toggle]="false" class="pointer">
<a
abpEllipsis="140px"
abpEllipsis="200px"
[abpEllipsisEnabled]="isDropdownChildDynamic"
role="button"
class="btn d-block text-left py-2 px-2 dropdown-toggle"
>
<i *ngIf="child.iconClass" [ngClass]="child.iconClass"></i>
{{ child.name | abpLocalization }}
</a>
</div>

@ -57,6 +57,7 @@ export class ProfileComponent implements OnChanges {
this.store.dispatch(new ProfileUpdate(this.form.value)).subscribe(() => {
this.visible = false;
this.form.reset();
});
}

@ -5,7 +5,7 @@
"@abp/ng.core": "^0.8.0",
"@angular/cdk": "^8.0.1",
"@ng-bootstrap/ng-bootstrap": "^5.1.0",
"@ngx-validate/core": "^0.0.1",
"@ngx-validate/core": "^0.0.4",
"bootstrap": "^4.3.1",
"font-awesome": "^4.7.0",
"ngx-perfect-scrollbar": "^8.0.0",

@ -11,14 +11,14 @@ import { Component, Renderer2, ElementRef } from '@angular/core';
<div class="col-md-12">
<div class="error-template">
<h1>
{{ title }}
{{ title | abpLocalization }}
</h1>
<div class="error-details">
{{ details }}
{{ details | abpLocalization }}
</div>
<div class="error-actions">
<a routerLink="/" class="btn btn-primary btn-md mt-2"
><span class="glyphicon glyphicon-home"></span> Take me home
<a (click)="destroy()" routerLink="/" class="btn btn-primary btn-md mt-2"
><span class="glyphicon glyphicon-home"></span> {{ '::Menu:Home' | abpLocalization }}
</a>
</div>
</div>

@ -0,0 +1,32 @@
import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
import { Validation, ValidationErrorComponent as ErrorComponent } from '@ngx-validate/core';
@Component({
selector: 'abp-validation-error',
template: `
<div class="invalid-feedback" *ngFor="let error of abpErrors; trackBy: trackByFn">
{{ error.message | abpLocalization: error.interpoliteParams }}
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class ValidationErrorComponent extends ErrorComponent {
get abpErrors(): Validation.Error[] & { interpoliteParams?: string[] } {
return this.validationErrors.map(error => {
if (!error.message) return error;
const index = error.message.indexOf('[');
if (index > -1) {
return {
...error,
message: error.message.slice(0, index),
interpoliteParams: error.message.slice(index + 1, error.message.length - 1).split(','),
};
}
return error;
});
}
}

@ -137,14 +137,16 @@ export class ModalComponent implements OnDestroy {
this.close();
});
if (!this.abpClose) return;
fromEvent(this.abpClose.nativeElement, 'click')
.pipe(
takeUntil(this.destroy$),
filter(() => !!(this.closable && this.modalContent)),
)
.subscribe(() => this.close());
setTimeout(() => {
if (!this.abpClose) return;
fromEvent(this.abpClose.nativeElement, 'click')
.pipe(
takeUntil(this.destroy$),
filter(() => !!(this.closable && this.modalContent)),
)
.subscribe(() => this.close());
}, 0);
this.init.emit();
}

@ -24,6 +24,10 @@ export default `
top: 18px;
}
.navbar .dropdown-menu {
min-width: 220px;
}
.modal {
background-color: rgba(0, 0, 0, .6);
}

@ -80,14 +80,14 @@ export class ErrorHandler {
case 500:
this.createErrorComponent({
title: '500',
details: 'Sorry, an error has occured.',
details: 'AbpAccount::InternalServerErrorMessage',
});
break;
case 0:
if ((err as HttpErrorResponse).statusText === 'Unknown Error') {
this.createErrorComponent({
title: 'Unknown Error',
details: 'Sorry, an error has occured.',
details: 'AbpAccount::InternalServerErrorMessage',
});
}
break;

@ -14,6 +14,7 @@ import { ToastComponent } from './components/toast/toast.component';
import styles from './contants/styles';
import { ErrorHandler } from './handlers/error.handler';
import { ButtonComponent } from './components/button/button.component';
import { ValidationErrorComponent } from './components/errors/validation-error.component';
export function appendScript(injector: Injector) {
const fn = function() {
@ -40,6 +41,16 @@ export function appendScript(injector: Injector) {
NgbModalModule,
NgxValidateCoreModule.forRoot({
targetSelector: '.form-group',
blueprints: {
email: `AbpAccount::ThisFieldIsNotAValidEmailAddress.`,
max: `AbpAccount::ThisFieldMustBeAStringWithAMaximumLengthOf{1}[{{ max }}]`,
maxlength: `AbpAccount::ThisFieldMustBeAStringWithAMaximumLengthOf{1}[{{ requiredLength }}]`,
min: `AbpAccount::ThisFieldMustBeAStringWithAMinimumLengthOf{1}AndAMaximumLengthOf{0}[{{ min }},{{ max }}]`,
minlength: `AbpAccount::ThisFieldMustBeAStringWithAMinimumLengthOf{1}AndAMaximumLengthOf{0}[{{ min }},{{ max }}]`,
required: `AbpAccount::ThisFieldIsRequired.`,
passwordMismatch: `AbpIdentity::Identity.PasswordConfirmationFailed`,
},
errorTemplate: ValidationErrorComponent,
}),
],
declarations: [
@ -49,9 +60,10 @@ export function appendScript(injector: Injector) {
ModalComponent,
ErrorComponent,
LoaderBarComponent,
ValidationErrorComponent,
],
exports: [NgbModalModule, ButtonComponent, ConfirmationComponent, ToastComponent, ModalComponent, LoaderBarComponent],
entryComponents: [ErrorComponent],
entryComponents: [ErrorComponent, ValidationErrorComponent],
})
export class ThemeSharedModule {
static forRoot(): ModuleWithProviders {

@ -6,9 +6,8 @@ import { ABP } from '@abp/ng.core';
import { TENANT_MANAGEMENT_ROUTES } from '@abp/ng.tenant-management';
const routes: Routes = [
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{
path: 'home',
path: '',
loadChildren: () => import('./home/home.module').then(m => m.HomeModule),
data: {
routes: {

Loading…
Cancel
Save