Browse Source

Add UI param and MVC/Angular variants to tutorial

Introduce a UI doc parameter and conditional content across modular-crm tutorial parts (part-04..part-08). Adds //[doc-params] JSON to enable MVC or Angular (NG) variants, inserts conditional blocks for screenshots and instructions, and adds Angular-specific guidance (proxy generation, component/template code, menu/routes, and build steps). Also includes small wording clarifications for Swagger/UX and updates summaries to reflect UI variants. TODO placeholders added for missing Angular screenshots.
pull/24953/head
Fahri Gedik 1 month ago
parent
commit
fe61e890b7
  1. 17
      docs/en/tutorials/modular-crm/part-04.md
  2. 90
      docs/en/tutorials/modular-crm/part-05.md
  3. 29
      docs/en/tutorials/modular-crm/part-06.md
  4. 21
      docs/en/tutorials/modular-crm/part-07.md
  5. 13
      docs/en/tutorials/modular-crm/part-08.md

17
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-nav]
{
@ -39,10 +46,20 @@ That command opens a dialog to define the properties of the new module:
Set `ModularCrm.Ordering` as the *Module name*, leave the *Output folder* as is and click the *Next* button.
{{if UI == "MVC"}}
![abp-studio-add-new-standard-module-ui-dialog](images/abp-studio-add-new-standard-module-ui-dialog.png)
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 *MVC* option and click *Next*.
{{else if UI == "NG"}}
> TODO: Add ABP Studio new module dialog screenshot for Angular UI selection.
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*.

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

@ -7,6 +7,13 @@
# Building the Ordering Module
```json
//[doc-params]
{
"UI": ["MVC", "NG"]
}
```
````json
//[doc-nav]
{
@ -379,10 +386,12 @@ If you check the database, you should see the entities created in the *Orders* t
## Creating the User Interface
In this section, you will create a very simple user interface to demonstrate how to build UI in the catalog module and make it work in the main application.
In this section, you will create a very simple user interface to demonstrate how to build UI in the ordering module and make it work in the main application.
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
Replace the `Index.cshtml.cs` content in the `Pages/Ordering` folder of the `ModularCrm.Ordering.UI` project with the following code block:
@ -493,6 +502,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>
```
> TODO: Add Angular Ordering component screenshot.
### 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.
> TODO: Add Angular Ordering page screenshot.
{{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.

29
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-nav]
{
@ -249,7 +256,9 @@ Let's see what we've changed:
* In the last line, we are converting the product list to a dictionary, where the key is `Guid Id` and the value is `string Name`. That way, we can easily find a product's name with its ID.
* Finally, we are mapping the orders to `OrderDto` objects and setting the product name by looking up the product ID in the dictionary.
Open the `Index.cshtml` file, and change the `@order.ProductId` part by `@Order.ProductName` to write the product name instead of the product ID. The final `Index.cshtml` content should be the following:
{{if UI == "MVC"}}
Open the `Index.cshtml` file, and change the `@order.ProductId` part by `@order.ProductName` to write the product name instead of the product ID. The final `Index.cshtml` content should be the following:
````html
@page
@ -279,10 +288,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.
> TODO: Add Angular Ordering page screenshot with product names.
{{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.

21
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-nav]
{
@ -240,12 +247,24 @@ 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.
> TODO: Add Angular Ordering and Catalog pages screenshot after order creation validation.
{{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
@ -147,9 +154,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)
@ -177,7 +184,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

Loading…
Cancel
Save