Browse Source

Merge branch 'dev' into cotur/component-base

pull/6008/head
Ahmet 6 years ago
parent
commit
8d32eafb38
  1. 1
      .gitignore
  2. 2
      docs/en/API/Dynamic-CSharp-API-Clients.md
  3. 2
      docs/en/Background-Workers-Quartz.md
  4. 4
      docs/en/Domain-Services.md
  5. 44
      docs/en/UI/AspNetCore/Branding.md
  6. 4
      docs/en/UI/AspNetCore/Customization-User-Interface.md
  7. 92
      docs/en/UI/AspNetCore/Dynamic-JavaScript-Proxies.md
  8. 3
      docs/en/UI/AspNetCore/Libraries/DatatablesNet.md
  9. 159
      docs/en/UI/AspNetCore/Overall.md
  10. 4
      docs/en/UI/AspNetCore/Tag-Helpers/Index.md
  11. 2
      docs/en/UI/AspNetCore/Toolbars.md
  12. 2
      docs/en/UI/Blazor/Localization.md
  13. 3
      docs/en/UI/Blazor/Message.md
  14. 3
      docs/en/UI/Blazor/Notification.md
  15. 4
      docs/en/UI/Blazor/Overall.md
  16. 3
      docs/en/UI/Blazor/Services/Notification.md
  17. 2
      docs/en/UI/Blazor/Settings.md
  18. 30
      docs/en/docs-nav.json
  19. BIN
      docs/en/images/branding-appname.png
  20. BIN
      docs/en/images/branding-nobrand.png
  21. 131
      framework/.editorconfig
  22. 1
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor
  23. 11
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/IUiNotificationService.cs
  24. 11
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/NullUiNotificationService.cs
  25. 23
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/UiNotificationEventArgs.cs
  26. 20
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/UiNotificationOptions.cs
  27. 10
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/UiNotificationType.cs
  28. 85
      framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs
  29. 57
      framework/src/Volo.Abp.BlazoriseUI/BlazoriseUiNotificationService.cs
  30. 1
      framework/src/Volo.Abp.BlazoriseUI/Components/UiNotificationAlert.razor
  31. 76
      framework/src/Volo.Abp.BlazoriseUI/Components/UiNotificationAlert.razor.cs
  32. 5
      framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj
  33. 3
      framework/src/Volo.Abp.BlazoriseUI/_Imports.razor
  34. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs
  35. 1
      framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs
  36. 41
      modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorMessageLocalizerHelper.cs
  37. 2
      modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorModule.cs
  38. 80
      modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor
  39. 4
      modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor.cs
  40. 240
      modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor
  41. 35
      modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor.cs
  42. 3
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityDomainSharedModule.cs
  43. 1
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/index.html

1
.gitignore

@ -6,6 +6,7 @@
*.user
*.userosscache
*.sln.docstates
*.editorconfig
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

2
docs/en/API/Dynamic-CSharp-API-Clients.md

@ -1,4 +1,4 @@
# Dynamic C# API Clients
# Dynamic C# API Client Proxies
ABP can dynamically create C# API client proxies to call remote HTTP services (REST APIs). In this way, you don't need to deal with `HttpClient` and other low level HTTP features to call remote services and get results.

2
docs/en/Background-Workers-Quartz.md

@ -37,7 +37,7 @@ public class YourModule : AbpModule
````
> Quartz background worker integration provided `QuartzPeriodicBackgroundWorkerAdapter` to adapt `PeriodicBackgroundWorkerBase` and `AsyncPeriodicBackgroundWorkerBase` derived class. So, you can still fllow the [background workers document](Background-Workers.md) to define the background worker.
> `BackgroundJobWorker` checks todo jobs every 5 seconds, but quartz will not block when long time jobs are executing. So,after Added Quartz background worker integration, you also need to add [Quartz Background Jobs](Background-Jobs-Quartz.md) or [Hangfire Background Jobs](Background-Jobs-Hangfire.md) to avoid duplicate execution jobs.
> `BackgroundJobWorker` checks jobs every 5 seconds, but quartz will not block when long time jobs are executing. So,after Added Quartz background worker integration, you also need to add [Quartz Background Jobs](Background-Jobs-Quartz.md) or [Hangfire Background Jobs](Background-Jobs-Hangfire.md) to avoid duplicate execution jobs.
## Configuration

4
docs/en/Domain-Services.md

@ -1,3 +1,3 @@
# ABP Documentation
# Domain Services
TODO!
TODO

44
docs/en/UI/AspNetCore/Branding.md

@ -1,3 +1,45 @@
# ASP.NET Core MVC / Razor Pages: Branding
TODO
## IBrandingProvider
`IBrandingProvider` is a simple interface that is used to show the application name and logo on the layout.
The screenshot below shows *MyProject* as the application name:
![branding-nobrand](../../images/branding-nobrand.png)
You can implement the `IBrandingProvider` interface or inherit from the `DefaultBrandingProvider` to set the application name:
````csharp
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Components;
using Volo.Abp.DependencyInjection;
namespace MyProject.Web
{
[Dependency(ReplaceServices = true)]
public class MyProjectBrandingProvider : DefaultBrandingProvider
{
public override string AppName => "Book Store";
}
}
````
The result will be like shown below:
![branding-appname](../../images/branding-appname.png)
`IBrandingProvider` has the following properties:
* `AppName`: The application name.
* `LogoUrl`: A URL to show the application logo.
* `LogoReverseUrl`: A URL to show the application logo on a reverse color theme (dark, for example).
> **Tip**: `IBrandingProvider` is used in every page refresh. For a multi-tenant application, you can return a tenant specific application name to customize it per tenant.
## Overriding the Branding Area
The [Basic Theme](Basic-Theme.md) doesn't implement the logos. However, you can see the [UI Customization Guide](Customization-User-Interface.md) to learn how you can replace the branding area with a custom view component.
An example screenshot with an image is used in the branding area:
![bookstore-added-logo](../../images/bookstore-added-logo.png)

4
docs/en/UI/AspNetCore/Customization-User-Interface.md

@ -128,11 +128,11 @@ The ABP Framework, pre-built themes and modules define some **re-usable view com
### Example
The screenshot below was taken from the **basic theme** comes with the application startup template.
The screenshot below was taken from the [Basic Theme](Basic-Theme.md) comes with the application startup template.
![bookstore-brand-area-highlighted](../../images/bookstore-brand-area-highlighted.png)
[The basic theme](Basic-Theme.md) defines some view components for the layout. For example, the highlighted area with the red rectangle above is called **Brand component**. You probably want to customize this component by adding your **own application logo**. Let's see how to do it.
The [Basic Theme](Basic-Theme.md) defines some view components for the layout. For example, the highlighted area with the red rectangle above is called **Brand component**. You probably want to customize this component by adding your **own application logo**. Let's see how to do it.
First, create your logo and place under a folder in your web application. We used `wwwroot/logos/bookstore-logo.png` path. Then copy the Brand component's view ([from here](https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Brand/Default.cshtml)) from the basic theme files under the `Themes/Basic/Components/Brand` folder. The result should be similar the picture below:

92
docs/en/UI/AspNetCore/Dynamic-JavaScript-Proxies.md

@ -1,3 +1,91 @@
# Dynamic JavaScript HTTP API Proxies
# Dynamic JavaScript API Client Proxies
TODO
It is typical to consume your HTTP APIs from your JavaScript code. To do that, you normally deal with low level AJAX calls, like $.ajax, or better [abp.ajax](JavaScript-API/Ajax.md). ABP Framework provides **a better way** to call your HTTP APIs from your JavaScript code: Dynamic JavaScript API Client Proxies!
## A Quick Example
Assume that you have an application service defined as shown below:
````csharp
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Acme.BookStore.Authors
{
public interface IAuthorAppService : IApplicationService
{
Task<AuthorDto> GetAsync(Guid id);
Task<PagedResultDto<AuthorDto>> GetListAsync(GetAuthorListDto input);
Task<AuthorDto> CreateAsync(CreateAuthorDto input);
Task UpdateAsync(Guid id, UpdateAuthorDto input);
Task DeleteAsync(Guid id);
}
}
````
> You can follow the [web application development tutorial](../../Tutorials/Part-1.md) to learn how to create [application services](../../Application-Services.md), expose them as [HTTP APIs](../../API/Auto-API-Controllers.md) and consume from the JavaScript code as a complete example.
You can call any of the methods just like calling a JavaScript function. The JavaScript function has the identical function **name**, **parameters** and the **return value** with the C# method.
**Example: Get the authors list**
````js
acme.bookStore.authors.author.getList({
maxResultCount: 10
}).then(function(result){
console.log(result.items);
});
````
**Example: Delete an author**
```js
acme.bookStore.authors.author
.delete('7245a066-5457-4941-8aa7-3004778775f0') //Get id from somewhere!
.then(function() {
abp.notify.info('Successfully deleted!');
});
```
## AJAX Details
Dynamic JavaScript client proxy functions use the [abp.ajax](JavaScript-API/Ajax.md) under the hood. So, you have the same benefits like **automatic error handling**. Also, you can fully control the AJAX call by providing the options.
### The Return Value
Every function returns a [Deferred object](https://api.jquery.com/category/deferred-object/). That means you can chain with `then` to get the result, `catch` to handle the error, `always` to perform an action once the operation completes (success or failed).
### AJAX Options
Every function gets an additional **last parameter** after your own parameters. The last parameter is called as `ajaxParams`. It is an object that overrides the AJAX options.
**Example: Set `type` and `dataType` AJAX options**
````js
acme.bookStore.authors.author
.delete('7245a066-5457-4941-8aa7-3004778775f0', {
type: 'POST',
dataType: 'xml'
})
.then(function() {
abp.notify.info('Successfully deleted!');
});
````
See the [jQuery.ajax](https://api.jquery.com/jQuery.ajax/) documentation for all the available options.
## Service Proxy Script Endpoint
The magic is done by the `/Abp/ServiceProxyScript` endpoint defined by the ABP Framework and automatically added to the layout. You can visit this endpoint in your application to see the client proxy function definitions. This script file is automatically generated by the ABP Framework based on the server side method definitions and the related HTTP endpoint details.
## See Also
* [Web Application Development Tutorial](../../Tutorials/Part-1.md)
* [Auto API Controllers](../../API/Auto-API-Controllers.md)
* [Dynamic C# API Client Proxies](../../API/Dynamic-CSharp-API-Clients.md)

3
docs/en/UI/AspNetCore/Libraries/DatatablesNet.md

@ -1,3 +0,0 @@
# ABP Datatables.Net Integration for ASP.NET Core UI
TODO

159
docs/en/UI/AspNetCore/Overall.md

@ -0,0 +1,159 @@
# ASP.NET Core MVC / Razor Pages UI
## Introduction
ABP Framework provides a convenient and comfortable way of creating web applications using the ASP.NET Core MVC / Razor Pages as the User Interface framework.
> ABP doesn't offer a new/custom way of UI development. You can continue to use your current skills to create the UI. However, it offers a lot of features to make your development easier and have a more maintainable code base.
### MVC vs Razor Pages
ASP.NET Core provides two models for UI development:
* **[MVC (Model-View-Controller)](https://docs.microsoft.com/en-us/aspnet/core/mvc/)** is the classic way that exists from the version 1.0. This model can be used to create UI pages/components and HTTP APIs.
* **[Razor Pages](https://docs.microsoft.com/en-us/aspnet/core/razor-pages/)** was introduced with the ASP.NET Core 2.0 as a new way to create web pages.
**ABP Framework supports both** of the MVC and the Razor Pages models. However, it is suggested to create the **UI pages with Razor Pages** approach and use the **MVC model to build HTTP APIs**. So, all the pre-build modules, samples and the documentation is based on the Razor Pages for the UI development, while you can always apply the MVC pattern to create your own pages.
### Modularity
[Modularity](../../Module-Development-Basics.md) is one of the key goals of the ABP Framework. It is not different for the UI; It is possible to develop modular applications and reusable application modules with isolated and reusable UI pages and components.
The [application startup template](../../Startup-Templates/Application.md) comes with some application modules pre-installed. These modules have their own UI pages embedded into their own NuGet packages. You don't see their code in your solution, but they work as expected on runtime.
## Theme System
ABP Framework provides a complete [Theming](Theming.md) system with the following goals:
* Reusable [application modules](../../Modules/Index.md) are developed **theme-independent**, so they can work with any UI theme.
* UI theme is **decided by the final application**.
* The theme is distributed via NuGet/NPM packages, so it is **easily upgradable**.
* The final application can **customize** the selected theme.
### Current Themes
Currently, two themes are **officially provided**:
* The [Basic Theme](Basic-Theme.md) is the minimalist theme with the plain Bootstrap style. It is **open source and free**.
* The [Lepton Theme](https://commercial.abp.io/themes) is a **commercial** theme developed by the core ABP team and is a part of the [ABP Commercial](https://commercial.abp.io/) license.
There are also some community-driven themes for the ABP Framework (you can search on the web).
### Base Libraries
There are a set of standard JavaScript/CSS libraries that comes pre-installed and supported by all the themes:
- [Twitter Bootstrap](https://getbootstrap.com/) as the fundamental HTML/CSS framework.
- [JQuery](https://jquery.com/) for DOM manipulation.
- [DataTables.Net](https://datatables.net/) for data grids.
- [JQuery Validation](https://jqueryvalidation.org/) for client side & [unobtrusive](https://github.com/aspnet/jquery-validation-unobtrusive) validation
- [FontAwesome](https://fontawesome.com/) as the fundamental CSS font library.
- [SweetAlert](https://sweetalert.js.org/) to show fancy alert message and confirmation dialogs.
- [Toastr](https://github.com/CodeSeven/toastr) to show toast notifications.
- [Lodesh](https://lodash.com/) as a utility library.
- [Luxon](https://moment.github.io/luxon/) for date/time operations.
- [JQuery Form](https://github.com/jquery-form/form) for AJAX forms.
- [bootstrap-datepicker](https://github.com/uxsolutions/bootstrap-datepicker) to show date pickers.
- [Select2](https://select2.org/) for better select/combo boxes.
- [Timeago](http://timeago.yarp.com/) to show automatically updating fuzzy timestamps.
- [malihu-custom-scrollbar-plugin](https://github.com/malihu/malihu-custom-scrollbar-plugin) for custom scrollbars.
You can use these libraries directly in your applications, without needing to manually import your page.
### Layouts
The themes provide the standard layouts. So, you have responsive layouts with the standard features already implemented. The screenshot below has taken from the Application Layout of the [Basic Theme](Basic-Theme.md):
![basic-theme-application-layout](../../images/basic-theme-application-layout.png)
See the [Theming](Theming.md) document for more layout options and other details.
### Layout Parts
A typical layout consists of multiple parts. The [Theming](Theming.md) system provides [menus](Navigation-Menu.md), [toolbars](Toolbars.md), [layout hooks](Layout-Hooks.md) and more to dynamically control the layout by your application and the modules you are using.
## Features
This section highlights some of the features provided by the ABP Framework for the ASP.NET Core MVC / Razor Pages UI.
### Dynamic JavaScript API Client Proxies
Dynamic JavaScript API Client Proxy system allows you to consume your server side HTTP APIs from your JavaScript client code, just like calling local functions.
**Example: Get a list of authors from the server**
````js
acme.bookStore.authors.author.getList({
maxResultCount: 10
}).then(function(result){
console.log(result.items);
});
````
`acme.bookStore.authors.author.getList` is an auto-generated function that internally makes an AJAX call to the server.
See the [Dynamic JavaScript API Client Proxies](Dynamic-JavaScript-Proxies.md) document for more.
### Bootstrap Tag Helpers
ABP makes it easier & type safe to write Bootstrap HTML.
**Example: Render a Bootstrap modal**
````html
<abp-modal>
<abp-modal-header title="Modal title" />
<abp-modal-body>
Woohoo, you're reading this text in a modal!
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Save|AbpModalButtons.Close)"></abp-modal-footer>
</abp-modal>
````
See the [Tag Helpers](Tag-Helpers/Index.md) document for more.
### Forms & Validation
ABP provides `abp-dynamic-form` and `abp-input` tag helpers to dramatically simplify to create a fully functional form that automates localization, validation and AJAX submission.
**Example: Use `abp-dynamic-form` to create a complete form based on a model**
````html
<abp-dynamic-form abp-model="Movie" submit-button="true" />
````
See the [Forms & Validation](Forms-Validation.md) document for details.
### Bundling & Minification / Client Side Libraries
ABP provides a flexible and modular Bundling & Minification system to create bundles and minify style/script files on runtime.
````html
<abp-style-bundle>
<abp-style src="/libs/bootstrap/css/bootstrap.css" />
<abp-style src="/libs/font-awesome/css/font-awesome.css" />
<abp-style src="/libs/toastr/toastr.css" />
<abp-style src="/styles/my-global-style.css" />
</abp-style-bundle>
````
Also, Client Side Package Management system offers a modular and consistent way of managing 3rd-party library dependencies.
See the [Bundling & Minification](Bundling-Minification.md) and [Client Side Package Management](Client-Side-Package-Management.md) documents.
### JavaScript APIs
[JavaScript APIs](JavaScript-API/Index.md) provides a strong abstractions to the server side localization, settings, permissions, features... etc. They also provide a simple way to show messages and **notifications** to the user.
### Modals, Alerts, Widgets and More
ABP Framework provides a lot of built-in solutions to common application requirements;
* [Widget System](Widgets.md) can be used to create reusable widgets & create dashboards.
* [Page Alerts](Page-Alerts.md) makes it easy to show alerts to the user.
* [Modal Manager](Modals.md) provides a simple way to build and use modals.
* [Data Tables](Data-Tables.md) integration makes straightforward to create data grids.
## Customization
There are a lot of ways to customize the theme and the UIs of the pre-built modules. You can override components, pages, static resources, bundles and more. See the [User Interface Customization Guide](Customization-User-Interface.md).

4
docs/en/UI/AspNetCore/Tag-Helpers/Index.md

@ -13,7 +13,7 @@ ABP Framework also adds some **useful features** to the standard bootstrap compo
Here, the list of components those are wrapped by the ABP Framework:
* [Alerts](Alerts.md)
* [Badges](Badges.md))
* [Badges](Badges.md)
* [Blockquote](Blockquote.md)
* [Borders](Borders.md)
* [Breadcrumb](Breadcrumb.md)
@ -42,4 +42,4 @@ Here, the list of components those are wrapped by the ABP Framework:
## Dynamic Forms
**Abp Tag helpers** offer an easy way to build complete **Bootstrap forms**. See [Dynamic Forms documentation](Dynamic-Forms.md).
**Abp Tag helpers** offer an easy way to build complete **Bootstrap forms**. See [Dynamic Forms documentation](Dynamic-Forms.md).

2
docs/en/UI/AspNetCore/Toolbars.md

@ -1,4 +1,4 @@
# Toolbars
# ASP.NET Core MVC / Razor Pages UI: Toolbars
The Toolbar system is used to define **toolbars** on the user interface. Modules (or your application) can add **items** to a toolbar, then the [theme](Theming.md) renders the toolbar on the **layout**.

2
docs/en/UI/Blazor/Localization.md

@ -1,3 +1,3 @@
# Blazor UI: Localization
# Blazor: Localization
Blazor applications can reuse the same `IStringLocalizer<T>` service that is explained in the [localization document](../../Localization.md). All the localization resources and texts available in the server side are usable in the Blazor application.

3
docs/en/UI/Blazor/Message.md

@ -0,0 +1,3 @@
# Blazor: UI Message Service
TODO

3
docs/en/UI/Blazor/Notification.md

@ -0,0 +1,3 @@
# Blazor: Notification
`UiNotificationService` is used to show toastr style notifications on the user interface. The documentation is in progress...

4
docs/en/UI/Blazor/Overall.md

@ -1,6 +1,8 @@
# Blazor UI for the ABP Framework
The detailed documentation for the Blazor UI is in progress. However, you can follow the documents below to start with the Blazor UI today.
## Getting Started
You can follow the documents below to start with the ABP Framework and the Blazor UI:
* [Get started](https://docs.abp.io/en/abp/latest/Getting-Started?UI=Blazor) with the Blazor UI for the ABP Framework.
* [Web Application Development Tutorial](https://docs.abp.io/en/abp/latest/Tutorials/Part-1?UI=Blazor) with the Blazor UI.

3
docs/en/UI/Blazor/Services/Notification.md

@ -1,3 +0,0 @@
# Blazor UI Notification
`UiNotificationService` is used to show toastr style notifications on the user interface. The documentation is in progress...

2
docs/en/UI/Blazor/Settings.md

@ -1,3 +1,3 @@
# Blazor UI: Settings
# Blazor: Settings
Blazor applications can reuse the same `ISettingProvider` service that is explained in the [settings document](../../Settings.md).

30
docs/en/docs-nav.json

@ -404,8 +404,12 @@
"text": "User Interface",
"items": [
{
"text": "ASP.NET Core MVC / Razor Pages",
"text": "MVC / Razor Pages",
"items": [
{
"text": "Overall",
"path": "UI/AspNetCore/Overall.md"
},
{
"text": "Navigation / Menus",
"path": "UI/AspNetCore/Navigation-Menu.md"
@ -426,6 +430,10 @@
"text": "Page Alerts",
"path": "UI/AspNetCore/Page-Alerts.md"
},
{
"text": "Dynamic JavaScript API Client Proxies",
"path": "UI/AspNetCore/Dynamic-JavaScript-Proxies.md"
},
{
"text": "Client Side Package Management",
"path": "UI/AspNetCore/Client-Side-Package-Management.md"
@ -460,6 +468,10 @@
"text": "Page Header",
"path": "UI/AspNetCore/Page-Header.md"
},
{
"text": "Branding",
"path": "UI/AspNetCore/Branding.md"
},
{
"text": "Layout Hooks",
"path": "UI/AspNetCore/Layout-Hooks.md"
@ -552,8 +564,20 @@
"text": "Services",
"items": [
{
"text": "Overall",
"path": "UI/Blazor/Services/Notification.md"
"text": "Localization",
"path": "UI/Blazor/Localization.md"
},
{
"text": "Settings",
"path": "UI/Blazor/Settings.md"
},
{
"text": "Notification",
"path": "UI/Blazor/Notification.md"
},
{
"text": "Message",
"path": "UI/Blazor/Message.md"
}
]
}

BIN
docs/en/images/branding-appname.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
docs/en/images/branding-nobrand.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

131
framework/.editorconfig

@ -1,131 +0,0 @@
# Rules in this file were initially inferred by Visual Studio IntelliCode from the D:\Projects\Volosoft\abp\framework codebase based on best match to current usage at 2.10.2020.
# You can modify the rules from these initially generated values to suit your own policies
# You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference
[*.cs]
#Core editorconfig formatting - indentation
#use soft tabs (spaces) for indentation
indent_style = space
#Formatting - indentation options
#indent switch case contents.
csharp_indent_case_contents = true
#indent switch labels
csharp_indent_switch_labels = true
#Formatting - new line options
#place catch statements on a new line
csharp_new_line_before_catch = true
#place else statements on a new line
csharp_new_line_before_else = true
#require members of object intializers to be on separate lines
csharp_new_line_before_members_in_object_initializers = true
#require braces to be on a new line for accessors, methods, lambdas, object_collection_array_initializers, control_blocks, types, and properties (also known as "Allman" style)
csharp_new_line_before_open_brace = accessors, methods, lambdas, object_collection_array_initializers, control_blocks, types, properties
#Formatting - organize using options
#sort System.* using directives alphabetically, and place them before other usings
dotnet_sort_system_directives_first = true
#Formatting - spacing options
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
#Formatting - wrapping options
#leave code block on single line
csharp_preserve_single_line_blocks = true
#Style - Code block preferences
#prefer curly braces even for one line of code
csharp_prefer_braces = true:suggestion
#Style - expression bodied member options
#prefer block bodies for constructors
csharp_style_expression_bodied_constructors = false:suggestion
#prefer block bodies for methods
csharp_style_expression_bodied_methods = false:suggestion
#prefer expression-bodied members for properties
csharp_style_expression_bodied_properties = true:suggestion
#Style - expression level options
#prefer out variables to be declared inline in the argument list of a method call when possible
csharp_style_inlined_variable_declaration = true:suggestion
#prefer the language keyword for member access expressions, instead of the type name, for types that have a keyword to represent them
dotnet_style_predefined_type_for_member_access = true:suggestion
#Style - Expression-level preferences
#prefer default over default(T)
csharp_prefer_simple_default_expression = true:suggestion
#prefer objects to be initialized using object initializers when possible
dotnet_style_object_initializer = true:suggestion
#prefer inferred tuple element names
dotnet_style_prefer_inferred_tuple_names = true:suggestion
#Style - implicit and explicit types
#prefer var over explicit type in all cases, unless overridden by another code style rule
csharp_style_var_elsewhere = true:suggestion
#prefer var is used to declare variables with built-in system types such as int
csharp_style_var_for_built_in_types = true:suggestion
#prefer var when the type is already mentioned on the right-hand side of a declaration expression
csharp_style_var_when_type_is_apparent = true:suggestion
#Style - language keyword and framework type options
#prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
#Style - modifier options
#prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods.
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
#Style - Modifier preferences
#when this rule is set to a list of modifiers, prefer the specified ordering.
csharp_preferred_modifier_order = public,protected,private,virtual,async,static,override,readonly,abstract:suggestion
#Style - Pattern matching
#prefer pattern matching instead of is expression with type casts
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
#Style - qualification options
#prefer fields not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_field = false:suggestion
#prefer methods not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_method = false:suggestion
#prefer properties not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_property = false:suggestion

1
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor

@ -22,4 +22,5 @@
@Body
<UiMessageAlert />
<UiNotificationAlert />
</div>

11
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/IUiNotificationService.cs

@ -1,12 +1,13 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Components.WebAssembly
{
public interface IUiNotificationService
{
Task Info(string message);
Task Success(string message);
Task Warn(string message);
Task Error(string message);
Task Info(string message, string title = null, Action<UiNotificationOptions> options = null);
Task Success(string message, string title = null, Action<UiNotificationOptions> options = null);
Task Warn(string message, string title = null, Action<UiNotificationOptions> options = null);
Task Error(string message, string title = null, Action<UiNotificationOptions> options = null);
}
}

11
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/NullUiNotificationService.cs

@ -1,25 +1,26 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.WebAssembly
{
public class NullUiNotificationService : IUiNotificationService, ITransientDependency
{
public Task Info(string message)
public Task Info(string message, string title = null, Action<UiNotificationOptions> options = null)
{
return Task.CompletedTask;
}
public Task Success(string message)
public Task Success(string message, string title = null, Action<UiNotificationOptions> options = null)
{
return Task.CompletedTask;
}
public Task Warn(string message)
public Task Warn(string message, string title = null, Action<UiNotificationOptions> options = null)
{
return Task.CompletedTask;
}
public Task Error(string message)
public Task Error(string message, string title = null, Action<UiNotificationOptions> options = null)
{
return Task.CompletedTask;
}

23
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/UiNotificationEventArgs.cs

@ -0,0 +1,23 @@
using System;
namespace Volo.Abp.AspNetCore.Components.WebAssembly
{
public class UiNotificationEventArgs : EventArgs
{
public UiNotificationEventArgs(UiNotificationType notificationType, string message, string title, UiNotificationOptions options)
{
NotificationType = notificationType;
Message = message;
Title = title;
Options = options;
}
public UiNotificationType NotificationType { get; set; }
public string Message { get; }
public string Title { get; }
public UiNotificationOptions Options { get; }
}
}

20
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/UiNotificationOptions.cs

@ -0,0 +1,20 @@
using Volo.Abp.Localization;
namespace Volo.Abp.AspNetCore.Components.WebAssembly
{
/// <summary>
/// Options to override notification appearance.
/// </summary>
public class UiNotificationOptions
{
/// <summary>
/// Custom text for the Ok button.
/// </summary>
public ILocalizableString OkButtonText { get; set; }
/// <summary>
/// Custom icon for the Ok button.
/// </summary>
public object OkButtonIcon { get; set; }
}
}

10
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/UiNotificationType.cs

@ -0,0 +1,10 @@
namespace Volo.Abp.AspNetCore.Components.WebAssembly
{
public enum UiNotificationType
{
Info,
Success,
Warning,
Error,
}
}

85
framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs

@ -186,6 +186,8 @@ namespace Volo.Abp.BlazoriseUI
protected TUpdateViewModel EditingEntity;
protected Modal CreateModal;
protected Modal EditModal;
protected Validations CreateValidationsRef;
protected Validations EditValidationsRef;
protected List<BreadcrumbItem> BreadcrumbItems = new List<BreadcrumbItem>(2);
protected string CreatePolicyName { get; set; }
@ -279,12 +281,26 @@ namespace Volo.Abp.BlazoriseUI
protected virtual async Task OpenCreateModalAsync()
{
await OnOpeningCreateModalAsync();
CreateValidationsRef.ClearAll();
await CheckCreatePolicyAsync();
NewEntity = new TCreateViewModel();
// Mapper will not notify Blazor that binded values are changed
// so we need to notify it manually by calling StateHasChanged
await InvokeAsync(() => StateHasChanged());
CreateModal.Show();
}
protected virtual Task OnOpeningCreateModalAsync()
{
return Task.CompletedTask;
}
protected virtual Task CloseCreateModalAsync()
{
CreateModal.Hide();
@ -293,14 +309,27 @@ namespace Volo.Abp.BlazoriseUI
protected virtual async Task OpenEditModalAsync(TKey id)
{
await OnOpeningEditModalAsync(id);
EditValidationsRef.ClearAll();
await CheckUpdatePolicyAsync();
var entityDto = await AppService.GetAsync(id);
EditingEntityId = id;
EditingEntity = MapToEditingEntity(entityDto);
await InvokeAsync(() => StateHasChanged());
EditModal.Show();
}
protected virtual Task OnOpeningEditModalAsync(TKey id)
{
return Task.CompletedTask;
}
protected virtual TUpdateViewModel MapToEditingEntity(TGetOutputDto entityDto)
{
return ObjectMapper.Map<TGetOutputDto, TUpdateViewModel>(entityDto);
@ -334,20 +363,56 @@ namespace Volo.Abp.BlazoriseUI
protected virtual async Task CreateEntityAsync()
{
await CheckCreatePolicyAsync();
var createInput = MapToCreateInput(NewEntity);
await AppService.CreateAsync(createInput);
await GetEntitiesAsync();
CreateModal.Hide();
if (CreateValidationsRef.ValidateAll())
{
await OnCreatingEntityAsync();
await CheckCreatePolicyAsync();
var createInput = MapToCreateInput(NewEntity);
await AppService.CreateAsync(createInput);
await GetEntitiesAsync();
await OnCreatedEntityAsync();
CreateModal.Hide();
}
}
protected virtual Task OnCreatingEntityAsync()
{
return Task.CompletedTask;
}
protected virtual Task OnCreatedEntityAsync()
{
return Task.CompletedTask;
}
protected virtual async Task UpdateEntityAsync()
{
await CheckUpdatePolicyAsync();
var updateInput = MapToUpdateInput(EditingEntity);
await AppService.UpdateAsync(EditingEntityId, updateInput);
await GetEntitiesAsync();
EditModal.Hide();
if (EditValidationsRef.ValidateAll())
{
await OnUpdatingEntityAsync();
await CheckUpdatePolicyAsync();
var updateInput = MapToUpdateInput(EditingEntity);
await AppService.UpdateAsync(EditingEntityId, updateInput);
await GetEntitiesAsync();
await OnUpdatedEntityAsync();
EditModal.Hide();
}
}
protected virtual Task OnUpdatingEntityAsync()
{
return Task.CompletedTask;
}
protected virtual Task OnUpdatedEntityAsync()
{
return Task.CompletedTask;
}
protected virtual async Task DeleteEntityAsync(TListViewModel entity)

57
framework/src/Volo.Abp.BlazoriseUI/BlazoriseUiNotificationService.cs

@ -1,40 +1,73 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Threading.Tasks;
using Localization.Resources.AbpUi;
using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Components.WebAssembly;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.BlazoriseUI
{
[Dependency(ReplaceServices = true)]
public class BlazoriseUiNotificationService : IUiNotificationService, ITransientDependency
public class BlazoriseUiNotificationService : IUiNotificationService, IScopedDependency
{
public ILogger<BlazoriseUiNotificationService> Logger { get; set; }
/// <summary>
/// An event raised after the notification is received.
/// </summary>
public event EventHandler<UiNotificationEventArgs> NotificationReceived;
public BlazoriseUiNotificationService()
private readonly IStringLocalizer<AbpUiResource> localizer;
public BlazoriseUiNotificationService(
IStringLocalizer<AbpUiResource> localizer)
{
Logger = NullLogger<BlazoriseUiNotificationService>.Instance;
this.localizer = localizer;
}
public Task Info(string message)
public Task Info(string message, string title = null, Action<UiNotificationOptions> options = null)
{
Logger.LogInformation(message);
var uiNotificationOptions = CreateDefaultOptions();
options?.Invoke(uiNotificationOptions);
NotificationReceived?.Invoke(this, new UiNotificationEventArgs(UiNotificationType.Info, message, title, uiNotificationOptions));
return Task.CompletedTask;
}
public Task Success(string message)
public Task Success(string message, string title = null, Action<UiNotificationOptions> options = null)
{
var uiNotificationOptions = CreateDefaultOptions();
options?.Invoke(uiNotificationOptions);
NotificationReceived?.Invoke(this, new UiNotificationEventArgs(UiNotificationType.Success, message, title, uiNotificationOptions));
return Task.CompletedTask;
}
public Task Warn(string message)
public Task Warn(string message, string title = null, Action<UiNotificationOptions> options = null)
{
var uiNotificationOptions = CreateDefaultOptions();
options?.Invoke(uiNotificationOptions);
NotificationReceived?.Invoke(this, new UiNotificationEventArgs(UiNotificationType.Warning, message, title, uiNotificationOptions));
return Task.CompletedTask;
}
public Task Error(string message)
public Task Error(string message, string title = null, Action<UiNotificationOptions> options = null)
{
var uiNotificationOptions = CreateDefaultOptions();
options?.Invoke(uiNotificationOptions);
NotificationReceived?.Invoke(this, new UiNotificationEventArgs(UiNotificationType.Error, message, title, uiNotificationOptions));
return Task.CompletedTask;
}
protected virtual UiNotificationOptions CreateDefaultOptions()
{
return new UiNotificationOptions
{
};
}
}
}

1
framework/src/Volo.Abp.BlazoriseUI/Components/UiNotificationAlert.razor

@ -0,0 +1 @@
<SnackbarStack @ref="SnackbarStack" Location="SnackbarStackLocation.Right" Closed="@OnSnackbarClosed" />

76
framework/src/Volo.Abp.BlazoriseUI/Components/UiNotificationAlert.razor.cs

@ -0,0 +1,76 @@
using System;
using System.Threading.Tasks;
using Blazorise.Snackbar;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Components.WebAssembly;
namespace Volo.Abp.BlazoriseUI.Components
{
public partial class UiNotificationAlert : ComponentBase, IDisposable
{
protected SnackbarStack SnackbarStack { get; set; }
[Parameter] public UiNotificationType NotificationType { get; set; }
[Parameter] public string Message { get; set; }
[Parameter] public string Title { get; set; }
[Parameter] public UiNotificationOptions Options { get; set; }
[Parameter] public EventCallback Okayed { get; set; }
[Parameter] public EventCallback Closed { get; set; }
[Inject] protected BlazoriseUiNotificationService UiNotificationService { get; set; }
[Inject] protected IStringLocalizerFactory StringLocalizerFactory { get; set; }
protected virtual SnackbarColor GetSnackbarColor(UiNotificationType notificationType)
{
return notificationType switch
{
UiNotificationType.Info => SnackbarColor.Info,
UiNotificationType.Success => SnackbarColor.Success,
UiNotificationType.Warning => SnackbarColor.Warning,
UiNotificationType.Error => SnackbarColor.Danger,
_ => SnackbarColor.None,
};
}
protected override void OnInitialized()
{
base.OnInitialized();
UiNotificationService.NotificationReceived += OnNotificationReceived;
}
protected virtual void OnNotificationReceived(object sender, UiNotificationEventArgs e)
{
NotificationType = e.NotificationType;
Message = e.Message;
Title = e.Title;
Options = e.Options;
var okButtonText = Options?.OkButtonText?.Localize(StringLocalizerFactory);
SnackbarStack.Push(Message, GetSnackbarColor( e.NotificationType ), okButtonText);
}
public virtual void Dispose()
{
if (UiNotificationService != null)
{
UiNotificationService.NotificationReceived -= OnNotificationReceived;
}
}
protected virtual Task OnSnackbarClosed(SnackbarClosedEventArgs eventArgs)
{
return eventArgs.CloseReason == SnackbarCloseReason.UserClosed
? Okayed.InvokeAsync()
: Closed.InvokeAsync();
}
}
}

5
framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj

@ -12,8 +12,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Blazorise" Version="0.9.2-preview9" />
<PackageReference Include="Blazorise.DataGrid" Version="0.9.2-preview9" />
<PackageReference Include="Blazorise" Version="0.9.2-rc1" />
<PackageReference Include="Blazorise.DataGrid" Version="0.9.2-rc1" />
<PackageReference Include="Blazorise.Snackbar" Version="0.9.2-rc1" />
</ItemGroup>
</Project>

3
framework/src/Volo.Abp.BlazoriseUI/_Imports.razor

@ -1,2 +1,3 @@
@using Microsoft.AspNetCore.Components.Web
@using Blazorise
@using Blazorise
@using Blazorise.Snackbar

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs

@ -17,7 +17,8 @@ namespace Volo.Abp.Cli.Http
{
public static TimeSpan DefaultTimeout { get; set; } = TimeSpan.FromMinutes(1);
public CliHttpClient(TimeSpan? timeout = null) : base(new CliHttpClientHandler())
public CliHttpClient(TimeSpan? timeout = null)
: base(new CliHttpClientHandler())
{
Timeout = timeout ?? DefaultTimeout;
@ -98,4 +99,4 @@ namespace Volo.Abp.Cli.Http
}
}
}
}

1
framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs

@ -2,6 +2,7 @@
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
namespace System
{

41
modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorMessageLocalizerHelper.cs

@ -0,0 +1,41 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.Extensions.Localization;
namespace Volo.Abp.Identity.Blazor
{
public class AbpIdentityBlazorMessageLocalizerHelper<T>
{
private readonly IStringLocalizer<T> stringLocalizer;
public AbpIdentityBlazorMessageLocalizerHelper(IStringLocalizer<T> stringLocalizer)
{
this.stringLocalizer = stringLocalizer;
}
public string Localize(string message, [CanBeNull] IEnumerable<string> arguments)
{
try
{
return arguments?.Count() > 0
? stringLocalizer[message, LocalizeMessageArguments(arguments)?.ToArray()]
: stringLocalizer[message];
}
catch
{
return stringLocalizer[message];
}
}
private IEnumerable<string> LocalizeMessageArguments(IEnumerable<string> arguments)
{
foreach (var argument in arguments)
{
yield return stringLocalizer[$"DisplayName:{argument}"]
?? stringLocalizer[argument]
?? argument;
}
}
}
}

2
modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorModule.cs

@ -32,6 +32,8 @@ namespace Volo.Abp.Identity.Blazor
{
options.AdditionalAssemblies.Add(typeof(AbpIdentityBlazorModule).Assembly);
});
context.Services.AddSingleton(typeof(AbpIdentityBlazorMessageLocalizerHelper<>));
}
}
}

80
modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor

@ -1,5 +1,5 @@
@page "/identity/roles"
@attribute [Authorize(IdentityPermissions.Roles.Default)]
@attribute [Authorize( IdentityPermissions.Roles.Default )]
@using Volo.Abp.Identity
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Forms
@ -7,13 +7,19 @@
@inherits AbpCrudPageBase<IIdentityRoleAppService, IdentityRoleDto, Guid, GetIdentityRolesInput, IdentityRoleCreateDto, IdentityRoleUpdateDto>
@using Microsoft.Extensions.Localization
@using Volo.Abp.Identity.Localization
@using Volo.Abp.PermissionManagement.Blazor.Components
@inherits RoleManagementBase
@inject IStringLocalizer<IdentityResource> L
@inject AbpIdentityBlazorMessageLocalizerHelper<IdentityResource> LH
@* ************************* PAGE HEADER ************************* *@
<Row>
<Column ColumnSize="ColumnSize.Is6">
<h1>@L["Roles"]</h1>
<Heading Size="HeadingSize.Is1">@L["Roles"]</Heading>
</Column>
<Column ColumnSize="ColumnSize.Is6">
@if (HasCreatePermission)
@if ( HasCreatePermission )
{
<Paragraph Alignment="TextAlignment.Right">
<Button Color="Color.Primary" Clicked="OpenCreateModalAsync">@L["NewRole"]</Button>
@ -30,7 +36,7 @@
ShowPager="true"
PageSize="PageSize">
<DataGridColumns>
@if (ShouldShowEntityActions)
@if ( ShouldShowEntityActions )
{
<DataGridColumn Width="150px" TItem="IdentityRoleDto" Field="@nameof(IdentityRoleDto.Name)" Sortable="false" Caption="@L["Actions"].Value">
<DisplayTemplate>
@ -39,15 +45,15 @@
@L["Actions"]
</DropdownToggle>
<DropdownMenu>
@if (HasUpdatePermission)
@if ( HasUpdatePermission )
{
<DropdownItem Clicked="() => OpenEditModalAsync(context.As<IdentityRoleDto>().Id)">@L["Edit"]</DropdownItem>
}
@if (HasManagePermissionsPermission)
@if ( HasManagePermissionsPermission )
{
<DropdownItem Clicked="() => PermissionManagementModal.OpenAsync(PermissionProviderName, context.As<IdentityRoleDto>().Name)">@L["Permissions"]</DropdownItem>
}
@if (HasDeletePermission)
@if ( HasDeletePermission )
{
<DropdownItem Clicked="() => DeleteEntityAsync(context.As<IdentityRoleDto>())">@L["Delete"]</DropdownItem>
}
@ -59,11 +65,11 @@
<DataGridColumn TItem="IdentityRoleDto" Field="@nameof(IdentityRoleDto.Name)" Caption="@L["RoleName"].Value">
<DisplayTemplate>
@(context.As<IdentityRoleDto>().Name)
@if (context.As<IdentityRoleDto>().IsDefault)
@if ( context.As<IdentityRoleDto>().IsDefault )
{
<Badge Color="Color.Primary">@L["DisplayName:IsDefault"]</Badge>
}
@if (context.As<IdentityRoleDto>().IsPublic)
@if ( context.As<IdentityRoleDto>().IsPublic )
{
<Badge Color="Color.Light">@L["DisplayName:IsPublic"]</Badge>
}
@ -73,56 +79,68 @@
</DataGrid>
@* ************************* CREATE MODAL ************************* *@
@if (HasCreatePermission)
@if ( HasCreatePermission )
{
<Modal @ref="CreateModal">
<ModalBackdrop />
<ModalContent IsCentered="true">
<ModalContent Centered="true">
<ModalHeader>
<ModalTitle>@L["NewRole"]</ModalTitle>
<CloseButton Clicked="CloseCreateModalAsync" />
</ModalHeader>
<ModalBody>
<EditForm id="IdentityRoleCreateForm" Model="@NewEntity" OnValidSubmit="CreateEntityAsync">
<Field>
<FieldLabel>@L["DisplayName:RoleName"]</FieldLabel>
<TextEdit @bind-text="@NewEntity.Name"/>
</Field>
<Validations @ref="@CreateValidationsRef" Model="@NewEntity" ValidateOnLoad="false">
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["DisplayName:RoleName"]</FieldLabel>
<TextEdit @bind-Text="@NewEntity.Name">
<Feedback>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
</Validation>
<Field>
<Check TValue="bool" @bind-checked="@NewEntity.IsDefault">@L["DisplayName:IsDefault"]</Check>
<Check TValue="bool" @bind-checked="@NewEntity.IsPublic">@L["DisplayName:IsPublic"]</Check>
<Check TValue="bool" @bind-Checked="@NewEntity.IsDefault">@L["DisplayName:IsDefault"]</Check>
<Check TValue="bool" @bind-Checked="@NewEntity.IsPublic">@L["DisplayName:IsPublic"]</Check>
</Field>
</EditForm>
</Validations>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary" Clicked="CloseCreateModalAsync">@L["Cancel"]</Button>
<Button form="IdentityRoleCreateForm" Color="Color.Primary" Clicked="CreateEntityAsync">@L["Save"]</Button>
<Button Color="Color.Primary" Clicked="CreateEntityAsync">@L["Save"]</Button>
</ModalFooter>
</ModalContent>
</Modal>
}
@* ************************* EDIT MODAL ************************* *@
@if (HasUpdatePermission)
@if ( HasUpdatePermission )
{
<Modal @ref="EditModal">
<ModalBackdrop />
<ModalContent IsCentered="true">
<ModalContent Centered="true">
<ModalHeader>
<ModalTitle>@L["Edit"]</ModalTitle>
<CloseButton Clicked="CloseEditModalAsync" />
</ModalHeader>
<ModalBody>
<EditForm id="IdentityRoleEditForm" Model="@EditingEntity" OnValidSubmit="UpdateEntityAsync">
<Validations @ref="@EditValidationsRef" Model="@EditingEntity" ValidateOnLoad="false">
<input type="hidden" name="ConcurrencyStamp" @bind-value="EditingEntity.ConcurrencyStamp" />
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["DisplayName:RoleName"]</FieldLabel>
<TextEdit @bind-Text="EditingEntity.Name">
<Feedback>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
</Validation>
<Field>
<FieldLabel>@L["DisplayName:RoleName"]</FieldLabel>
<TextEdit @bind-text="EditingEntity.Name" />
</Field>
<Field>
<Check TValue="bool" @bind-checked="@EditingEntity.IsDefault">@L["DisplayName:IsDefault"]</Check>
<Check TValue="bool" @bind-checked="@EditingEntity.IsPublic">@L["DisplayName:IsPublic"]</Check>
<Check TValue="bool" @bind-Checked="@EditingEntity.IsDefault">@L["DisplayName:IsDefault"]</Check>
<Check TValue="bool" @bind-Checked="@EditingEntity.IsPublic">@L["DisplayName:IsPublic"]</Check>
</Field>
</EditForm>
</Validations>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary" Clicked="CloseEditModalAsync">@L["Cancel"]</Button>
@ -132,4 +150,4 @@
</Modal>
}
<PermissionManagementModal @ref="PermissionManagementModal"/>
<PermissionManagementModal @ref="PermissionManagementModal" />

4
modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor.cs

@ -1,4 +1,6 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
using Blazorise;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Identity.Localization;
using Volo.Abp.PermissionManagement.Blazor.Components;

240
modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor

@ -1,18 +1,24 @@
@page "/identity/users"
@attribute [Authorize(IdentityPermissions.Users.Default)]
@attribute [Authorize( IdentityPermissions.Users.Default )]
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Volo.Abp.PermissionManagement.Blazor.Components
@inherits AbpCrudPageBase<IIdentityUserAppService, IdentityUserDto, Guid, GetIdentityUsersInput, IdentityUserCreateDto, IdentityUserUpdateDto>
@using Microsoft.Extensions.Localization
@using Volo.Abp.Identity.Localization
@using Volo.Abp.PermissionManagement.Blazor.Components
@inherits UserManagementBase
@inject IStringLocalizer<IdentityResource> L
@inject AbpIdentityBlazorMessageLocalizerHelper<IdentityResource> LH
@* ************************* PAGE HEADER ************************* *@
<Row>
<Column ColumnSize="ColumnSize.Is6">
<h1>@L["Users"]</h1>
</Column>
<Column ColumnSize="ColumnSize.Is6">
@if (HasCreatePermission)
@if ( HasCreatePermission )
{
<Paragraph Alignment="TextAlignment.Right">
<Button Color="Color.Primary" Clicked="OpenCreateModalAsync">@L["NewUser"]</Button>
@ -29,7 +35,7 @@
ShowPager="true"
PageSize="PageSize">
<DataGridColumns>
@if (ShouldShowEntityActions)
@if ( ShouldShowEntityActions )
{
<DataGridColumn Width="150px" TItem="IdentityUserDto" Field="@nameof(IdentityUserDto.UserName)" Sortable="false" Caption="@L["Actions"].Value">
<DisplayTemplate>
@ -38,17 +44,17 @@
@L["Actions"]
</DropdownToggle>
<DropdownMenu>
@if (HasUpdatePermission)
@if ( HasUpdatePermission )
{
<DropdownItem Clicked="() => OpenEditModalAsync(context.As<IdentityUserDto>().Id)">@L["Edit"]</DropdownItem>
}
@if (HasManagePermissionsPermission)
@if ( HasManagePermissionsPermission )
{
<DropdownItem Clicked="() => PermissionManagementModal.OpenAsync(PermissionProviderName, context.As<IdentityUserDto>().Id.ToString())">@L["Permissions"]</DropdownItem>
}
@if (HasDeletePermission)
@if ( HasDeletePermission )
{
<DropdownDivider/>
<DropdownDivider />
<DropdownItem Clicked="() => DeleteEntityAsync(context.As<IdentityUserDto>())">@L["Delete"]</DropdownItem>
}
</DropdownMenu>
@ -75,17 +81,17 @@
</DataGrid>
@* ************************* CREATE MODAL ************************* *@
@if (HasCreatePermission)
@if ( HasCreatePermission )
{
<Modal @ref="CreateModal">
<ModalBackdrop/>
<ModalContent IsCentered="true">
<ModalBackdrop />
<ModalContent Centered="true">
<ModalHeader>
<ModalTitle>@L["NewUser"]</ModalTitle>
<CloseButton Clicked="CloseCreateModalAsync"/>
<CloseButton Clicked="CloseCreateModalAsync" />
</ModalHeader>
<ModalBody>
<EditForm id="IdentityUserCreateForm" Model="@NewEntity" OnValidSubmit="CreateEntityAsync">
<Validations @ref="@CreateValidationsRef" Model="@NewEntity" ValidateOnLoad="false">
<Tabs @bind-SelectedTab="@CreateModalSelectedTab">
<Items>
<Tab Name="UserInformations">@L["UserInformations"]</Tab>
@ -93,71 +99,107 @@
</Items>
<Content>
<TabPanel Name="UserInformations">
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["DisplayName:UserName"]</FieldLabel>
<TextEdit @bind-Text="NewEntity.UserName">
<Feedback>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["DisplayName:Name"]</FieldLabel>
<TextEdit @bind-Text="NewEntity.Name">
<Feedback>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["DisplayName:Surname"]</FieldLabel>
<TextEdit @bind-Text="NewEntity.Surname">
<Feedback>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["DisplayName:Password"]</FieldLabel>
<TextEdit Role="TextRole.Password" @bind-Text="NewEntity.Password">
<Feedback>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["DisplayName:Email"]</FieldLabel>
<TextEdit @bind-Text="NewEntity.Email">
<Feedback>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["DisplayName:PhoneNumber"]</FieldLabel>
<TextEdit @bind-Text="NewEntity.PhoneNumber">
<Feedback>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
</Validation>
<Field>
<FieldLabel>@L["DisplayName:UserName"]</FieldLabel>
<TextEdit @bind-text="NewEntity.UserName"/>
</Field>
<Field>
<FieldLabel>@L["DisplayName:Name"]</FieldLabel>
<TextEdit @bind-text="NewEntity.Name"/>
</Field>
<Field>
<FieldLabel>@L["DisplayName:Surname"]</FieldLabel>
<TextEdit @bind-text="NewEntity.Surname"/>
</Field>
<Field>
<FieldLabel>@L["DisplayName:Password"]</FieldLabel>
<TextEdit Role="TextRole.Password" @bind-text="NewEntity.Password"/>
</Field>
<Field>
<FieldLabel>@L["DisplayName:Email"]</FieldLabel>
<TextEdit @bind-text="NewEntity.Email"/>
</Field>
<Field>
<FieldLabel>@L["DisplayName:PhoneNumber"]</FieldLabel>
<TextEdit @bind-text="NewEntity.PhoneNumber"/>
</Field>
<Field>
<Check TValue="bool" @bind-checked="@NewEntity.LockoutEnabled">@L["DisplayName:LockoutEnabled"]</Check>
<Check TValue="bool" @bind-Checked="@NewEntity.LockoutEnabled">@L["DisplayName:LockoutEnabled"]</Check>
</Field>
</TabPanel>
<TabPanel Name="Roles">
@if (NewUserRoles != null)
@if ( NewUserRoles != null )
{
@foreach (var role in NewUserRoles)
@foreach ( var role in NewUserRoles )
{
<Field>
<input type="hidden" @bind-value="@role.Name"/>
<Check TValue="bool" @bind-checked="@role.IsAssigned">@role.Name</Check>
<input type="hidden" @bind-value="@role.Name" />
<Check TValue="bool" @bind-Checked="@role.IsAssigned">@role.Name</Check>
</Field>
}
}
</TabPanel>
</Content>
</Tabs>
</EditForm>
</Validations>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary" Clicked="CloseCreateModalAsync">@L["Cancel"]</Button>
<Button form="IdentityUserCreateForm" Color="Color.Primary" Clicked="CreateEntityAsync">@L["Save"]</Button>
<Button Color="Color.Primary" Clicked="CreateEntityAsync">@L["Save"]</Button>
</ModalFooter>
</ModalContent>
</Modal>
}
@* ************************* EDIT MODAL ************************* *@
@if (HasUpdatePermission)
@if ( HasUpdatePermission )
{
<Modal @ref="EditModal">
<ModalBackdrop/>
<ModalContent IsCentered="true">
<ModalBackdrop />
<ModalContent Centered="true">
<ModalHeader>
<ModalTitle>@L["Edit"]</ModalTitle>
<CloseButton Clicked="CloseEditModalAsync"/>
<CloseButton Clicked="CloseEditModalAsync" />
</ModalHeader>
<ModalBody>
<EditForm id="IdentityUserEditForm" Model="@EditingEntity" OnValidSubmit="UpdateEntityAsync">
<input type="hidden" name="ConcurrencyStamp" @bind-value="EditingEntity.ConcurrencyStamp"/>
<Validations @ref="@EditValidationsRef" Model="@NewEntity" ValidateOnLoad="false">
<input type="hidden" name="ConcurrencyStamp" @bind-value="EditingEntity.ConcurrencyStamp" />
<Tabs @bind-SelectedTab="@EditModalSelectedTab">
<Items>
@ -166,56 +208,92 @@
</Items>
<Content>
<TabPanel Name="UserInformations">
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["DisplayName:UserName"]</FieldLabel>
<TextEdit @bind-Text="EditingEntity.UserName">
<Feedback>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["DisplayName:Name"]</FieldLabel>
<TextEdit @bind-Text="EditingEntity.Name">
<Feedback>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["DisplayName:Surname"]</FieldLabel>
<TextEdit @bind-Text="EditingEntity.Surname">
<Feedback>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["DisplayName:Password"]</FieldLabel>
<TextEdit Role="TextRole.Password" @bind-Text="EditingEntity.Password">
<Feedback>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["DisplayName:Email"]</FieldLabel>
<TextEdit @bind-Text="EditingEntity.Email">
<Feedback>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["DisplayName:PhoneNumber"]</FieldLabel>
<TextEdit @bind-Text="EditingEntity.PhoneNumber">
<Feedback>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
</Validation>
<Field>
<FieldLabel>@L["DisplayName:UserName"]</FieldLabel>
<TextEdit @bind-text="EditingEntity.UserName"/>
</Field>
<Field>
<FieldLabel>@L["DisplayName:Name"]</FieldLabel>
<TextEdit @bind-text="EditingEntity.Name"/>
</Field>
<Field>
<FieldLabel>@L["DisplayName:Surname"]</FieldLabel>
<TextEdit @bind-text="EditingEntity.Surname"/>
</Field>
<Field>
<FieldLabel>@L["DisplayName:Password"]</FieldLabel>
<TextEdit Role="TextRole.Password" @bind-text="EditingEntity.Password"/>
</Field>
<Field>
<FieldLabel>@L["DisplayName:Email"]</FieldLabel>
<TextEdit @bind-text="EditingEntity.Email"/>
</Field>
<Field>
<FieldLabel>@L["DisplayName:PhoneNumber"]</FieldLabel>
<TextEdit @bind-text="EditingEntity.PhoneNumber"/>
</Field>
<Field>
<Check TValue="bool" @bind-checked="EditingEntity.LockoutEnabled">@L["DisplayName:LockoutEnabled"]</Check>
<Check TValue="bool" @bind-Checked="EditingEntity.LockoutEnabled">@L["DisplayName:LockoutEnabled"]</Check>
</Field>
</TabPanel>
<TabPanel Name="Roles">
@if (EditUserRoles != null)
@if ( EditUserRoles != null )
{
@foreach (var role in EditUserRoles)
@foreach ( var role in EditUserRoles )
{
<Field>
<input type="hidden" @bind-value="@role.Name"/>
<Check TValue="bool" @bind-checked="@role.IsAssigned">@role.Name</Check>
<input type="hidden" @bind-value="@role.Name" />
<Check TValue="bool" @bind-Checked="@role.IsAssigned">@role.Name</Check>
</Field>
}
}
</TabPanel>
</Content>
</Tabs>
</EditForm>
</Validations>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary" Clicked="CloseEditModalAsync">@L["Cancel"]</Button>
<Button form="IdentityUserEditForm" Color="Color.Primary" Clicked="UpdateEntityAsync">@L["Save"]</Button>
<Button Color="Color.Primary" Clicked="UpdateEntityAsync">@L["Save"]</Button>
</ModalFooter>
</ModalContent>
</Modal>
}
<PermissionManagementModal @ref="PermissionManagementModal"/>
<PermissionManagementModal @ref="PermissionManagementModal" />

35
modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor.cs

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Blazorise;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Identity.Localization;
using Volo.Abp.PermissionManagement.Blazor.Components;
@ -59,46 +60,48 @@ namespace Volo.Abp.Identity.Blazor.Pages.Identity
HasManagePermissionsPermission;
}
protected override Task OpenCreateModalAsync()
protected override async Task OnOpeningCreateModalAsync()
{
CreateModalSelectedTab = DefaultSelectedTab;
NewUserRoles = Roles.Select(x => new AssignedRoleViewModel
{
Name = x.Name,
IsAssigned = x.IsDefault
}).ToArray();
{
Name = x.Name,
IsAssigned = x.IsDefault
}).ToArray();
return base.OpenCreateModalAsync();
await base.OnOpeningCreateModalAsync();
}
protected override Task CreateEntityAsync()
protected override Task OnCreatingEntityAsync()
{
// apply roles before saving
NewEntity.RoleNames = NewUserRoles.Where(x => x.IsAssigned).Select(x => x.Name).ToArray();
return base.CreateEntityAsync();
return base.OnCreatingEntityAsync();
}
protected override async Task OpenEditModalAsync(Guid id)
protected override async Task OnOpeningEditModalAsync(Guid id)
{
EditModalSelectedTab = DefaultSelectedTab;
var userRoleNames = (await AppService.GetRolesAsync(id)).Items.Select(r => r.Name).ToList();
EditUserRoles = Roles.Select(x => new AssignedRoleViewModel
{
Name = x.Name,
IsAssigned = userRoleNames.Contains(x.Name)
}).ToArray();
{
Name = x.Name,
IsAssigned = userRoleNames.Contains(x.Name)
}).ToArray();
await base.OpenEditModalAsync(id);
await base.OnOpeningEditModalAsync(id);
}
protected override Task UpdateEntityAsync()
protected override Task OnUpdatingEntityAsync()
{
// apply roles before saving
EditingEntity.RoleNames = EditUserRoles.Where(x => x.IsAssigned).Select(x => x.Name).ToArray();
return base.UpdateEntityAsync();
return base.OnUpdatingEntityAsync();
}
}

3
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityDomainSharedModule.cs

@ -1,4 +1,5 @@
using Volo.Abp.Features;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Features;
using Volo.Abp.Identity.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Localization.ExceptionHandling;

1
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/index.html

@ -12,6 +12,7 @@
<link href="_content/Blazorise/blazorise.css" rel="stylesheet" />
<link href="_content/Blazorise.Bootstrap/blazorise.bootstrap.css" rel="stylesheet" />
<link href="_content/Blazorise.Snackbar/blazorise.snackbar.css" rel="stylesheet" />
<link href="_content/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/libs/abp/css/theme.css" rel="stylesheet" />
<link href="main.css" rel="stylesheet" />
</head>

Loading…
Cancel
Save