diff --git a/docs/en/Tutorials/Part-10.md b/docs/en/Tutorials/Part-10.md index 6418db7e71..0b77bd2645 100644 --- a/docs/en/Tutorials/Part-10.md +++ b/docs/en/Tutorials/Part-10.md @@ -55,7 +55,7 @@ public Guid AuthorId { get; set; } {{if DB=="EF"}} -> In this tutorial, we preferred to not add a **navigation property** to the `Author` entity from the `Book` class (like `public Author Author { get; set; }`). This is due to follow the DDD best practices (rule: refer to other aggregates only by id). However, you can add such a navigation property and configure it for the EF Core. In this way, you don't need to write join queries while getting books with their authors (like we will done below) which makes your application code simpler. +> In this tutorial, we preferred to not add a **navigation property** to the `Author` entity from the `Book` class (like `public Author Author { get; set; }`). This is due to follow the DDD best practices (rule: refer to other aggregates only by id). However, you can add such a navigation property and configure it for the EF Core. In this way, you don't need to write join queries while getting books with their authors (like we will be doing below) which makes your application code simpler. {{end}} @@ -105,6 +105,7 @@ This should create a new migration class with the following code in its `Up` met migrationBuilder.AddColumn( name: "AuthorId", table: "AppBooks", + type: "uniqueidentifier", nullable: false, defaultValue: new Guid("00000000-0000-0000-0000-000000000000")); @@ -708,7 +709,7 @@ namespace Acme.BookStore.Books ### The Book List -Book list page change is trivial. Open the `Pages/Books/Index.js` in the `Acme.BookStore.Web` project and add the following column definition between the `name` and `type` columns: +Book list page change is trivial. Open the `Pages/Books/Index.js` in the `Acme.BookStore.Web` project and add an `authorName` column between the `name` and `type` columns: ````js ... @@ -735,7 +736,7 @@ Book list page change is trivial. Open the `Pages/Books/Index.js` in the `Acme.B When you run the application, you can see the *Author* column on the table: -![bookstore-added-author-to-book-list](images/bookstore-added-author-to-book-list.png) +![bookstore-added-author-to-book-list](images/bookstore-added-author-to-book-list-2.png) ### Create Modal @@ -937,7 +938,7 @@ CreateMap(); You can run the application and try to create a new book or update an existing book. You will see a drop down list on the create/update form to select the author of the book: -![bookstore-added-authors-to-modals](images/bookstore-added-authors-to-modals.png) +![bookstore-added-authors-to-modals](images/bookstore-added-authors-to-modals-2.png) {{else if UI=="NG"}} diff --git a/docs/en/Tutorials/Part-2.md b/docs/en/Tutorials/Part-2.md index 3e7a1bc735..a229d3d146 100644 --- a/docs/en/Tutorials/Part-2.md +++ b/docs/en/Tutorials/Part-2.md @@ -215,7 +215,7 @@ context.Menu.AddItem( Run the project, login to the application with the username `admin` and the password `1q2w3E*` and you can see that the new menu item has been added to the main menu: -![bookstore-menu-items](images/bookstore-new-menu-item.png) +![bookstore-menu-items](images/bookstore-new-menu-item-2.png) When you click on the Books menu item under the Book Store parent, you will be redirected to the new empty Books Page. @@ -328,7 +328,7 @@ $(function () { You can run the application! The final UI of this part is shown below: -![Book list](images/bookstore-book-list-3.png) +![Book list](images/bookstore-book-list-4.png) This is a fully working, server side paged, sorted and localized table of books. diff --git a/docs/en/Tutorials/Part-3.md b/docs/en/Tutorials/Part-3.md index 18ae29ae96..fdfa39dd58 100644 --- a/docs/en/Tutorials/Part-3.md +++ b/docs/en/Tutorials/Part-3.md @@ -53,7 +53,7 @@ This part is also recorded as a video tutorial and ** Identity -> Roles* page, select *Permissions* action for the admin role to open the permission management modal: -![bookstore-permissions-ui](images/bookstore-permissions-ui.png) +![bookstore-permissions-ui](images/bookstore-permissions-ui-2.png) Grant the permissions you want and save the modal. @@ -202,7 +202,7 @@ Now, unauthorized users are redirected to the **login page**. The book management page has a *New Book* button that should be invisible if the current user has no *Book Creation* permission. -![bookstore-new-book-button-small](images/bookstore-new-book-button-small.png) +![bookstore-new-book-button-small](images/bookstore-new-book-button-small-2.png) Open the `Pages/Books/Index.cshtml` file and change the content as shown below: @@ -251,7 +251,7 @@ Open the `Pages/Books/Index.cshtml` file and change the content as shown below: Books table in the book management page has an actions button for each row. The actions button includes *Edit* and *Delete* actions: -![bookstore-edit-delete-actions](images/bookstore-edit-delete-actions.png) +![bookstore-edit-delete-actions](images/bookstore-edit-delete-actions-2.png) We should hide an action if the current user has not granted for the related permission. Datatables row actions has a `visible` option that can be set to `false` to hide the action item. @@ -301,82 +301,22 @@ context.Menu.AddItem( And replace this code block with the following: ````csharp -var bookStoreMenu = new ApplicationMenuItem( - "BooksStore", - l["Menu:BookStore"], - icon: "fa fa-book" +context.Menu.AddItem( + new ApplicationMenuItem( + "BooksStore", + l["Menu:BookStore"], + icon: "fa fa-book" + ).AddItem( + new ApplicationMenuItem( + "BooksStore.Books", + l["Menu:Books"], + url: "/Books" + ).RequirePermissions(BookStorePermissions.Books.Default) // Check the permission! + ) ); - -context.Menu.AddItem(bookStoreMenu); - -//CHECK the PERMISSION -if (await context.IsGrantedAsync(BookStorePermissions.Books.Default)) -{ - bookStoreMenu.AddItem(new ApplicationMenuItem( - "BooksStore.Books", - l["Menu:Books"], - url: "/Books" - )); -} ```` -You also need to add `async` keyword to the `ConfigureMenuAsync` method and re-arrange the return values. The final `BookStoreMenuContributor` class should be the following: - -````csharp -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Localization; -using Acme.BookStore.Localization; -using Acme.BookStore.MultiTenancy; -using Acme.BookStore.Permissions; -using Volo.Abp.TenantManagement.Web.Navigation; -using Volo.Abp.UI.Navigation; - -namespace Acme.BookStore.Web.Menus -{ - public class BookStoreMenuContributor : IMenuContributor - { - public async Task ConfigureMenuAsync(MenuConfigurationContext context) - { - if (context.Menu.Name == StandardMenus.Main) - { - await ConfigureMainMenuAsync(context); - } - } - - private async Task ConfigureMainMenuAsync(MenuConfigurationContext context) - { - if (!MultiTenancyConsts.IsEnabled) - { - var administration = context.Menu.GetAdministration(); - administration.TryRemoveMenuItem(TenantManagementMenuNames.GroupName); - } - - var l = context.GetLocalizer(); - - context.Menu.Items.Insert(0, new ApplicationMenuItem("BookStore.Home", l["Menu:Home"], "~/")); - - var bookStoreMenu = new ApplicationMenuItem( - "BooksStore", - l["Menu:BookStore"], - icon: "fa fa-book" - ); - - context.Menu.AddItem(bookStoreMenu); - - //CHECK the PERMISSION - if (await context.IsGrantedAsync(BookStorePermissions.Books.Default)) - { - bookStoreMenu.AddItem(new ApplicationMenuItem( - "BooksStore.Books", - l["Menu:Books"], - url: "/Books" - )); - } - } - } -} -```` +We've only added the `.RequirePermissions(BookStorePermissions.Books.Default)` extension method call for the inner menu item. {{else if UI == "NG"}} diff --git a/docs/en/Tutorials/Part-6.md b/docs/en/Tutorials/Part-6.md index 7d7c4e2d94..a21d310157 100644 --- a/docs/en/Tutorials/Part-6.md +++ b/docs/en/Tutorials/Part-6.md @@ -265,7 +265,7 @@ namespace Acme.BookStore.Authors We will implement this repository in the next part. -> Both of these methods might **seem unnecessary** since the standard repositories already `IQueryable` and you can directly use them instead of defining such custom methods. You're right and do it like in a real application. However, for this **"learning" tutorial**, it is useful to explain how to create custom repository methods when you really need it. +> Both of these methods might **seem unnecessary** since the standard repositories already provide generic querying methods and you can easily use them instead of defining such custom methods. You're right and do it like in a real application. However, for this **"learning" tutorial**, it is useful to explain how to create custom repository methods when you really need it. ## Conclusion diff --git a/docs/en/Tutorials/Part-8.md b/docs/en/Tutorials/Part-8.md index d8dd4bc5b1..0076a1b07a 100644 --- a/docs/en/Tutorials/Part-8.md +++ b/docs/en/Tutorials/Part-8.md @@ -361,13 +361,10 @@ Then open the `BookStorePermissionDefinitionProvider` in the same project and ad ````csharp var authorsPermission = bookStoreGroup.AddPermission( BookStorePermissions.Authors.Default, L("Permission:Authors")); - authorsPermission.AddChild( BookStorePermissions.Authors.Create, L("Permission:Authors.Create")); - authorsPermission.AddChild( BookStorePermissions.Authors.Edit, L("Permission:Authors.Edit")); - authorsPermission.AddChild( BookStorePermissions.Authors.Delete, L("Permission:Authors.Delete")); ```` diff --git a/docs/en/Tutorials/Part-9.md b/docs/en/Tutorials/Part-9.md index 76d6d9c8d8..ff747cf8b0 100644 --- a/docs/en/Tutorials/Part-9.md +++ b/docs/en/Tutorials/Part-9.md @@ -223,28 +223,39 @@ Notice that we've added more keys. They will be used in the next sections. ### Add to the Main Menu -Open the `BookStoreMenuContributor.cs` in the `Menus` folder of the `Acme.BookStore.Web` project and add the following code in the end of the `ConfigureMainMenuAsync` method: +Open the `BookStoreMenuContributor.cs` in the `Menus` folder of the `Acme.BookStore.Web` project and add a new *Authors* menu item under the *Book Store* menu item. The following code (in the `ConfigureMainMenuAsync` method) shows the final code part: ````csharp -if (await context.IsGrantedAsync(BookStorePermissions.Authors.Default)) -{ - bookStoreMenu.AddItem(new ApplicationMenuItem( - "BooksStore.Authors", - l["Menu:Authors"], - url: "/Authors" - )); -} +context.Menu.AddItem( + new ApplicationMenuItem( + "BooksStore", + l["Menu:BookStore"], + icon: "fa fa-book" + ).AddItem( + new ApplicationMenuItem( + "BooksStore.Books", + l["Menu:Books"], + url: "/Books" + ).RequirePermissions(BookStorePermissions.Books.Default) + ).AddItem( // ADDED THE NEW "AUTHORS" MENU ITEM UNDER THE "BOOK STORE" MENU + new ApplicationMenuItem( + "BooksStore.Authors", + l["Menu:Authors"], + url: "/Authors" + ).RequirePermissions(BookStorePermissions.Books.Default) + ) +); ```` ### Run the Application Run and login to the application. **You can not see the menu item since you don't have permission yet.** Go to the `Identity/Roles` page, click to the *Actions* button and select the *Permissions* action for the **admin role**: -![bookstore-author-permissions](images/bookstore-author-permissions.png) +![bookstore-author-permissions](images/bookstore-author-permissions-2.png) As you see, the admin role has no *Author Management* permissions yet. Click to the checkboxes and save the modal to grant the necessary permissions. You will see the *Authors* menu item under the *Book Store* in the main menu, after **refreshing the page**: -![bookstore-authors-page](images/bookstore-authors-page.png) +![bookstore-authors-page](images/bookstore-authors-page-2.png) The page is fully working except *New author* and *Actions/Edit* since we haven't implemented them yet. @@ -369,7 +380,7 @@ namespace Acme.BookStore.Web "New author" button will work as expected and open a new model when you run the application again: -![bookstore-new-author-modal](images/bookstore-new-author-modal.png) +![bookstore-new-author-modal](images/bookstore-new-author-modal-2.png) ## Edit Modal diff --git a/docs/en/Tutorials/images/bookstore-added-author-to-book-list-2.png b/docs/en/Tutorials/images/bookstore-added-author-to-book-list-2.png new file mode 100644 index 0000000000..ca39f239c1 Binary files /dev/null and b/docs/en/Tutorials/images/bookstore-added-author-to-book-list-2.png differ diff --git a/docs/en/Tutorials/images/bookstore-added-authors-to-modals-2.png b/docs/en/Tutorials/images/bookstore-added-authors-to-modals-2.png new file mode 100644 index 0000000000..2b09baf642 Binary files /dev/null and b/docs/en/Tutorials/images/bookstore-added-authors-to-modals-2.png differ diff --git a/docs/en/Tutorials/images/bookstore-author-permissions-2.png b/docs/en/Tutorials/images/bookstore-author-permissions-2.png new file mode 100644 index 0000000000..26911fc664 Binary files /dev/null and b/docs/en/Tutorials/images/bookstore-author-permissions-2.png differ diff --git a/docs/en/Tutorials/images/bookstore-authors-page-2.png b/docs/en/Tutorials/images/bookstore-authors-page-2.png new file mode 100644 index 0000000000..2ec2d42fe2 Binary files /dev/null and b/docs/en/Tutorials/images/bookstore-authors-page-2.png differ diff --git a/docs/en/Tutorials/images/bookstore-book-list-4.png b/docs/en/Tutorials/images/bookstore-book-list-4.png new file mode 100644 index 0000000000..3d0897339d Binary files /dev/null and b/docs/en/Tutorials/images/bookstore-book-list-4.png differ diff --git a/docs/en/Tutorials/images/bookstore-create-dialog-3.png b/docs/en/Tutorials/images/bookstore-create-dialog-3.png new file mode 100644 index 0000000000..d945ed6337 Binary files /dev/null and b/docs/en/Tutorials/images/bookstore-create-dialog-3.png differ diff --git a/docs/en/Tutorials/images/bookstore-edit-button-3.png b/docs/en/Tutorials/images/bookstore-edit-button-3.png new file mode 100644 index 0000000000..a464d543e7 Binary files /dev/null and b/docs/en/Tutorials/images/bookstore-edit-button-3.png differ diff --git a/docs/en/Tutorials/images/bookstore-edit-delete-actions-2.png b/docs/en/Tutorials/images/bookstore-edit-delete-actions-2.png new file mode 100644 index 0000000000..98b09ca712 Binary files /dev/null and b/docs/en/Tutorials/images/bookstore-edit-delete-actions-2.png differ diff --git a/docs/en/Tutorials/images/bookstore-new-author-modal-2.png b/docs/en/Tutorials/images/bookstore-new-author-modal-2.png new file mode 100644 index 0000000000..628dcd4db5 Binary files /dev/null and b/docs/en/Tutorials/images/bookstore-new-author-modal-2.png differ diff --git a/docs/en/Tutorials/images/bookstore-new-book-button-3.png b/docs/en/Tutorials/images/bookstore-new-book-button-3.png new file mode 100644 index 0000000000..9ac6e0d45e Binary files /dev/null and b/docs/en/Tutorials/images/bookstore-new-book-button-3.png differ diff --git a/docs/en/Tutorials/images/bookstore-new-book-button-small-2.png b/docs/en/Tutorials/images/bookstore-new-book-button-small-2.png new file mode 100644 index 0000000000..8540cbb18d Binary files /dev/null and b/docs/en/Tutorials/images/bookstore-new-book-button-small-2.png differ diff --git a/docs/en/Tutorials/images/bookstore-new-menu-item-2.png b/docs/en/Tutorials/images/bookstore-new-menu-item-2.png new file mode 100644 index 0000000000..3353eec83c Binary files /dev/null and b/docs/en/Tutorials/images/bookstore-new-menu-item-2.png differ diff --git a/docs/en/Tutorials/images/bookstore-permissions-ui-2.png b/docs/en/Tutorials/images/bookstore-permissions-ui-2.png new file mode 100644 index 0000000000..d0110b0877 Binary files /dev/null and b/docs/en/Tutorials/images/bookstore-permissions-ui-2.png differ