From 205b0056b4ab2030d31fc59525ea29fe09445d15 Mon Sep 17 00:00:00 2001 From: Fahri Gedik <53567152+fahrigedik@users.noreply.github.com> Date: Wed, 25 Feb 2026 11:04:36 +0300 Subject: [PATCH 1/4] Add UI param and Angular steps to modular-crm Introduce a doc-params UI option (MVC/NG) across the modular-crm tutorial and update text to use conditional UI values. Add Angular-specific instructions: how to run the frontend, generate proxies, and an example Catalog component (TS + HTML) with notes on routing/menu configuration and TODO screenshots. Minor wording tweaks and summary updates for clarity. --- docs/en/tutorials/modular-crm/index.md | 11 +++- docs/en/tutorials/modular-crm/part-01.md | 12 +++- docs/en/tutorials/modular-crm/part-02.md | 27 +++++++- docs/en/tutorials/modular-crm/part-03.md | 80 +++++++++++++++++++++++- 4 files changed, 125 insertions(+), 5 deletions(-) diff --git a/docs/en/tutorials/modular-crm/index.md b/docs/en/tutorials/modular-crm/index.md index 856fe7957f..5cd7baaecf 100644 --- a/docs/en/tutorials/modular-crm/index.md +++ b/docs/en/tutorials/modular-crm/index.md @@ -7,6 +7,13 @@ # Modular Monolith Application Development Tutorial +```json +//[doc-params] +{ + "UI": ["MVC", "NG"] +} +``` + ````json //[doc-nav] { @@ -17,9 +24,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 diff --git a/docs/en/tutorials/modular-crm/part-01.md b/docs/en/tutorials/modular-crm/part-01.md index 862f5ecc6b..d3b5d64380 100644 --- a/docs/en/tutorials/modular-crm/part-01.md +++ b/docs/en/tutorials/modular-crm/part-01.md @@ -7,6 +7,13 @@ # Creating the Initial Solution +```json +//[doc-params] +{ + "UI": ["MVC", "NG"] +} +``` + ````json //[doc-nav] { @@ -28,9 +35,12 @@ In this first part of this tutorial, we will create a new ABP solution with modu Follow the *[Get Started](../../get-started/single-layer-web-application.md)* guide to create a single layer web application with the following configuration: * **Solution name**: `ModularCrm` -* **UI Framework**: ASP.NET Core MVC / Razor Pages +* **UI Framework**: {{if UI == "MVC"}}ASP.NET Core MVC / Razor Pages{{else if UI == "NG"}}Angular{{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) diff --git a/docs/en/tutorials/modular-crm/part-02.md b/docs/en/tutorials/modular-crm/part-02.md index 9e715b6c30..28cadbec11 100644 --- a/docs/en/tutorials/modular-crm/part-02.md +++ b/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-nav] { @@ -57,10 +64,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. + +> TODO: Add Angular Catalog page screenshot. + +{{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. diff --git a/docs/en/tutorials/modular-crm/part-03.md b/docs/en/tutorials/modular-crm/part-03.md index 36b418c7fb..3d14b28cdf 100644 --- a/docs/en/tutorials/modular-crm/part-03.md +++ b/docs/en/tutorials/modular-crm/part-03.md @@ -7,6 +7,13 @@ # Building the Catalog Module +```json +//[doc-params] +{ + "UI": ["MVC", "NG"] +} +``` + ````json //[doc-nav] { @@ -404,6 +411,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 Open the `ModularCrm.Catalog` .NET solution in your IDE, and find the `Pages/Catalog/Index.cshtml` file under the `ModularCrm.Catalog.UI` project: @@ -471,6 +480,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 +

Products

+ + + + + @for (product of products; track product.id) { + + {%{{{ product.name }}}%} (stock: {%{{{ product.stockCount }}}%}) + + } + + + +``` + +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`. + +> TODO: Add Angular Catalog component screenshot. + +Finally, start the Angular app from the root `angular` folder and navigate to the *Catalog* page to see the products list: + +```bash +yarn start +``` + +> TODO: Add Angular Catalog page screenshot. + +{{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. \ No newline at end of file +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. From fe61e890b7665c51dbd335390571ffc9eb14165f Mon Sep 17 00:00:00 2001 From: Fahri Gedik <53567152+fahrigedik@users.noreply.github.com> Date: Wed, 25 Feb 2026 11:37:39 +0300 Subject: [PATCH 2/4] 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. --- docs/en/tutorials/modular-crm/part-04.md | 17 +++++ docs/en/tutorials/modular-crm/part-05.md | 90 +++++++++++++++++++++++- docs/en/tutorials/modular-crm/part-06.md | 29 +++++++- docs/en/tutorials/modular-crm/part-07.md | 21 +++++- docs/en/tutorials/modular-crm/part-08.md | 13 +++- 5 files changed, 162 insertions(+), 8 deletions(-) diff --git a/docs/en/tutorials/modular-crm/part-04.md b/docs/en/tutorials/modular-crm/part-04.md index bc2fa9fa4c..f3b25071a8 100644 --- a/docs/en/tutorials/modular-crm/part-04.md +++ b/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*. diff --git a/docs/en/tutorials/modular-crm/part-05.md b/docs/en/tutorials/modular-crm/part-05.md index fa3c2769a4..ae7ab3c996 100644 --- a/docs/en/tutorials/modular-crm/part-05.md +++ b/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 +

Orders

+ + + + + @for (order of orders; track order.id) { + + Customer: {%{{{ order.customerName }}}%}
+ Product: {%{{{ order.productId }}}%}
+ State: {%{{{ order.state }}}%} +
+ } +
+
+
+``` + +> 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. diff --git a/docs/en/tutorials/modular-crm/part-06.md b/docs/en/tutorials/modular-crm/part-06.md index c4ad6a5e6f..28f667f3b0 100644 --- a/docs/en/tutorials/modular-crm/part-06.md +++ b/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 +Product: {%{{{ order.productName }}}%}
+``` + +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. diff --git a/docs/en/tutorials/modular-crm/part-07.md b/docs/en/tutorials/modular-crm/part-07.md index 454c62d780..ffd34ac5d9 100644 --- a/docs/en/tutorials/modular-crm/part-07.md +++ b/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 diff --git a/docs/en/tutorials/modular-crm/part-08.md b/docs/en/tutorials/modular-crm/part-08.md index d4a78a6b53..476edb7f6d 100644 --- a/docs/en/tutorials/modular-crm/part-08.md +++ b/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 From 0ff2a750fc078b9eda2c2cc282beada462622047 Mon Sep 17 00:00:00 2001 From: Fahri Gedik <53567152+fahrigedik@users.noreply.github.com> Date: Wed, 25 Feb 2026 17:25:04 +0300 Subject: [PATCH 3/4] Add Angular symlink setup instructions in docs Update modular CRM tutorial docs to include Angular symlink setup and startup steps. In part-04, remove the TODO screenshot placeholder and add a note to run `yarn symlinks:setup` from the root `angular` folder after installing a new Angular module (and again when adding more local modules). In part-07, replace the TODO screenshot note with instructions to run `yarn symlinks:setup` and `yarn start` from the `angular` folder to launch the app for validation. --- docs/en/tutorials/modular-crm/part-04.md | 14 ++++++++++++-- docs/en/tutorials/modular-crm/part-07.md | 7 ++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/docs/en/tutorials/modular-crm/part-04.md b/docs/en/tutorials/modular-crm/part-04.md index f3b25071a8..26e312f05a 100644 --- a/docs/en/tutorials/modular-crm/part-04.md +++ b/docs/en/tutorials/modular-crm/part-04.md @@ -54,8 +54,6 @@ You can choose the type of UI you want to support in your module or select *No U {{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}} @@ -92,6 +90,18 @@ Select the `ModularCrm.Ordering` module and check the *Install this module* opti Select the `ModularCrm.Ordering` and `ModularCrm.Ordering.UI` packages from the left area and ensure the `ModularCrm` package from the middle area was checked as shown in the preceding figure. 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. diff --git a/docs/en/tutorials/modular-crm/part-07.md b/docs/en/tutorials/modular-crm/part-07.md index ffd34ac5d9..4cfd272a18 100644 --- a/docs/en/tutorials/modular-crm/part-07.md +++ b/docs/en/tutorials/modular-crm/part-07.md @@ -261,7 +261,12 @@ Here are sample screenshots from the Products and Orders pages: 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. +If the Angular app is not already running, start it from the root `angular` folder: + +```bash +yarn symlinks:setup +yarn start +``` {{end}} From 0c5257af0133015b3c7b543f1d153395b97e5978 Mon Sep 17 00:00:00 2001 From: Fahri Gedik <53567152+fahrigedik@users.noreply.github.com> Date: Wed, 25 Feb 2026 17:44:54 +0300 Subject: [PATCH 4/4] Add screenshots to modular CRM tutorial parts Replace TODO screenshot placeholders with actual image links in modular CRM tutorial parts 02, 03, 05 and 06. This adds screenshots for the Angular Catalog and Ordering pages/components to help verify the UI integration and product/order listings. --- docs/en/tutorials/modular-crm/part-02.md | 2 +- docs/en/tutorials/modular-crm/part-03.md | 4 ++-- docs/en/tutorials/modular-crm/part-05.md | 4 ++-- docs/en/tutorials/modular-crm/part-06.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/en/tutorials/modular-crm/part-02.md b/docs/en/tutorials/modular-crm/part-02.md index 28cadbec11..76c23d5e2e 100644 --- a/docs/en/tutorials/modular-crm/part-02.md +++ b/docs/en/tutorials/modular-crm/part-02.md @@ -82,7 +82,7 @@ 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. -> TODO: Add Angular Catalog page screenshot. +![abp-studio-solution-runner-initial-catalog-page](images/abp-studio-solution-runner-initial-catalog-page.png) {{end}} diff --git a/docs/en/tutorials/modular-crm/part-03.md b/docs/en/tutorials/modular-crm/part-03.md index 3d14b28cdf..43457a9cca 100644 --- a/docs/en/tutorials/modular-crm/part-03.md +++ b/docs/en/tutorials/modular-crm/part-03.md @@ -537,7 +537,7 @@ Now, open the `projects/catalog/src/lib/components/catalog.component.html` file 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`. -> TODO: Add Angular Catalog component screenshot. +![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: @@ -545,7 +545,7 @@ Finally, start the Angular app from the root `angular` folder and navigate to th yarn start ``` -> TODO: Add Angular Catalog page screenshot. +![abp-studio-browser-list-of-products](images/abp-studio-browser-list-of-products.png) {{end}} diff --git a/docs/en/tutorials/modular-crm/part-05.md b/docs/en/tutorials/modular-crm/part-05.md index ae7ab3c996..ffce44fda2 100644 --- a/docs/en/tutorials/modular-crm/part-05.md +++ b/docs/en/tutorials/modular-crm/part-05.md @@ -559,7 +559,7 @@ Then open `projects/ordering/src/lib/components/ordering.component.html` and upd ``` -> TODO: Add Angular Ordering component screenshot. +![visual-studio-ordering-contracts](images/visual-studio-ordering-contracts-v2.png) ### Editing the Menu Item @@ -575,7 +575,7 @@ 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. +![abp-studio-browser-orders-menu-item](images/abp-studio-browser-orders-menu-item-v2.png) {{end}} diff --git a/docs/en/tutorials/modular-crm/part-06.md b/docs/en/tutorials/modular-crm/part-06.md index 28f667f3b0..40647a9ec8 100644 --- a/docs/en/tutorials/modular-crm/part-06.md +++ b/docs/en/tutorials/modular-crm/part-06.md @@ -300,7 +300,7 @@ If your generated Angular proxy files are not up to date, run `abp generate-prox 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. +![abp-studio-browser-list-of-orders-with-product-name](images/abp-studio-browser-list-of-orders-with-product-name.png) {{end}}