diff --git a/docs/en/JSON.md b/docs/en/JSON.md new file mode 100644 index 0000000000..29e93007af --- /dev/null +++ b/docs/en/JSON.md @@ -0,0 +1,60 @@ +# JSON +The ABP Framework provides an abstraction to work with JSON. Having such an abstraction has some benefits; + +* You can write library independent code. Therefore, you can change the underlying library with the minimum effort and code change. +* You can use the predefined converters defined in the ABP without worrying about the underlying library's internal details. + +> The JSON serialization system is implemented with the [Volo.Abp.Json](https://www.nuget.org/packages/Volo.Abp.Json) NuGet package. Most of the time, you don't need to manually [install it](https://abp.io/package-detail/Volo.Abp.Json) since it comes pre-installed with the [application startup template](Startup-Templates/Application.md). + +## IJsonSerializer + +You can inject `IJsonSerializer` and use it for JSON operations. Here is the available operations in the `IJsonSerializer` interface. + +```csharp +public interface IJsonSerializer +{ + string Serialize(object obj, bool camelCase = true, bool indented = false); + T Deserialize(string jsonString, bool camelCase = true); + object Deserialize(Type type, string jsonString, bool camelCase = true); +} +``` +Usage Example: + +```csharp +public class ProductManager +{ + public IJsonSerializer JsonSerializer { get; } + + public ProductManager(IJsonSerializer jsonSerializer) + { + JsonSerializer = jsonSerializer; + } + + public void SendRequest(Product product) + { + var json= JsonSerializer.Serialize(product); + // Left blank intentionally for demo purposes... + } +} +``` + +## Configuration + +### AbpJsonOptions + +`AbpJsonOptions` type provides options for the JSON operations in the ABP Framework. + +Properties: +* **DefaultDateTimeFormat(`string`)**: Default `DateTime` format. +* **UseHybridSerializer(`bool`)**: True by default. Boolean field indicating whether the ABP Framework uses the hybrid approach or not. If the field is true, it will try to use `System.Json.Text` to handle JSON if it can otherwise use the `Newtonsoft.Json.` +* **Providers(`ITypeList`)**: List of JSON serializer providers implementing the `IJsonSerializerProvider` interface. You can create and add custom serializers to the list, and the ABP Framework uses them automatically. When the `Serialize` or `Deserialize` method is called on the `IJsonSerializer` interface, the ABP Framework calls the `CanHandle` methods of the given providers in reverse order and uses the first provider that returns `true` to do the JSON operation. + +### AbpSystemTextJsonSerializerOptions + +`AbpSystemTextJsonSerializerOptions` provides options for `System.Text.Json` usage. + +Properties: + +- **JsonSerializerOptions(`System.Text.Json.JsonSerializerOptions`)**: Global options for System.Text.Json library operations. See [here](https://docs.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions) for reference. +- **UnsupportedTypes(`ITypeList`)**: List of the unsupported types. You can add types of the unsupported types to the list and, the hybrid JSON serializer automatically uses the `Newtonsoft.Json` library instead of `System.Text.Json`. + diff --git a/docs/en/Modules/Cms-Kit.md b/docs/en/Modules/Cms-Kit.md index 1259686f8e..59fa6ce15c 100644 --- a/docs/en/Modules/Cms-Kit.md +++ b/docs/en/Modules/Cms-Kit.md @@ -1,70 +1,61 @@ # CMS Kit Module -This module provides CMS(Content Management System) capabilities for your application. +This module provides CMS (Content Management System) capabilities for your application. It provides **core building blocks** and fully working **sub-systems** to create your own website with CMS features enabled, or use the building blocks in your web sites with any purpose. -* Provides a **page** management system to manage dynamic pages. -* Provides a [**blog**](cms-kit/Blog-System.md) system to create blogs and publish posts. -* Provides a [**tag**](cms-kit/Tag-Management.md) system to tag any kind of resources, like blog posts. -* Provides a [**comment**](cms-kit/Comment-System.md) system to add comments feature to any kind of resource, like blog posts, products, etc. -* Provides a [**reaction**](cms-kit/Reaction-System.md) system to add reactions feature to any kind of resource, like blog posts or comments. +> **This module currently available only for the MVC UI**. While there is no official Blazor package, it can also work in a Blazor Server UI since a Blazor Server UI application is actually a hybrid application that runs within the MVC UI. + +The following features are currently available: + +* Provides a [**page**](cms-kit/Pages.md) management system to manage dynamic pages with dynamic URLs. +* Provides a [**blog**](cms-kit/Blog-System.md) system to create publish blog posts with multiple blog support. +* Provides a [**tagging**](cms-kit/Tag-Management.md) system to tag any kind of resource, like a blog post. +* Provides a [**comment**](cms-kit/Comment-System.md) system to add comments feature to any kind of resource, like blog post or a product review page. +* Provides a [**reaction**](cms-kit/Reaction-System.md) system to add reactions (smileys) feature to any kind of resource, like a blog post or a comment. * Provides a [**rating**](cms-kit/Rating-System.md) system to add rating feature to any kind of resource. -## How to install +Click to a feature to understand and learn how to use it. + +All features are individually usable. If you disable a feature, it completely disappears from your application, even from the database tables, by the help of the [Global Features](../Global-Features.md) system. + +## How to Install -The ABP CLI allows adding a module to a solution using `add-module` command. CMS kit module can be added using the command below; +[ABP CLI](../CLI.md) allows installing a module to a solution using the `add-module` command. You can install the CMS Kit module in a command-line terminal with the following command: ```bash abp add-module Volo.CmsKit ``` -Open the `GlobalFeatureConfigurator` class in the `Domain.Shared` project and place the following code to the `Configure` method to enable all features in the CMS kit module. +After the installation process, open the `GlobalFeatureConfigurator` class in the `Domain.Shared` project of your solution and place the following code into the `Configure` method to enable all the features in the CMS Kit module. ```csharp GlobalFeatureManager.Instance.Modules.CmsKit(cmsKit => { cmsKit.EnableAll(); }); - ``` -> If you are using EntityFrameworkCore, do not forget to add a new migration and update your database. - -## Packages - -This module follows the [module development best practices guide](https://docs.abp.io/en/abp/latest/Best-Practices/Index) and consists of several NuGet and NPM packages. See the guide if you want to understand the packages and relations between them. - -CMS kit packages are designed for various usage scenarios. When you visit the [CMS kit package list page](https://www.nuget.org/packages?q=Volo.CmsKit), you will see that packages have admin, public and unified versions. -For example, - - `Volo.CmsKit.Admin.Application`: Contains functionality required by admin websites. - - `Volo.CmsKit.Public.Application`: Contains functionality required by public websites. - - `Volo.CmsKit.Application` : Unified package dependent on both public and admin packages. - -If you want to separate admin and public website codes, you can use the admin and public packages. However, if you want to keep admin and public website codes in a shared project, you can use the unified packages to include admin and public packages. - -It is recommended to use the unified packages instead of adding both admin and public packages. - -## Feature System - -CMS kit uses the [global feature](https://docs.abp.io/en/abp/latest/Global-Features) system for all implemented features. You can use the global feature system to enable all features or only enabled specific features easily. +Instead of enabling all, you may prefer to enable the features one by one. The following example enables only the [tags](cms-kit/Tag-Management.md) and [comments](cms-kit/Comment-System.md) features: -To enable all features in the CMS kit, open the `GlobalFeatureConfigurator` class in the `Domain.Shared` project. - -```csharp +````csharp GlobalFeatureManager.Instance.Modules.CmsKit(cmsKit => { - cmsKit.EnableAll(); + cmsKit.Tags.Enable(); + cmsKit.Comments.Enable(); }); -``` +```` -You can only enable specific features such as pages, like below. +> If you are using Entity Framework Core, do not forget to add a new migration and update your database. -```csharp -GlobalFeatureManager.Instance.Modules.CmsKit(cmsKit => -{ - cmsKit.Pages.Enable(); -}); -``` +## The Packages + +This module follows the [module development best practices guide](https://docs.abp.io/en/abp/latest/Best-Practices/Index) and consists of several NuGet and NPM packages. See the guide if you want to understand the packages and relations between them. + +CMS kit packages are designed for various usage scenarios. When you visit the [CMS kit package list page](https://www.nuget.org/packages?q=Volo.CmsKit), you will see that packages have admin, public and unified versions: + + - `Volo.CmsKit.Admin.*` packages contain the functionalities required by admin (back office) applications. + - `Volo.CmsKit.Public.*` packages contain the functionalities used in public websites where users read blog posts or leave comments. + - `Volo.CmsKit.*` (without Admin/Public suffix) packages are called as unified packages. Unified packages are shortcuts for adding Admin & Public packages (of the related layer) separately. If you have a single application for administration and public web site, you can use these packages. -## User interface +## The User Interface ### Menu items @@ -156,4 +147,4 @@ You can also customize the reaction icons shown in the reaction component. You can use the rating component to add rating a mechanism to your content. Here how the rating component looks on a sample page. -![ratings](../images/cmskit-module-ratings.png) +![ratings](../images/cmskit-module-ratings.png) \ No newline at end of file diff --git a/docs/en/Modules/cms-kit/Pages.md b/docs/en/Modules/cms-kit/Pages.md new file mode 100644 index 0000000000..33336f21d6 --- /dev/null +++ b/docs/en/Modules/cms-kit/Pages.md @@ -0,0 +1,3 @@ +# CMS Kit: Pages + +This document is in progress... \ No newline at end of file diff --git a/docs/en/UI/Angular/Component-Replacement.md b/docs/en/UI/Angular/Component-Replacement.md index 0010a30a2f..1b757c7c23 100644 --- a/docs/en/UI/Angular/Component-Replacement.md +++ b/docs/en/UI/Angular/Component-Replacement.md @@ -84,11 +84,10 @@ export class AppComponent { Run the following command in `angular` folder to create a new component called `LogoComponent`. ```bash -yarn ng generate component logo --inlineTemplate --inlineStyle --entryComponent - -# You don't need the --entryComponent option in Angular 9 +yarn ng generate component logo --inlineTemplate --inlineStyle ``` + Open the generated `logo.component.ts` in `src/app/logo` folder and replace its content with the following: ```js @@ -115,7 +114,7 @@ Open `app.component.ts` in `src/app` folder and modify it as shown below: ```js import { ..., ReplaceableComponentsService } from '@abp/ng.core'; // imported ReplaceableComponentsService -import { LogoComponent } from './logo/logo.component'; // imported NavItemsComponent +import { LogoComponent } from './logo/logo.component'; // imported LogoComponent import { eThemeBasicComponents } from '@abp/ng.theme.basic'; // imported eThemeBasicComponents //... @@ -151,36 +150,18 @@ yarn ng generate component routes Open the generated `routes.component.ts` in `src/app/routes` folder and replace its content with the following: ```js -import { ABP } from '@abp/ng.core'; -import { - Component, - HostBinding, - Inject, - Renderer2, - TrackByFunction, - AfterViewInit, -} from '@angular/core'; -import { fromEvent } from 'rxjs'; -import { debounceTime } from 'rxjs/operators'; +import { Component, HostBinding } from '@angular/core'; @Component({ selector: 'app-routes', templateUrl: 'routes.component.html', }) -export class RoutesComponent implements AfterViewInit { +export class RoutesComponent { @HostBinding('class.mx-auto') marginAuto = true; - smallScreen = window.innerWidth < 992; - - constructor(private renderer: Renderer2) {} - - ngAfterViewInit() { - fromEvent(window, 'resize') - .pipe(debounceTime(150)) - .subscribe(() => { - this.smallScreen = window.innerWidth < 992; - }); + get smallScreen() { + return window.innerWidth < 992; } } ``` @@ -310,7 +291,7 @@ Open `app.component.ts` in `src/app` folder and modify it as shown below: ```js import { ..., ReplaceableComponentsService } from '@abp/ng.core'; // imported ReplaceableComponentsService -import { RoutesComponent } from './routes/routes.component'; // imported NavItemsComponent +import { RoutesComponent } from './routes/routes.component'; // imported RoutesComponent import { eThemeBasicComponents } from '@abp/ng.theme.basic'; // imported eThemeBasicComponents //... @@ -347,51 +328,51 @@ Open the generated `nav-items.component.ts` in `src/app/nav-items` folder and re ```js import { - ApplicationConfiguration, AuthService, - ConfigState, + ConfigStateService, + CurrentUserDto, + LanguageInfo, + NAVIGATE_TO_MANAGE_PROFILE, SessionStateService, - SetLanguage, } from '@abp/ng.core'; -import { Component, AfterViewInit } from '@angular/core'; -import { Navigate, RouterState } from '@ngxs/router-plugin'; -import { Select, Store } from '@ngxs/store'; -import { Observable, fromEvent } from 'rxjs'; -import { map, debounceTime } from 'rxjs/operators'; +import { Component, Inject } from '@angular/core'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; import snq from 'snq'; @Component({ selector: 'app-nav-items', templateUrl: 'nav-items.component.html', }) -export class NavItemsComponent implements AfterViewInit { - @Select(ConfigState.getOne('currentUser')) - currentUser$: Observable; +export class NavItemsComponent { + currentUser$: Observable = this.configState.getOne$('currentUser'); + selectedTenant$ = this.sessionState.getTenant$(); - @Select(ConfigState.getDeep('localization.languages')) - languages$: Observable; + languages$: Observable = this.configState.getDeep$('localization.languages'); - smallScreen = window.innerWidth < 992; + get smallScreen(): boolean { + return window.innerWidth < 992; + } get defaultLanguage$(): Observable { return this.languages$.pipe( map( languages => snq( - () => languages.find(lang => lang.cultureName === this.selectedLangCulture).displayName, + () => languages.find(lang => lang.cultureName === this.selectedLangCulture).displayName ), - '', - ), + '' + ) ); } - get dropdownLanguages$(): Observable { + get dropdownLanguages$(): Observable { return this.languages$.pipe( map( languages => snq(() => languages.filter(lang => lang.cultureName !== this.selectedLangCulture)), - [], - ), + [] + ) ); } @@ -399,28 +380,23 @@ export class NavItemsComponent implements AfterViewInit { return this.sessionState.getLanguage(); } - constructor(private store: Store, private authService: AuthService, private sessionState: SessionStateService) {} + constructor( + @Inject(NAVIGATE_TO_MANAGE_PROFILE) public navigateToManageProfile, + private configState: ConfigStateService, + private authService: AuthService, + private sessionState: SessionStateService + ) {} - ngAfterViewInit() { - fromEvent(window, 'resize') - .pipe(debounceTime(150)) - .subscribe(() => { - this.smallScreen = window.innerWidth < 992; - }); + onChangeLang(cultureName: string) { + this.sessionState.setLanguage(cultureName); } - onChangeLang(cultureName: string) { - this.store.dispatch(new SetLanguage(cultureName)); + navigateToLogin() { + this.authService.navigateToLogin(); } logout() { - this.authService.logout().subscribe(() => { - this.store.dispatch( - new Navigate(['/'], null, { - state: { redirectUrl: this.store.selectSnapshot(RouterState).state.url }, - }), - ); - }); + this.authService.logout().subscribe(); } } ``` @@ -445,8 +421,14 @@ Open the generated `nav-items.component.html` in `src/app/nav-items` folder and ```html