From 43af3b7f72b46b8e89b833a93d2a37607f92621d Mon Sep 17 00:00:00 2001 From: Ilkay Ilknur Date: Fri, 2 Apr 2021 16:02:00 +0300 Subject: [PATCH 01/29] blazor UI extensions documentation --- .../Customizing-Application-Modules-Guide.md | 3 + .../UI/Blazor/Data-Table-Column-Extensions.md | 128 ++++++++++++++++++ docs/en/UI/Blazor/Entity-Action-Extensions.md | 111 +++++++++++++++ docs/en/UI/Blazor/Page-Toolbar-Extensions.md | 126 +++++++++++++++++ ...nsion-blazor-component-render-solution.png | Bin 0 -> 4854 bytes ...olum-extension-blazor-component-render.png | Bin 0 -> 19197 bytes docs/en/images/page-toolbar-button-blazor.png | Bin 0 -> 35352 bytes .../page-toolbar-custom-component-blazor.png | Bin 0 -> 9491 bytes .../table-column-extension-example-blazor.png | Bin 0 -> 19154 bytes .../user-action-blazor-extension-click-me.png | Bin 0 -> 21729 bytes ...ser-action-extension-on-blazor-project.png | Bin 0 -> 7964 bytes 11 files changed, 368 insertions(+) create mode 100644 docs/en/UI/Blazor/Data-Table-Column-Extensions.md create mode 100644 docs/en/UI/Blazor/Entity-Action-Extensions.md create mode 100644 docs/en/UI/Blazor/Page-Toolbar-Extensions.md create mode 100644 docs/en/images/data-table-colum-extension-blazor-component-render-solution.png create mode 100644 docs/en/images/data-table-colum-extension-blazor-component-render.png create mode 100644 docs/en/images/page-toolbar-button-blazor.png create mode 100644 docs/en/images/page-toolbar-custom-component-blazor.png create mode 100644 docs/en/images/table-column-extension-example-blazor.png create mode 100644 docs/en/images/user-action-blazor-extension-click-me.png create mode 100644 docs/en/images/user-action-extension-on-blazor-project.png diff --git a/docs/en/Customizing-Application-Modules-Guide.md b/docs/en/Customizing-Application-Modules-Guide.md index 56b94ae4fc..438c087e0c 100644 --- a/docs/en/Customizing-Application-Modules-Guide.md +++ b/docs/en/Customizing-Application-Modules-Guide.md @@ -75,6 +75,7 @@ There are some low level systems that you can control entity actions, table colu Entity action extension system allows you to add a new action to the action menu for an entity on the user interface; * [Entity Action Extensions for ASP.NET Core UI](UI/AspNetCore/Entity-Action-Extensions.md) +* [Entity Action Extensions for Blazor UI](UI/Blazor/Entity-Action-Extensions.md) * [Entity Action Extensions for Angular](UI/Angular/Entity-Action-Extensions.md) #### Data Table Column Extensions @@ -82,6 +83,7 @@ Entity action extension system allows you to add a new action to the action menu Data table column extension system allows you to add a new column in the data table on the user interface; * [Data Table Column Extensions for ASP.NET Core UI](UI/AspNetCore/Data-Table-Column-Extensions.md) +* [Data Table Column Extensions for Blazor UI](UI/Blazor/Data-Table-Column-Extensions.md) * [Data Table Column Extensions for Angular](UI/Angular/Data-Table-Column-Extensions.md) #### Page Toolbar @@ -89,6 +91,7 @@ Data table column extension system allows you to add a new column in the data ta Page toolbar system allows you to add components to the toolbar of a page; * [Page Toolbar Extensions for ASP.NET Core UI](UI/AspNetCore/Page-Toolbar-Extensions.md) +* [Page Toolbar Extensions for Blazor UI](UI/Blazor/Page-Toolbar-Extensions.md) * [Page Toolbar Extensions for Angular](UI/Angular/Page-Toolbar-Extensions.md) #### Others diff --git a/docs/en/UI/Blazor/Data-Table-Column-Extensions.md b/docs/en/UI/Blazor/Data-Table-Column-Extensions.md new file mode 100644 index 0000000000..e86dfd08c7 --- /dev/null +++ b/docs/en/UI/Blazor/Data-Table-Column-Extensions.md @@ -0,0 +1,128 @@ +# Data Table Column Extensions for Blazor UI + +## Introduction + +Data table column extension system allows you to add a **new table column** on the user interface. The example below adds a new column with the "Email Confirmed" title: + +![datatable-column-extension-](../../images/table-column-extension-example-blazor.png) + +You can use the standard column options to fine control the table column. + +> Note that this is a low level API to find control the table column. If you want to show an extension property on the table, see the [module entity extension](../../Module-Entity-Extensions.md) document. + +## How to Set Up + +### Create a C# File + +First, add a new C# file to your solution. We added inside the `/Pages/Identity/` folder of the `.Blazor` project: + +![user-action-extension-on-solution](../../images/user-action-extension-on-blazor-project.png) + +We will use the [component override system](Customization-Overriding-Components.md) in the Blazor. After creating a class inherits from the `UserManagement` component, we will override the `SetTableColumnsAsync` method and add the table column programmatically. + +Here, the content of the overridden `SetTableColumnsAsync` method. + +```csharp +protected override async ValueTask SetTableColumnsAsync() +{ + await base.SetTableColumnsAsync(); + var confirmedColumn = new TableColumn + { + Title = "Email Confirmed", + Data = nameof(IdentityUserDto.EmailConfirmed) + }; + TableColumns.Get().Add(confirmedColumn); +} +``` +Here, the entire content of the file. + +```csharp +using System.Threading.Tasks; +using Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Identity; +using Volo.Abp.Identity.Blazor.Pages.Identity; + +namespace MyCompanyName.MyProjectName.Blazor.Pages.Identity +{ + [ExposeServices(typeof(UserManagement))] + [Dependency(ReplaceServices = true)] + public class CustomizedUserManagement : UserManagement + { + protected override async ValueTask SetTableColumnsAsync() + { + await base.SetTableColumnsAsync(); + var confirmedColumn = new TableColumn + { + Title = "Email Confirmed", + Data = nameof(IdentityUserDto.EmailConfirmed) + }; + TableColumns.Get().Add(confirmedColumn); + } + } +} +``` + +## Customizing Data Table Columns + +This section explains how to customize data table columns using the properties in the `TableColumn` type. + +* `Title`: Title of the column. +* `Data`: Name of the field in the supplied model. +* `Component`: Type of the component that you want to render. See the "Rendering Custom Components In The Data Table Columns" section for details. +* `Actions`: Action lists for the column. You can render additional action columns by adding actions to this collection. +* `ValueConverter`: Simple converter function that is being called before rendering the content. +* `DisplayFormat`: You can specify a custom format for the column. + +## Rendering Custom Components In The Data Table Columns + +This section explains how to render custom blazor components in data table columns. In this example, we're going to display custom icons instead of text representations of the property. + +First of all, create a blazor component. We will name it `CustomTableColumn`. + +![data-table-colum-extension-blazor-component-render-solution](../../images/data-table-colum-extension-blazor-component-render-solution.png) + +Add an object parameter named `Data`. + +```csharp +public class CustomTableColumn +{ + [Parameter] + public object Data { get; set; } +} +``` + +Navigate to the razor file and paste the following code. + +```csharp +@using System +@using Volo.Abp.Identity + +@if (Data.As().EmailConfirmed) +{ + +} +else +{ + +} +``` + +Navigate back to the `CustomizedUserManagement` class, and use `Component` property to specify the custom blazor component. + +```csharp +protected override async ValueTask SetTableColumnsAsync() +{ + await base.SetTableColumnsAsync(); + var confirmedColumn = new TableColumn + { + Title = "Email Confirmed", + Component = typeof(CustomTableColumn) + }; + TableColumns.Get().Add(confirmedColumn); +} +``` + +Run the project and you will see the icons instead of text fields. + +![data-table-colum-extension-blazor-component-render](../../images/data-table-colum-extension-blazor-component-render.png) \ No newline at end of file diff --git a/docs/en/UI/Blazor/Entity-Action-Extensions.md b/docs/en/UI/Blazor/Entity-Action-Extensions.md new file mode 100644 index 0000000000..c0be73cb3c --- /dev/null +++ b/docs/en/UI/Blazor/Entity-Action-Extensions.md @@ -0,0 +1,111 @@ +# Entity Action Extensions for Blazor UI + +## Introduction + +Entity action extension system allows you to add a **new action** to the action menu for an entity. A **Click Me** action was added to the *User Management* page below: + +![user-action-extension-click-me](../../images/user-action-blazor-extension-click-me.png) + +You can take any action (open a modal, make an HTTP API call, redirect to another page... etc) by writing your custom code. You can access to the current entity in your code. + +## How to Set Up + +In this example, we will add a "Click Me!" action and execute a C# code for the user management page of the [Identity Module](../../Modules/Identity.md). + +### Create a C# File + +First, add a new C# file to your solution. We added inside the `/Pages/Identity/` folder of the `.Blazor` project: + +![user-action-extension-on-solution](../../images/user-action-extension-on-blazor-project.png) + +We will use the [component override system](Customization-Overriding-Components.md) in the Blazor. After creating a class inherits from the `UserManagement` component, we will override the `SetToolbarItemsAsync` method and add the entity action programmatically. + +Here, the content of the overridden `SetToolbarItemsAsync` method. + +```csharp +protected override async ValueTask SetToolbarItemsAsync() +{ + await base.SetToolbarItemsAsync(); + var clickMeAction = new EntityAction() + { + Text = "Click Me!", + Clicked = (data) => + { + //TODO: Write your custom code + + return Task.CompletedTask; + } + }; + + EntityActions.Get().Add(clickMeAction); +} +``` + +In the `Clicked` property, you can do anything you need. + +Here, the entire content of the file. +```csharp +using System.Threading.Tasks; +using Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Identity.Blazor.Pages.Identity; + +namespace MyCompanyName.MyProjectName.Blazor.Pages.Identity +{ + [ExposeServices(typeof(UserManagement))] + [Dependency(ReplaceServices = true)] + public class CustomizedUserManagement : UserManagement + { + protected override async ValueTask SetToolbarItemsAsync() + { + await base.SetToolbarItemsAsync(); + var clickMeAction = new EntityAction() + { + Text = "Click Me!", + Clicked = (data) => + { + //TODO: Write your custom code + + return Task.CompletedTask; + } + }; + EntityActions.Get().Add(clickMeAction); + } + } +} +``` + +## Customizing Entity Actions + +This section explains how to customize entity actions using the properties in the `EntityAction` type. + +Here, the list of the properties that you use in the `EntityAction`. +* `Text` : Entity action text. +* `Clicked` : Click event handler for the action. You can use the `data` parameter to access the selected item in the `DataGrid`. +* `Icon` : Icon for the action. +* `Color` : Color for the action. +* `Visible`: Visible function to determine the actions' visibility based on the data grid items individually. You can make the action invisible for some data grid items. You can also use the `data` parameter to access the selected item in the `DataGrid`. +* `Confirmation`: Confirmation message for the action. You can use the `data` parameter to access the selected item in the `DataGrid`. + +#### Example + +```csharp +var clickMeAction = new EntityAction() +{ + Text = "Click Me!", + Clicked = (data) => + { + //TODO: Write your custom code + + return Task.CompletedTask; + }, + Color = Blazorise.Color.Danger, + Icon = "fas fa-hand-point-right", + ConfirmationMessage = (data) => "Are you sure you want to click to the action?", + Visible = (data) => + { + //TODO: Write your custom visibility action + //var selectedUser = data.As(); + } +}; +``` diff --git a/docs/en/UI/Blazor/Page-Toolbar-Extensions.md b/docs/en/UI/Blazor/Page-Toolbar-Extensions.md new file mode 100644 index 0000000000..34e7c5b1b1 --- /dev/null +++ b/docs/en/UI/Blazor/Page-Toolbar-Extensions.md @@ -0,0 +1,126 @@ +# Page Toolbar Extensions for Blazor UI + +Page toolbar system allows you to add components to the toolbar of any page. The page toolbar is the area right to the header of a page. A button ("Import users from excel") was added to the user management page below: + +![page-toolbar-button](../../images/page-toolbar-button-blazor.png) + +You can add any type of view component item to the page toolbar or modify existing items. + +## How to Set Up + +In this example, we will add an "Import users from excel" button and execute a C# code for the user management page of the [Identity Module](../../Modules/Identity.md). + +### Create a C# File + +First, add a new C# file to your solution. We added inside the `/Pages/Identity/` folder of the `.Blazor` project: + +![user-action-extension-on-solution](../../images/user-action-extension-on-blazor-project.png) + +We will use the [component override system](Customization-Overriding-Components.md) in the Blazor. After creating a class inherits from the `UserManagement` component, we will override the `SetToolbarItemsAsync` method and add the toolbar item programmatically. + +Here, the content of the overridden `SetToolbarItemsAsync` method. + +```csharp +protected override async ValueTask SetToolbarItemsAsync() +{ + await base.SetToolbarItemsAsync(); + Toolbar.AddButton("Import users from excel", () => + { + //TODO: Write your custom code + return Task.CompletedTask; + }, "file-import", Blazorise.Color.Secondary); +} +``` +> In order to use the `AddButton` extension method, you need to add a using statement for the `Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars` namespace. + +Here, the entire content of the file. + +```csharp +using System.Threading.Tasks; +using Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Identity.Blazor.Pages.Identity; + +namespace MyCompanyName.MyProjectName.Blazor.Pages.Identity +{ + [ExposeServices(typeof(UserManagement))] + [Dependency(ReplaceServices = true)] + public class CustomizedUserManagement : UserManagement + { + protected override async ValueTask SetToolbarItemsAsync() + { + await base.SetToolbarItemsAsync(); + Toolbar.AddButton("Import users from excel", () => + { + //TODO: Write your custom code + return Task.CompletedTask; + }, "file-import", Blazorise.Color.Secondary); + } + } +} +``` + +When you run the application, you will see the button added next to the current button list. There are some other parameters of the `AddButton` method (for example, use `Order` to set the order of the button component relative to the other components). + +## Advanced Use Cases + +While you typically want to add a button action to the page toolbar, it is possible to add any type of blazor component. + +### Add A Blazor Component to a Page Toolbar + +First, create a new blazor component in your project: + +![page-toolbar-custom-component-blazor](../../images/page-toolbar-custom-component-blazor.png) + +For this example, we've created a `MyToolbarComponent` component under the `/Pages/Identity/` folder. + +`MyToolbarComponent.razor` content: + +````csharp + +```` +We will leave the `MyToolbarComponent.razor.cs` file empty. + +Then you can add the `MyToolbarComponent` to the user management page toolbar: + +````csharp +protected override async ValueTask SetToolbarItemsAsync() +{ + await base.SetToolbarItemsAsync(); + Toolbar.AddComponent(); +} +```` + +* If your component accepts parameters, you can pass them as key/value pairs using the `arguments` parameter. + +#### Permissions + +If your button/component should be available based on a [permission/policy](../../Authorization.md), you can pass the permission/policy name as the `RequiredPolicyName` parameter to the `AddButton` and `AddComponent` methods. + +### Add a Page Toolbar Contributor + +If you perform advanced custom logic while adding an item to a page toolbar, you can create a class that implements the `IPageToolbarContributor` interface or inherits from the `PageToolbarContributor` class: + +````csharp +public class MyToolbarContributor : PageToolbarContributor +{ + public override Task ContributeAsync(PageToolbarContributionContext context) + { + context.Items.Insert(0, new PageToolbarItem(typeof(MyToolbarComponent))); + return Task.CompletedTask; + } +} +```` + +* You can use `context.ServiceProvider` to resolve dependencies if you need. + +Then add your class to the `Contributors` list: + +````csharp +protected override async ValueTask SetToolbarItemsAsync() +{ + await base.SetToolbarItemsAsync(); + Toolbar.Contributors.Add(new PageContributor()); +} +```` + diff --git a/docs/en/images/data-table-colum-extension-blazor-component-render-solution.png b/docs/en/images/data-table-colum-extension-blazor-component-render-solution.png new file mode 100644 index 0000000000000000000000000000000000000000..77612b5d34c3bacab7208ed139503123c6facf73 GIT binary patch literal 4854 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 HVvqPAk||fF literal 0 HcmV?d00001 diff --git a/docs/en/images/data-table-colum-extension-blazor-component-render.png b/docs/en/images/data-table-colum-extension-blazor-component-render.png new file mode 100644 index 0000000000000000000000000000000000000000..9d018e2ab963e0882babc6b740dc0521b40e402a GIT binary patch literal 19197 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 z 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 W3r@G*L0!0&F}`7bz5LqUKmRW)M)<-2 literal 0 HcmV?d00001 diff --git a/docs/en/images/page-toolbar-button-blazor.png b/docs/en/images/page-toolbar-button-blazor.png new file mode 100644 index 0000000000000000000000000000000000000000..fb907e797a0cc201c654170e32daf689c83941d8 GIT binary patch literal 35352 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

K$vvH^4Z5YNdGxP$KqIW;QZ<3+*y`SONi7t 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 z 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 VA(ciA`bQ=hd1)1?DhZRI{{o8MSzrJF literal 0 HcmV?d00001 diff --git a/docs/en/images/table-column-extension-example-blazor.png b/docs/en/images/table-column-extension-example-blazor.png new file mode 100644 index 0000000000000000000000000000000000000000..3079fa278c9bb58d911643375729d86cd41d3ccb GIT binary patch literal 19154 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 literal 0 HcmV?d00001 diff --git a/docs/en/images/user-action-blazor-extension-click-me.png b/docs/en/images/user-action-blazor-extension-click-me.png new file mode 100644 index 0000000000000000000000000000000000000000..fb1ea801824f922774bd499abd2d83493a0db6d9 GIT binary patch literal 21729 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 brt>TKXOkjvH#>Mi=>TY}>#J3$*oOZfSwDE{ literal 0 HcmV?d00001 From fccc3fffab45bd88fc8baa051d2fd8d89e476d83 Mon Sep 17 00:00:00 2001 From: Ilkay Ilknur Date: Mon, 5 Apr 2021 12:25:02 +0300 Subject: [PATCH 02/29] introduction headers have been removed. --- docs/en/UI/Blazor/Data-Table-Column-Extensions.md | 2 -- docs/en/UI/Blazor/Entity-Action-Extensions.md | 2 -- 2 files changed, 4 deletions(-) diff --git a/docs/en/UI/Blazor/Data-Table-Column-Extensions.md b/docs/en/UI/Blazor/Data-Table-Column-Extensions.md index e86dfd08c7..6fad41af81 100644 --- a/docs/en/UI/Blazor/Data-Table-Column-Extensions.md +++ b/docs/en/UI/Blazor/Data-Table-Column-Extensions.md @@ -1,7 +1,5 @@ # Data Table Column Extensions for Blazor UI -## Introduction - Data table column extension system allows you to add a **new table column** on the user interface. The example below adds a new column with the "Email Confirmed" title: ![datatable-column-extension-](../../images/table-column-extension-example-blazor.png) diff --git a/docs/en/UI/Blazor/Entity-Action-Extensions.md b/docs/en/UI/Blazor/Entity-Action-Extensions.md index c0be73cb3c..57666e5362 100644 --- a/docs/en/UI/Blazor/Entity-Action-Extensions.md +++ b/docs/en/UI/Blazor/Entity-Action-Extensions.md @@ -1,7 +1,5 @@ # Entity Action Extensions for Blazor UI -## Introduction - Entity action extension system allows you to add a **new action** to the action menu for an entity. A **Click Me** action was added to the *User Management* page below: ![user-action-extension-click-me](../../images/user-action-blazor-extension-click-me.png) From 0c9871465012372fdf19c297324c95e4d764bc83 Mon Sep 17 00:00:00 2001 From: EngincanV Date: Mon, 5 Apr 2021 12:59:53 +0300 Subject: [PATCH 03/29] Update Getting-Started-Create-Solution.md --- docs/en/Getting-Started-Create-Solution.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/Getting-Started-Create-Solution.md b/docs/en/Getting-Started-Create-Solution.md index f2f41e29ce..7caa26159a 100644 --- a/docs/en/Getting-Started-Create-Solution.md +++ b/docs/en/Getting-Started-Create-Solution.md @@ -15,7 +15,7 @@ We will use the ABP CLI to create a new ABP project. -> Alternatively, you can **create and download** projects from [ABP Framework website](https://abp.io/get-started) by easily selecting the all the options from the page. +> Alternatively, you can **create and download** projects from the [ABP Framework website](https://abp.io/get-started) by easily selecting all options from the page. Use the `new` command of the ABP CLI to create a new project: @@ -49,7 +49,7 @@ The solution has a layered structure (based on the [Domain Driven Design](Domain #### MongoDB Transactions -The [startup template](Startup-templates/Index.md) **disables** transactions in the `.MongoDB` project by default. If your MongoDB server supports transactions, you can enable the it in the *YourProjectMongoDbModule* class's `ConfigureServices` method: +The [startup template](Startup-templates/Index.md) **disables** transactions in the `.MongoDB` project by default. If your MongoDB server supports transactions, you can enable it in the *YourProjectMongoDbModule* class's `ConfigureServices` method: ```csharp Configure(options => From 8a8453ca24cd88e4a7d0fe1f1224afd73faa6866 Mon Sep 17 00:00:00 2001 From: Ilkay Ilknur Date: Mon, 5 Apr 2021 16:03:20 +0300 Subject: [PATCH 04/29] page header documentation has been added. --- docs/en/UI/Blazor/Page-Header.md | 89 +++++++++++++++++- docs/en/images/page-header-toolbar-blazor.png | Bin 0 -> 22962 bytes 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 docs/en/images/page-header-toolbar-blazor.png diff --git a/docs/en/UI/Blazor/Page-Header.md b/docs/en/UI/Blazor/Page-Header.md index 2c7921bbd2..59748b717a 100644 --- a/docs/en/UI/Blazor/Page-Header.md +++ b/docs/en/UI/Blazor/Page-Header.md @@ -1,3 +1,90 @@ # Blazor UI: Page Header -TODO \ No newline at end of file +You can use the`PageHeader` component to set the page title, the breadcrumb items and the toolbar items for a page. Before using the `PageHeader` component, you need to add a using statement for the `Volo.Abp.AspNetCore.Components.Web.Theming.Layout` namespace. + +Once you add the `PageHeader` component to your page, you can control the related values using the parameters. + +## Page Title + + You can use the `Title` parameter to control the page header. + +```csharp + + +``` + +## Breadcrumb + +> **The [Basic Theme](Basic-Theme.md) currently doesn't implement the breadcrumbs.** + +Breadcrumbs can be added using the `BreadcrumbItems` property. + +**Example: Add Language Management to the breadcrumb items.** + +Create a collection of `Volo.Abp.BlazoriseUI.BreadcrumbItem` objects and set the collection to the `BreadcrumbItems` parameter. + +```csharp +public partial class Index +{ + protected List BreadcrumbItems { get; } = new(); + + protected override void OnInitialized() + { + BreadcrumbItems.Add(new BreadcrumbItem("Language Management")); + } +} +``` + +Navigate back to the razor page. + +```csharp + +``` + +The theme then renders the breadcrumb. An example render result can be: + +![breadcrumbs-example](../../images/breadcrumbs-example.png) + +* The Home icon is rendered by default. Set `BreadcrumbShowHome` to `false` to hide it. +* Breadcrumb items will be activated based on current navigation. Set `BreadcrumbShowCurrent` to `false` to disable it. + +You can add as many items as you need. `BreadcrumbItem` constructor gets three parameters: + +* `text`: The text to show for the breadcrumb item. +* `url` (optional): A URL to navigate to, if the user clicks to the breadcrumb item. +* `icon` (optional): An icon class (like `fas fa-user-tie` for Font-Awesome) to show with the `text`. + +## Page Toolbar + +Page toolbar can be set using the `Toolbar` property. + +**Example: Add a "New Item" toolbar item to the page toolbar.** + +Create a `PageToolbar` object and define toolbar items using the `AddButton` extension method. + +```csharp +public partial class Index +{ + protected PageToolbar Toolbar { get; } = new(); + + protected override void OnInitialized() + { + Toolbar.AddButton("New Item", () => + { + //Write your click action here + return Task.CompletedTask; + }, icon:IconName.Add); + } +} +``` + +Navigate back to the razor page and set the `Toolbar` parameter. + +```csharp + +``` + +An example render result can be: + +![breadcrumbs-example](../../images/page-header-toolbar-blazor.png) + diff --git a/docs/en/images/page-header-toolbar-blazor.png b/docs/en/images/page-header-toolbar-blazor.png new file mode 100644 index 0000000000000000000000000000000000000000..a4d045489374545fe634c15812b2959a5e81af45 GIT binary patch literal 22962 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 Date: Tue, 6 Apr 2021 09:19:15 +0300 Subject: [PATCH 05/29] Move MobileDevelopment section into CreateSolution part --- docs/en/Getting-Started-Create-Solution.md | 6 ++++++ docs/en/Getting-Started-Running-Solution.md | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/en/Getting-Started-Create-Solution.md b/docs/en/Getting-Started-Create-Solution.md index 7caa26159a..8c62246010 100644 --- a/docs/en/Getting-Started-Create-Solution.md +++ b/docs/en/Getting-Started-Create-Solution.md @@ -41,6 +41,12 @@ abp new Acme.BookStore{{if UI == "NG"}} -u angular{{else if UI == "Blazor"}} -u > [ABP CLI document](./CLI.md) covers all of the available commands and options. +## Mobile Development + +If you want to include a [React Native](https://reactnative.dev/) project in your solution, add `-m react-native` (or `--mobile react-native`) argument to project creation command. This is a basic React Native startup template to develop mobile applications integrated to your ABP based backends. + +See the [Getting Started with the React Native](Getting-Started-React-Native.md) document to learn how to configure and run the React Native application. + ### The Solution Structure The solution has a layered structure (based on the [Domain Driven Design](Domain-Driven-Design.md)) and contains unit & integration test projects. See the [application template document](Startup-Templates/Application.md) to understand the solution structure in details. diff --git a/docs/en/Getting-Started-Running-Solution.md b/docs/en/Getting-Started-Running-Solution.md index e871ec882f..3f508589a3 100644 --- a/docs/en/Getting-Started-Running-Solution.md +++ b/docs/en/Getting-Started-Running-Solution.md @@ -193,12 +193,6 @@ It may take a longer time for the first build. Once it finishes, it opens the An Enter **admin** as the username and **1q2w3E*** as the password to login to the application. The application is up and running. You can start developing your application based on this startup template. -## Mobile Development - -If you want to include a [React Native](https://reactnative.dev/) project in your solution, add `-m react-native` (or `--mobile react-native`) argument to project creation command. This is a basic React Native startup template to develop mobile applications integrated to your ABP based backends. - -See the [Getting Started with the React Native](Getting-Started-React-Native.md) document to learn how to configure and run the React Native application. - ## See Also * [Web Application Development Tutorial](Tutorials/Part-1.md) From a6983b5510887f12ac06cab114ab1b2b414ee06d Mon Sep 17 00:00:00 2001 From: Ilkay Ilknur Date: Tue, 6 Apr 2021 15:48:03 +0300 Subject: [PATCH 06/29] `Sortable` and `DisplayFormatProvider` properties have been added to the `TableColumn` --- .../Extensibility/TableColumns/TableColumn.cs | 3 ++ .../Components/AbpExtensibleDataGrid.razor | 41 ++++++++++++------- .../Components/AbpExtensibleDataGrid.razor.cs | 12 ++++++ 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumn.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumn.cs index 0676c14399..2121b8a128 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumn.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumn.cs @@ -1,6 +1,7 @@ using JetBrains.Annotations; using System; using System.Collections.Generic; +using System.Globalization; using Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions; namespace Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns @@ -11,11 +12,13 @@ namespace Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns public string Data { get; set; } [CanBeNull] public string DisplayFormat { get; set; } + public IFormatProvider DisplayFormatProvider { get; set; } = CultureInfo.CurrentCulture; [CanBeNull] public Type Component { get; set; } public List Actions { get; set; } [CanBeNull] public Func ValueConverter { get; set; } + public bool Sortable { get; set; } public TableColumn() { diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor index f060450ffd..e0b867492e 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor @@ -25,11 +25,11 @@ if (action.ConfirmationMessage != null) { } @@ -37,9 +37,9 @@ { } @@ -62,7 +62,26 @@ { if (!ExtensionPropertiesRegex.IsMatch(column.Data)) { - + @if (column.ValueConverter == null) + { + + } + else + { + + + @(GetConvertedFieldValue(context, column)) + + + } } else { @@ -87,14 +106,7 @@ { if (column.ValueConverter != null) { - if (column.DisplayFormat == null) - { - @(column.ValueConverter(propertyValue)) - } - else - { - @(string.Format(column.DisplayFormat, column.ValueConverter(propertyValue))) - } + @(GetConvertedFieldValue(context, column)) } else { @@ -104,10 +116,9 @@ } else { - @(string.Format(column.DisplayFormat, propertyValue)) + @(string.Format(column.DisplayFormatProvider, column.DisplayFormat, propertyValue)) } } - } } diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor.cs index 72a58f94a5..71ff4b61ec 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor.cs @@ -46,5 +46,17 @@ namespace Volo.Abp.BlazoriseUI.Components builder.CloseComponent(); }; } + + protected virtual string GetConvertedFieldValue(TItem item, TableColumn columnDefinition) + { + var convertedValue = columnDefinition.ValueConverter.Invoke(item); + if (!columnDefinition.DisplayFormat.IsNullOrEmpty()) + { + return string.Format(columnDefinition.DisplayFormatProvider, columnDefinition.DisplayFormat, + convertedValue); + } + + return convertedValue; + } } } \ No newline at end of file From 8a67c5408a5a248e6ad6e42c3540bf6a7f437906 Mon Sep 17 00:00:00 2001 From: Ilkay Ilknur Date: Tue, 6 Apr 2021 16:14:24 +0300 Subject: [PATCH 07/29] new member definitions have been added. --- docs/en/UI/Blazor/Data-Table-Column-Extensions.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/en/UI/Blazor/Data-Table-Column-Extensions.md b/docs/en/UI/Blazor/Data-Table-Column-Extensions.md index 6fad41af81..ebb2f27cbf 100644 --- a/docs/en/UI/Blazor/Data-Table-Column-Extensions.md +++ b/docs/en/UI/Blazor/Data-Table-Column-Extensions.md @@ -70,7 +70,9 @@ This section explains how to customize data table columns using the properties i * `Component`: Type of the component that you want to render. See the "Rendering Custom Components In The Data Table Columns" section for details. * `Actions`: Action lists for the column. You can render additional action columns by adding actions to this collection. * `ValueConverter`: Simple converter function that is being called before rendering the content. +* `Sortable`: A boolean field indicating whether the column is sortable or not. * `DisplayFormat`: You can specify a custom format for the column. +* `DisplayFormatProvider` : You can provide a custom `IFormatProvider` for the column. Default value is `CultureInfo.CurrentCulture`. ## Rendering Custom Components In The Data Table Columns From a6cf39db1c54e2cf60831b12e1a65daddc5c68de Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 7 Apr 2021 14:58:17 +0800 Subject: [PATCH 08/29] Remove duplicate depend --- .../Abp/SettingManagement/SettingManagementApplicationModule.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo/Abp/SettingManagement/SettingManagementApplicationModule.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo/Abp/SettingManagement/SettingManagementApplicationModule.cs index 9ed44d59c0..9b7b809b47 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo/Abp/SettingManagement/SettingManagementApplicationModule.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo/Abp/SettingManagement/SettingManagementApplicationModule.cs @@ -6,7 +6,6 @@ namespace Volo.Abp.SettingManagement [DependsOn( typeof(AbpSettingManagementDomainModule), typeof(AbpSettingManagementApplicationContractsModule), - typeof(AbpSettingManagementDomainModule), typeof(AbpEmailingModule) )] public class AbpSettingManagementApplicationModule : AbpModule From 38dd3f3c65ebb2b82812f36452179cd9366f3e54 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Wed, 7 Apr 2021 10:35:50 +0300 Subject: [PATCH 09/29] Docs: Use default value when value from query is wrong resolves https://github.com/abpframework/abp/issues/8455 --- .../Pages/Documents/Project/Index.cshtml.cs | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs index 94cee58d1a..6a23afba29 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs @@ -568,10 +568,24 @@ namespace Volo.Docs.Pages.Documents.Project UserPreferences.Remove(key + "_Value"); } + var values = DocumentPreferences?.Parameters?.FirstOrDefault(p => p.Name == key)?.Values; + + if (values == null) + { + continue; + } + + if (!values.Any(v => v.Key == value)) + { + var defaultValue = values.FirstOrDefault(); + UserPreferences.Add(key, defaultValue.Key); + UserPreferences.Add(key + "_Value", defaultValue.Value); + + continue; + } + UserPreferences.Add(key, value); - UserPreferences.Add(key + "_Value", - DocumentPreferences?.Parameters?.FirstOrDefault(p => p.Name == key)?.Values - .FirstOrDefault(v => v.Key == value).Value); + UserPreferences.Add(key + "_Value", values.FirstOrDefault(v => v.Key == value).Value); } if (DocumentPreferences?.Parameters == null) From a4f8025d3c4a4dfdc0cbb31d7d15df7b3c605a9f Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Wed, 7 Apr 2021 11:01:57 +0300 Subject: [PATCH 10/29] Cli: blazor.server project should convert efcore to mongodb --- ...eSwitchEntityFrameworkCoreToMongoDbStep.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateSwitchEntityFrameworkCoreToMongoDbStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateSwitchEntityFrameworkCoreToMongoDbStep.cs index b0a778c323..290da79157 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateSwitchEntityFrameworkCoreToMongoDbStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateSwitchEntityFrameworkCoreToMongoDbStep.cs @@ -76,6 +76,29 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App "/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/appsettings.json" ); + //MyCompanyName.MyProjectName.Blazor.Server + + ChangeProjectReference( + context, + "/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj", + "EntityFrameworkCore.DbMigrations", + "MongoDB" + ); + + ChangeNamespaceAndKeyword( + context, + "/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs", + "MyCompanyName.MyProjectName.EntityFrameworkCore", + "MyCompanyName.MyProjectName.MongoDB", + "MyProjectNameEntityFrameworkCoreDbMigrationsModule", + "MyProjectNameMongoDbModule" + ); + + ChangeConnectionStringToMongoDb( + context, + "/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/appsettings.json" + ); + //MyCompanyName.MyProjectName.HttpApi.HostWithIds ChangeProjectReference( From 5fd63860990512559b22fa23de3ef4f383198f53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Apr 2021 11:24:46 +0300 Subject: [PATCH 11/29] Added blazor server & mongodb options to the todoapp article. --- docs/en/Tutorials/Todo/Index.md | 66 ++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 14 deletions(-) diff --git a/docs/en/Tutorials/Todo/Index.md b/docs/en/Tutorials/Todo/Index.md index c906dce0a7..1363933e14 100644 --- a/docs/en/Tutorials/Todo/Index.md +++ b/docs/en/Tutorials/Todo/Index.md @@ -3,7 +3,8 @@ ````json //[doc-params] { - "UI": ["MVC", "Blazor"] + "UI": ["MVC", "Blazor", "BlazorServer"], + "DB": ["EF", "Mongo"] } ```` @@ -15,39 +16,45 @@ You can find source code of the completed application [here](https://github.com/ ## Pre-Requirements -### IDE +* An IDE (e.g. [Visual Studio](https://visualstudio.microsoft.com/vs/)) that supports [.NET 5.0+](https://dotnet.microsoft.com/download/dotnet) development. -You will need to an IDE (e.g. [Visual Studio](https://visualstudio.microsoft.com/vs/)) that supports [.NET 5.0+](https://dotnet.microsoft.com/download/dotnet) development. +{{if DB=="Mongo"}} -### ABP CLI +* [MongoDB Server 4.0+](https://docs.mongodb.com/manual/administration/install-community/) -We will use the ABP CLI to create new solutions with the ABP Framework. You can run the following command in a command-line terminal to install it: +{{end}} + +## Creating a New Solution + +We will use the [ABP CLI](../../CLI.md) to create new solutions with the ABP Framework. You can run the following command in a command-line terminal to install it: ````bash dotnet tool install -g Volo.Abp.Cli ```` -## Creating a New Solution - -Create an empty folder, open a command-line terminal and execute the following command in the terminal: +Then create an empty folder, open a command-line terminal and execute the following command in the terminal: ````bash -abp new TodoApp{{if UI=="Blazor"}} -u blazor{{end}} +abp new TodoApp{{if UI=="Blazor"}} -u blazor{{else if UI=="BlazorServer"}} -u blazor-server{{end}}{{if DB=="Mongo"}} -d mongodb{{end}} ```` -This will create a new solution, named *TodoApp*. Open the solution in your favorite IDE. +This will create a new solution, named *TodoApp*. Once the solution is ready, open it in your favorite IDE. ### Create the Database If you are using Visual Studio, right click to the `TodoApp.DbMigrator` project, select *Set as StartUp Project*, then hit *Ctrl+F5* to run it without debugging. It will create the initial database and seed the initial data. +{{if DB=="EF"}} + > Some IDEs (e.g. Rider) may have problems for the first run since *DbMigrator* adds the initial migration and re-compiles the project. In this case, open a command-line terminal in the folder of the `.DbMigrator` project and execute the `dotnet run` command. +{{end}} + ### Run the Application -{{if UI=="MVC"}} +{{if UI=="MVC" || UI=="BlazorServer"}} -It is good to run the application before starting the development. Ensure the `TodoApp.Web` project is the startup project, then run the application (Ctrl+F5 in Visual Studio) to see the initial UI: +It is good to run the application before starting the development. Ensure the {{if UI=="BlazorServer"}}`TodoApp.Blazor`{{else}}`TodoApp.Web`{{end}} project is the startup project, then run the application (Ctrl+F5 in Visual Studio) to see the initial UI: {{else if UI=="Blazor"}} @@ -91,6 +98,8 @@ namespace TodoApp ## Database Integration +{{if DB=="EF"}} + Next step is to setup the [Entity Framework Core](../../Entity-Framework-Core.md) configuration. ### Mapping Configuration @@ -139,6 +148,27 @@ dotnet ef database update > If you are using Visual Studio, you may want to use `Add-Migration Added_TodoItem` and `Update-Database` commands in the *Package Manager Console (PMC)*. In this case, ensure that {{if UI=="MVC"}}`TodoApp.Web`{{else if UI=="Blazor"}}`TodoApp.HttpApi.Host`{{end}} is the startup project and `TodoApp.EntityFrameworkCore.DbMigrations` is the *Default Project* in PMC. +{{else if DB=="Mongo"}} + +Next step is to setup the [MongoDB](../../MongoDB.md) configuration. Open the `TodoAppMongoDbContext` class in the `MongoDb` folder of the *TodoApp.MongoDB* project and make the following changes; + +1. Add a new property to the class: + +````csharp +public IMongoCollection TodoItems => Collection(); +```` + +2. Add the following code inside the `CreateModel` method: + +````csharp +modelBuilder.Entity(b => +{ + b.CollectionName = "TodoItems"; +}); +```` + +{{end}} + Now, we can use ABP repositories to save and retrieve todo items, as we'll do in the next section. ## Application Layer @@ -445,7 +475,7 @@ If you open the [Swagger UI](https://swagger.io/tools/swagger-ui/) by entering t ![todo-api](todo-api.png) -{{else if UI=="Blazor"}} +{{else if UI=="Blazor" || UI=="BlazorServer"}} ### Index.razor.cs @@ -490,8 +520,12 @@ namespace TodoApp.Blazor.Pages This class uses the `ITodoAppService` to perform operations for the todo items. It manipulates the `TodoItems` list after create and delete operations. In this way, we don't need to refresh the whole todo list from the server. +{{if UI=="Blazor"}} + See the *Dynamic C# Proxies & Auto API Controllers* section below to learn how we could inject and use the application service interface from the Blazor application which is running on the browser! But now, let's continue and complete the application. +{{end # Blazor}} + ### Index.razor Open the `Index.razor` file in the `Pages` folder of the *TodoApp.Blazor* project and replace the content with the following code block: @@ -570,6 +604,8 @@ This is a simple styling for the todo page. We believe that you can do much bett Now, you can run the application again to see the result. +{{if UI=="Blazor"}} + ### Dynamic C# Proxies & Auto API Controllers In the `Index.razor.cs` file, we've injected (with the `[Inject]` attribute) and used the `ITodoAppService` just like using a local service. Remember that the Blazor application is running on the browser while the implementation of this application service is running on the server. @@ -582,7 +618,9 @@ If you run the `TodoApp.HttpApi.Host` application, you can see the Todo API: ![todo-api](todo-api.png) -{{end}} +{{end # Blazor}} + +{{end # Blazor || BlazorServer}} ## Conclusion From 929c4aae86a2f441ad721f9150477378f909a73b Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Wed, 7 Apr 2021 14:01:34 +0300 Subject: [PATCH 12/29] add warning about dotnet run in proxy generation doc --- docs/en/UI/Angular/Service-Proxies.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/en/UI/Angular/Service-Proxies.md b/docs/en/UI/Angular/Service-Proxies.md index 3a10f1b6e8..18e5a3a0cc 100644 --- a/docs/en/UI/Angular/Service-Proxies.md +++ b/docs/en/UI/Angular/Service-Proxies.md @@ -10,6 +10,8 @@ To avoid manual effort, we might use a tool like [NSWAG](https://github.com/Rico ABP introduces an endpoint that exposes server-side method contracts. When the `generate-proxy` command is run, ABP CLI makes an HTTP request to this endpoint and generates better-aligned client proxies in TypeScript. It organizes folders according to namespaces, adds barrel exports, and reflects method signatures in Angular services. +> Before you start, please make sure you start the backend application with `dotnet run`. There is a [known limitation about Visual Studio](#known-limitations), so please do not run the project using its built-in web server. + Run the following command in the **root folder** of the angular application: ```bash From d948057cda0e08db3f008ab3edf5d6fa151243bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Apr 2021 14:49:39 +0300 Subject: [PATCH 13/29] Add Angular option to the todoapp tutorial. --- docs/en/Tutorials/Todo/Index.md | 193 +++++++++++++++++++++++++++++++- 1 file changed, 188 insertions(+), 5 deletions(-) diff --git a/docs/en/Tutorials/Todo/Index.md b/docs/en/Tutorials/Todo/Index.md index 1363933e14..39ceb36351 100644 --- a/docs/en/Tutorials/Todo/Index.md +++ b/docs/en/Tutorials/Todo/Index.md @@ -3,7 +3,7 @@ ````json //[doc-params] { - "UI": ["MVC", "Blazor", "BlazorServer"], + "UI": ["MVC", "Blazor", "BlazorServer", "NG"], "DB": ["EF", "Mongo"] } ```` @@ -24,6 +24,12 @@ You can find source code of the completed application [here](https://github.com/ {{end}} +{{if UI=="NG"}} + +* [Node v14.x](https://nodejs.org/) + +{{end}} + ## Creating a New Solution We will use the [ABP CLI](../../CLI.md) to create new solutions with the ABP Framework. You can run the following command in a command-line terminal to install it: @@ -35,11 +41,19 @@ dotnet tool install -g Volo.Abp.Cli Then create an empty folder, open a command-line terminal and execute the following command in the terminal: ````bash -abp new TodoApp{{if UI=="Blazor"}} -u blazor{{else if UI=="BlazorServer"}} -u blazor-server{{end}}{{if DB=="Mongo"}} -d mongodb{{end}} +abp new TodoApp{{if UI=="Blazor"}} -u blazor{{else if UI=="BlazorServer"}} -u blazor-server{{else if UI=="NG"}} -u angular{{end}}{{if DB=="Mongo"}} -d mongodb{{end}} ```` +{{if UI=="NG"}} + +This will create a new solution, named *TodoApp* with `angular` and `aspnet-core` folders. Once the solution is ready, open the ASP.NET Core solution in your favorite IDE. + +{{else}} + This will create a new solution, named *TodoApp*. Once the solution is ready, open it in your favorite IDE. +{{end}} + ### Create the Database If you are using Visual Studio, right click to the `TodoApp.DbMigrator` project, select *Set as StartUp Project*, then hit *Ctrl+F5* to run it without debugging. It will create the initial database and seed the initial data. @@ -69,6 +83,33 @@ Ensure the `TodoApp.HttpApi.Host` project is the startup project, then run the a You can explore and test your HTTP API with this UI. Now, we can set the `TodoApp.Blazor` as the startup project and run it to open the actual Blazor application UI: +{{else if UI=="NG"}} + +It is good to run the application before starting the development. The solution has two main applications; + +* `TodoApp.HttpApi.Host` (in the .NET solution) host the server-side HTTP API. +* `angular` folder contains the Angular application. + +Ensure the `TodoApp.HttpApi.Host` project is the startup project, then run the application (Ctrl+F5 in Visual Studio) to see the server-side HTTP API on the [Swagger UI](https://swagger.io/tools/swagger-ui/): + +![todo-swagger-ui-initial](todo-swagger-ui-initial.png) + +You can explore and test your HTTP API with this UI. If that works, we can run the Angular client application. + +First, run the following command to restore the NPM packages; + +````bash +npm install +```` + +It will take some time to install all the packages. Then you can run the application using the following command: + +````bash +npm start +```` + +This command takes time, but eventually runs and opens the application in your default browser: + {{end}} ![todo-ui-initial](todo-ui-initial.png) @@ -146,7 +187,7 @@ You can apply changes to the database using the following command, in the same c dotnet ef database update ```` -> If you are using Visual Studio, you may want to use `Add-Migration Added_TodoItem` and `Update-Database` commands in the *Package Manager Console (PMC)*. In this case, ensure that {{if UI=="MVC"}}`TodoApp.Web`{{else if UI=="Blazor"}}`TodoApp.HttpApi.Host`{{end}} is the startup project and `TodoApp.EntityFrameworkCore.DbMigrations` is the *Default Project* in PMC. +> If you are using Visual Studio, you may want to use `Add-Migration Added_TodoItem` and `Update-Database` commands in the *Package Manager Console (PMC)*. In this case, ensure that {{if UI=="MVC"}}`TodoApp.Web`{{else if UI=="BlazorServer"}}`TodoApp.Blazor`{{else if UI=="Blazor" || UI=="NG"}}`TodoApp.HttpApi.Host`{{end}} is the startup project and `TodoApp.EntityFrameworkCore.DbMigrations` is the *Default Project* in PMC. {{else if DB=="Mongo"}} @@ -242,7 +283,7 @@ namespace TodoApp _todoItemRepository = todoItemRepository; } - // TODO: Implement the methods + // TODO: Implement the methods here... } } ```` @@ -620,7 +661,149 @@ If you run the `TodoApp.HttpApi.Host` application, you can see the Todo API: {{end # Blazor}} -{{end # Blazor || BlazorServer}} +{{else if UI=="NG"}} + +### Service Proxy Generation + +ABP provides a handy feature to automatically create client-side services to easily consume HTTP APIs provided by the server. + +Ensure that the `TodoApp.HttpApi.Host` project is running, open a command-line terminal in the `angular` folder and type the following command: + +```` +abp generate-proxy +```` + +If everything goes well, it should generate an output like shown below: + +```` +CREATE src/app/proxy/generate-proxy.json (170978 bytes) +CREATE src/app/proxy/README.md (1000 bytes) +CREATE src/app/proxy/todo.service.ts (794 bytes) +CREATE src/app/proxy/models.ts (66 bytes) +CREATE src/app/proxy/index.ts (58 bytes) +```` + +We can then use the `todoService` to use the server-side HTTP APIs, as we'll do in the next section. + +### home.component.ts + +Open the `/angular/src/app/home/home.component.ts` file and replace its content with the following code block: + +````js +import { ToasterService } from '@abp/ng.theme.shared'; +import { Component, OnInit } from '@angular/core'; +import { TodoItemDto, TodoService } from '@proxy'; + +@Component({ + selector: 'app-home', + templateUrl: './home.component.html', + styleUrls: ['./home.component.css'] +}) +export class HomeComponent implements OnInit { + + todoItems: TodoItemDto[]; + newTodoText: string; + + constructor( + private todoService: TodoService, + private toasterService: ToasterService) + { } + + ngOnInit(): void { + this.todoService.getList().subscribe(response => { + this.todoItems = response; + }); + } + + create(): void{ + this.todoService.create(this.newTodoText).subscribe((result) => { + this.todoItems = this.todoItems.concat(result); + this.newTodoText = null; + }); + } + + delete(id: string): void { + this.todoService.delete(id).subscribe(() => { + this.todoItems = this.todoItems.filter(item => item.id !== id); + this.toasterService.info('Deleted the todo item.'); + }); + } +} + +```` + +We've used the `todoService` to get the list of todo items and assigned the returning value to the `todoItems` array. We've also added `create` and `delete` methods. These methods will be used in the view side. + +### home.component.html + +Open the `/angular/src/app/home/home.component.html` file and replace its content with the following code block: + +````html +
+
+
+
TODO LIST
+
+
+ +
+ + +
+ + +
    +
  • + {{ todoItem.text }} +
  • +
+
+
+
+```` + +### Index.razor.css + +As the final touch, open the `/angular/src/app/home/home.component.css` file in the `Pages` and replace with the following content: + +````css +#TodoList{ + list-style: none; + margin: 0; + padding: 0; +} + +#TodoList li { + padding: 5px; + margin: 5px 0px; + border: 1px solid #cccccc; + background-color: #f5f5f5; +} + +#TodoList li i +{ + opacity: 0.5; +} + +#TodoList li i:hover +{ + opacity: 1; + color: #ff0000; + cursor: pointer; +} +```` + +This is a simple styling for the todo page. We believe that you can do much better :) + +Now, you can run the application again to see the result. + +{{end}} ## Conclusion From 6b50eeee1d38543eb52b498d81caea9452fbef2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Apr 2021 14:52:58 +0300 Subject: [PATCH 14/29] Add link to the Quick start tutorial --- docs/en/Index.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/en/Index.md b/docs/en/Index.md index 95052add38..cdd0908821 100644 --- a/docs/en/Index.md +++ b/docs/en/Index.md @@ -4,8 +4,9 @@ ABP Framework is a complete **infrastructure** based on the **ASP.NET Core** to ## Getting Started -* [Getting Started Guide](Getting-Started.md) is the easiest way to start a new web application with the ABP Framework. -* [Web Application Development Tutorial](Tutorials/Part-1.md) is a complete tutorial to develop a full stack web application. +* [Quick Start](Tutorials/Todo/Index.md) is a single-part, quick-start tutorial to build a simple application with the ABP Framework. Start with this tutorial if you want to quickly understand how ABP works. +* [Getting Started](Getting-Started.md) guide can be used to create and run ABP based solutions with different options and details. +* [Web Application Development Tutorial](Tutorials/Part-1.md) is a complete tutorial to develop a full stack web application with all aspects of a real-life solution. ### UI Framework Options From 0c7892de0254abf1574c2d4061eb465cf8b9688b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Apr 2021 15:00:04 +0300 Subject: [PATCH 15/29] Fix tutorial curly bracket usage --- docs/en/Tutorials/Todo/Index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Tutorials/Todo/Index.md b/docs/en/Tutorials/Todo/Index.md index 39ceb36351..3e540eacca 100644 --- a/docs/en/Tutorials/Todo/Index.md +++ b/docs/en/Tutorials/Todo/Index.md @@ -760,7 +760,7 @@ Open the `/angular/src/app/home/home.component.html` file and replace its conten
  • - {{ todoItem.text }} + {%{{{ todoItem.text }}}%}
From 6b3ae5fa555ff8b4dab330c744e5e08cb803a43e Mon Sep 17 00:00:00 2001 From: EngincanV Date: Wed, 7 Apr 2021 15:01:37 +0300 Subject: [PATCH 16/29] Blogging: Cache invalidation --- .../Admin/Blogs/IBlogManagementAppService.cs | 2 + .../Admin/Blogs/BlogManagementAppService.cs | 14 +- .../Admin/BlogManagementController.cs | 7 + .../Pages/Blogging/Admin/Blogs/index.js | 16 +++ .../BloggingPermissionDefinitionProvider.cs | 1 + .../Volo/Blogging/BloggingPermissions.cs | 1 + .../BloggingApplicationAutoMapperProfile.cs | 10 ++ .../Volo/Blogging/Posts/PostAppService.cs | 125 +++++++++--------- .../Blogging/Localization/Resources/en.json | 5 +- .../Blogging/Localization/Resources/tr.json | 5 +- .../Volo.Blogging.Domain.csproj | 1 + .../Volo/Blogging/BloggingDomainModule.cs | 5 +- .../Blogging/Posts/PostCacheInvalidator.cs | 25 ++++ .../Volo/Blogging/Posts/PostCacheItem.cs | 39 ++++++ 14 files changed, 188 insertions(+), 68 deletions(-) create mode 100644 modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheInvalidator.cs create mode 100644 modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheItem.cs diff --git a/modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Blogs/IBlogManagementAppService.cs b/modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Blogs/IBlogManagementAppService.cs index 35d6d1c97e..1e363c8578 100644 --- a/modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Blogs/IBlogManagementAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Admin.Application.Contracts/Volo/Blogging/Admin/Blogs/IBlogManagementAppService.cs @@ -18,5 +18,7 @@ namespace Volo.Blogging.Admin.Blogs Task UpdateAsync(Guid id, UpdateBlogDto input); Task DeleteAsync(Guid id); + + Task ClearCacheAsync(Guid id); } } diff --git a/modules/blogging/src/Volo.Blogging.Admin.Application/Volo/Blogging/Admin/Blogs/BlogManagementAppService.cs b/modules/blogging/src/Volo.Blogging.Admin.Application/Volo/Blogging/Admin/Blogs/BlogManagementAppService.cs index b11bd481fe..1c5f282d7c 100644 --- a/modules/blogging/src/Volo.Blogging.Admin.Application/Volo/Blogging/Admin/Blogs/BlogManagementAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Admin.Application/Volo/Blogging/Admin/Blogs/BlogManagementAppService.cs @@ -3,18 +3,22 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using Volo.Abp.Application.Dtos; +using Volo.Abp.Caching; using Volo.Blogging.Blogs; using Volo.Blogging.Blogs.Dtos; +using Volo.Blogging.Posts; namespace Volo.Blogging.Admin.Blogs { public class BlogManagementAppService : BloggingAdminAppServiceBase, IBlogManagementAppService { private readonly IBlogRepository _blogRepository; - - public BlogManagementAppService(IBlogRepository blogRepository) + private readonly IDistributedCache> _postsCache; + + public BlogManagementAppService(IBlogRepository blogRepository, IDistributedCache> postsCache) { _blogRepository = blogRepository; + _postsCache = postsCache; } public async Task> GetListAsync() @@ -63,5 +67,11 @@ namespace Volo.Blogging.Admin.Blogs { await _blogRepository.DeleteAsync(id); } + + [Authorize(BloggingPermissions.Blogs.ClearCache)] + public async Task ClearCacheAsync(Guid id) + { + await _postsCache.RemoveAsync(id.ToString()); + } } } diff --git a/modules/blogging/src/Volo.Blogging.Admin.HttpApi/Volo/Blogging/Admin/BlogManagementController.cs b/modules/blogging/src/Volo.Blogging.Admin.HttpApi/Volo/Blogging/Admin/BlogManagementController.cs index 815604e871..ce6457dcc7 100644 --- a/modules/blogging/src/Volo.Blogging.Admin.HttpApi/Volo/Blogging/Admin/BlogManagementController.cs +++ b/modules/blogging/src/Volo.Blogging.Admin.HttpApi/Volo/Blogging/Admin/BlogManagementController.cs @@ -54,5 +54,12 @@ namespace Volo.Blogging.Admin { await _blogManagementAppService.DeleteAsync(id); } + + [HttpGet] + [Route("clear-cache/{id}")] + public async Task ClearCacheAsync(Guid id) + { + await _blogManagementAppService.ClearCacheAsync(id); + } } } diff --git a/modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/index.js b/modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/index.js index a2b618b89f..aaa378cabd 100644 --- a/modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/index.js +++ b/modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/index.js @@ -52,6 +52,22 @@ }); }, }, + { + text: l("ClearCache"), + visible: abp.auth.isGranted( + 'Blogging.Blog.ClearCache' + ), + confirmMessage: function (data) { + return l("ClearCacheConfirmationMessage"); + }, + action: function (data) { + volo.blogging.admin.blogManagement + .clearCache(data.record.id) + .then(function () { + _dataTable.ajax.reload(); + }) + } + } ], }, }, diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts.Shared/Volo/Blogging/BloggingPermissionDefinitionProvider.cs b/modules/blogging/src/Volo.Blogging.Application.Contracts.Shared/Volo/Blogging/BloggingPermissionDefinitionProvider.cs index 65a6ab1ab7..595e32199c 100644 --- a/modules/blogging/src/Volo.Blogging.Application.Contracts.Shared/Volo/Blogging/BloggingPermissionDefinitionProvider.cs +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts.Shared/Volo/Blogging/BloggingPermissionDefinitionProvider.cs @@ -15,6 +15,7 @@ namespace Volo.Blogging blogs.AddChild(BloggingPermissions.Blogs.Update, L("Permission:Edit")); blogs.AddChild(BloggingPermissions.Blogs.Delete, L("Permission:Delete")); blogs.AddChild(BloggingPermissions.Blogs.Create, L("Permission:Create")); + blogs.AddChild(BloggingPermissions.Blogs.ClearCache, L("Permission:ClearCache")); var posts = bloggingGroup.AddPermission(BloggingPermissions.Posts.Default, L("Permission:Posts")); posts.AddChild(BloggingPermissions.Posts.Update, L("Permission:Edit")); diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts.Shared/Volo/Blogging/BloggingPermissions.cs b/modules/blogging/src/Volo.Blogging.Application.Contracts.Shared/Volo/Blogging/BloggingPermissions.cs index fae85acf88..617b4d06f1 100644 --- a/modules/blogging/src/Volo.Blogging.Application.Contracts.Shared/Volo/Blogging/BloggingPermissions.cs +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts.Shared/Volo/Blogging/BloggingPermissions.cs @@ -13,6 +13,7 @@ namespace Volo.Blogging public const string Delete = Default + ".Delete"; public const string Update = Default + ".Update"; public const string Create = Default + ".Create"; + public const string ClearCache = Default + ".ClearCache"; } public static class Posts diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs index b9e3cf0dea..2d40c7fad9 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs @@ -20,6 +20,16 @@ namespace Volo.Blogging CreateMap().Ignore(x=>x.Writer).Ignore(x=>x.CommentCount).Ignore(x=>x.Tags); CreateMap().Ignore(x => x.Writer); CreateMap(); + CreateMap().Ignore(x=>x.Writer).Ignore(x=>x.CommentCount).Ignore(x=>x.Tags); + CreateMap() + .Ignore(x=>x.LastModificationTime) + .Ignore(x=>x.LastModifierId) + .Ignore(x=>x.DeleterId) + .Ignore(x=>x.IsDeleted) + .Ignore(x=>x.DeletionTime) + .Ignore(x=>x.CommentCount) + .Ignore(x=>x.Tags); + } } } diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs index 07d22d3385..9e8acba57d 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs @@ -20,9 +20,15 @@ namespace Volo.Blogging.Posts private readonly IPostRepository _postRepository; private readonly ITagRepository _tagRepository; private readonly ICommentRepository _commentRepository; - private readonly IDistributedCache> _postsCache; - - public PostAppService(IPostRepository postRepository, ITagRepository tagRepository, ICommentRepository commentRepository, IBlogUserLookupService userLookupService, IDistributedCache> postsCache) + private readonly IDistributedCache> _postsCache; + + public PostAppService( + IPostRepository postRepository, + ITagRepository tagRepository, + ICommentRepository commentRepository, + IBlogUserLookupService userLookupService, + IDistributedCache> postsCache + ) { UserLookupService = userLookupService; _postRepository = postRepository; @@ -33,21 +39,47 @@ namespace Volo.Blogging.Posts public async Task> GetListByBlogIdAndTagName(Guid id, string tagName) { - var cacheKey = id.ToString() + "-" + tagName; + var posts = await _postRepository.GetPostsByBlogId(id); + var tag = tagName.IsNullOrWhiteSpace() ? null : await _tagRepository.FindByNameAsync(id, tagName); + var userDictionary = new Dictionary(); + var postDtos = new List(ObjectMapper.Map, List>(posts)); - return await _postsCache.GetOrAddAsync( - cacheKey, - async () => await GetPostsByBlogIdAndTagName(id, tagName), - () => new DistributedCacheEntryOptions + foreach (var postDto in postDtos) + { + postDto.Tags = await GetTagsOfPost(postDto.Id); + } + + if (tag != null) + { + postDtos = await FilterPostsByTag(postDtos, tag); + } + + foreach (var postDto in postDtos) + { + if (postDto.CreatorId.HasValue) { - AbsoluteExpiration = DateTimeOffset.Now.AddHours(6) + if (!userDictionary.ContainsKey(postDto.CreatorId.Value)) + { + var creatorUser = await UserLookupService.FindByIdAsync(postDto.CreatorId.Value); + if (creatorUser != null) + { + userDictionary[creatorUser.Id] = ObjectMapper.Map(creatorUser); + } + } + + if (userDictionary.ContainsKey(postDto.CreatorId.Value)) + { + postDto.Writer = userDictionary[(Guid)postDto.CreatorId]; + } } - ); + } + + return new ListResultDto(postDtos); } public async Task> GetTimeOrderedListAsync(Guid blogId) { - return await _postsCache.GetOrAddAsync( + var postCacheItems = await _postsCache.GetOrAddAsync( blogId.ToString(), async () => await GetTimeOrderedPostsAsync(blogId), () => new DistributedCacheEntryOptions @@ -55,6 +87,22 @@ namespace Volo.Blogging.Posts AbsoluteExpiration = DateTimeOffset.Now.AddHours(6) } ); + + var postsWithDetails = ObjectMapper.Map, List>(postCacheItems); + + foreach (var post in postsWithDetails) + { + if (post.CreatorId.HasValue) + { + var creatorUser = await UserLookupService.FindByIdAsync(post.CreatorId.Value); + if (creatorUser != null) + { + post.Writer = ObjectMapper.Map(creatorUser); + } + } + } + + return new ListResultDto(postsWithDetails); } public async Task GetForReadingAsync(GetPostInput input) @@ -157,62 +205,13 @@ namespace Volo.Blogging.Posts return ObjectMapper.Map(post); } - private async Task> GetPostsByBlogIdAndTagName(Guid id, string tagName) - { - var posts = await _postRepository.GetPostsByBlogId(id); - var tag = tagName.IsNullOrWhiteSpace() ? null : await _tagRepository.FindByNameAsync(id, tagName); - var userDictionary = new Dictionary(); - var postDtos = new List(ObjectMapper.Map, List>(posts)); - - foreach (var postDto in postDtos) - { - postDto.Tags = await GetTagsOfPost(postDto.Id); - } - - if (tag != null) - { - postDtos = await FilterPostsByTag(postDtos, tag); - } - - foreach (var postDto in postDtos) - { - if (postDto.CreatorId.HasValue) - { - if (!userDictionary.ContainsKey(postDto.CreatorId.Value)) - { - var creatorUser = await UserLookupService.FindByIdAsync(postDto.CreatorId.Value); - if (creatorUser != null) - { - userDictionary[creatorUser.Id] = ObjectMapper.Map(creatorUser); - } - } - - if (userDictionary.ContainsKey(postDto.CreatorId.Value)) - { - postDto.Writer = userDictionary[(Guid)postDto.CreatorId]; - } - } - } - - return new ListResultDto(postDtos); - } - - private async Task> GetTimeOrderedPostsAsync(Guid blogId) + private async Task> GetTimeOrderedPostsAsync(Guid blogId) { var posts = await _postRepository.GetOrderedList(blogId); - var postDtos = new List(ObjectMapper.Map, List>(posts)); + var postCacheItems = ObjectMapper.Map, List>(posts); - foreach (var postDto in postDtos) - { - var creatorUser = await UserLookupService.FindByIdAsync(postDto.CreatorId.Value); - if (creatorUser != null) - { - postDto.Writer = ObjectMapper.Map(creatorUser); - } - } - - return new ListResultDto(postDtos); + return postCacheItems; } private async Task RenameUrlIfItAlreadyExistAsync(Guid blogId, string url, Post existingPost = null) diff --git a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/en.json b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/en.json index 5ebdf25d9f..2219aa9fcd 100644 --- a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/en.json +++ b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/en.json @@ -12,6 +12,7 @@ "Permission:Posts": "Posts", "Permission:Tags": "Tags", "Permission:Comments": "Comments", + "Permission:ClearCache": "Clear cache", "Title": "Title", "Delete": "Delete", "Reply": "Reply", @@ -53,6 +54,8 @@ "Blogs": "Blogs", "Tags": "Tags", "ShareOn": "Share on", - "TitleLengthWarning": "Keep your title size under 60 characters to be SEO friendly!" + "TitleLengthWarning": "Keep your title size under 60 characters to be SEO friendly!", + "ClearCache": "Clear cache", + "ClearCacheConfirmationMessage": "Are you sure you want to clear the cache?" } } diff --git a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/tr.json b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/tr.json index 4a9a38b040..915e8b233e 100644 --- a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/tr.json +++ b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/tr.json @@ -12,6 +12,7 @@ "Permission:Posts": "Yazılar", "Permission:Tags": "Etiketler", "Permission:Comments": "Yorumlar", + "Permission:ClearCache": "Önbelleği temizle", "Title": "Başlık", "Delete": "Sil", "Reply": "Yanıtla", @@ -53,6 +54,8 @@ "Blogs": "Bloglar", "Tags": "Etiketler", "ShareOn": "Paylaş", - "TitleLengthWarning": "Başlığınınz SEO dostu olabilmesi için 60 karakterden az olmasını sağlayın!" + "TitleLengthWarning": "Başlığınınz SEO dostu olabilmesi için 60 karakterden az olmasını sağlayın!", + "ClearCache": "Önbelleği temizle", + "ClearCacheConfirmationMessage": "Önbelleği temizlemek istediğinizden emin misiniz?" } } diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.csproj b/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.csproj index 73cf0498c5..c6c096105b 100644 --- a/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.csproj +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.csproj @@ -15,6 +15,7 @@ + diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingDomainModule.cs b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingDomainModule.cs index 3179303215..2e5e9a68e0 100644 --- a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingDomainModule.cs +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingDomainModule.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AutoMapper; +using Volo.Abp.Caching; using Volo.Abp.Domain; using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.Modularity; @@ -13,7 +14,9 @@ namespace Volo.Blogging [DependsOn( typeof(BloggingDomainSharedModule), typeof(AbpDddDomainModule), - typeof(AbpAutoMapperModule))] + typeof(AbpAutoMapperModule), + typeof(AbpCachingModule) + )] public class BloggingDomainModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheInvalidator.cs b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheInvalidator.cs new file mode 100644 index 0000000000..abbfcd8d88 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheInvalidator.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities.Events; +using Volo.Abp.EventBus; + +namespace Volo.Blogging.Posts +{ + public class PostCacheInvalidator : ILocalEventHandler>, ITransientDependency + { + protected IDistributedCache> Cache { get; } + + public PostCacheInvalidator(IDistributedCache> cache) + { + Cache = cache; + } + + public virtual async Task HandleEventAsync(EntityChangedEventData eventData) + { + var cacheKey = eventData.Entity.BlogId.ToString(); + await Cache.RemoveAsync(cacheKey); + } + } +} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheItem.cs b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheItem.cs new file mode 100644 index 0000000000..f08424aaf1 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheItem.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using JetBrains.Annotations; +using Volo.Abp.Auditing; +using Volo.Abp.Domain.Entities; +using Volo.Blogging.Tagging; +using Volo.Blogging.Users; + +namespace Volo.Blogging.Posts +{ + [Serializable] + public class PostCacheItem + { + public Guid Id { get; set; } + public Guid BlogId { get; set; } + + public string Title { get; set; } + + public string CoverImage { get; set; } + + public string Url { get; set; } + + public string Content { get; set; } + + public string Description { get; set; } + + public int ReadCount { get; set; } + + public int CommentCount { get; set; } + + [CanBeNull] + public BlogUser Writer { get; set; } + + public List Tags { get; set; } + public Guid? CreatorId { get; set; } + + public DateTime CreationTime { get; set; } + } +} \ No newline at end of file From 262d23e6798d517a121949869496ddbaf2d6d7f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Apr 2021 15:03:52 +0300 Subject: [PATCH 17/29] Update Index.md --- docs/en/Tutorials/Todo/Index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/Tutorials/Todo/Index.md b/docs/en/Tutorials/Todo/Index.md index 3e540eacca..7b74fa4056 100644 --- a/docs/en/Tutorials/Todo/Index.md +++ b/docs/en/Tutorials/Todo/Index.md @@ -669,13 +669,13 @@ ABP provides a handy feature to automatically create client-side services to eas Ensure that the `TodoApp.HttpApi.Host` project is running, open a command-line terminal in the `angular` folder and type the following command: -```` +````bash abp generate-proxy ```` If everything goes well, it should generate an output like shown below: -```` +````bash CREATE src/app/proxy/generate-proxy.json (170978 bytes) CREATE src/app/proxy/README.md (1000 bytes) CREATE src/app/proxy/todo.service.ts (794 bytes) From 39dd3eade269235c222333ab4b46b64e6d94a7aa Mon Sep 17 00:00:00 2001 From: Alper Ebicoglu Date: Wed, 7 Apr 2021 15:12:31 +0300 Subject: [PATCH 18/29] add oracle to DatabaseManagementSystems --- docs/en/CLI-New-Command-Samples.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/CLI-New-Command-Samples.md b/docs/en/CLI-New-Command-Samples.md index 8ddd985e85..eedf03353c 100644 --- a/docs/en/CLI-New-Command-Samples.md +++ b/docs/en/CLI-New-Command-Samples.md @@ -167,7 +167,7 @@ ABP CLI always uses the latest version. In order to create a solution from a pre ## Choose database management system -The default database management system (DBMS) is `Entity Framework Core` / ` SQL Server`. You can choose a DBMS by passing `--database-management-system` parameter. Accepted values are `SqlServer`, `MySQL`, `SQLite`, `Oracle-Devart`, `PostgreSQL`. The default value is `SqlServer`. +The default database management system (DBMS) is `Entity Framework Core` / ` SQL Server`. You can choose a DBMS by passing `--database-management-system` parameter. [Accepted values](https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/DatabaseManagementSystem.cs) are `SqlServer`, `MySQL`, `SQLite`, `Oracle`, `Oracle-Devart`, `PostgreSQL`. The default value is `SqlServer`. * Angular UI, **PostgreSQL** database, creates the project in a new folder: From 7be01cefddceb4a38007c319042b9f176dd51449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Apr 2021 15:48:57 +0300 Subject: [PATCH 19/29] Added style file for the home component. --- templates/app/angular/src/app/home/home.component.css | 1 + templates/app/angular/src/app/home/home.component.ts | 1 + 2 files changed, 2 insertions(+) create mode 100644 templates/app/angular/src/app/home/home.component.css diff --git a/templates/app/angular/src/app/home/home.component.css b/templates/app/angular/src/app/home/home.component.css new file mode 100644 index 0000000000..4e3bf68aa0 --- /dev/null +++ b/templates/app/angular/src/app/home/home.component.css @@ -0,0 +1 @@ +/* Styles for the home component */ \ No newline at end of file diff --git a/templates/app/angular/src/app/home/home.component.ts b/templates/app/angular/src/app/home/home.component.ts index c0b4602ee2..cd0aca4034 100644 --- a/templates/app/angular/src/app/home/home.component.ts +++ b/templates/app/angular/src/app/home/home.component.ts @@ -5,6 +5,7 @@ import { OAuthService } from 'angular-oauth2-oidc'; @Component({ selector: 'app-home', templateUrl: './home.component.html', + styleUrls: ['./home.component.css'], }) export class HomeComponent { get hasLoggedIn(): boolean { From 9ef263c7db4e83b6c2cfb9eb9e9ce2a8c0f9d0ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Apr 2021 15:59:07 +0300 Subject: [PATCH 20/29] Update Index.md --- docs/en/Tutorials/Todo/Index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Tutorials/Todo/Index.md b/docs/en/Tutorials/Todo/Index.md index 7b74fa4056..925527c507 100644 --- a/docs/en/Tutorials/Todo/Index.md +++ b/docs/en/Tutorials/Todo/Index.md @@ -768,7 +768,7 @@ Open the `/angular/src/app/home/home.component.html` file and replace its conten ```` -### Index.razor.css +### home.component.css As the final touch, open the `/angular/src/app/home/home.component.css` file in the `Pages` and replace with the following content: From 4fcf7fafdaf4c23df1ce3b63c8de83feaf626eba Mon Sep 17 00:00:00 2001 From: EngincanV Date: Wed, 7 Apr 2021 16:08:48 +0300 Subject: [PATCH 21/29] Refactoring --- .../Blogging/BloggingApplicationAutoMapperProfile.cs | 12 ++++-------- .../Volo/Blogging/Posts/PostAppService.cs | 4 +--- .../Volo/Blogging/Posts/PostCacheItem.cs | 6 ++++-- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs index 2d40c7fad9..b2113926ad 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs @@ -22,14 +22,10 @@ namespace Volo.Blogging CreateMap(); CreateMap().Ignore(x=>x.Writer).Ignore(x=>x.CommentCount).Ignore(x=>x.Tags); CreateMap() - .Ignore(x=>x.LastModificationTime) - .Ignore(x=>x.LastModifierId) - .Ignore(x=>x.DeleterId) - .Ignore(x=>x.IsDeleted) - .Ignore(x=>x.DeletionTime) - .Ignore(x=>x.CommentCount) - .Ignore(x=>x.Tags); - + .IgnoreModificationAuditedObjectProperties() + .IgnoreDeletionAuditedObjectProperties() + .Ignore(x => x.CommentCount) + .Ignore(x => x.Tags); } } } diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs index 9e8acba57d..d804e7a004 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs @@ -209,9 +209,7 @@ namespace Volo.Blogging.Posts { var posts = await _postRepository.GetOrderedList(blogId); - var postCacheItems = ObjectMapper.Map, List>(posts); - - return postCacheItems; + return ObjectMapper.Map, List>(posts); } private async Task RenameUrlIfItAlreadyExistAsync(Guid blogId, string url, Post existingPost = null) diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheItem.cs b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheItem.cs index f08424aaf1..450feec9dd 100644 --- a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheItem.cs +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheItem.cs @@ -9,9 +9,10 @@ using Volo.Blogging.Users; namespace Volo.Blogging.Posts { [Serializable] - public class PostCacheItem + public class PostCacheItem : ICreationAuditedObject { public Guid Id { get; set; } + public Guid BlogId { get; set; } public string Title { get; set; } @@ -32,8 +33,9 @@ namespace Volo.Blogging.Posts public BlogUser Writer { get; set; } public List Tags { get; set; } - public Guid? CreatorId { get; set; } + public Guid? CreatorId { get; set; } + public DateTime CreationTime { get; set; } } } \ No newline at end of file From 2a147a1832a20ef2d58e907212aa50db2c4ab7fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Apr 2021 16:11:35 +0300 Subject: [PATCH 22/29] Add warning for iis express --- docs/en/Tutorials/Todo/Index.md | 6 +++++- .../Tutorials/Todo/run-without-iisexpress.png | Bin 0 -> 23261 bytes 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 docs/en/Tutorials/Todo/run-without-iisexpress.png diff --git a/docs/en/Tutorials/Todo/Index.md b/docs/en/Tutorials/Todo/Index.md index 925527c507..c927d5c925 100644 --- a/docs/en/Tutorials/Todo/Index.md +++ b/docs/en/Tutorials/Todo/Index.md @@ -667,7 +667,11 @@ If you run the `TodoApp.HttpApi.Host` application, you can see the Todo API: ABP provides a handy feature to automatically create client-side services to easily consume HTTP APIs provided by the server. -Ensure that the `TodoApp.HttpApi.Host` project is running, open a command-line terminal in the `angular` folder and type the following command: +You first need to run the `TodoApp.HttpApi.Host` project since the proxy generator reads API definitions from the server application. However, there is a problem with IIS Express; it doesn't allow to connect to the application from another process. If you are using Visual Studio, select the `TodoApp.HttpApi.Host` instead of IIS Express in the run button drop down menu, as shown in the figure below: + +![run-without-iisexpress](run-without-iisexpress.png) + +Once you run the `TodoApp.HttpApi.Host` project, open a command-line terminal in the `angular` folder and type the following command: ````bash abp generate-proxy diff --git a/docs/en/Tutorials/Todo/run-without-iisexpress.png b/docs/en/Tutorials/Todo/run-without-iisexpress.png new file mode 100644 index 0000000000000000000000000000000000000000..41898e6c003090de4dcb8ac001bf03fdacee2c17 GIT binary patch literal 23261 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 A+5i9m literal 0 HcmV?d00001 From bb21073928aff999402cbd8e87831ca66c8d85b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Apr 2021 16:14:35 +0300 Subject: [PATCH 23/29] Update Index.md --- docs/en/Tutorials/Todo/Index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/Tutorials/Todo/Index.md b/docs/en/Tutorials/Todo/Index.md index c927d5c925..acccd71ea2 100644 --- a/docs/en/Tutorials/Todo/Index.md +++ b/docs/en/Tutorials/Todo/Index.md @@ -667,7 +667,9 @@ If you run the `TodoApp.HttpApi.Host` application, you can see the Todo API: ABP provides a handy feature to automatically create client-side services to easily consume HTTP APIs provided by the server. -You first need to run the `TodoApp.HttpApi.Host` project since the proxy generator reads API definitions from the server application. However, there is a problem with IIS Express; it doesn't allow to connect to the application from another process. If you are using Visual Studio, select the `TodoApp.HttpApi.Host` instead of IIS Express in the run button drop down menu, as shown in the figure below: +You first need to run the `TodoApp.HttpApi.Host` project since the proxy generator reads API definitions from the server application. + +> **Warning**: There is a problem with IIS Express; it doesn't allow to connect to the application from another process. If you are using Visual Studio, select the `TodoApp.HttpApi.Host` instead of IIS Express in the run button drop-down list, as shown in the figure below: ![run-without-iisexpress](run-without-iisexpress.png) From ba007b3672c94cf3aec32c0c46c87318052c3c8f Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Wed, 7 Apr 2021 16:24:46 +0300 Subject: [PATCH 24/29] rename home.component.css as home.component.scss --- docs/en/Tutorials/Todo/Index.md | 6 +++--- .../app/home/{home.component.css => home.component.scss} | 0 templates/app/angular/src/app/home/home.component.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename templates/app/angular/src/app/home/{home.component.css => home.component.scss} (100%) diff --git a/docs/en/Tutorials/Todo/Index.md b/docs/en/Tutorials/Todo/Index.md index c927d5c925..7a41f8523c 100644 --- a/docs/en/Tutorials/Todo/Index.md +++ b/docs/en/Tutorials/Todo/Index.md @@ -701,7 +701,7 @@ import { TodoItemDto, TodoService } from '@proxy'; @Component({ selector: 'app-home', templateUrl: './home.component.html', - styleUrls: ['./home.component.css'] + styleUrls: ['./home.component.scss'] }) export class HomeComponent implements OnInit { @@ -772,9 +772,9 @@ Open the `/angular/src/app/home/home.component.html` file and replace its conten ```` -### home.component.css +### home.component.scss -As the final touch, open the `/angular/src/app/home/home.component.css` file in the `Pages` and replace with the following content: +As the final touch, open the `/angular/src/app/home/home.component.scss` file in the `Pages` and replace with the following content: ````css #TodoList{ diff --git a/templates/app/angular/src/app/home/home.component.css b/templates/app/angular/src/app/home/home.component.scss similarity index 100% rename from templates/app/angular/src/app/home/home.component.css rename to templates/app/angular/src/app/home/home.component.scss diff --git a/templates/app/angular/src/app/home/home.component.ts b/templates/app/angular/src/app/home/home.component.ts index cd0aca4034..5e19367b34 100644 --- a/templates/app/angular/src/app/home/home.component.ts +++ b/templates/app/angular/src/app/home/home.component.ts @@ -5,7 +5,7 @@ import { OAuthService } from 'angular-oauth2-oidc'; @Component({ selector: 'app-home', templateUrl: './home.component.html', - styleUrls: ['./home.component.css'], + styleUrls: ['./home.component.scss'], }) export class HomeComponent { get hasLoggedIn(): boolean { From 4a69feed2ecf1f27ea06ea3a7d5c3ff4f844ee4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Apr 2021 16:38:22 +0300 Subject: [PATCH 25/29] Add iis express warning --- docs/en/Tutorials/Part-2.md | 6 +++++- .../images/vs-run-without-iisexpress.png | Bin 0 -> 13760 bytes 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 docs/en/Tutorials/images/vs-run-without-iisexpress.png diff --git a/docs/en/Tutorials/Part-2.md b/docs/en/Tutorials/Part-2.md index 17bc98c538..5df5dae343 100644 --- a/docs/en/Tutorials/Part-2.md +++ b/docs/en/Tutorials/Part-2.md @@ -447,7 +447,11 @@ For more information, see the [RoutesService document](../UI/Angular/Modifying-t [ABP CLI](../CLI.md) provides `generate-proxy` command that generates client proxies for your HTTP APIs to make easy to consume your HTTP APIs from the client side. Before running `generate-proxy` command, your host must be up and running. -Run the following command in the `angular` folder: +> **Warning**: There is a problem with IIS Express; it doesn't allow to connect to the application from another process. If you are using Visual Studio, select the `Acme.BookStore.HttpApi.Host` instead of IIS Express in the run button drop-down list, as shown in the figure below: + +![vs-run-without-iisexpress](images/vs-run-without-iisexpress.png) + +Once the host application is running, execute the following command in the `angular` folder: ```bash abp generate-proxy diff --git a/docs/en/Tutorials/images/vs-run-without-iisexpress.png b/docs/en/Tutorials/images/vs-run-without-iisexpress.png new file mode 100644 index 0000000000000000000000000000000000000000..03c30e2b481c95d102f6aaf1cdbd5348d7d64b3d GIT binary patch literal 13760 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 Date: Wed, 7 Apr 2021 16:42:28 +0300 Subject: [PATCH 26/29] Remove unnecessary property --- .../Volo/Blogging/BloggingApplicationAutoMapperProfile.cs | 3 ++- .../Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheItem.cs | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs index b2113926ad..3572e00113 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs @@ -20,10 +20,11 @@ namespace Volo.Blogging CreateMap().Ignore(x=>x.Writer).Ignore(x=>x.CommentCount).Ignore(x=>x.Tags); CreateMap().Ignore(x => x.Writer); CreateMap(); - CreateMap().Ignore(x=>x.Writer).Ignore(x=>x.CommentCount).Ignore(x=>x.Tags); + CreateMap().Ignore(x=>x.CommentCount).Ignore(x=>x.Tags); CreateMap() .IgnoreModificationAuditedObjectProperties() .IgnoreDeletionAuditedObjectProperties() + .Ignore(x=>x.Writer) .Ignore(x => x.CommentCount) .Ignore(x => x.Tags); } diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheItem.cs b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheItem.cs index 450feec9dd..d65b64ba43 100644 --- a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheItem.cs +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheItem.cs @@ -29,9 +29,6 @@ namespace Volo.Blogging.Posts public int CommentCount { get; set; } - [CanBeNull] - public BlogUser Writer { get; set; } - public List Tags { get; set; } public Guid? CreatorId { get; set; } From 713c9c536bf2c63efd1258ec5dc670ec8bf48804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Apr 2021 16:50:10 +0300 Subject: [PATCH 27/29] Update Index.md --- docs/en/Tutorials/Todo/Index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Tutorials/Todo/Index.md b/docs/en/Tutorials/Todo/Index.md index 1b201277b9..5bbf4c8eaf 100644 --- a/docs/en/Tutorials/Todo/Index.md +++ b/docs/en/Tutorials/Todo/Index.md @@ -776,7 +776,7 @@ Open the `/angular/src/app/home/home.component.html` file and replace its conten ### home.component.scss -As the final touch, open the `/angular/src/app/home/home.component.scss` file in the `Pages` and replace with the following content: +As the final touch, open the `/angular/src/app/home/home.component.scss` file and replace its content with the following code block: ````css #TodoList{ From a744fa45371f1e8b6a232b9a3b3e397ab785f56a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Apr 2021 17:07:16 +0300 Subject: [PATCH 28/29] Add login button to the home page --- .../Controllers/AccountController.cs | 2 +- .../Pages/Index.razor | 5 +++++ .../Pages/Index.razor | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/Controllers/AccountController.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/Controllers/AccountController.cs index 29fa140e4d..44d63fa0f2 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/Controllers/AccountController.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/Controllers/AccountController.cs @@ -1,6 +1,6 @@ using Volo.Abp.AspNetCore.Mvc.Authentication; -namespace MyCompanyName.MyProjectName.Web.Controllers +namespace MyCompanyName.MyProjectName.Blazor.Server.Tiered.Controllers { public class AccountController : ChallengeAccountController { diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/Pages/Index.razor b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/Pages/Index.razor index c83e436a5d..bdc59498f0 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/Pages/Index.razor +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/Pages/Index.razor @@ -12,6 +12,11 @@

Welcome to the Application

@L["LongWelcomeMessage"]

+ + @if (!CurrentUser.IsAuthenticated) + { + @L["Login"] + }
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/Pages/Index.razor b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/Pages/Index.razor index c83e436a5d..bdc59498f0 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/Pages/Index.razor +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/Pages/Index.razor @@ -12,6 +12,11 @@

Welcome to the Application

@L["LongWelcomeMessage"]

+ + @if (!CurrentUser.IsAuthenticated) + { + @L["Login"] + }
From 0040569fb2f501281af46ef33de7eeb3d8f220f2 Mon Sep 17 00:00:00 2001 From: EngincanV Date: Wed, 7 Apr 2021 17:54:58 +0300 Subject: [PATCH 29/29] Blogging: Publish PostChangedEvent for cache invalidation --- .../Volo/Blogging/Posts/PostAppService.cs | 20 +++++++++++++++++-- .../Blogging/Posts/PostCacheInvalidator.cs | 8 +++----- .../Volo/Blogging/Posts/PostChangedEvent.cs | 9 +++++++++ 3 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostChangedEvent.cs diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs index d804e7a004..7b42d25f84 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Caching.Distributed; using Volo.Abp.Caching; +using Volo.Abp.EventBus.Local; using Volo.Blogging.Comments; using Volo.Blogging.Tagging; using Volo.Blogging.Tagging.Dtos; @@ -21,13 +22,15 @@ namespace Volo.Blogging.Posts private readonly ITagRepository _tagRepository; private readonly ICommentRepository _commentRepository; private readonly IDistributedCache> _postsCache; + private readonly ILocalEventBus _localEventBus; public PostAppService( IPostRepository postRepository, ITagRepository tagRepository, ICommentRepository commentRepository, IBlogUserLookupService userLookupService, - IDistributedCache> postsCache + IDistributedCache> postsCache, + ILocalEventBus localEventBus ) { UserLookupService = userLookupService; @@ -35,6 +38,7 @@ namespace Volo.Blogging.Posts _tagRepository = tagRepository; _commentRepository = commentRepository; _postsCache = postsCache; + _localEventBus = localEventBus; } public async Task> GetListByBlogIdAndTagName(Guid id, string tagName) @@ -84,7 +88,7 @@ namespace Volo.Blogging.Posts async () => await GetTimeOrderedPostsAsync(blogId), () => new DistributedCacheEntryOptions { - AbsoluteExpiration = DateTimeOffset.Now.AddHours(6) + AbsoluteExpiration = DateTimeOffset.Now.AddHours(1) } ); @@ -155,6 +159,7 @@ namespace Volo.Blogging.Posts await _commentRepository.DeleteOfPost(id); await _postRepository.DeleteAsync(id); + await PublishPostChangedEventAsync(post.BlogId); } [Authorize(BloggingPermissions.Posts.Update)] @@ -176,6 +181,7 @@ namespace Volo.Blogging.Posts var tagList = SplitTags(input.Tags); await SaveTags(tagList, post); + await PublishPostChangedEventAsync(post.BlogId); return ObjectMapper.Map(post); } @@ -201,6 +207,7 @@ namespace Volo.Blogging.Posts var tagList = SplitTags(input.Tags); await SaveTags(tagList, post); + await PublishPostChangedEventAsync(post.BlogId); return ObjectMapper.Map(post); } @@ -297,5 +304,14 @@ namespace Volo.Blogging.Posts return Task.FromResult(filteredPostDtos); } + + private async Task PublishPostChangedEventAsync(Guid blogId) + { + await _localEventBus.PublishAsync( + new PostChangedEvent + { + BlogId = blogId + }); + } } } diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheInvalidator.cs b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheInvalidator.cs index abbfcd8d88..e18e6de23b 100644 --- a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheInvalidator.cs +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostCacheInvalidator.cs @@ -2,12 +2,11 @@ using System.Threading.Tasks; using Volo.Abp.Caching; using Volo.Abp.DependencyInjection; -using Volo.Abp.Domain.Entities.Events; using Volo.Abp.EventBus; namespace Volo.Blogging.Posts { - public class PostCacheInvalidator : ILocalEventHandler>, ITransientDependency + public class PostCacheInvalidator : ILocalEventHandler, ITransientDependency { protected IDistributedCache> Cache { get; } @@ -16,10 +15,9 @@ namespace Volo.Blogging.Posts Cache = cache; } - public virtual async Task HandleEventAsync(EntityChangedEventData eventData) + public virtual async Task HandleEventAsync(PostChangedEvent post) { - var cacheKey = eventData.Entity.BlogId.ToString(); - await Cache.RemoveAsync(cacheKey); + await Cache.RemoveAsync(post.BlogId.ToString()); } } } \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostChangedEvent.cs b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostChangedEvent.cs new file mode 100644 index 0000000000..c32ed92224 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostChangedEvent.cs @@ -0,0 +1,9 @@ +using System; + +namespace Volo.Blogging.Posts +{ + public class PostChangedEvent + { + public Guid BlogId { get; set; } + } +} \ No newline at end of file