Browse Source

Merge pull request #25036 from abpframework/auto-merge/rel-10-2/4411

Merge branch dev with rel-10.2
pull/25039/head
Volosoft Agent 3 weeks ago
committed by GitHub
parent
commit
a1f07b44df
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      docs/en/package-version-changes.md
  2. 4
      docs/en/release-info/migration-guides/abp-10-1.md
  3. 11
      docs/en/tutorials/modular-crm/index.md
  4. 10
      docs/en/tutorials/modular-crm/part-01.md
  5. 27
      docs/en/tutorials/modular-crm/part-02.md
  6. 80
      docs/en/tutorials/modular-crm/part-03.md
  7. 25
      docs/en/tutorials/modular-crm/part-04.md
  8. 88
      docs/en/tutorials/modular-crm/part-05.md
  9. 25
      docs/en/tutorials/modular-crm/part-06.md
  10. 26
      docs/en/tutorials/modular-crm/part-07.md
  11. 13
      docs/en/tutorials/modular-crm/part-08.md
  12. 1
      npm/ng-packs/packages/permission-management/src/lib/components/resource-permission-management/resource-permission-form/resource-permission-form.component.html

4
docs/en/package-version-changes.md

@ -30,6 +30,6 @@
| Package | Old Version | New Version | PR |
|---------|-------------|-------------|-----|
| Microsoft.SemanticKernel | 1.67.1 | 1.71.0 | #24891 |
| Microsoft.SemanticKernel.Abstractions | 1.67.1 | 1.71.0 | #24891 |
| Microsoft.SemanticKernel | 1.67.1 | 1.71.0 | [#24891](https://github.com/abpframework/abp/pull/24891) |
| Microsoft.SemanticKernel.Abstractions | 1.67.1 | 1.71.0 | [#24891](https://github.com/abpframework/abp/pull/24891) |

4
docs/en/release-info/migration-guides/abp-10-1.md

@ -7,7 +7,7 @@
# ABP Version 10.1 Migration Guide
This document is a guide for upgrading ABP v10.0 solutions to ABP v10.1. There are some changes in this version that may affect your applications. Please read them carefully and apply the necessary changes to your application.
This document is a guide for upgrading ABP v10.0 solutions to ABP v10.1. There are some changes in this version that may affect your applications. Please read them carefully and apply the necessary changes to your application. You may also need to update or check package versions; for internal NuGet package changes, see [package-version-changes.md](../../package-version-changes.md) for reference.
## Open-Source (Framework)
@ -88,7 +88,7 @@ ABP now targets Angular v21 (up from v20). For existing Angular projects, apply
}
```
For more details, see the [Angular version reference](https://angular.dev/reference/versions#actively-supported-versions).
You may need to update your Node.js version as well. For more details, see the [Angular version reference](https://angular.dev/reference/versions#actively-supported-versions).
## PRO

11
docs/en/tutorials/modular-crm/index.md

@ -7,6 +7,13 @@
# Modular Monolith Application Development Tutorial
```json
//[doc-params]
{
"UI": ["MVC", "NG"]
}
```
````json
//[doc-params]
{
@ -24,9 +31,9 @@
}
````
ABP provides a great infrastructure and tooling to build modular software solutions. In this tutorial, you will learn how to create application modules, compose and communicate them to build a monolith modular web application.
ABP provides great infrastructure and tooling to build modular software solutions. In this tutorial, you will learn how to create application modules, compose and communicate them to build a modular monolith web application with the {{UI_Value}} UI.
> **This tutorial focuses on modularity.** The example application's functionality and user interface are intentionally kept simple. If you want to learn real world, full featured application logic development with ABP, please follow the [Book Store tutorial](../book-store/index.md).
> **This tutorial focuses on modularity.** The sample application's UI is intentionally kept simple so you can focus on module design and integration. For a real-world, full-featured application walkthrough with ABP, follow the [Book Store tutorial](../book-store/index.md).
## Tutorial Outline

10
docs/en/tutorials/modular-crm/part-01.md

@ -7,6 +7,13 @@
# Creating the Initial Solution
```json
//[doc-params]
{
"UI": ["MVC", "NG"]
}
```
````json
//[doc-params]
{
@ -38,6 +45,9 @@ Follow the *[Get Started](../../get-started/single-layer-web-application.md)* gu
* **UI Framework**: {{if UI == "MVC"}}ASP.NET Core MVC / Razor Pages{{else if UI == "BlazorWebApp"}}Blazor WebApp{{end}}
* **Database Provider**: Entity Framework Core
{{if UI == "NG"}}> **Note:** Angular users can continue with the Angular UI steps in the upcoming parts while following the same modularity flow.
{{end}}
You can select the other options based on your preference but at the **Modularity** step, check the _Setup as a modular solution_ option and add a new **Standard Module** named `ModularCrm.Catalog`:
![](./images/modular-crm-wizard-modularity-step.png)

27
docs/en/tutorials/modular-crm/part-02.md

@ -7,6 +7,13 @@
# Setting Up the Catalog Module
```json
//[doc-params]
{
"UI": ["MVC", "NG"]
}
```
````json
//[doc-params]
{
@ -68,10 +75,28 @@ Graph Build is a dotnet CLI command that recursively builds all the referenced d
## Running the Main Application
{{if UI == "MVC"}}
Open the *Solution Runner* panel, click the *Play* button (near to the solution root), right-click the `ModularCrm` application and select the *Browse* command. It will open the web application in the built-in browser. Then you can navigate to the *Catalog* page on the main menu of the application to see the Catalog page that is coming from the `ModularCrm.Catalog` module:
![abp-studio-solution-runner-initial-catalog-page](images/abp-studio-solution-runner-initial-catalog-page.png)
{{else if UI == "NG"}}
Open the *Solution Runner* panel and start the `ModularCrm` application to run the backend host.
Then open a terminal in the `angular` folder and start the Angular application:
```bash
yarn start
```
After the Angular app starts, open the URL shown in the terminal (typically `http://localhost:4200`), sign in, and navigate to the *Catalog* page from the main menu to verify the `ModularCrm.Catalog` module UI is integrated.
![abp-studio-solution-runner-initial-catalog-page](images/abp-studio-solution-runner-initial-catalog-page.png)
{{end}}
## Summary
In this part, you installed the `ModularCrm.Catalog` module to the main application and run the solution to test if it has successfully installed. In the [next part](part-03.md), you will learn how to create entities, services and a basic user interface for the catalog module.
In this part, you installed the `ModularCrm.Catalog` module to the main application and ran the solution to verify that it was installed successfully. In the [next part](part-03.md), you will learn how to create entities, services and a basic user interface for the catalog module.

80
docs/en/tutorials/modular-crm/part-03.md

@ -7,6 +7,13 @@
# Building the Catalog Module
```json
//[doc-params]
{
"UI": ["MVC", "NG"]
}
```
````json
//[doc-params]
{
@ -447,6 +454,8 @@ In this section, you will create a very simple user interface to demonstrate how
As a first step, you can stop the application on ABP Studio's Solution Runner if it is currently running.
{{if UI == "MVC"}}
### Creating the Products Page
{{if UI == "MVC"}}
@ -559,6 +568,75 @@ Now, you can browse the *Catalog* page to see the list of the products:
As you can see, developing a UI page in a modular ABP application is pretty straightforward. We kept the UI very simple to focus on modularity. To learn how to build complex application UIs, please check the [Book Store Tutorial](../book-store/index.md).
{{else if UI == "NG"}}
### Updating the Catalog Angular Page
First, run the `ModularCrm` application so the backend APIs are available.
Then open a terminal in the `modules/modularcrm.catalog/angular` folder and run the proxy generation command:
```bash
abp generate-proxy -t ng
```
This command generates or updates TypeScript client proxies for the `catalog` APIs under `projects/catalog/src/lib/proxy`. You will use the generated `ProductService` and related DTOs in the Catalog UI project.
Now, open the `projects/catalog/src/lib/components/catalog.component.ts` file and replace its content with the following code:
```ts
import { Component, OnInit, inject } from '@angular/core';
import { ProductDto, ProductService } from '../proxy/products';
@Component({
selector: 'lib-catalog',
templateUrl: './catalog.component.html',
})
export class CatalogComponent implements OnInit {
products: ProductDto[] = [];
protected readonly productService = inject(ProductService);
ngOnInit(): void {
this.productService.getList().subscribe(response => {
this.products = response;
});
}
}
```
Now, open the `projects/catalog/src/lib/components/catalog.component.html` file and replace its content with the following code:
```html
<h1>Products</h1>
<abp-card>
<abp-card-body>
<abp-list-group>
@for (product of products; track product.id) {
<abp-list-group-item>
{%{{{ product.name }}}%} <span class="text-muted">(stock: {%{{{ product.stockCount }}}%})</span>
</abp-list-group-item>
}
</abp-list-group>
</abp-card-body>
</abp-card>
```
In a module-based Angular UI, the route and menu are configured in the module's config project. Ensure `projects/catalog/config/src/providers/route.provider.ts` includes the `/catalog` route, and `projects/catalog/src/lib/catalog.routes.ts` lazy-loads `CatalogComponent`.
![vscode-catalog-cshtml](images/vscode-catalog-cshtml.png)
Finally, start the Angular app from the root `angular` folder and navigate to the *Catalog* page to see the products list:
```bash
yarn start
```
![abp-studio-browser-list-of-products](images/abp-studio-browser-list-of-products.png)
{{end}}
## Summary
In this part of the tutorial, you've built the functionality inside the _Catalog_ module, which was created in the [previous part](part-02.md). In the next part, you will create a new _Ordering_ module and install it into the main application.
In this part of the tutorial, you've built the functionality inside the _Catalog_ module, which was created in the [previous part](part-02.md), and created a basic {{if UI == "MVC"}}MVC{{else if UI == "NG"}}Angular{{end}} UI to list products. In the next part, you will create a new _Ordering_ module and install it into the main application.

25
docs/en/tutorials/modular-crm/part-04.md

@ -7,6 +7,13 @@
# Creating the Initial Ordering Module
```json
//[doc-params]
{
"UI": ["MVC", "NG"]
}
```
````json
//[doc-params]
{
@ -54,6 +61,12 @@ Set `ModularCrm.Ordering` as the *Module name*, leave the *Output folder* as is
You can choose the type of UI you want to support in your module or select *No UI* if you don't need a user interface. In this example, we'll select the {{if UI == "MVC"}}*MVC*{{else if UI == "BlazorWebApp"}}*Blazor WebApp*{{end}} option and click *Next*.
{{else if UI == "NG"}}
You can choose the type of UI you want to support in your module or select *No UI* if you don't need a user interface. In this example, we'll select the *Angular* UI option and click *Next*.
{{end}}
![abp-studio-add-new-standard-module-db-dialog](images/abp-studio-add-new-standard-module-db-dialog.png)
In this screen, select the *Entity Framework Core* option and click *Next*.
@ -94,6 +107,18 @@ Select the `ModularCrm.Ordering` module and check the *Install this module* opti
Select the `ModularCrm.Ordering` and {{if UI == "MVC"}}`ModularCrm.Ordering.UI`{{else if UI == "BlazorWebApp"}}`ModularCrm.Ordering.Blazor`{{end}} packages from the left area. {{if UI == "MVC"}}Ensure `ModularCrm` was checked in the middle area as shown in the preceding figure.{{else if UI == "BlazorWebApp"}}For `ModularCrm.Ordering`, ensure `ModularCrm` is checked. For `ModularCrm.Ordering.Blazor`, ensure both `ModularCrm` and `ModularCrm.Client` are checked in the middle area as shown in the preceding figure.{{end}} Finally, click _OK_.
{{if UI == "NG"}}
After installing a new Angular module, run the symlink setup command from the root `angular` folder to align shared package versions between the main app and local module packages:
```bash
yarn symlinks:setup
```
You should run this command again whenever you add another local module with Angular packages.
{{end}}
## Summary
In this part of the tutorial, you've created a new module and installed it into the main solution. In the [next part](part-05), you will add functionality to the new Ordering module.

88
docs/en/tutorials/modular-crm/part-05.md

@ -7,6 +7,13 @@
# Building the Ordering Module
```json
//[doc-params]
{
"UI": ["MVC", "NG"]
}
```
````json
//[doc-params]
{
@ -419,6 +426,8 @@ In this section, you will create a very simple user interface to demonstrate how
As a first step, you can stop the application on ABP Studio's Solution Runner if it is currently running.
{{if UI == "MVC"}}
### Creating the Orders Page
{{if UI == "MVC"}}
@ -615,6 +624,83 @@ You've performed a graph build since you've made a change on a module, and more
Great! We can see the list of orders. However, there is a problem: We see Product's GUID ID instead of its name. This is because the Ordering module has no integration with the Catalog module and doesn't have access to Product module's database to perform a JOIN query. We will solve this problem in the [next part](part-06.md).
{{else if UI == "NG"}}
### Creating the Orders Page
First, run the `ModularCrm` application so the backend APIs are available.
Then open a terminal in the `modules/modularcrm.ordering/angular` folder and generate (or refresh) the Angular client proxies:
```bash
abp generate-proxy -t ng
```
This command creates/updates the TypeScript client proxies under `projects/ordering/src/lib/proxy`. You will use the generated `OrderService` and DTO types to render the orders page.
Now, open `projects/ordering/src/lib/components/ordering.component.ts` and update it to query and show the order list:
```ts
import { Component, OnInit, inject } from '@angular/core';
import { OrderDto, OrderService } from '../proxy/orders';
@Component({
selector: 'lib-ordering',
templateUrl: './ordering.component.html',
})
export class OrderingComponent implements OnInit {
orders: OrderDto[] = [];
protected readonly orderService = inject(OrderService);
ngOnInit(): void {
this.orderService.getList().subscribe(response => {
this.orders = response;
});
}
}
```
Then open `projects/ordering/src/lib/components/ordering.component.html` and update it as follows:
```html
<h1>Orders</h1>
<abp-card>
<abp-card-body>
<abp-list-group>
@for (order of orders; track order.id) {
<abp-list-group-item>
<strong>Customer:</strong> {%{{{ order.customerName }}}%} <br />
<strong>Product:</strong> {%{{{ order.productId }}}%} <br />
<strong>State:</strong> {%{{{ order.state }}}%}
</abp-list-group-item>
}
</abp-list-group>
</abp-card-body>
</abp-card>
```
![visual-studio-ordering-contracts](images/visual-studio-ordering-contracts-v2.png)
### Editing the Menu Item
In a module-based Angular UI, menu and route registration are done in the config and app route files. Ensure `projects/ordering/config/src/providers/route.provider.ts` adds the `/ordering` menu route, and the main Angular app (`angular/src/app/app.routes.ts`) lazy-loads the Ordering module routes.
### Building the Application
Start the Angular app from the root `angular` folder:
```bash
yarn start
```
Navigate to the *Ordering* page and verify that the orders are listed. At this stage, showing `productId` is expected.
![abp-studio-browser-orders-menu-item](images/abp-studio-browser-orders-menu-item-v2.png)
{{end}}
## Summary
In this part of the *Modular CRM* tutorial, you've built the functionality inside the Ordering module you created in the [previous part](part-04.md). In the [next part](part-06.md), you will work on establishing communication between the Orders module and the Catalog module.
In this part of the *Modular CRM* tutorial, you've built the functionality inside the Ordering module you created in the [previous part](part-04.md) and created a basic {{if UI == "MVC"}}MVC{{else if UI == "NG"}}Angular{{end}} UI to list orders. In the [next part](part-06.md), you will work on establishing communication between the Orders module and the Catalog module.

25
docs/en/tutorials/modular-crm/part-06.md

@ -7,6 +7,13 @@
# Integrating the Modules: Implementing Integration Services
```json
//[doc-params]
{
"UI": ["MVC", "NG"]
}
```
````json
//[doc-params]
{
@ -332,10 +339,26 @@ That's all. Now, you can graph build the main application and run it in ABP Stud
As you can see, we can see the product names instead of product IDs.
{{else if UI == "NG"}}
Open the `ordering.component.html` file in the `modules/modularcrm.ordering/angular/projects/ordering/src/lib/components` folder, and replace the `productId` display with `productName`:
```html
<strong>Product:</strong> {%{{{ order.productName }}}%} <br />
```
If your generated Angular proxy files are not up to date, run `abp generate-proxy -t ng` in the `modules/modularcrm.ordering/angular` folder.
Then run the Angular app (`yarn start` in the `angular` folder), navigate to the *Ordering* page, and verify product names are shown instead of product IDs.
![abp-studio-browser-list-of-orders-with-product-name](images/abp-studio-browser-list-of-orders-with-product-name.png)
{{end}}
> **Design Tip**
>
> It is suggested that you keep that type of communication to a minimum and not couple your modules with each other. It can make your solution complicated and may also decrease your system performance. When you need to do it, think about performance and try to make some optimizations. For example, if the Ordering module frequently needs product data, you can use a kind of [cache layer](../../framework/fundamentals/caching.md), so it doesn't make frequent requests to the Catalog module. Especially if you consider converting your system to a microservice solution in the future, too many direct integration API calls can be a performance bottleneck.
## Conclusion
In the way explained in this part of this tutorial, you can easily create integration services for your modules and consume these integration services in any other module. In the [next part](part-07.md), we will explore event based messaging between the modules.
In this part of the tutorial, you created and consumed an integration service between modules, then reflected the product name on the {{if UI == "MVC"}}MVC{{else if UI == "NG"}}Angular{{end}} UI. In the [next part](part-07.md), we will explore event based messaging between the modules.

26
docs/en/tutorials/modular-crm/part-07.md

@ -7,6 +7,13 @@
# Integrating the Modules: Communication via Messages (Events)
```json
//[doc-params]
{
"UI": ["MVC", "NG"]
}
```
````json
//[doc-params]
{
@ -255,12 +262,29 @@ Find the *Orders* API, click the *Try it out* button, enter a sample value the t
> **IMPORTANT:** Here, you should type a valid product Id from the *CatalogProducts* table of your database!
Once you press the *Execute* button, a new order is created. At that point, you can check the `/Orders` page to see if the new order is shown on the UI, and check the `/Products` page to see if the related product's stock count has decreased.
Once you press the *Execute* button, a new order is created.
{{if UI == "MVC"}}
At that point, you can check the `/Orders` page to see if the new order is shown on the UI, and check the `/Products` page to see if the related product's stock count has decreased.
Here are sample screenshots from the Products and Orders pages:
![products-orders-pages-crop](images/products-orders-pages-crop.png)
{{else if UI == "NG"}}
At that point, open the Angular UI and validate the result on the *Ordering* (`/ordering`) and *Catalog* (`/catalog`) pages. Verify that the new order is listed in Ordering and the related product's stock count is decreased in Catalog.
If the Angular app is not already running, start it from the root `angular` folder:
```bash
yarn symlinks:setup
yarn start
```
{{end}}
We placed a new order for Product C. As a result, Product C's stock count has decreased from 55 to 54 and a new line is added to the Orders page.
## Conclusion

13
docs/en/tutorials/modular-crm/part-08.md

@ -5,6 +5,13 @@
}
```
```json
//[doc-params]
{
"UI": ["MVC", "NG"]
}
```
# Integrating the Modules: Joining the Products and Orders Data
````json
@ -154,9 +161,9 @@ That's all. In that way, you can execute JOIN queries that use data from multipl
### Testing the Reporting Service
We haven't created a UI to show list of the latest orders using `OrderReportingAppService`. However, we can use the Swagger UI again to test it.
We haven't created a page to show the latest orders using `OrderReportingAppService` yet. However, we can use the Swagger UI again to test it.
Open the ABP Studio UI, stop the application if it is running, build and run it again. Once the application starts, browse it, then add `/swagger` to the end of the URL to open the Swagger UI. Here, find the `OrderReporting` API and execute it as shown below:
Open ABP Studio, stop the application if it is running, build and run it again. Once the application starts, open its URL, then add `/swagger` to the end of the URL to open the Swagger UI. Here, find the `OrderReporting` API and execute it as shown below:
![abp-studio-swagger-list-orders](images/abp-studio-swagger-list-orders.png)
@ -184,7 +191,7 @@ See the following sections for additional resources.
### The Book Store Tutorial
In this tutorial, we intentionally kept the application logic very simple and didn't build a usable user interface for the modules. Also, didn't implement authorization and localization for the modules. This was to keep your focus on modularity. If you want to learn how to build real-world user interfaces with ABP, you can check the [Book Store tutorial](../book-store/index.md). All the principles and approaches explained there are already possible with a modular system too.
In this tutorial, we intentionally kept the application logic very simple and didn't build a usable UI for the modules. Also, didn't implement authorization and localization for the modules. This was to keep your focus on modularity. If you want to learn how to build real-world ABP UIs (MVC or Angular), you can check the [Book Store tutorial](../book-store/index.md). All the principles and approaches explained there are already possible with a modular system too.
### ABP Reusable Application Modules

1
npm/ng-packs/packages/permission-management/src/lib/components/resource-permission-management/resource-permission-form/resource-permission-form.component.html

@ -27,7 +27,6 @@
<abp-permission-checkbox-list [permissions]="state.permissionDefinitions()" idPrefix="add" />
} @else {
<div class="mb-3" id="permissionList">
<h4>{{ 'AbpPermissionManagement::Permissions' | abpLocalization }}</h4>
<abp-permission-checkbox-list
[permissions]="state.permissionsWithProvider()"
idPrefix="edit"

Loading…
Cancel
Save