mirror of https://github.com/abpframework/abp.git
120 changed files with 1183 additions and 266 deletions
@ -1,3 +1,220 @@ |
|||
# Angular UI: Theme Configurations |
|||
|
|||
> This document is in draft version. |
|||
Theme packages no longer import styles as CSS modules as of ABP version 6.0. The following style settings need to be included to the angular.json file in order for theme packages to load styles. |
|||
## Lepton X Lite |
|||
```json |
|||
{ |
|||
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/bootstrap-dim.css", |
|||
"inject": false, |
|||
"bundleName": "bootstrap-dim" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/ng-bundle.css", |
|||
"inject": false, |
|||
"bundleName": "ng-bundle" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/side-menu/layout-bundle.css", |
|||
"inject": false, |
|||
"bundleName": "layout-bundle" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@abp/ng.theme.lepton-x/assets/css/abp-bundle.css", |
|||
"inject": false, |
|||
"bundleName": "abp-bundle" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/bootstrap-dim.rtl.css", |
|||
"inject": false, |
|||
"bundleName": "bootstrap-dim.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/ng-bundle.rtl.css", |
|||
"inject": false, |
|||
"bundleName": "ng-bundle.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/side-menu/layout-bundle.rtl.css", |
|||
"inject": false, |
|||
"bundleName": "layout-bundle.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@abp/ng.theme.lepton-x/assets/css/abp-bundle.rtl.css", |
|||
"inject": false, |
|||
"bundleName": "abp-bundle.rtl" |
|||
}, |
|||
``` |
|||
|
|||
## Theme Basic |
|||
```json |
|||
{ |
|||
"input": "node_modules/bootstrap/dist/css/bootstrap.rtl.min.css", |
|||
"inject": false, |
|||
"bundleName": "bootstrap-rtl.min" |
|||
}, |
|||
{ |
|||
"input": "node_modules/bootstrap/dist/css/bootstrap.min.css", |
|||
"inject": true, |
|||
"bundleName": "bootstrap-ltr.min" |
|||
}, |
|||
``` |
|||
|
|||
## Lepton X |
|||
```json |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/dark.css", |
|||
"inject": false, |
|||
"bundleName": "dark" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/light.css", |
|||
"inject": false, |
|||
"bundleName": "light" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/dim.css", |
|||
"inject": false, |
|||
"bundleName": "dim" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-dim.css", |
|||
"inject": false, |
|||
"bundleName": "bootstrap-dim" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-dark.css", |
|||
"inject": false, |
|||
"bundleName": "bootstrap-dark" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-light.css", |
|||
"inject": false, |
|||
"bundleName": "bootstrap-light" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/ng-bundle.css", |
|||
"inject": false, |
|||
"bundleName": "ng-bundle" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/side-menu/layout-bundle.css", |
|||
"inject": false, |
|||
"bundleName": "layout-bundle" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/abp.ng.theme.lepton-x/assets/css/abp-bundle.css", |
|||
"inject": false, |
|||
"bundleName": "abp-bundle" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/dark.rtl.css", |
|||
"inject": false, |
|||
"bundleName": "dark.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/light.rtl.css", |
|||
"inject": false, |
|||
"bundleName": "light.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/dim.rtl.css", |
|||
"inject": false, |
|||
"bundleName": "dim.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-dim.rtl.css", |
|||
"inject": false, |
|||
"bundleName": "bootstrap-dim.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-dark.rtl.css", |
|||
"inject": false, |
|||
"bundleName": "bootstrap-dark.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-light.rtl.css", |
|||
"inject": false, |
|||
"bundleName": "bootstrap-light.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/ng-bundle.rtl.css", |
|||
"inject": false, |
|||
"bundleName": "ng-bundle.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/side-menu/layout-bundle.rtl.css", |
|||
"inject": false, |
|||
"bundleName": "layout-bundle.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volosoft/abp.ng.theme.lepton-x/assets/css/abp-bundle.rtl.css", |
|||
"inject": false, |
|||
"bundleName": "abp-bundle.rtl" |
|||
} |
|||
``` |
|||
|
|||
## Theme Lepton |
|||
```json |
|||
{ |
|||
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton1.min.css", |
|||
"inject": false, |
|||
"bundleName": "lepton1" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton2.min.css", |
|||
"inject": false, |
|||
"bundleName": "lepton2" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton3.min.css", |
|||
"inject": false, |
|||
"bundleName": "lepton3" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton4.min.css", |
|||
"inject": false, |
|||
"bundleName": "lepton4" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton5.min.css", |
|||
"inject": false, |
|||
"bundleName": "lepton5" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton6.min.css", |
|||
"inject": false, |
|||
"bundleName": "lepton6" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton1.rtl.min.css", |
|||
"inject": false, |
|||
"bundleName": "lepton1.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton2.rtl.min.css", |
|||
"inject": false, |
|||
"bundleName": "lepton2.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton3.rtl.min.css", |
|||
"inject": false, |
|||
"bundleName": "lepton3.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton4.rtl.min.css", |
|||
"inject": false, |
|||
"bundleName": "lepton4.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton5.rtl.min.css", |
|||
"inject": false, |
|||
"bundleName": "lepton5.rtl" |
|||
}, |
|||
{ |
|||
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton6.rtl.min.css", |
|||
"inject": false, |
|||
"bundleName": "lepton6.rtl" |
|||
}, |
|||
``` |
|||
|
|||
|
|||
|
|||
@ -0,0 +1,32 @@ |
|||
using System; |
|||
using System.Data; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.Uow; |
|||
using Volo.Abp.Users; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling; |
|||
|
|||
public class ExceptionHandingUnitOfWork : UnitOfWork |
|||
{ |
|||
public ExceptionHandingUnitOfWork( |
|||
IServiceProvider serviceProvider, |
|||
IUnitOfWorkEventPublisher unitOfWorkEventPublisher, |
|||
IOptions<AbpUnitOfWorkDefaultOptions> options) |
|||
: base(serviceProvider, unitOfWorkEventPublisher, options) |
|||
{ |
|||
|
|||
} |
|||
public async override Task SaveChangesAsync(CancellationToken cancellationToken = default) |
|||
{ |
|||
if (ServiceProvider.GetRequiredService<ICurrentUser>().Id == Guid.Empty) |
|||
{ |
|||
throw new AbpDbConcurrencyException(); |
|||
} |
|||
|
|||
await base.SaveChangesAsync(cancellationToken); |
|||
} |
|||
} |
|||
@ -1,16 +1,22 @@ |
|||
namespace Volo.Abp.BackgroundJobs; |
|||
using System; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
public class MyAsyncJobArgs |
|||
namespace Volo.Abp.BackgroundJobs; |
|||
|
|||
public class MyAsyncJobArgs: IMultiTenant |
|||
{ |
|||
public string Value { get; set; } |
|||
|
|||
public Guid? TenantId { get; } |
|||
|
|||
public MyAsyncJobArgs() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public MyAsyncJobArgs(string value) |
|||
public MyAsyncJobArgs(string value, Guid? tenantId = null) |
|||
{ |
|||
Value = value; |
|||
TenantId = tenantId; |
|||
} |
|||
} |
|||
|
|||
@ -1,14 +1,26 @@ |
|||
using System.Collections.Generic; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Volo.Abp.BackgroundJobs; |
|||
|
|||
public class MyJob : BackgroundJob<MyJobArgs>, ISingletonDependency |
|||
{ |
|||
public List<string> ExecutedValues { get; } = new List<string>(); |
|||
|
|||
public Guid? TenantId { get; set; } |
|||
|
|||
private readonly ICurrentTenant _currentTenant; |
|||
|
|||
public MyJob(ICurrentTenant currentTenant) |
|||
{ |
|||
_currentTenant = currentTenant; |
|||
} |
|||
|
|||
public override void Execute(MyJobArgs args) |
|||
{ |
|||
ExecutedValues.Add(args.Value); |
|||
TenantId = _currentTenant.Id; |
|||
} |
|||
} |
|||
|
|||
@ -1,5 +1,5 @@ |
|||
{ |
|||
"ConnectionStrings": { |
|||
"Default": "Server=localhost;Database=BackgroundJobsDemoApp;Trusted_Connection=True" |
|||
"Default": "Server=localhost;Database=BackgroundJobsDemoApp;Trusted_Connection=True;TrustServerCertificate=True" |
|||
} |
|||
} |
|||
@ -1,5 +1,5 @@ |
|||
{ |
|||
"ConnectionStrings": { |
|||
"Default": "Server=localhost;Database=BackgroundJobsDemoApp;Trusted_Connection=True" |
|||
"Default": "Server=localhost;Database=BackgroundJobsDemoApp;Trusted_Connection=True;TrustServerCertificate=True" |
|||
} |
|||
} |
|||
@ -1,17 +1,10 @@ |
|||
@inject NavigationManager Navigation |
|||
@inject IJSRuntime JSRuntime |
|||
|
|||
@code { |
|||
@code { |
|||
|
|||
protected override void OnInitialized() |
|||
{ |
|||
bool isWebAssembly = JSRuntime is IJSInProcessRuntime; |
|||
if (isWebAssembly) |
|||
{ |
|||
Navigation.NavigateTo($"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}"); |
|||
} |
|||
else |
|||
{ |
|||
Navigation.NavigateTo($"account/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}", true); |
|||
} |
|||
} |
|||
} |
|||
Navigation.NavigateTo($"account/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}", true); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
@inject NavigationManager Navigation |
|||
|
|||
@using Volo.Abp.DependencyInjection |
|||
@using Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic |
|||
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication |
|||
@inherits RedirectToLogin |
|||
@attribute [ExposeServices(typeof(RedirectToLogin))] |
|||
@attribute [Dependency(ReplaceServices = true)] |
|||
|
|||
@code { |
|||
|
|||
protected override void OnInitialized() |
|||
{ |
|||
Navigation.NavigateToLogin("authentication/login"); |
|||
} |
|||
|
|||
} |
|||
@ -1,5 +1,5 @@ |
|||
{ |
|||
"ConnectionStrings": { |
|||
"Default": "Server=localhost;Database=BlobStoring_Host;Trusted_Connection=True" |
|||
"Default": "Server=localhost;Database=BlobStoring_Host;Trusted_Connection=True;TrustServerCertificate=True" |
|||
} |
|||
} |
|||
|
|||
@ -1,6 +1,6 @@ |
|||
{ |
|||
"ConnectionStrings": { |
|||
"SqlServer": "Server=localhost;Database=BloggingTestApp;Trusted_Connection=True", |
|||
"SqlServer": "Server=localhost;Database=BloggingTestApp;Trusted_Connection=True;TrustServerCertificate=True", |
|||
"MongoDb": "mongodb://localhost:27017/BloggingTestApp" |
|||
} |
|||
} |
|||
@ -1,5 +1,5 @@ |
|||
{ |
|||
"ConnectionStrings": { |
|||
"Default": "Server=(localdb)\\MSSQLLocalDB;Database=CmsKit_Unified;Trusted_Connection=True" |
|||
"Default": "Server=(localdb)\\MSSQLLocalDB;Database=CmsKit_Unified;Trusted_Connection=True;TrustServerCertificate=True" |
|||
} |
|||
} |
|||
|
|||
@ -1,3 +1,3 @@ |
|||
{ |
|||
"ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True" |
|||
"ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True;TrustServerCertificate=True" |
|||
} |
|||
@ -1,5 +1,5 @@ |
|||
{ |
|||
"ConnectionStrings": { |
|||
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=SettingManagementDemoApp;Trusted_Connection=True" |
|||
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=SettingManagementDemoApp;Trusted_Connection=True;TrustServerCertificate=True" |
|||
} |
|||
} |
|||
|
|||
@ -1,2 +1,3 @@ |
|||
export * from './config-options.token'; |
|||
export * from './re-login-confirmation.token'; |
|||
export * from './extensions.token'; |
|||
|
|||
@ -0,0 +1,5 @@ |
|||
import { InjectionToken } from '@angular/core'; |
|||
|
|||
export const RE_LOGIN_CONFIRMATION_TOKEN = new InjectionToken<boolean>( |
|||
'RE_LOGIN_CONFIRMATION_TOKEN', |
|||
); |
|||
@ -0,0 +1,62 @@ |
|||
import { CoreTestingModule } from '@abp/ng.core/testing'; |
|||
import { ThemeBasicTestingModule } from '@abp/ng.theme.basic/testing'; |
|||
import { ThemeSharedTestingModule } from '@abp/ng.theme.shared/testing'; |
|||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; |
|||
import { NgxValidateCoreModule } from '@ngx-validate/core'; |
|||
import { HomeComponent } from './home.component'; |
|||
import { OAuthService } from 'angular-oauth2-oidc'; |
|||
import { AuthService } from '@abp/ng.core'; |
|||
|
|||
describe('HomeComponent', () => { |
|||
let fixture: ComponentFixture<HomeComponent>; |
|||
const mockOAuthService = jasmine.createSpyObj('OAuthService', ['hasValidAccessToken']); |
|||
const mockAuthService = jasmine.createSpyObj('AuthService', ['navigateToLogin']); |
|||
beforeEach(waitForAsync(() => { |
|||
TestBed.configureTestingModule({ |
|||
declarations: [HomeComponent], |
|||
imports: [ |
|||
CoreTestingModule.withConfig(), |
|||
ThemeSharedTestingModule.withConfig(), |
|||
ThemeBasicTestingModule.withConfig(), |
|||
NgxValidateCoreModule, |
|||
], |
|||
providers: [ |
|||
/* mock providers here */ |
|||
{ |
|||
provide: OAuthService, |
|||
useValue: mockOAuthService, |
|||
}, |
|||
{ |
|||
provide: AuthService, |
|||
useValue: mockAuthService, |
|||
}, |
|||
], |
|||
}).compileComponents(); |
|||
})); |
|||
|
|||
beforeEach(() => { |
|||
fixture = TestBed.createComponent(HomeComponent); |
|||
fixture.detectChanges(); |
|||
}); |
|||
|
|||
it('should be initiated', () => { |
|||
expect(fixture.componentInstance).toBeTruthy(); |
|||
}); |
|||
|
|||
describe('when login state is true', () => { |
|||
beforeAll(() => { |
|||
mockOAuthService.hasValidAccessToken.and.returnValue(true); |
|||
}); |
|||
|
|||
it('hasLoggedIn should be true', () => { |
|||
expect(fixture.componentInstance.hasLoggedIn).toBeTrue(); |
|||
expect(mockOAuthService.hasValidAccessToken).toHaveBeenCalled(); |
|||
}); |
|||
|
|||
it('button should not be exists', () => { |
|||
const element = fixture.nativeElement; |
|||
const cardTitle = element.querySelector('.card-title'); |
|||
expect(cardTitle).toBeTruthy(); |
|||
}); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,100 @@ |
|||
import { CoreTestingModule } from "@abp/ng.core/testing"; |
|||
import { ThemeBasicTestingModule } from "@abp/ng.theme.basic/testing"; |
|||
import { ThemeSharedTestingModule } from "@abp/ng.theme.shared/testing"; |
|||
import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; |
|||
import { NgxValidateCoreModule } from "@ngx-validate/core"; |
|||
import { HomeComponent } from "./home.component"; |
|||
import { OAuthService } from 'angular-oauth2-oidc'; |
|||
import { AuthService } from '@abp/ng.core'; |
|||
|
|||
|
|||
describe("HomeComponent", () => { |
|||
let fixture: ComponentFixture<HomeComponent>; |
|||
const mockOAuthService = jasmine.createSpyObj('OAuthService', ['hasValidAccessToken']) |
|||
const mockAuthService = jasmine.createSpyObj('AuthService', ['navigateToLogin']) |
|||
beforeEach( |
|||
waitForAsync(() => { |
|||
TestBed.configureTestingModule({ |
|||
declarations: [HomeComponent], |
|||
imports: [ |
|||
CoreTestingModule.withConfig(), |
|||
ThemeSharedTestingModule.withConfig(), |
|||
ThemeBasicTestingModule.withConfig(), |
|||
NgxValidateCoreModule, |
|||
], |
|||
providers: [ |
|||
/* mock providers here */ |
|||
{ |
|||
provide: OAuthService, |
|||
useValue: mockOAuthService |
|||
}, |
|||
{ |
|||
provide: AuthService, |
|||
useValue: mockAuthService |
|||
} |
|||
], |
|||
}).compileComponents(); |
|||
}) |
|||
); |
|||
|
|||
beforeEach(() => { |
|||
fixture = TestBed.createComponent(HomeComponent); |
|||
fixture.detectChanges(); |
|||
}); |
|||
|
|||
it("should be initiated", () => { |
|||
expect(fixture.componentInstance).toBeTruthy(); |
|||
}); |
|||
|
|||
|
|||
|
|||
describe('when login state is true', () => { |
|||
beforeAll(() => { |
|||
mockOAuthService.hasValidAccessToken.and.returnValue(true) |
|||
}); |
|||
|
|||
it("hasLoggedIn should be true", () => { |
|||
|
|||
expect(fixture.componentInstance.hasLoggedIn).toBeTrue(); |
|||
expect(mockOAuthService.hasValidAccessToken).toHaveBeenCalled() |
|||
}) |
|||
|
|||
it("button should not be exists", () => { |
|||
const element = fixture.nativeElement |
|||
const button = element.querySelector('[role="button"]') |
|||
expect(button).toBeNull() |
|||
}) |
|||
|
|||
}) |
|||
|
|||
describe('when login state is false', () => { |
|||
beforeAll(() => { |
|||
mockOAuthService.hasValidAccessToken.and.returnValue(false) |
|||
}); |
|||
|
|||
it("hasLoggedIn should be false", () => { |
|||
|
|||
expect(fixture.componentInstance.hasLoggedIn).toBeFalse(); |
|||
expect(mockOAuthService.hasValidAccessToken).toHaveBeenCalled() |
|||
}) |
|||
|
|||
it("button should be exists", () => { |
|||
const element = fixture.nativeElement |
|||
const button = element.querySelector('[role="button"]') |
|||
expect(button).toBeDefined() |
|||
}) |
|||
describe('when button clicked', () => { |
|||
|
|||
beforeEach(() => { |
|||
const element = fixture.nativeElement |
|||
const button = element.querySelector('[role="button"]') |
|||
button.click() |
|||
}); |
|||
|
|||
it("navigateToLogin have been called", () => { |
|||
expect(mockAuthService.navigateToLogin).toHaveBeenCalled() |
|||
}) |
|||
}) |
|||
}) |
|||
|
|||
}); |
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue