| + + + | +
+
+> What if I want Azure AD as my authorization server and not IdentityServer?
+
+This means your application will be using AzureAD user store for authentication. By registering both angular app and HttpApi to AzureAD, authentication might work but **authorization won't**. Users need to be registered to Abp identity system for auditing, permissions etc. So the flow should be 3rd party registration.
+
+## Setting up OpenId Connection
+
+Lets start with adding OpenId connection. Open the **HttpApiHostModule.cs** and update the **ConfigureAuthentication** method as below:
+
+```csharp
+JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
+JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Add("sub", ClaimTypes.NameIdentifier);
+
+context.Services.AddAuthentication()
+ .AddIdentityServerAuthentication(options =>
+ {
+ options.Authority = configuration["AuthServer:Authority"];
+ options.RequireHttpsMetadata = false;
+ options.ApiName = "NonTieredAngular";
+ options.JwtBackChannelHandler = new HttpClientHandler()
+ {
+ ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
+ };
+ })
+ .AddOpenIdConnect("AzureOpenId", "Azure AD OpenId", options =>
+ {
+ options.Authority = "https://login.microsoftonline.com/" + configuration["AzureAd:TenantId"] + "/v2.0/";
+ options.ClientId = configuration["AzureAd:ClientId"];
+ options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
+ options.CallbackPath = configuration["AzureAd:CallbackPath"];
+ options.ClientSecret = configuration["AzureAd:ClientSecret"];
+ options.RequireHttpsMetadata = false;
+ options.SaveTokens = true;
+ options.GetClaimsFromUserInfoEndpoint = true;
+ options.Scope.Add("email");
+ });
+```
+
+> If you are using tiered (separate identity server) application, open **IdentityServerModule.cs** and add the OpenIdConnection manually to **ConfigureServices** method as following:
+
+```csharp
+public override void ConfigureServices(ServiceConfigurationContext context)
+{
+ var hostingEnvironment = context.Services.GetHostingEnvironment();
+ var configuration = context.Services.GetConfiguration();
+
+ JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
+ JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Add("sub", ClaimTypes.NameIdentifier);
+
+ context.Services.AddAuthentication()
+ .AddOpenIdConnect("AzureOpenId", "Azure AD OpenId", options =>
+ {
+ ... // Same configuration above
+ });
+```
+
+Now we can add AzureAD settings. Open the **appsettings.json** located in **HttpApi.Host** project (or **IdentityServer** project if you are using tiered application). Add the following;
+
+```csharp
+"AzureAd": {
+ "Instance": "https://login.microsoftonline.com/",
+ "TenantId": "Tenants page
On the page above, you can; @@ -13,13 +13,12 @@ On the page above, you can; - Edit an existing tenant. - Delete a tenant. -  +Tenant Switching Component
You can switch between existing tenants by using the tenant switching component in the child pages of the `AccountLayoutComponent` (like Login page). Angular UI sends the selected tenant id to the backend as `__tenant` header on each request. - ## Domain Tenant Resolver Angular UI can get the tenant name from the app running URL. You can determine the current tenant by subdomain (like mytenant1.mydomain.com) or by the whole domain (like mytenant.com). To do this, you need to set the `application.baseUrl` property in the environment: @@ -32,10 +31,10 @@ Subdomain resolver: export const environment = { //... application: { - baseUrl: 'https://{0}.mydomain.com/' + baseUrl: "https://{0}.mydomain.com/", }, //... -} +}; ``` **{0}** is the placeholder to determine current tenant's unique name. @@ -44,7 +43,6 @@ After the configuration above, if your app runs on the `mytenant1.mydomain.com`, > **Important Note:** If you define the `baseUrl` with the placeholder (**{0}**), the tenant switching component in the child pages of the `AccountLayoutComponent` (like Login page) will be hidden. - Domain resolver: ```js @@ -53,10 +51,10 @@ Domain resolver: export const environment = { //... application: { - baseUrl: 'https://{0}.com/' + baseUrl: "https://{0}.com/", }, //... -} +}; ``` After the configuration above, if your app runs on the `mytenant.com`, the app will get the tenant name as **mytenant**. @@ -71,29 +69,28 @@ The **{0}** placeholder can be put to the API URLs in the environment to determi export const environment = { //... application: { - baseUrl: 'https://{0}.mydomain.com/', + baseUrl: "https://{0}.mydomain.com/", //... }, oAuthConfig: { - issuer: 'https://{0}.ids.mydomain.com', + issuer: "https://{0}.ids.mydomain.com", //... }, apis: { default: { - url: 'https://{0}.api.mydomain.com', + url: "https://{0}.api.mydomain.com", }, AbpIdentity: { - url: 'https://{0}.identity.mydomain.com', + url: "https://{0}.identity.mydomain.com", }, }, -} +}; ``` > **Important Note:** The `application.baseUrl` and the `{0}` placeholder in the value of the `baseUrl` property are required to be able to get tenant from running URL. Other placeholders in API URLs are optional. After the configuration above, if your app runs on the `mytenant1.mydomain.com`, the app will get tenant name as **mytenant1** and replace the environment object in `ConfigState` on app initialization as follows: - ```js // environment object in ConfigState @@ -128,8 +125,8 @@ The app sends the `__tenant` header that contains the current tenant id on each ## See Also -* [Multi Tenancy in ABP](../../Multi-Tenancy.md) +- [Multi Tenancy in ABP](../../Multi-Tenancy.md) ## What's Next? -- [Confirmation Popup](./Confirmation-Service.md) +- [Managing RxJS Subscriptions](./Subscription-Service.md) diff --git a/docs/en/UI/Angular/PWA-Configuration.md b/docs/en/UI/Angular/PWA-Configuration.md new file mode 100644 index 0000000000..a6aee244ba --- /dev/null +++ b/docs/en/UI/Angular/PWA-Configuration.md @@ -0,0 +1,346 @@ +# PWA Configuration + +[Progressive Web Apps](https://web.dev/progressive-web-apps/) are web applications which, although not as integrated to the OS as a native app, can take advantage of native features. They can be discovered via search engines, installed on devices with a single tap or click, and shared via a regular link. They also can work offline and get updates when new content is available. + +Converting your Angular application to a PWA is easy. + +## 1. Install Angular PWA + +Run the following command in the root folder of your Angular application: + +```shell +yarn ng add @angular/pwa +``` + +...or... + +```shell +npm run ng add @angular/pwa +``` + +This will install the `@angular/service-worker` package and make your default app a PWA. Alternatively, you may add `project` parameter to target a specific app in your workspace: + +```shell +yarn ng add @angular/pwa --project MyProjectName +``` + +Here is the output of the command: + +
+
+So, Angular CLI updates some files and add a few others:
+
+- **ngsw-config.json** is where the [service worker configuration](https://angular.io/guide/service-worker-config) is placed. Not all PWAs have this file. It is specific to Angular.
+- **manifest.webmanifest** is a [web app manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) and provides information about your app in JSON format.
+- **icons** are placeholder icons that are referred to in your web app manifest. We will replace these in a minute.
+- **angular.json** has following modifications:
+ - `assets` include _manifest.webmanifest_.
+ - `serviceWorker` is `true` in production build.
+ - `ngswConfigPath` refers to _ngsw-config.json_.
+- **package.json** has _@angular/service-worker_ as a new dependency.
+- **app.module.ts** imports `ServiceWorkerModule` and registers a service worker filename.
+- **index.html** has following modifications:
+ - A `` element that refers to _manifest.webmanifest_.
+ - A `` tag that sets a theme color.
+
+## 2. Update the Web App Manifest
+
+### 2.1. Set the Name of Your App
+
+The `name` and the `short_name` properties in the generated manifest are derived from your project name. Let's change them.
+
+Open the _manifest.webmanifest_ file and update `name` and `short_name` props:
+
+```json
+{
+ /* rest of the manifest meta data */
+ "short_name": "My Project",
+ "name": "My Project: My Catch-Phrase"
+}
+```
+
+The short name must be really short because it will be displayed on anywhere with limited space, like the launcher and the home screen.
+
+### 2.2. Add a Description
+
+The `@angular/pwa` schematic we just added does not insert a description to your manifest file, but, according to [web app manifest standards](https://www.w3.org/TR/appmanifest/#description-member), you should.
+
+So, open the _manifest.webmanifest_ file and place the description as seen below:
+
+```json
+{
+ /* rest of the manifest meta data */
+ "description": "My short project description giving a slightly better idea about my app"
+}
+```
+
+As a bonus, providing a description [along with other criteria](https://docs.microsoft.com/en-us/microsoft-edge/progressive-web-apps-edgehtml/microsoft-store#criteria-for-automatic-submission) helps Bing web crawler to index your app and automatically submit your app to Microsoft Store in `.appx` format.
+
+### 2.3. Set App Colors
+
+Angular generates the manifest file with a default `theme_color` and `background_color`. Change these according to your brand identity:
+
+Open the _manifest.webmanifest_ file and update `theme_color` and `background_color` properties:
+
+```json
+{
+ /* rest of the manifest meta data */
+ "theme_color": "#000000",
+ "background_color": "#ffffff"
+}
+```
+
+Then open _index.html_ and change the theme color meta tag as below:
+
+```html
+
+```
+
+### 2.4. Replace App Icons & Add Splash Screens
+
+We need to update the icons and add some splash screens. This normally is time-consuming, but we will use the marvelous [pwa-asset-generator](https://github.com/onderceylan/pwa-asset-generator#readme) library.
+
+First, open the _manifest.webmanifest_ file and remove all elements in the `icons` property:
+
+```json
+{
+ /* rest of the manifest meta data */
+ "icons": []
+}
+```
+
+Then, run the following command in your terminal (changing the path of course):
+
+```shell
+npx pwa-asset-generator /path/to/your/logo.png ./src/assets/pwa -i ./src/index.html -m ./src/manifest.webmanifest
+```
+
+Open the _manifest.webmanifest_ file again. You will see this:
+
+```json
+{
+ /* rest of the manifest meta data */
+ "icons": [
+ {
+ "src": "../manifest-icon-192.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "maskable any"
+ },
+ {
+ "src": "../manifest-icon-512.png",
+ "sizes": "512x512",
+ "type": "image/png",
+ "purpose": "maskable any"
+ }
+ ]
+}
+```
+
+In addition to updated icons, the library will generate splash screens. However, Apple requires all splash screens to be added in your _index.html_ and displays a blank screen at startup otherwise. So, the following tags will be inserted into the _index.html_ file:
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## 3. Configure Service Worker
+
+### 3.1 Modify Asset Groups
+
+Angular has defined some static files to be cached by the service worker, but they are not 100% accurate. Let's change it.
+
+Open _ngsw-config.json_ file and replace its content with this:
+
+```json
+{
+ "$schema": "./node_modules/@angular/service-worker/config/schema.json",
+ "index": "/index.html",
+ "assetGroups": [
+ {
+ "name": "app",
+ "installMode": "prefetch",
+ "resources": {
+ "files": [
+ "/favicon.ico",
+ "/index.html",
+ "/manifest.webmanifest",
+ "/*.css",
+ "/common-es2015.*.js",
+ "/main-es2015.*.js",
+ "/polyfills-es2015.*.js",
+ "/runtime-es2015.*.js",
+ "/vendor-es2015.*.js"
+ ]
+ }
+ },
+ {
+ "name": "modules",
+ "installMode": "lazy",
+ "updateMode": "prefetch",
+ "resources": {
+ "files": [
+ "/*-es2015.*.js",
+ "!/common-es2015.*.js",
+ "!/main-es2015.*.js",
+ "!/polyfills-es2015.*.js",
+ "!/runtime-es2015.*.js",
+ "!/vendor-es2015.*.js"
+ ]
+ }
+ },
+ {
+ "name": "assets",
+ "installMode": "lazy",
+ "updateMode": "prefetch",
+ "resources": {
+ "files": [
+ "/assets/**",
+ "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
+ ]
+ }
+ }
+ ]
+}
+```
+
+In case you want to cache other static files, please refer to the [service worker configuration document](https://angular.io/guide/service-worker-config#assetgroups) on Angular.io.
+
+### 3.2 Set Data Groups
+
+This part is unique to your project. We recommend being very careful about which endpoints to cache. Please refer to [service worker configuration document](https://angular.io/guide/service-worker-config#datagroups) on Angular.io for details.
+
+## What's Next?
+
+- [Config State](./Config-State.md)
diff --git a/docs/en/UI/Angular/Quick-Start.md b/docs/en/UI/Angular/Quick-Start.md
new file mode 100644
index 0000000000..a58671156c
--- /dev/null
+++ b/docs/en/UI/Angular/Quick-Start.md
@@ -0,0 +1,212 @@
+# ABP Angular Quick Start
+
+## How to Prepare Development Environment
+
+Please follow the steps below to prepare your development environment for Angular.
+
+1. **Install Node.js:** Please visit [Node.js downloads page](https://nodejs.org/en/download/) and download proper Node.js v12 or v14 installer for your OS. An alternative is to install [NVM](https://github.com/nvm-sh/nvm) and use it to have multiple versions of Node.js in your operating system.
+2. **[Optional] Install Yarn:** You may install Yarn v1 (not v2) following the instructions on [the installation page](https://classic.yarnpkg.com/en/docs/install). Yarn v1 delivers an arguably better developer experience compared to npm v6 and below. You may skip this step and work with npm, which is built-in in Node.js, instead.
+3. **[Optional] Install VS Code:** [VS Code](https://code.visualstudio.com/) is a free, open-source IDE which works seamlessly with TypeScript. Although you can use any IDE including Visual Studio or Rider, VS Code will most likely deliver the best developer experience when it comes to Angular projects. ABP project templates even contain plugin recommendations for VS Code users, which VS Code will ask you to install when you open the Angular project folder. Here is a list of recommended extensions:
+ - [Angular Language Service](https://marketplace.visualstudio.com/items?itemName=angular.ng-template)
+ - [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
+ - [TSLint](https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-typescript-tslint-plugin)
+ - [Visual Studio IntelliCode](https://marketplace.visualstudio.com/items?itemName=visualstudioexptteam.vscodeintellicode)
+ - [Path Intellisense](https://marketplace.visualstudio.com/items?itemName=christian-kohler.path-intellisense)
+ - [npm Intellisense](https://marketplace.visualstudio.com/items?itemName=christian-kohler.npm-intellisense)
+ - [Angular 10 Snippets - TypeScript, Html, Angular Material, ngRx, RxJS & Flex Layout](https://marketplace.visualstudio.com/items?itemName=Mikael.Angular-BeastCode)
+ - [JavaScript (ES6) code snippets](https://marketplace.visualstudio.com/items?itemName=xabikos.JavaScriptSnippets)
+ - [Debugger for Chrome](https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome)
+ - [Git History](https://marketplace.visualstudio.com/items?itemName=donjayamanne.githistory)
+ - [indent-rainbow](https://marketplace.visualstudio.com/items?itemName=oderwat.indent-rainbow)
+
+## How to Start a New Angular Project
+
+You have multiple options to initiate a new Angular project that works with ABP:
+
+### 1. Using ABP CLI
+
+ABP CLI is probably the most convenient and flexible way to initiate an ABP solution with an Angular frontend. Simply [install the ABP CLI](../../CLI.md) and run the following command in your terminal:
+
+```shell
+abp new MyCompanyName.MyProjectName -csf -u angular
+```
+
+> To see further options in the CLI, please visit the [CLI manual](../../CLI.md).
+
+This command will prepare a solution with an Angular and a .NET Core project in it. Please visit [Getting Started section](../../Getting-Started.md?UI=NG&DB=EF&Tiered=No#abp-cli-commands-options) for further instructions on how to set up the backend of your solution.
+
+To continue reading without checking other methods, visit [Angular project structure section](#angular-project-structure).
+
+### 2. Direct Download
+
+You may [download a solution scaffold directly on ABP.io](https://abp.io/get-started) if you are more comfortable with GUI or simply want to try ABP without installing the CLI.
+
+Please do the following:
+
+1. Click on the "DIRECT DOWNLOAD" tab.
+2. Fill out the short form about your project.
+3. Click on the "Create now" button.
+
+...and a customized download will start in a few seconds.
+
+To avoid IDE warnings, run `yarn` or `npm install` in the Angular root folder before you continue to the next section. It is not imperative but recommended.
+
+## Angular Project Structure
+
+After creating a solution, open its "angular" directory in your IDE. This is how the contents of the root folder looks like:
+
+
+
+Here is what these folders and files are for:
+
+- **.vscode** has extension recommendations in it.
+- **e2e** is a separate app for possible end-to-end tests.
+- **src** is where the source files for your application are placed. We will have a closer look in a minute.
+- **.browserlistrc** helps [configuring browser compatibility of your Angular app](https://angular.io/guide/build#configuring-browser-compatibility).
+- **.editorconfig** helps you have a shared coding style for separate editors and IDEs. Check [EditorConfig.org](https://editorconfig.org/) for details.
+- **.gitignore** defined which files and folders should not be tracked by git. Check [git documentation](https://git-scm.com/docs/gitignore) for details.
+- **.prettierrc** includes simple coding style choices for [Prettier](https://prettier.io/), an auto-formatter for TypeScript, HTML, CSS, and more. If you install recommended extensions to VS Code, you will never have to format your code anymore.
+- **angular.json** is where Angular workspace is defined. It holds project configurations and workspace preferences. Please refer to [Angular workspace configuration](https://angular.io/guide/workspace-config) for details.
+- **karma.conf.js** holds [Karma test runner](https://karma-runner.github.io/) configurations.
+- **package.json** is where your [package dependencies](https://angular.io/guide/npm-packages) are listed. It also includes some useful scripts for developing, testing, and building your application.
+- **README.md** includes some of Angular CLI command examples. You either have to install Angular CLI globally or run these commands starting with `yarn` or `npx` to make them work.
+- **start.ps1** is a simple PowerShell script to install dependencies and start a [development server via Angular CLI](https://angular.io/cli/serve), but you probably will not need that after reading this document.
+- **tsconfig.json** and all other [tsconfig files](https://angular.io/guide/typescript-configuration) in general, include some TypeScript and Angular compile options.
+- **yarn.lock** enables installing consistent package versions across different devices so that working application build will not break because of a package update. Please read [Yarn documentation](https://classic.yarnpkg.com/en/docs/yarn-lock/) if you are interested in more information on the topic. If you have decided to use npm, please remove this file and keep the [package-lock.json](https://docs.npmjs.com/files/package-lock.json) instead.
+
+Now let us take a look at the contents of the source folder.
+
+
+
+- **app** is the main directory you put your application files in. Any module, component, directive, service, pipe, guard, interceptor, etc. should be placed here. You are free to choose any folder structure, but [organizing Angular applications based on modules](https://angular.io/guide/module-types) is generally a fine practice.
+- **home** is a predefined module and acts as a welcome page. It also demonstrates how a feature-based folder structure may look like. More complex features will probably have sub-features, thus inner folders. You may change the home folder however you like.
+- **shared** is spared for reusable code that works for several modules. Some, including yours truly, may disagree with using a single module for all shared code, so consider adding standalone sub-modules inside this folder instead of adding everything into **shared.module.ts**.
+- **app-routing.module.ts** is where your top-level routes are defined. Angular is capable of [lazy loading feature modules](https://angular.io/guide/lazy-loading-ngmodules), so not all routes will be here. You may think of Angular routing as a tree and this file is the top of the tree.
+- **app.component.ts** is essentially the top component that holds the dynamic application layout.
+- **app.module.ts** is the [root module](https://angular.io/guide/bootstrapping) that includes information about how parts of your application are related and what to run at the initiation of your application.
+- **route.provider.ts** is used for [modifying the menu](https://docs.abp.io/en/abp/latest/UI/Angular/Modifying-the-Menu).
+- **assets** is for static files. A file (e.g. an image) placed in this folder will be available as is when the application is served.
+- **environments** includes one file per environment configuration. There are two configurations by default, but you may always introduce another one. These files are directly referred to in _angular.json_ and help you have different builds and application variables. Please refer to [configuring Angular application environments](https://angular.io/guide/build#configuring-application-environments) for details.
+- **index.html** is the HTML page served to visitors and will contain everything required to run your application. Servers should be configured to redirect every request to this page so that the Angular router can take over. Do not worry about how to add JavaScript and CSS files to it, because Angular CLI will do it automatically.
+- **main.ts** bootstraps and configures Angular application to run in the browser. It is production-ready, so forget about it.
+- **polyfill.ts** is where you can add polyfills if you want to [support legacy browsers](https://angular.io/guide/browser-support).
+- **style.scss** is the default entry point for application styles. You can change this or add new entry points in _angular.json_.
+- **test.ts** helps the unit test runner discover and bootstrap spec files.
+
+Phew! So many files, right? Yet, **most of them are typically not subject to change** or, even when they are so, the CLI tooling will do the job for you. The main focus should be on the app folder and its content.
+
+Next, we will take a look at the commands used to prepare, build, and serve our application.
+
+## How to Run the Angular Application
+
+Now that you know about the files and folders, we can get the application up and running.
+
+1. Make sure the [database migration is complete](../../Getting-Started?UI=NG&DB=EF&Tiered=No#create-the-database) and the [API is up and running](../../Getting-Started?UI=NG&DB=EF&Tiered=No#run-the-application).
+2. Run `yarn` or `npm install` if you have not already.
+3. Run `yarn start` or `npm start`. The first compilation may take a while. This will start a [live development server](#angular-live-development-server) and launch your default browser in the end.
+4. Visit the browser page that opens after the compilation [1](#f-certificate-error).
+
+
+
+You may modify the behavior of the **start script** (in the package.json file) by changing the parameters passed to the `ng serve` command. For instance, if you do not want a browser window to open next time you run the script, remove `--open` from the end of it. Please check [ng serve documentation](https://angular.io/cli/serve) for all available options.
+
+### Angular Live Development Server
+
+The development server of Angular is based on [Webpack DevServer](https://webpack.js.org/configuration/dev-server/). It tracks changes to source files and syncs the browser window after an incremental re-compilation every time [2](#f-dev-server) you make one. Your experience will be like this:
+
+
+
+Please keep in mind that you should not use this server in production. To provide the fastest experience, the compiler skips some heavy optimizations and the development server is simply not built for multiple clients. The next section will describe what to do.
+
+---
+
+
+
+1 _If you see the error above when you run the Angular app, your browser might be blocking access to the API because of the self-signed certificate. Visit that address and allow access to it (once). When you see the Swagger interface, you are good to go._ [↩](#a-certificate-error)
+
+2 _Sometimes, depending on the file changed, Webpack may miss the change and cannot reflect it in the browser. For example, tsconfig files are not being tracked. In such a case, please restart the development server._ [↩](#a-dev-server)
+
+---
+
+## How to Build the Angular Application
+
+An Angular application can have multiple [build targets](https://angular.io/guide/glossary#target), i.e. **configurations in angular.json** which define how [Architect](https://angular.io/guide/glossary#architect) will build applications and libraries. Usually, each build configuration has a separate environment variable file. Currently, the project has two: One for development and one for production.
+
+```js
+// this is what environment variables look like
+// can be found at /src/environments/environment.ts
+
+import { Config } from '@abp/ng.core';
+
+const baseUrl = 'http://localhost:4200';
+
+export const environment = {
+ production: false,
+ application: {
+ baseUrl,
+ name: 'MyProjectName',
+ logoUrl: '',
+ },
+ oAuthConfig: {
+ issuer: 'https://localhost:44381',
+ redirectUri: baseUrl,
+ clientId: 'MyProjectName_App',
+ responseType: 'code',
+ scope: 'offline_access MyProjectName',
+ },
+ apis: {
+ default: {
+ url: 'https://localhost:44381',
+ rootNamespace: 'MyCompanyName.MyProjectName',
+ },
+ },
+} as Config.Environment;
+```
+
+When you run the development server, variables defined in _environment.ts_ take effect. Similarly, in production mode, the default environment is replaced by _environment.prod.ts_ and completely different variables become effective. You may even [create a new build configuration](https://angular.io/guide/workspace-config#build-configs) and set [file replacements](https://angular.io/guide/build#configure-target-specific-file-replacements) to use a completely new environment. For now, we will start a production build:
+
+1. Open your terminal and navigate to the root Angular folder.
+2. Run `yarn` or `npm install` if you have not installed dependencies already.
+3. Run `yarn build:prod` or `npm run build:prod`.
+
+
+
+Depending on project size, the compilation may take a few minutes. When it is finished, the compiled output will be placed inside the _/dist_ folder. Voila! You have deployment-ready build artifacts.
+
+> The amount of optimization performed on the source is the main difference between a regular build and a production one. Production builds have a much smaller size and are more performant.
+
+## How to Deploy the Angular Application
+
+Angular web applications run on the browser and require no server except for a [static web server](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_web_server) to deliver files to the client. To see that it works, please make sure the backend application is up and then run the following command in your terminal:
+
+```shell
+# please replace MyProjectName with your project name
+
+npx servor dist/MyProjectName index.html 4200 --browse
+```
+
+This command will download and start a simple static server, a browser window at `http://localhost:4200` will open, and the compiled output of your project will be served.
+
+Of course, you need your application to run on an optimized web server and become available to everyone. This is quite straight-forward:
+
+1. Create a new static web server instance. You can use a service like [Azure App Service](https://azure.microsoft.com/tr-tr/services/app-service/web/), [Firebase](https://firebase.google.com/docs/hosting), [Netlify](https://www.netlify.com/), [Vercel](https://vercel.com/), or even [GitHub Pages](https://angular.io/guide/deployment#deploy-to-github-pages). Another option is maintaining own web server with [NGINX](https://www.nginx.com/), [IIS](https://www.iis.net/), [Apache HTTP Server](https://httpd.apache.org/), or equivalent.
+2. Copy the files from `dist/MyProjectName` [1](#f-dist-folder-name) to a publicly served destination on the server via CLI of the service provider, SSH, or FTP (whichever is available). This step would be defined as a job if you have a CI/CD flow.
+3. [Configure the server](https://angular.io/guide/deployment#server-configuration) to redirect all requests to the _index.html_ file. Some services do that automatically. Others require you [to add a file to the bundle via assets](https://angular.io/guide/workspace-config#assets-configuration) which describes the server how to do the redirections. Occasionally, you may need to do manual configuration.
+
+In addition, you can [deploy your application to certain targets using the Angular CLI](https://angular.io/guide/deployment#automatic-deployment-with-the-cli). Here are some deploy targets:
+
+- [Azure](https://github.com/Azure/ng-deploy-azure#readme)
+- [Firebase](https://github.com/angular/angularfire#readme)
+- [Netlify](https://github.com/ngx-builders/netlify-builder#readme)
+- [Vercel](https://github.com/vercel/ng-deploy-vercel#readme)
+- [GitHub Pages](https://github.com/angular-schule/angular-cli-ghpages/#readme)
+
+---
+
+1 _The compiled output will be placed under `/dist` in a folder by the project name._ [↩](#a-dist-folder-name)
+
+---
+
+## What's Next?
+
+- [Environment Variables](./Environment.md)
diff --git a/docs/en/UI/Angular/Service-Proxies.md b/docs/en/UI/Angular/Service-Proxies.md
index 7dfb2c052c..92c4b01871 100644
--- a/docs/en/UI/Angular/Service-Proxies.md
+++ b/docs/en/UI/Angular/Service-Proxies.md
@@ -1,16 +1,15 @@
## Service Proxies
-It is common to call a REST endpoint in the server from our Angular applications. In this case, we generally create **services** (those have methods for each service method on the server side) and **model objects** (matches to [DTOs](../../Data-Transfer-Objects) in the server side).
+Calling a REST endpoint from Angular applications is common. We usually create **services** matching server-side controllers and **interfaces** matching [DTOs](../../Data-Transfer-Objects) to interact with the server. This often results in manually transforming C# code into TypeScript equivalents and that is unfortunate, if not intolerable.
-In addition to manually creating such server-interacting services, we could use tools like [NSWAG](https://github.com/RicoSuter/NSwag) to generate service proxies for us. But NSWAG has the following problems we've experienced:
+To avoid manual effort, we might use a tool like [NSWAG](https://github.com/RicoSuter/NSwag) that generates service proxies. However, NSWAG has some disadvantages:
-- It generates a **big, single** .ts file which has some problems;
- - It get **too large** when your application grows.
- - It doesn't fit into the **[modular](../../Module-Development-Basics) approach** of the ABP framework.
-- It creates a bit **ugly code**. We want to have a clean code (just like if we write manually).
-- It can not generate the same **method signature** declared in the server side (because swagger.json doesn't exactly reflect the method signature of the backend service). We've created an endpoint that exposes server side method contacts to allow clients generate a better aligned client proxies.
+- It generates **a single .ts file** which gets **too large** as your application grows. Also, this single file does not fit the **[modular](../../Module-Development-Basics) approach** of ABP.
+- To be honest, the generated code is a bit **ugly**. We would like to produce code that looks as if someone wrote it.
+- Since swagger.json **does not reflect the exact method signature** of backend services, NSWAG cannot reflect them on the client-side as well.
+
+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.
-ABP CLI changes that via the `generate-proxy` command. It automatically generates the client proxies in TypeScript. by creating folders which separated by module names in the `src/app` folder.
Run the following command in the **root folder** of the angular application:
```bash
@@ -19,13 +18,13 @@ abp generate-proxy
The command without any parameters creates proxies only for your own application's services and places them in your default Angular application. There are several parameters you may use to modify this behavior. See the [CLI documentation](../../CLI) for details.
-The generated files will be placed in a folder called `proxy` at the root of target project.
+The generated files will be placed in a folder called `proxy` at the root of the target project.

Each folder will have models, enums, and services defined at related namespace accompanied by a barrel export, i.e. an `index.ts` file for easier imports.
-> The cammand is able to find application/library roots by reading `angular.json` file. Make sure you have either defined your target project as the `defaultProject` or pass the `--target` parameter to the command. This also means that you may have a monorepo workspace.
+> The command can find application/library roots by reading the `angular.json` file. Make sure you have either defined your target project as the `defaultProject` or pass the `--target` parameter to the command. This also means that you may have a monorepo workspace.
### Angular Project Configuration
@@ -74,9 +73,9 @@ export const environment: Config.Environment = {
The `generate-proxy` command generates one service per back-end controller and a method (property with a function value actually) for each action in the controller. These methods call backend APIs via [RestService](./Http-Requests#restservice).
-A variable named `apiName` (available as of v2.4) is defined in each service. `apiName` matches the module's RemoteServiceName. This variable passes to the `RestService` as a parameter at each request. If there is no microservice API defined in the environment, `RestService` uses the default. See [getting a specific API endpoint from application config](./Http-Requests#how-to-get-a-specific-api-endpoint-from-application-config)
+A variable named `apiName` (available as of v2.4) is defined in each service. `apiName` matches the module's `RemoteServiceName`. This variable passes to the `RestService` as a parameter at each request. If there is no microservice API defined in the environment, `RestService` uses the default. See [getting a specific API endpoint from application config](./Http-Requests#how-to-get-a-specific-api-endpoint-from-application-config)
-The `providedIn` property of the services is defined as `'root'`. Therefore there is no need to provide them in a module. You can use them directly by injecting them into constructor as shown below:
+The `providedIn` property of the services is defined as `'root'`. Therefore there is no need to provide them in a module. You can use them directly by injecting them into the constructor as shown below:
```js
import { BookService } from '@proxy/books';
@@ -114,7 +113,7 @@ export class BookComponent implements OnInit {
### Enums
-Enums have always been difficult to populate in the frontend. The `generate-proxy` command genarates enums in a separate file and exports a ready-to-use options constant from the same file. So you can import them as follows:
+Enums have always been difficult to populate in the frontend. The `generate-proxy` command generates enums in a separate file and exports a ready-to-use "options constant" from the same file. So you can import them as follows:
```js
import { bookGenreOptions } from "@proxy/books";
@@ -132,7 +131,7 @@ export class BookComponent implements OnInit {
```
@@ -141,4 +140,4 @@ export class BookComponent implements OnInit {
## What's Next?
-- [HTTP Requests](./Http-Requests)
+- [PWA Configuration](./PWA-Configuration.md)
diff --git a/docs/en/UI/Angular/Settings.md b/docs/en/UI/Angular/Settings.md
new file mode 100644
index 0000000000..f3a5775838
--- /dev/null
+++ b/docs/en/UI/Angular/Settings.md
@@ -0,0 +1,59 @@
+# Settings
+
+You can get settings on the client-side using the [config state service](./Config-State.md) if they are allowed by their setting definition on the server-side.
+
+> This document only explains how settings work in the Angular UI projects. See the [settings document](../../../Settings.md) to understand the ABP setting system.
+
+## Before Use
+
+To use the `ConfigStateService`, you must inject it in your class as a dependency. You do not have to provide the service explicitly, because it is already **provided in root**.
+
+```js
+import { ConfigStateService } from '@abp/ng.core';
+
+@Component({
+ /* class metadata here */
+})
+class DemoComponent {
+ constructor(private config: ConfigStateService) {}
+}
+```
+
+## How to Get a Specific Setting
+
+You can use the `getSetting` method of `ConfigStateService` to get a specific setting from the configuration state. Here is an example:
+
+```js
+// this.config is instance of ConfigStateService
+
+const defaultLang = this.config.getSetting("Abp.Localization.DefaultLanguage");
+// 'en'
+```
+
+### How to Get All Settings From the Store
+
+You can use the `getSettings` method of `ConfigStateService` to obtain all settings as an object where the object properties are setting names and property values are setting values.
+
+```js
+// this.config is instance of ConfigStateService
+
+const settings = this.config.getSettings();
+// all settings as a key value pair
+```
+
+Additionally, the method lets you search settings by **passing a keyword** to it.
+
+```js
+const localizationSettings = this.config.getSettings("Localization");
+/*
+{
+ 'Abp.Localization.DefaultLanguage': 'en'
+}
+*/
+```
+
+Beware though, **settings search is case-sensitive**.
+
+## What's Next?
+
+- [Features](./Features.md)
diff --git a/docs/en/UI/Angular/Subscription-Service.md b/docs/en/UI/Angular/Subscription-Service.md
index 5d920df96e..dee77cbf1e 100644
--- a/docs/en/UI/Angular/Subscription-Service.md
+++ b/docs/en/UI/Angular/Subscription-Service.md
@@ -1,4 +1,4 @@
-# Easy Unsubscription for Your Observables
+# Managing RxJS Subscriptions
`SubscriptionService` is a utility service to provide an easy unsubscription from RxJS observables in Angular components and directives. Please see [why you should unsubscribe from observables on instance destruction](https://angular.io/guide/lifecycle-hooks#cleaning-up-on-instance-destruction).
@@ -200,4 +200,4 @@ class DemoComponent implements OnInit {
## What's Next?
-- [ListService](./List-Service.md)
+- [Working with Lists](./List-Service.md)
diff --git a/docs/en/UI/Angular/Toaster-Service.md b/docs/en/UI/Angular/Toaster-Service.md
index faa5632ab8..4d94b8cf6d 100644
--- a/docs/en/UI/Angular/Toaster-Service.md
+++ b/docs/en/UI/Angular/Toaster-Service.md
@@ -67,7 +67,7 @@ With the options above, the toast overlay looks like this:

-### How to Remove a Toast Overlay
+### How to Remove a Toast Overlay
The open toast overlay can be removed manually via the `remove` method by passing the `id` of toast:
@@ -85,7 +85,103 @@ The all open toasts can be removed manually via the `clear` method:
```js
this.toaster.clear();
```
+## Replacing ToasterService with 3rd party toaster libraries
+If you want the ABP Framework to utilize 3rd party libraries for the toasters instead of the built-in one, you can provide a service that implements `Toaster.Service` interface, and provide it as follows (ngx-toastr library used in example):
+
+> You can use *LocalizationService* for toaster messages translations.
+```js
+// your-custom-toaster.service.ts
+import { Injectable } from '@angular/core';
+import { Config, LocalizationService } from '@abp/ng.core';
+import { Toaster } from '@abp/ng.theme.shared';
+import { ToastrService } from 'ngx-toastr';
+
+@Injectable()
+export class CustomToasterService implements Toaster.Service {
+ constructor(private toastr: ToastrService, private localizationService: LocalizationService) {}
+
+ error(
+ message: Config.LocalizationParam,
+ title?: Config.LocalizationParam,
+ options?: PartialSample message
++ @Model.ProductDescription +
++ Reference: https://acme.com/catalog/ +
+